2011-05-30 23:37:33 +01:00
|
|
|
|
2011-05-31 09:00:51 +01:00
|
|
|
/* SSDV - Slow Scan Digital Video */
|
|
|
|
/*=======================================================================*/
|
2016-04-03 23:27:54 +01:00
|
|
|
/* Copyright 2011-2016 Philip Heron <phil@sanslogic.co.uk> */
|
2011-05-31 09:00:51 +01:00
|
|
|
/* */
|
|
|
|
/* This program is free software: you can redistribute it and/or modify */
|
|
|
|
/* it under the terms of the GNU General Public License as published by */
|
|
|
|
/* the Free Software Foundation, either version 3 of the License, or */
|
|
|
|
/* (at your option) any later version. */
|
|
|
|
/* */
|
|
|
|
/* This program is distributed in the hope that it will be useful, */
|
|
|
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
|
|
/* GNU General Public License for more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public License */
|
|
|
|
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
2011-05-30 23:37:33 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#ifndef INC_SSDV_H
|
|
|
|
#define INC_SSDV_H
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define SSDV_ERROR (-1)
|
|
|
|
#define SSDV_OK (0)
|
|
|
|
#define SSDV_FEED_ME (1)
|
|
|
|
#define SSDV_HAVE_PACKET (2)
|
|
|
|
#define SSDV_BUFFER_FULL (3)
|
|
|
|
#define SSDV_EOI (4)
|
|
|
|
|
|
|
|
/* Packet details */
|
|
|
|
#define SSDV_PKT_SIZE (0x100)
|
2012-03-04 09:43:52 +00:00
|
|
|
#define SSDV_PKT_SIZE_HEADER (0x0F)
|
2012-09-16 12:32:53 +01:00
|
|
|
#define SSDV_PKT_SIZE_CRC (0x04)
|
2011-05-30 23:37:33 +01:00
|
|
|
#define SSDV_PKT_SIZE_RSCODES (0x20)
|
|
|
|
|
2012-03-03 22:43:23 +00:00
|
|
|
#define TBL_LEN (546) /* Maximum size of the DQT and DHT tables */
|
|
|
|
#define HBUFF_LEN (16) /* Extra space for reading marker data */
|
2015-10-20 00:15:15 +01:00
|
|
|
|
|
|
|
#define SSDV_MAX_CALLSIGN (6) /* Maximum number of characters in a callsign */
|
2011-05-30 23:37:33 +01:00
|
|
|
|
2016-04-04 00:28:25 +01:00
|
|
|
#define SSDV_TYPE_INVALID (0xFF)
|
|
|
|
#define SSDV_TYPE_NORMAL (0x00)
|
|
|
|
#define SSDV_TYPE_NOFEC (0x01)
|
2014-08-28 20:13:46 +01:00
|
|
|
|
2011-05-30 23:37:33 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
2014-08-28 20:13:46 +01:00
|
|
|
/* Packet type configuration */
|
2023-03-04 13:10:13 +00:00
|
|
|
uint8_t type; /* 0 = Normal mode (nom. 224 byte packet + 32 bytes FEC),
|
|
|
|
1 = No-FEC mode (nom. 256 byte packet) */
|
2014-08-28 20:13:46 +01:00
|
|
|
uint16_t pkt_size_payload;
|
|
|
|
uint16_t pkt_size_crcdata;
|
2023-03-04 13:10:13 +00:00
|
|
|
int pkt_size;
|
2014-08-27 23:49:25 +01:00
|
|
|
|
2011-05-30 23:37:33 +01:00
|
|
|
/* Image information */
|
|
|
|
uint16_t width;
|
|
|
|
uint16_t height;
|
2012-02-25 20:06:15 +00:00
|
|
|
uint32_t callsign;
|
2012-03-04 09:43:52 +00:00
|
|
|
uint8_t image_id;
|
2011-05-30 23:37:33 +01:00
|
|
|
uint16_t packet_id;
|
2012-02-25 00:25:25 +00:00
|
|
|
uint8_t mcu_mode; /* 0 = 2x2, 1 = 2x1, 2 = 1x2, 3 = 1x1 */
|
2011-05-30 23:37:33 +01:00
|
|
|
uint16_t mcu_id;
|
|
|
|
uint16_t mcu_count;
|
2016-06-16 23:29:30 +01:00
|
|
|
uint8_t quality; /* JPEG quality level for encoding, 0-7 */
|
2011-05-30 23:37:33 +01:00
|
|
|
uint16_t packet_mcu_id;
|
2012-03-04 09:43:52 +00:00
|
|
|
uint8_t packet_mcu_offset;
|
2011-05-30 23:37:33 +01:00
|
|
|
|
|
|
|
/* Source buffer */
|
|
|
|
uint8_t *inp; /* Pointer to next input byte */
|
|
|
|
size_t in_len; /* Number of input bytes remaining */
|
|
|
|
size_t in_skip; /* Number of input bytes to skip */
|
|
|
|
|
|
|
|
/* Source bits */
|
|
|
|
uint32_t workbits; /* Input bits currently being worked on */
|
|
|
|
uint8_t worklen; /* Number of bits in the input bit buffer */
|
|
|
|
|
|
|
|
/* JPEG / Packet output buffer */
|
|
|
|
uint8_t *out; /* Pointer to the beginning of the output buffer */
|
|
|
|
uint8_t *outp; /* Pointer to the next output byte */
|
|
|
|
size_t out_len; /* Number of output bytes remaining */
|
|
|
|
char out_stuff; /* Flag to add stuffing bytes to output */
|
|
|
|
|
|
|
|
/* Output bits */
|
|
|
|
uint32_t outbits; /* Output bit buffer */
|
|
|
|
uint8_t outlen; /* Number of bits in the output bit buffer */
|
|
|
|
|
|
|
|
/* JPEG decoder state */
|
|
|
|
enum {
|
|
|
|
S_MARKER = 0,
|
|
|
|
S_MARKER_LEN,
|
|
|
|
S_MARKER_DATA,
|
|
|
|
S_HUFF,
|
|
|
|
S_INT,
|
|
|
|
S_EOI,
|
|
|
|
} state;
|
|
|
|
uint16_t marker; /* Current marker */
|
|
|
|
uint16_t marker_len; /* Length of data following marker */
|
|
|
|
uint8_t *marker_data; /* Where to copy marker data too */
|
|
|
|
uint16_t marker_data_len; /* How much is there */
|
2018-06-13 16:01:43 +01:00
|
|
|
uint8_t greyscale; /* 0 = Normal (3 channels), 1 = Greyscale */
|
2011-05-30 23:37:33 +01:00
|
|
|
uint8_t component; /* 0 = Y, 1 = Cb, 2 = Cr */
|
2012-02-25 00:25:25 +00:00
|
|
|
uint8_t ycparts; /* Number of Y component parts per MCU */
|
2011-05-30 23:37:33 +01:00
|
|
|
uint8_t mcupart; /* 0-3 = Y, 4 = Cb, 5 = Cr */
|
|
|
|
uint8_t acpart; /* 0 - 64; 0 = DC, 1 - 64 = AC */
|
2012-03-03 22:43:23 +00:00
|
|
|
int dc[3]; /* DC value for each component */
|
|
|
|
int adc[3]; /* DC adjusted value for each component */
|
2011-05-30 23:37:33 +01:00
|
|
|
uint8_t acrle; /* RLE value for current AC value */
|
2011-06-24 22:01:08 +01:00
|
|
|
uint8_t accrle; /* Accumulative RLE value */
|
2012-02-21 22:07:14 +00:00
|
|
|
uint16_t dri; /* Reset interval */
|
2012-01-29 18:56:17 +00:00
|
|
|
enum {
|
|
|
|
S_ENCODING = 0,
|
|
|
|
S_DECODING,
|
|
|
|
} mode;
|
|
|
|
uint32_t reset_mcu; /* MCU block to do absolute encoding */
|
2018-06-27 08:45:07 +01:00
|
|
|
uint32_t next_reset_mcu;
|
2011-05-30 23:37:33 +01:00
|
|
|
char needbits; /* Number of bits needed to decode integer */
|
|
|
|
|
2012-03-03 22:43:23 +00:00
|
|
|
/* The input huffman and quantisation tables */
|
|
|
|
uint8_t stbls[TBL_LEN + HBUFF_LEN];
|
|
|
|
uint8_t *sdht[2][2], *sdqt[2];
|
|
|
|
uint16_t stbl_len;
|
|
|
|
|
|
|
|
/* The same for output */
|
|
|
|
uint8_t dtbls[TBL_LEN];
|
|
|
|
uint8_t *ddht[2][2], *ddqt[2];
|
|
|
|
uint16_t dtbl_len;
|
2011-05-30 23:37:33 +01:00
|
|
|
|
|
|
|
} ssdv_t;
|
|
|
|
|
|
|
|
typedef struct {
|
2015-10-20 09:59:48 +01:00
|
|
|
uint8_t type;
|
2012-02-25 20:06:15 +00:00
|
|
|
uint32_t callsign;
|
2015-10-20 00:15:15 +01:00
|
|
|
char callsign_s[SSDV_MAX_CALLSIGN + 1];
|
2011-05-30 23:37:33 +01:00
|
|
|
uint8_t image_id;
|
|
|
|
uint16_t packet_id;
|
|
|
|
uint16_t width;
|
|
|
|
uint16_t height;
|
2015-10-20 00:15:15 +01:00
|
|
|
uint8_t eoi;
|
2016-06-16 23:29:30 +01:00
|
|
|
uint8_t quality;
|
2012-02-25 00:25:25 +00:00
|
|
|
uint16_t mcu_mode;
|
2012-03-04 09:43:52 +00:00
|
|
|
uint8_t mcu_offset;
|
2011-05-30 23:37:33 +01:00
|
|
|
uint16_t mcu_id;
|
|
|
|
uint16_t mcu_count;
|
|
|
|
} ssdv_packet_info_t;
|
|
|
|
|
|
|
|
/* Encoding */
|
2023-03-04 13:10:13 +00:00
|
|
|
extern char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id, int8_t quality, int pkt_size);
|
2011-05-30 23:37:33 +01:00
|
|
|
extern char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer);
|
|
|
|
extern char ssdv_enc_get_packet(ssdv_t *s);
|
|
|
|
extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length);
|
|
|
|
|
|
|
|
/* Decoding */
|
2023-03-04 13:10:13 +00:00
|
|
|
extern char ssdv_dec_init(ssdv_t *s, int pkt_size);
|
2011-05-30 23:37:33 +01:00
|
|
|
extern char ssdv_dec_set_buffer(ssdv_t *s, uint8_t *buffer, size_t length);
|
|
|
|
extern char ssdv_dec_feed(ssdv_t *s, uint8_t *packet);
|
|
|
|
extern char ssdv_dec_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length);
|
|
|
|
|
2023-03-04 13:10:13 +00:00
|
|
|
extern char ssdv_dec_is_packet(uint8_t *packet, int pkt_size, int *errors);
|
2011-05-30 23:37:33 +01:00
|
|
|
extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|