Skip to content

Commit

Permalink
rtpdec_jpeg: handle custom static Q tables
Browse files Browse the repository at this point in the history
Handle Q=128-254, which are defined by the transport but in opposite
to Q=255, its values don't change over time.
  • Loading branch information
MartinPulec committed Aug 2, 2024
1 parent 128935d commit 835a7c0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 20 deletions.
52 changes: 32 additions & 20 deletions src/rtp/rtpdec_jpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @author Martin Pulec <[email protected]>
*
* @todo
* * handle predefined (0-127) and custom static (128-254) quantization tables
* * handle predefined (0-127) quantization tables
* * handle precision=1 (?)
* * error meesage for zero-len quantization tables
*/
Expand Down Expand Up @@ -68,6 +68,7 @@
*(data) += sizeof(uint16_t)

enum {
QUANT_TAB_T_FIRST_STATIC = 128,
QUANT_TAB_T_DYN = 255, ///< Q=255
RTP_SZ_MULTIPLIER = 8, ///< size in RTP hdr is /8
RTP_TYPE_RST_BIT = 64, ///< indicates presence of RST markers
Expand All @@ -90,20 +91,31 @@ parse_restart_interval(unsigned char **pckt_data, int verbose_adj)
}

static void
parse_quant_tables(char *dqt_start, unsigned char **pckt_data, int verbose_adj)
parse_quant_tables(struct decode_data_rtsp *dec, unsigned char **pckt_data,
int q)
{
assert (q >= QUANT_TAB_T_FIRST_STATIC);

uint8_t mbz = GET_BYTE(pckt_data);
uint8_t precision = GET_BYTE(pckt_data);
uint16_t length = GET_2BYTE(pckt_data);

MSG(VERBOSE + verbose_adj,
MSG(VERBOSE + dec->jpeg.not_first_run,
"JPEG quant hdr mbz=%" PRIu8 " prec=%" PRIu8 " len=%" PRIu16 "\n",
mbz, precision, length);

if (dec->jpeg.quantization_table_set[q] || // already set
length == 0) { // quantization table not included in this frame
*pckt_data += length;
return;
}

assert(length == JPEG_QUANT_SIZE || length == 2 * JPEG_QUANT_SIZE);
assert(precision == 0);

uint8_t quant_table[2][JPEG_QUANT_SIZE];
uint8_t(*quant_table)[JPEG_QUANT_SIZE] =
dec->jpeg.quantization_tables[q];

memcpy(quant_table[0], *pckt_data, sizeof quant_table[0]);
*pckt_data += sizeof quant_table[0];
if (length == 2 * JPEG_QUANT_SIZE) {
Expand All @@ -117,8 +129,7 @@ parse_quant_tables(char *dqt_start, unsigned char **pckt_data, int verbose_adj)
"Single quantization table includedd (len=64)!\n");
memcpy(quant_table[1], quant_table[0], sizeof quant_table[1]);
}

jpeg_writer_fill_dqt(dqt_start, quant_table);
dec->jpeg.quantization_table_set[q] = true;
}

static char *
Expand Down Expand Up @@ -157,8 +168,6 @@ create_jpeg_frame(struct video_frame *frame, unsigned char **pckt_data,
type_spec);
}

assert(q == QUANT_TAB_T_DYN); // TODO(mpulec): see TODO in file docu

frame->callbacks.data_deleter = vf_data_deleter;
frame->tiles[0].data =
calloc(1, 1000 + 3 * info.width * info.height * 2);
Expand All @@ -175,14 +184,11 @@ skip_jpeg_headers(unsigned char **pckt_data)
{
*pckt_data += sizeof(uint32_t); // skip type_spec + offset
uint8_t type = GET_BYTE(pckt_data);
uint8_t q = GET_BYTE(pckt_data);
*pckt_data += 2; // skip Width, Height
*pckt_data += 3; // skip Q, Width, Height

if ((type & RTP_TYPE_RST_BIT) != 0) { // skip Restart Marker header
*pckt_data += sizeof(uint32_t);
}

assert(q == QUANT_TAB_T_DYN); // TODO(mpulec): see TODO in file docu
}

int
Expand All @@ -191,7 +197,9 @@ decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
struct decode_data_rtsp *dec_data = decode_data;

struct video_frame *frame = dec_data->frame;
bool quant_tables_present = false;
// table with Q=255 must be always (re)set
dec_data->jpeg.quantization_table_set[QUANT_TAB_T_DYN] = false;
uint8_t q = -1;

while (cdata != NULL) {
rtp_packet *pckt = cdata->data;
Expand All @@ -200,6 +208,7 @@ decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
uint32_t hdr = 0;
memcpy(&hdr, pckt_data, sizeof hdr);
const unsigned off = ntohl(hdr) & 0xFFFFFFU;
memcpy(&q, pckt_data + 5, sizeof q);
if (frame->tiles[0].width == 0) {
char *hdr_end = create_jpeg_frame(
frame, &pckt_data, &dec_data->jpeg.dqt_start,
Expand All @@ -209,10 +218,9 @@ decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
} else {
skip_jpeg_headers(&pckt_data);
}
if (off == 0) { // for q=255, 1st pckt contains tables
parse_quant_tables(dec_data->jpeg.dqt_start, &pckt_data,
dec_data->jpeg.not_first_run);
quant_tables_present = true;
// for q>=128, 1st pckt contains tables
if (off == 0 && q >= QUANT_TAB_T_FIRST_STATIC) {
parse_quant_tables(dec_data, &pckt_data, q);
}

const long payload_hdr_len =
Expand All @@ -228,12 +236,16 @@ decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
cdata = cdata->nxt;
}

if (!quant_tables_present) {
MSG(WARNING, "Dropping frame - missing quantization tables "
"(1st packet missing)!\n");
if (!dec_data->jpeg.quantization_table_set[q]) {
MSG(WARNING,
"Dropping frame - missing quantization tables for Q=%d!\n",
q);
return false;
}

jpeg_writer_fill_dqt(dec_data->jpeg.dqt_start,
dec_data->jpeg.quantization_tables[q]);

char *buffer = frame->tiles[0].data + frame->tiles[0].data_len;
jpeg_writer_write_eoi(&buffer);
frame->tiles[0].data_len = buffer - frame->tiles[0].data;
Expand Down
14 changes: 14 additions & 0 deletions src/rtp/rtpdec_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,19 @@
#ifndef RTP_RTPDEC_STATE_H_1712C4BC_F5CA_44DE_AF8B_EB2996D0E8A5
#define RTP_RTPDEC_STATE_H_1712C4BC_F5CA_44DE_AF8B_EB2996D0E8A5

#include <stdbool.h> // for bool
#include <stdint.h> // for uint8_t

#include "utils/jpeg_writer.h" // for JPEG_QUANT_SIZE

struct coded_data;
struct video_frame;

enum {
JPEG_QUANT_TAB_COUNT = 256,
JPEG_Q_TAB_COUNT = 2, // for RFC 2435 defined JPEG Types
};

struct decode_data_rtsp {
int (*decode)(struct coded_data *cdata, void *decode_data);
struct video_frame *frame;
Expand All @@ -61,6 +71,10 @@ struct decode_data_rtsp {
unsigned char offset_buffer[2048];
} h264;
struct {
uint8_t quantization_tables[JPEG_QUANT_TAB_COUNT]
[JPEG_Q_TAB_COUNT]
[JPEG_QUANT_SIZE];
bool quantization_table_set[JPEG_QUANT_TAB_COUNT];
char *dqt_start;
int not_first_run; ///< decrease verbosity next time
} jpeg;
Expand Down

0 comments on commit 835a7c0

Please sign in to comment.