UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rtpdec_jpeg.c File Reference
#include "rtp/rtpdec_jpeg.h"
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "rtp/pbuf.h"
#include "rtp/rtp.h"
#include "rtp/rtpdec_state.h"
#include "types.h"
#include "utils/jpeg_writer.h"
#include "utils/macros.h"
#include "video_frame.h"
Include dependency graph for rtpdec_jpeg.c:

Go to the source code of this file.

Macros

#define GET_2BYTE(data)
 
#define GET_BYTE(data)
 
#define MOD_NAME   "[rtpdec_jpeg] "
 

Enumerations

enum  { QUANT_TAB_T_FIRST_STATIC = 128 , QUANT_TAB_T_DYN = 255 , RTP_SZ_MULTIPLIER = 8 , RTP_TYPE_RST_BIT = 64 }
 

Functions

static char * create_jpeg_frame (struct video_frame *frame, unsigned char **pckt_data, char **dqt_start, int verbose_adj)
 
int decode_frame_jpeg (struct coded_data *cdata, void *decode_data)
 
static void MakeTables (int q, u_char *lqt, u_char *cqt)
 
static void parse_quant_tables (struct decode_data_rtsp *dec, unsigned char **pckt_data, const unsigned char *end, int q)
 
static unsigned parse_restart_interval (unsigned char **pckt_data, int verbose_adj)
 
static void skip_jpeg_headers (unsigned char **pckt_data)
 

Variables

static const int jpeg_chroma_quantizer [64]
 
static const int jpeg_luma_quantizer [64]
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file rtpdec_jpeg.c.

Macro Definition Documentation

◆ GET_2BYTE

#define GET_2BYTE ( data)
Value:
ntohs(*((uint16_t *) (*(data)))); \
*(data) += sizeof(uint16_t)

Definition at line 61 of file rtpdec_jpeg.c.

61#define GET_2BYTE(data) \
62 ntohs(*((uint16_t *) (*(data)))); \
63 *(data) += sizeof(uint16_t)

Referenced by parse_quant_tables(), and parse_restart_interval().

◆ GET_BYTE

#define GET_BYTE ( data)
Value:
*(*(data))++

Definition at line 60 of file rtpdec_jpeg.c.

Referenced by create_jpeg_frame(), parse_quant_tables(), and skip_jpeg_headers().

◆ MOD_NAME

#define MOD_NAME   "[rtpdec_jpeg] "

Definition at line 58 of file rtpdec_jpeg.c.

Referenced by create_jpeg_frame(), and parse_quant_tables().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
QUANT_TAB_T_FIRST_STATIC 
QUANT_TAB_T_DYN 

Q=255.

RTP_SZ_MULTIPLIER 

size in RTP hdr is /8

RTP_TYPE_RST_BIT 

indicates presence of RST markers

Definition at line 65 of file rtpdec_jpeg.c.

65 {
67 QUANT_TAB_T_DYN = 255,
69 RTP_TYPE_RST_BIT = 64,
70};
@ RTP_SZ_MULTIPLIER
size in RTP hdr is /8
Definition rtpdec_jpeg.c:68
@ RTP_TYPE_RST_BIT
indicates presence of RST markers
Definition rtpdec_jpeg.c:69
@ QUANT_TAB_T_DYN
Q=255.
Definition rtpdec_jpeg.c:67
@ QUANT_TAB_T_FIRST_STATIC
Definition rtpdec_jpeg.c:66

Function Documentation

◆ create_jpeg_frame()

static char * create_jpeg_frame ( struct video_frame * frame,
unsigned char ** pckt_data,
char ** dqt_start,
int verbose_adj )
static

Definition at line 142 of file rtpdec_jpeg.c.

144{
145 struct jpeg_writer_data info = { 0 };
146
147 uint8_t type_spec = GET_BYTE(pckt_data);
148 *pckt_data += 3; // skip 24 bit Fragment Offset
149 uint8_t type = GET_BYTE(pckt_data);
150 uint8_t q = GET_BYTE(pckt_data);
151 uint8_t width = GET_BYTE(pckt_data);
152 uint8_t height = GET_BYTE(pckt_data);
153
156
157 MSG(VERBOSE + verbose_adj,
158 "JPEG type_spec=%" PRIu8 " type=%" PRIu8 " q=%" PRIu8
159 " width=%d height=%d\n",
160 type_spec, type, q, frame->tiles[0].width, frame->tiles[0].height);
161
162 if ((type & ~(RTP_TYPE_RST_BIT | 1)) != 0) { // 0,1,64,65
163 MSG(ERROR,
164 "Only RFC 2534 defined JPEG types are currently supported "
165 "but got %d! Please report",
166 type);
167 return NULL;
168 }
169
170 if ((type & RTP_TYPE_RST_BIT) != 0) {
171 info.restart_interval =
172 parse_restart_interval(pckt_data, verbose_adj);
173 type &= ~RTP_TYPE_RST_BIT;
174 }
175 info.subsampling = type;
176
177 if (type_spec != 0) {
178 log_msg_once(LOG_LEVEL_WARNING, to_fourcc('R', 'D', 'J', 't'),
179 MOD_NAME "JPEG type %d; only 0 (progressive) is "
180 "currently supported!\n",
181 type_spec);
182 }
183
185 frame->tiles[0].data =
186 calloc(1, 1000 + 3 * info.width * info.height * 2);
187
188 char *buffer = frame->tiles[0].data;
189 jpeg_writer_write_headers(&buffer, &info);
190 *dqt_start = info.dqt_marker_start;
191
192 return buffer;
193}
struct video_frame * frame
void vf_data_deleter(struct video_frame *buf)
void log_msg_once(int level, uint32_t id, const char *msg,...)
Definition debug.cpp:137
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
void jpeg_writer_write_headers(char **buffer, struct jpeg_writer_data *info)
writes JPEG/JFIF headers up to the scan (including SOS header)
#define to_fourcc(a, b, c, d)
Creates FourCC word.
Definition macros.h:114
static unsigned parse_restart_interval(unsigned char **pckt_data, int verbose_adj)
Definition rtpdec_jpeg.c:73
#define GET_BYTE(data)
Definition rtpdec_jpeg.c:60
#define MOD_NAME
Definition rtpdec_jpeg.c:58
Option::OptType type
Definition settings.cpp:194
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int height
Definition types.h:281
void(* data_deleter)(struct video_frame *)
Definition types.h:256
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
struct video_frame_callbacks callbacks
Definition types.h:324

References video_frame::callbacks, tile::data, video_frame_callbacks::data_deleter, frame, GET_BYTE, jpeg_writer_data::height, tile::height, jpeg_writer_write_headers(), LOG_LEVEL_WARNING, log_msg_once(), MOD_NAME, MSG, parse_restart_interval(), RTP_SZ_MULTIPLIER, RTP_TYPE_RST_BIT, video_frame::tiles, to_fourcc, type, vf_data_deleter(), jpeg_writer_data::width, and tile::width.

Referenced by decode_frame_jpeg().

Here is the call graph for this function:

◆ decode_frame_jpeg()

int decode_frame_jpeg ( struct coded_data * cdata,
void * decode_data )

Definition at line 267 of file rtpdec_jpeg.c.

268{
269 struct decode_data_rtsp *dec_data = decode_data;
270
271 struct video_frame *frame = dec_data->frame;
272 // table with Q=255 must be always (re)set
274 uint8_t q = -1;
275 unsigned received_bytes = 0;
276 unsigned frame_max_len = 0; // off + data_len
277
278 while (cdata != NULL) {
279 rtp_packet *pckt = cdata->data;
280 unsigned char *pckt_data = (unsigned char *) pckt->data;
281
282 uint32_t hdr = 0;
283 memcpy(&hdr, pckt_data, sizeof hdr);
284 const unsigned off = ntohl(hdr) & 0xFFFFFFU;
285 memcpy(&q, pckt_data + 5, sizeof q);
286 if (frame->tiles[0].width == 0) {
287 char *hdr_end = create_jpeg_frame(
288 frame, &pckt_data, &dec_data->jpeg.dqt_start,
289 dec_data->jpeg.not_first_run);
290 if (hdr_end == NULL) {
291 return false;
292 }
293 dec_data->offset_len =
294 (int) (hdr_end - frame->tiles[0].data);
295 } else {
296 skip_jpeg_headers(&pckt_data);
297 }
298 // for q>=128, 1st pckt contains tables
299 if (off == 0 && q >= QUANT_TAB_T_FIRST_STATIC) {
300 const unsigned char *end =
301 (unsigned char *) pckt->data + pckt->data_len;
302 parse_quant_tables(dec_data, &pckt_data, end, q);
303 }
304
305 const long payload_hdr_len =
306 pckt_data - (unsigned char *) pckt->data;
307 const long data_len = pckt->data_len - payload_hdr_len;
308 const unsigned frame_off = off + dec_data->offset_len;
309 memcpy(frame->tiles[0].data + frame_off, pckt_data, data_len);
310
311 received_bytes += data_len;
312 frame_max_len = MAX(frame_max_len, off + data_len);
313
314 cdata = cdata->nxt;
315 }
316
317 if (!dec_data->jpeg.quantization_table_set[q] &&
319 MakeTables(q, dec_data->jpeg.quantization_tables[q][0],
320 dec_data->jpeg.quantization_tables[q][1]);
321 dec_data->jpeg.quantization_table_set[q] = true;
322 }
323
324 if (!dec_data->jpeg.quantization_table_set[q]) {
325 MSG(WARNING,
326 "Dropping frame - missing quantization tables for Q=%d!\n",
327 q);
328 return false;
329 }
330
332 dec_data->jpeg.quantization_tables[q]);
333
334 char *frame_end =
335 frame->tiles[0].data + dec_data->offset_len + frame_max_len;
336 jpeg_writer_write_eoi(&frame_end);
337 frame->tiles[0].data_len = frame_end - frame->tiles[0].data;
338
339 if (received_bytes != frame_max_len) {
340 MSG(DEBUG, "Frame incomplete - expected %u bytes, got %u B!\n",
341 frame_max_len, received_bytes);
342 }
343
344 dec_data->jpeg.not_first_run = 1;
345
346 return true;
347}
void jpeg_writer_fill_dqt(char *buffer, uint8_t quant_table[2][JPEG_QUANT_SIZE])
void jpeg_writer_write_eoi(char **buffer)
#define MAX(a, b)
Definition macros.h:65
#define DEBUG
Definition main.c:27
rtp_packet
Definition rtp.h:126
static char * create_jpeg_frame(struct video_frame *frame, unsigned char **pckt_data, char **dqt_start, int verbose_adj)
static void MakeTables(int q, u_char *lqt, u_char *cqt)
static void skip_jpeg_headers(unsigned char **pckt_data)
static void parse_quant_tables(struct decode_data_rtsp *dec, unsigned char **pckt_data, const unsigned char *end, int q)
Definition rtpdec_jpeg.c:89
rtp_packet * data
Definition pbuf.h:75
struct coded_data * nxt
Definition pbuf.h:72
struct decode_data_rtsp::@46::@49 jpeg
int not_first_run
decrease verbosity next time
bool quantization_table_set[JPEG_QUANT_TAB_COUNT]
struct video_frame * frame
uint8_t quantization_tables[JPEG_QUANT_TAB_COUNT][JPEG_Q_TAB_COUNT][JPEG_QUANT_SIZE]
unsigned int data_len
length of the data
Definition types.h:288
Struct video_frame represents a video frame and contains video description.
Definition types.h:305

References create_jpeg_frame(), coded_data::data, tile::data, tile::data_len, DEBUG, decode_data_rtsp::dqt_start, decode_data_rtsp::frame, frame, decode_data_rtsp::jpeg, jpeg_writer_fill_dqt(), jpeg_writer_write_eoi(), MakeTables(), MAX, MSG, decode_data_rtsp::not_first_run, coded_data::nxt, decode_data_rtsp::offset_len, parse_quant_tables(), QUANT_TAB_T_DYN, QUANT_TAB_T_FIRST_STATIC, decode_data_rtsp::quantization_table_set, decode_data_rtsp::quantization_tables, rtp_packet, skip_jpeg_headers(), video_frame::tiles, and tile::width.

Referenced by init_rtsp().

Here is the call graph for this function:

◆ MakeTables()

static void MakeTables ( int q,
u_char * lqt,
u_char * cqt )
static

Definition at line 239 of file rtpdec_jpeg.c.

240{
241 int i;
242 int factor = q;
243
244 if (q < 1) factor = 1;
245 if (q > 99) factor = 99;
246 if (q < 50)
247 q = 5000 / factor;
248 else
249 q = 200 - factor*2;
250
251 for (i=0; i < 64; i++) {
252 int lq = (jpeg_luma_quantizer[i] * q + 50) / 100;
253 int cq = (jpeg_chroma_quantizer[i] * q + 50) / 100;
254
255 /* Limit the quantizers to 1 <= q <= 255 */
256 if (lq < 1) lq = 1;
257 else if (lq > 255) lq = 255;
258 lqt[i] = lq;
259
260 if (cq < 1) cq = 1;
261 else if (cq > 255) cq = 255;
262 cqt[i] = cq;
263 }
264}
static const int jpeg_luma_quantizer[64]
static const int jpeg_chroma_quantizer[64]

References jpeg_chroma_quantizer, and jpeg_luma_quantizer.

Referenced by decode_frame_jpeg().

◆ parse_quant_tables()

static void parse_quant_tables ( struct decode_data_rtsp * dec,
unsigned char ** pckt_data,
const unsigned char * end,
int q )
static

Definition at line 89 of file rtpdec_jpeg.c.

91{
92 assert (q >= QUANT_TAB_T_FIRST_STATIC);
93
94 uint8_t mbz = GET_BYTE(pckt_data);
95 uint8_t precision = GET_BYTE(pckt_data);
96 uint16_t length = GET_2BYTE(pckt_data);
97
98 MSG(VERBOSE + dec->jpeg.not_first_run,
99 "JPEG quant hdr mbz=%" PRIu8 " prec=%" PRIu8 " len=%" PRIu16 "\n",
100 mbz, precision, length);
101
102 if (dec->jpeg.quantization_table_set[q] || // already set
103 length == 0) { // quantization table not included in this frame
104 *pckt_data += length;
105 return;
106 }
107
108 assert(length == JPEG_QUANT_SIZE || length == 2 * JPEG_QUANT_SIZE);
109 assert(precision == 0); // 8-bit JPEG should not use 16 bit tables
110
111 const ptrdiff_t remaining_bytes = end - *pckt_data;
112 if (length > remaining_bytes) {
113 MSG(ERROR,
114 "Bogus JPEG packet (q table len %" PRIu16
115 " > %td remaining bytes! "
116 "Dropping packet...\n",
117 length, remaining_bytes);
118 *pckt_data += remaining_bytes;;
119 return;
120 }
121
122 uint8_t(*quant_table)[JPEG_QUANT_SIZE] =
123 dec->jpeg.quantization_tables[q];
124
125 memcpy(quant_table[0], *pckt_data, sizeof quant_table[0]);
126 *pckt_data += sizeof quant_table[0];
127 if (length == 2 * JPEG_QUANT_SIZE) {
128 memcpy(quant_table[1], *pckt_data, sizeof quant_table[1]);
129 *pckt_data += sizeof quant_table[1];
130 } else {
131 // FFmpeg uses single table if used as suggested in vcap/rtsp.c
132 // but according to RFC 2 tables should be present so dup 1st
133 log_msg_once(LOG_LEVEL_WARNING, to_fourcc('R', 'D', 'J', 'q'),
135 "Single quantization table includedd (len=64)!\n");
136 memcpy(quant_table[1], quant_table[0], sizeof quant_table[1]);
137 }
138 dec->jpeg.quantization_table_set[q] = true;
139}
@ JPEG_QUANT_SIZE
items, bytes (for precision=0)
Definition jpeg_writer.h:54
#define GET_2BYTE(data)
Definition rtpdec_jpeg.c:61

References GET_2BYTE, GET_BYTE, JPEG_QUANT_SIZE, LOG_LEVEL_WARNING, log_msg_once(), MOD_NAME, MSG, QUANT_TAB_T_FIRST_STATIC, and to_fourcc.

Referenced by decode_frame_jpeg().

Here is the call graph for this function:

◆ parse_restart_interval()

static unsigned parse_restart_interval ( unsigned char ** pckt_data,
int verbose_adj )
static

Definition at line 73 of file rtpdec_jpeg.c.

74{
75 const uint16_t rst_int = GET_2BYTE(pckt_data);
76 const uint16_t tmp = GET_2BYTE(pckt_data);
77 const unsigned f = tmp >> 15;
78 const unsigned l = (tmp >> 14) & 0x1;
79 const unsigned rst_count = tmp & 0x3FFFU;
80
81 MSG(VERBOSE + verbose_adj,
82 "JPEG rst int=%" PRIu16 " f=%u l=%u count=%u\n", rst_int, f, l,
83 rst_count);
84
85 return rst_int;
86}

References GET_2BYTE, and MSG.

Referenced by create_jpeg_frame().

◆ skip_jpeg_headers()

static void skip_jpeg_headers ( unsigned char ** pckt_data)
static

Definition at line 196 of file rtpdec_jpeg.c.

197{
198 *pckt_data += sizeof(uint32_t); // skip type_spec + offset
199 uint8_t type = GET_BYTE(pckt_data);
200 *pckt_data += 3; // skip Q, Width, Height
201
202 if ((type & RTP_TYPE_RST_BIT) != 0) { // skip Restart Marker header
203 *pckt_data += sizeof(uint32_t);
204 }
205}

References GET_BYTE, RTP_TYPE_RST_BIT, and type.

Referenced by decode_frame_jpeg().

Variable Documentation

◆ jpeg_chroma_quantizer

const int jpeg_chroma_quantizer[64]
static
Initial value:
= {
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
}

Definition at line 224 of file rtpdec_jpeg.c.

224 {
225 17, 18, 24, 47, 99, 99, 99, 99,
226 18, 21, 26, 66, 99, 99, 99, 99,
227 24, 26, 56, 99, 99, 99, 99, 99,
228 47, 66, 99, 99, 99, 99, 99, 99,
229 99, 99, 99, 99, 99, 99, 99, 99,
230 99, 99, 99, 99, 99, 99, 99, 99,
231 99, 99, 99, 99, 99, 99, 99, 99,
232 99, 99, 99, 99, 99, 99, 99, 99
233};

Referenced by MakeTables().

◆ jpeg_luma_quantizer

const int jpeg_luma_quantizer[64]
static
Initial value:
= {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
}

Definition at line 210 of file rtpdec_jpeg.c.

210 {
211 16, 11, 10, 16, 24, 40, 51, 61,
212 12, 12, 14, 19, 26, 58, 60, 55,
213 14, 13, 16, 24, 40, 57, 69, 56,
214 14, 17, 22, 29, 51, 87, 80, 62,
215 18, 22, 37, 56, 68, 109, 103, 77,
216 24, 35, 55, 64, 81, 104, 113, 92,
217 49, 64, 78, 87, 103, 121, 120, 101,
218 72, 92, 95, 98, 112, 100, 103, 99
219};

Referenced by MakeTables().