UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rtpdec_jpeg.c
Go to the documentation of this file.
1
6/*
7 * Copyright (c) 2024 CESNET
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, is permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * 3. Neither the name of CESNET nor the names of its contributors may be
22 * used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
27 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
29 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "rtp/rtpdec_jpeg.h"
40
41#include <assert.h> // for assert
42#include <inttypes.h> // for uint8_t, uint16_t, uint32_t
43#include <stdbool.h> // for true
44#include <stdint.h> // for PRIu8
45#include <stdio.h> // for fclose, fopen, fwrite, printf, FILE
46#include <stdlib.h> // for exit, malloc, NULL
47#include <string.h> // for memcpy
48
49#include "debug.h" // for LOG_LEVEL_VERBOSE, MSG, log_msg_once
50#include "rtp/pbuf.h" // for coded_data
51#include "rtp/rtp.h" // for rtp_packet
52#include "rtp/rtpdec_state.h" // for decode_data_rtsp
53#include "types.h" // for tile, video_frame, video_frame_callbacks
54#include "utils/jpeg_writer.h" // for jpeg_writer_data, JPEG_QUANT_SIZE, jpeg_wr...
55#include "utils/macros.h" // for MAX, to_fourcc
56#include "video_frame.h" // for vf_data_deleter
57
58#define MOD_NAME "[rtpdec_jpeg] "
59
60#define GET_BYTE(data) *(*(data))++
61#define GET_2BYTE(data) \
62 ntohs(*((uint16_t *) (*(data)))); \
63 *(data) += sizeof(uint16_t)
64
65enum {
70};
71
72static unsigned
73parse_restart_interval(unsigned char **pckt_data, int verbose_adj)
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}
87
88static void
89parse_quant_tables(struct decode_data_rtsp *dec, unsigned char **pckt_data,
90 const unsigned char *end, int q)
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}
140
141static char *
142create_jpeg_frame(struct video_frame *frame, unsigned char **pckt_data,
143 char **dqt_start, int verbose_adj)
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
154 info.width = frame->tiles[0].width = width * RTP_SZ_MULTIPLIER;
155 info.height = frame->tiles[0].height = height * RTP_SZ_MULTIPLIER;
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}
194
195static void
196skip_jpeg_headers(unsigned char **pckt_data)
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}
206
207/*
208 * Table K.1 from JPEG spec.
209 */
210static const int jpeg_luma_quantizer[64] = {
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};
220
221/*
222 * Table K.2 from JPEG spec.
223 */
224static const int jpeg_chroma_quantizer[64] = {
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};
234
235/*
236 * Call MakeTables with the Q factor and two u_char[64] return arrays
237 */
238static void
239MakeTables(int q, u_char *lqt, u_char *cqt)
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}
265
266int
267decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
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}
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_fill_dqt(char *buffer, uint8_t quant_table[2][JPEG_QUANT_SIZE])
void jpeg_writer_write_eoi(char **buffer)
void jpeg_writer_write_headers(char **buffer, struct jpeg_writer_data *info)
writes JPEG/JFIF headers up to the scan (including SOS header)
@ JPEG_QUANT_SIZE
items, bytes (for precision=0)
Definition jpeg_writer.h:54
#define to_fourcc(a, b, c, d)
Creates FourCC word.
Definition macros.h:114
#define MAX(a, b)
Definition macros.h:65
#define DEBUG
Definition main.c:27
rtp_packet
Definition rtp.h:126
static unsigned parse_restart_interval(unsigned char **pckt_data, int verbose_adj)
Definition rtpdec_jpeg.c:73
@ 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
int decode_frame_jpeg(struct coded_data *cdata, void *decode_data)
static char * create_jpeg_frame(struct video_frame *frame, unsigned char **pckt_data, char **dqt_start, int verbose_adj)
#define GET_BYTE(data)
Definition rtpdec_jpeg.c:60
static void MakeTables(int q, u_char *lqt, u_char *cqt)
static void skip_jpeg_headers(unsigned char **pckt_data)
static const int jpeg_luma_quantizer[64]
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
#define GET_2BYTE(data)
Definition rtpdec_jpeg.c:61
#define MOD_NAME
Definition rtpdec_jpeg.c:58
static const int jpeg_chroma_quantizer[64]
Option::OptType type
Definition settings.cpp:194
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 width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
unsigned int height
Definition types.h:281
void(* data_deleter)(struct video_frame *)
Definition types.h:256
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
struct video_frame_callbacks callbacks
Definition types.h:324