UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
jpeg_reader.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2018-2024 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
42#include <assert.h>
43#include <ctype.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "debug.h"
48#include "utils/jpeg_reader.h"
49
50#define MOD_NAME "[JPEG reader] "
51
52// RFC 2435 Appendix B
53static const uint8_t lum_dc_codelens[] = {
54 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
55};
56
57static const uint8_t lum_dc_symbols[] = {
58 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
59};
60
61static const uint8_t lum_ac_codelens[] = {
62 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d,
63};
64
65static const uint8_t lum_ac_symbols[] = {
66 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
67 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
68 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
69 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
70 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
71 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
72 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
73 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
74 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
75 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
76 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
77 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
78 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
79 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
80 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
81 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
82 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
83 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
84 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
85 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
86 0xf9, 0xfa,
87};
88
89static const uint8_t chm_dc_codelens[] = {
90 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
91};
92
93static const uint8_t chm_dc_symbols[] = {
94 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
95};
96
97static const uint8_t chm_ac_codelens[] = {
98 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77,
99};
100
101static const uint8_t chm_ac_symbols[] = {
102 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
103 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
104 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
105 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
106 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
107 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
108 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
109 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
110 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
111 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
112 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
113 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
114 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
115 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
116 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
117 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
118 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
119 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
120 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
121 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
122 0xf9, 0xfa,
123};
124
131
137
141
146
150
152
154
163
172
189
193
195
196 JPEG_MARKER_ERROR = 0x100
198
199
200static const char* jpeg_marker_name(enum jpeg_marker_code code)
201{
202 switch (code) {
203 case JPEG_MARKER_SOF0: return "SOF0";
204 case JPEG_MARKER_SOF1: return "SOF1";
205 case JPEG_MARKER_SOF2: return "SOF2";
206 case JPEG_MARKER_SOF3: return "SOF3";
207 case JPEG_MARKER_SOF5: return "SOF5";
208 case JPEG_MARKER_SOF6: return "SOF6";
209 case JPEG_MARKER_SOF7: return "SOF7";
210 case JPEG_MARKER_JPG: return "JPG";
211 case JPEG_MARKER_SOF9: return "SOF9";
212 case JPEG_MARKER_SOF10: return "SOF10";
213 case JPEG_MARKER_SOF11: return "SOF11";
214
215 case JPEG_MARKER_SOF13: return "SOF13";
216 case JPEG_MARKER_SOF14: return "SOF14";
217 case JPEG_MARKER_SOF15: return "SOF15";
218 case JPEG_MARKER_DHT: return "DHT";
219 case JPEG_MARKER_DAC: return "DAC";
220 case JPEG_MARKER_RST0: return "RST0";
221 case JPEG_MARKER_RST1: return "RST1";
222 case JPEG_MARKER_RST2: return "RST2";
223 case JPEG_MARKER_RST3: return "RST3";
224 case JPEG_MARKER_RST4: return "RST4";
225 case JPEG_MARKER_RST5: return "RST5";
226 case JPEG_MARKER_RST6: return "RST6";
227 case JPEG_MARKER_RST7: return "RST7";
228 case JPEG_MARKER_SOI: return "SOI";
229 case JPEG_MARKER_EOI: return "EOI";
230 case JPEG_MARKER_SOS: return "SOS";
231 case JPEG_MARKER_DQT: return "DQT";
232 case JPEG_MARKER_DNL: return "DNL";
233 case JPEG_MARKER_DRI: return "DRI";
234 case JPEG_MARKER_DHP: return "DHP";
235 case JPEG_MARKER_EXP: return "EXP";
236 case JPEG_MARKER_APP0: return "APP0";
237 case JPEG_MARKER_APP1: return "APP1";
238 case JPEG_MARKER_APP2: return "APP2";
239 case JPEG_MARKER_APP3: return "APP3";
240 case JPEG_MARKER_APP4: return "APP4";
241 case JPEG_MARKER_APP5: return "APP5";
242 case JPEG_MARKER_APP6: return "APP6";
243 case JPEG_MARKER_APP7: return "APP7";
244 case JPEG_MARKER_APP8: return "APP8";
245 case JPEG_MARKER_APP9: return "APP9";
246 case JPEG_MARKER_APP10: return "APP10";
247 case JPEG_MARKER_APP11: return "APP11";
248 case JPEG_MARKER_APP12: return "APP12";
249 case JPEG_MARKER_APP13: return "APP13";
250 case JPEG_MARKER_APP14: return "APP14";
251 case JPEG_MARKER_APP15: return "APP15";
252 case JPEG_MARKER_JPG0: return "JPG0";
253 case JPEG_MARKER_JPG13: return "JPG13";
254 case JPEG_MARKER_COM: return "COM";
255 case JPEG_MARKER_TEM: return "TEM";
256 case JPEG_MARKER_ERROR: return "ERROR";
257 default:
258 {
259 static char buffer[255];
260 snprintf(buffer, sizeof buffer, "Unknown (0x%X)", code);
261 return buffer;
262 }
263 }
264}
265
266#define read_byte(image) \
267 (uint8_t)(*(image)++)
268
269#define read_2byte(image) \
270 (uint16_t)(((*(image)) << 8) + (*((image) + 1))); \
271 image += 2;
272
273static int read_marker(uint8_t** image)
274{
275 uint8_t byte = read_byte(*image);
276 if( byte != 0xFF ) {
277 return -1;
278 }
279 int marker = read_byte(*image);
280 return marker;
281}
282
283static void skip_marker_content(uint8_t** image)
284{
285 int length = (int)read_2byte(*image);
286
287 *image += length - 2;
288}
289
290static int read_sof0(struct jpeg_info *param, uint8_t** image)
291{
292 int length = (int)read_2byte(*image);
293 if ( length < 6 ) {
294 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] SOF0 marker length should be greater than 6 but %d was presented!\n", length);
295 return -1;
296 }
297 length -= 2;
298
299 int precision = (int)read_byte(*image);
300 if ( precision != 8 ) {
301 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] SOF0 marker precision should be 8 but %d was presented!\n", precision);
302 return -1;
303 }
304
305 param->height = (int)read_2byte(*image);
306 param->width = (int)read_2byte(*image);
307 param->comp_count = (int)read_byte(*image);
308 length -= 6;
309
310 for ( int comp = 0; comp < param->comp_count; comp++ ) {
311 int index = (int)read_byte(*image);
312 if ( index != (comp + 1) ) {
313 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] SOF0 marker component %d id should be %d but %d was presented!\n", comp, comp + 1, index);
314 return -1;
315 }
316
317 int sampling = (int)read_byte(*image);
318 param->sampling_factor_h[comp] = (sampling >> 4) & 15;
319 param->sampling_factor_v[comp] = (sampling) & 15;
320
321 int table_index = (int)read_byte(*image);
322 if (table_index > 3) {
323 MSG(VERBOSE,
324 "SOF0 marker contains unexpected quantization "
325 "table index %d!\n",
326 table_index);
327 return -1;
328 }
329 param->comp_table_quantization_map[comp] = table_index;
330 length -= 3;
331 }
332
333 // Check length
334 if ( length > 0 ) {
335 log_msg(LOG_LEVEL_WARNING, "[JPEG] [Warning] SOF0 marker contains %d more bytes than needed!\n", length);
336 *image += length;
337 }
338
339 return 0;
340}
341
342static int read_dri(struct jpeg_info *param, uint8_t** image)
343{
344 int length = (int)read_2byte(*image);
345 if ( length != 4 ) {
346 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] DRI marker length should be 4 but %d was presented!\n", length);
347 return -1;
348 }
349
350 param->restart_interval = read_2byte(*image);
351 return 0;
352}
353
354static int read_dht(struct jpeg_info *param, uint8_t** image)
355{
356 int length = (int)read_2byte(*image);
357 length -= 2;
358
359 while (length > 0) {
360 int index = read_byte(*image);
361 uint8_t *table;
362 switch(index) {
363 case 0:
364 table = param->huff_lum_dc;
365 break;
366 case 16:
367 table = param->huff_lum_ac;
368 break;
369 case 1:
370 table = param->huff_chm_dc;
371 break;
372 case 17:
373 table = param->huff_chm_ac;
374 break;
375 default:
376 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] DHT marker index should be 0, 1, 16 or 17 but %d was presented!\n", index);
377 return -1;
378 }
379 length -= 1;
380
381 // Read in bits[]
382 int count = 0;
383 for ( int i = 0; i < 16; i++ ) {
384 table[i] = read_byte(*image);
385 count += table[i];
386 if ( length > 0 ) {
387 length--;
388 } else {
389 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] DHT marker unexpected end when reading bit counts!\n");
390 return -1;
391 }
392 }
393
394 // Read in huffval
395 for ( int i = 0; i < count; i++ ){
396 table[16 + i] = read_byte(*image);
397 if ( length > 0 ) {
398 length--;
399 } else {
400 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] DHT marker unexpected end when reading huffman values!\n");
401 return -1;
402 }
403 }
404 }
405 return 0;
406}
407
408
409static int read_dqt(struct jpeg_info *param, uint8_t** image)
410{
411 int length = (int)read_2byte(*image);
412 length -= 2;
413
414 if ( (length % 65) != 0 ) {
415 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] DQT marker length should be 65 but %d was presented!\n", length);
416 return -1;
417 }
418
419 for (;length > 0; length-=65) {
420 int index = read_byte(*image);
421 const int Pq = index >> 4; // precision - 0 for 8-bit, 1 for 16-bit
422 const int Tq = index & 0xF; // destination (0-3)
423 if (Pq == 1) {
424 MSG(ERROR, "16-bit quant tables not supported!\n");
425 return -1;
426 }
427 if (Pq != 0) {
428 MSG(ERROR, "Wrong quant table precision %d!\n", Pq);
429 return -1;
430 }
431 if (Tq >= JPEG_MAX_COMPONENT_COUNT) {
432 MSG(ERROR,
433 "DQT marker Tq should be at most 3 "
434 "but %d was presented!\n",
435 Tq);
436 return -1;
437 }
438 param->quantization_tables[Tq] = *image;
439
440 *image += 64; // skip table content
441 }
442 return 0;
443}
444
445static int read_com(struct jpeg_info *param, uint8_t** image) {
446 int length = (int)read_2byte(*image);
447 length -= 2;
448
449 for (int i = 0; i < length; ++i) {
450 param->com[i] = read_byte(*image);
451 }
452
453 // add terminating zero (if not present)
454 param->com[length] = '\0';
455
456 return 0;
457}
458
459static int read_sos(struct jpeg_info *param, uint8_t** image)
460{
461 int length = (int)read_2byte(*image);
462 length -= 2;
463
464 if (length == 0) {
465 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] Wrong SOS length: %d\n", length);
466 return -1;
467 }
468 int comp_count = (int)read_byte(*image);
469 if ( comp_count != param->comp_count ) {
470 param->interleaved = false;
471 }
472 if (length < 1 + comp_count * 2 + 3) {
473 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] Wrong SOS length: %d\n", length);
474 return -1;
475 }
476
477 // Collect the component-spec parameters
478 for ( int comp = 0; comp < comp_count; comp++ )
479 {
480 int index = (int)read_byte(*image);
481 int table = (int)read_byte(*image);
482 int table_dc = (table >> 4) & 15;
483 int table_ac = table & 15;
484
485 if ( index == 1 && (table_ac != 0 || table_dc != 0) ) {
486 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] SOS marker for Y should have huffman tables 0,0 but %d,%d was presented!\n", table_dc, table_ac);
487 return -1;
488 }
489 if ( (index == 2 || index == 3) && (table_ac != 1 || table_dc != 1) ) {
490 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] SOS marker for Cb or Cr should have huffman tables 1,1 but %d,%d was presented!\n", table_dc, table_ac);
491 return -1;
492 }
493 }
494
495 // Collect the additional scan parameters Ss, Se, Ah/Al.
496 int Ss __attribute__((unused)) = (int)read_byte(*image);
497 int Se __attribute__((unused)) = (int)read_byte(*image);
498 int Ax __attribute__((unused)) = (int)read_byte(*image);
499 int Ah __attribute__((unused)) = (Ax >> 4) & 15;
500 int Al __attribute__((unused)) = (Ax) & 15;
501
502 // Get scan structure
503 param->data = *image;
504
505 return 0;
506}
507
508static int read_adobe_app14(struct jpeg_info *param, uint8_t** image)
509{
510 int length = read_2byte(*image);
511 if (length != 14) { // not an Adobe APP14 marker
512 return 0;
513 }
514
515 char adobe[6] = "";
516 adobe[0] = read_byte(*image);
517 adobe[1] = read_byte(*image);
518 adobe[2] = read_byte(*image);
519 adobe[3] = read_byte(*image);
520 adobe[4] = read_byte(*image);
521 if (strcmp(adobe, "Adobe") != 0) { // not an Adobe APP14 marker
522 return 0;
523 }
524
525 int version __attribute__((unused)) = read_2byte(*image);
526 int flags0 __attribute__((unused)) = read_2byte(*image);
527 int flags1 __attribute__((unused)) = read_2byte(*image);
528 int color_transform = read_byte(*image);
529
530 if (color_transform == 0) {
531 param->color_spec = JPEG_COLOR_SPEC_CMYK; // or RGB - will be determined later
532 } else if (color_transform == 1) {
533 param->color_spec = JPEG_COLOR_SPEC_YCBCR;
534 } else if (color_transform == 2) {
535 param->color_spec = JPEG_COLOR_SPEC_YCCK;
536 } else {
537 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] Unsupported color transformation value '%d' was presented in APP14 marker!\n", color_transform);
538 return -1;
539 }
540
541 return 0;
542}
543
551int jpeg_read_info(uint8_t *image, int len, struct jpeg_info *info)
552{
553 uint8_t *image_start = image;
554
555 // Check first SOI marker
556 int marker_soi = read_marker(&image);
557 if (marker_soi != JPEG_MARKER_SOI) {
558 log_msg(LOG_LEVEL_ERROR, "[JPEG] [Error] JPEG data should begin with SOI marker, but marker %s was found!\n", jpeg_marker_name((enum jpeg_marker_code)marker_soi));
559 return -1;
560 }
561
562 info->huff_lum_dc[0] = 255;
563 info->huff_lum_ac[0] = 255;
564 info->huff_chm_dc[0] = 255;
565 info->huff_chm_ac[0] = 255;
566 info->comp_count = 0;
567 info->interleaved = true;
568 info->restart_interval = 0; // if DRI is not present
569 info->com[0] = '\0'; // if COM is not present
570 info->color_spec = JPEG_COLOR_SPEC_YCBCR; // default
571 bool marker_present[255] = { 0 };
572
573 // currently reading up to SOS marker gives us all needed data
574 while (!marker_present[JPEG_MARKER_EOI] && !marker_present[JPEG_MARKER_SOS]
575 && image < image_start + len) {
576 // Read marker
577 int marker = read_marker(&image);
578 if ( marker == 0) { // not a marker (byte stuffing)
579 continue;
580 }
581 if (marker == -1) {
582 log_msg(LOG_LEVEL_WARNING, "Unknown marker!\n");
583 continue;
584 }
585 if (marker == 0xff) { // first byte might have been padding and the second byte marker start
586 image--;
587 continue;
588 }
589
590 marker_present[marker] = true;
591 int rc;
592
593 // Read more info according to the marker
594 switch (marker)
595 {
596 case JPEG_MARKER_SOF0: // Baseline
597 if ((rc = read_sof0(info, &image)) != 0) {
598 log_msg(LOG_LEVEL_ERROR, "Error reading SOF0!\n");
599 return rc;
600 }
601 break;
602
603 case JPEG_MARKER_DHT:
604 if ((rc = read_dht(info, &image)) != 0) {
605 log_msg(LOG_LEVEL_ERROR, "Error reading DQT!\n");
606 return rc;
607 }
608 break;
609
610 case JPEG_MARKER_DQT:
611 if ((rc = read_dqt(info, &image)) != 0) {
612 log_msg(LOG_LEVEL_ERROR, "Error reading DQT!\n");
613 return rc;
614 }
615 break;
616
617 case JPEG_MARKER_DRI:
618 if ((rc = read_dri(info, &image)) != 0) {
619 log_msg(LOG_LEVEL_ERROR, "Error reading DRI!\n");
620 return rc;
621 }
622 break;
623
624 case JPEG_MARKER_COM:
625 if ((rc = read_com(info, &image)) != 0) {
626 log_msg(LOG_LEVEL_ERROR, "Error reading COM!\n");
627 return rc;
628 }
629 break;
630
632 if ((rc = read_adobe_app14(info, &image)) != 0) {
633 log_msg(LOG_LEVEL_ERROR, "Error reading APP14!\n");
634 return rc;
635 }
636 break;
637
638 case JPEG_MARKER_SOS:
639 if ((rc = read_sos(info, &image)) != 0) {
640 log_msg(LOG_LEVEL_ERROR, "Error reading SOS!\n");
641 return rc;
642 }
643 break;
644
645 case JPEG_MARKER_EOI:
646 break;
647
648 // included because these fixed-sized markers do not contain lenght field
649 // thus skipping in default branch will misbehave
650 case JPEG_MARKER_RST0:
651 case JPEG_MARKER_RST1:
652 case JPEG_MARKER_RST2:
653 case JPEG_MARKER_RST3:
654 case JPEG_MARKER_RST4:
655 case JPEG_MARKER_RST5:
656 case JPEG_MARKER_RST6:
657 case JPEG_MARKER_RST7:
658 break;
659
660 default:
661 skip_marker_content(&image);
662 break;
663 }
664 }
665
667 for (unsigned int i = 0; i < sizeof req_markers / sizeof req_markers[0]; ++i) {
668 if (!marker_present[req_markers[i]]) {
669 log_msg(LOG_LEVEL_ERROR, "Marker \"%s\" missing in JPEG file!\n",
670 jpeg_marker_name(req_markers[i]));
671 if (req_markers[i] == JPEG_MARKER_SOF0) {
672 log_msg(LOG_LEVEL_INFO, "Perhaps unsupported JPEG type.\n");
673 }
674 return -2;
675 }
676 }
677
678 // APP14 doesn't distinguis between CMYK and RGB thus we deduce from comp count
679 if (info->color_spec == JPEG_COLOR_SPEC_CMYK && info->comp_count == 3) {
680 info->color_spec = JPEG_COLOR_SPEC_RGB;
681 }
682
683 return 0;
684}
685
686static bool
688{
689 // tables defined implicitly
690 if (param->huff_lum_dc[0] == 255 || param->huff_lum_ac[0] == 255 ||
691 param->huff_chm_dc[0] == 255 || param->huff_chm_ac[0] == 255) {
692 return true;
693 }
694
695 for (unsigned int i = 0; i < sizeof lum_dc_codelens; ++i) {
696 if (param->huff_lum_dc[i] != lum_dc_codelens[i])
697 return false;
698 }
699 for (unsigned int i = 0; i < sizeof lum_dc_symbols; ++i) {
700 if (param->huff_lum_dc[16 + i] != lum_dc_symbols[i])
701 return false;
702 }
703
704 for (unsigned int i = 0; i < sizeof lum_ac_codelens; ++i) {
705 if (param->huff_lum_ac[i] != lum_ac_codelens[i])
706 return false;
707 }
708 for (unsigned int i = 0; i < sizeof lum_ac_symbols; ++i) {
709 if (param->huff_lum_ac[16 + i] != lum_ac_symbols[i])
710 return false;
711 }
712
713 for (unsigned int i = 0; i < sizeof chm_dc_codelens; ++i) {
714 if (param->huff_chm_dc[i] != chm_dc_codelens[i])
715 return false;
716 }
717 for (unsigned int i = 0; i < sizeof chm_dc_symbols; ++i) {
718 if (param->huff_chm_dc[16 + i] != chm_dc_symbols[i])
719 return false;
720 }
721
722 for (unsigned int i = 0; i < sizeof chm_ac_codelens; ++i) {
723 if (param->huff_chm_ac[i] != chm_ac_codelens[i])
724 return false;
725 }
726 for (unsigned int i = 0; i < sizeof chm_ac_symbols; ++i) {
727 if (param->huff_chm_ac[16 + i] != chm_ac_symbols[i])
728 return false;
729 }
730
731 return true;
732}
733
734static bool arr_eq3(const int *a1, const int *a2) { for (int i = 0; i < 3; ++i) if (a1[i] != a2[i]) return false; return true; }
735
736static bool
738{
739 if (info->comp_count != 3) {
740 log_msg(LOG_LEVEL_ERROR, "Unsupported JPEG component count: %d!\n", info->comp_count);
741 return false;
742 }
743 if (info->color_spec != JPEG_COLOR_SPEC_YCBCR) {
744 log_msg(LOG_LEVEL_ERROR, "Unsupported JPEG color space (only YCbCr supported!\n");
745 return false;
746 }
747 if (!info->interleaved) {
748 if (strstr(info->com, "GPUJPEG")) {
749 log_msg(LOG_LEVEL_ERROR, "Non-interleaved JPEG detected, use \"-c GPUJPEG:interleaved\"!\n");
750 } else {
751 log_msg(LOG_LEVEL_ERROR, "Non-interleaved JPEG detected!\n");
752 }
753 return false;
754 }
755 if (!check_huff_tables(info)) {
756 log_msg(LOG_LEVEL_ERROR, "Non-default Huffman tables detected!\n");
757 return false;
758 }
759
760 for (int c = 0; c < info->comp_count; c++) {
761 if (info->comp_table_quantization_map[c] >= 2) {
762 MSG(ERROR, "Quantization table index %d (>=2) used!\n",
763 info->comp_table_quantization_map[c]);
764 return false;
765 }
766 }
767 if (info->comp_table_quantization_map[1] !=
768 info->comp_table_quantization_map[2]) {
769 MSG(ERROR, "Quantization table for Cb and Cr differ!\n");
770 }
771
772 return true;
773}
774
775bool jpeg_get_rtp_hdr_data(uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
776{
777 struct jpeg_info i;
778 int rc = jpeg_read_info(jpeg_data, len, &i);
779
780 if (rc != 0) {
781 log_msg(LOG_LEVEL_ERROR, "Cannot parse JPEG!\n");
782 return false;
783 }
784 if (!check_rtp_compatibility(&i)) {
785 return false;
786 }
787
788 hdr_data->width = i.width;
789 hdr_data->height = i.height;
791 hdr_data->data = i.data;
792 const int a111[] = { 1, 1, 1 },
793 a211[] = { 2, 1, 1 },
794 a222[] = { 2, 2, 2 };
795 if (arr_eq3(i.sampling_factor_v, a111) && arr_eq3(i.sampling_factor_h, a211)) { // 4:2:2
796 hdr_data->type = 0;
797 } else if (arr_eq3(i.sampling_factor_v, a211) && arr_eq3(i.sampling_factor_h, a211)) { // 4:2:0
798 hdr_data->type = 1;
799 } else {
800 log_msg(LOG_LEVEL_ERROR, "Unsupported JPEG type - sampling horizontal: %d, %d, %d; vertical: %d, %d, %d\n", i.sampling_factor_h[0], i.sampling_factor_h[1], i.sampling_factor_h[2], i.sampling_factor_v[0], i.sampling_factor_v[1], i.sampling_factor_v[2]);
801 if (arr_eq3(i.sampling_factor_v, a222) && arr_eq3(i.sampling_factor_h, a211)) {
802 MSG(ERROR, "FFmpeg-generated JPEG 4:2:2 is "
803 "incompatible with RFC 2435.\n");
804 MSG(WARNING, "Try \"-c lavc:subs=420\"\n");
805 }
806 return false;
807 }
808 if (i.restart_interval != 0) {
809 hdr_data->type |= 0x40;
810 }
811
812 hdr_data->q = 255;
813 // we try deduce quality from COM marker
814 const char *q_str = "quality = ";
815 if (strstr(i.com, q_str) && isdigit(*(strstr(i.com, q_str) + strlen(q_str)))) {
816 hdr_data->q = atoi(strstr(i.com, q_str) + strlen(q_str));
817 assert(hdr_data->q <= 127);
818 }
819 if (hdr_data->q == 255) {
820 hdr_data->quantization_tables[0] =
822 hdr_data->quantization_tables[1] = // shared Cb/Cr table
824 }
825
826 return true;
827}
828
int void size_t * len
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
static bool arr_eq3(const int *a1, const int *a2)
static int read_com(struct jpeg_info *param, uint8_t **image)
static const uint8_t chm_dc_symbols[]
Definition jpeg_reader.c:93
const struct huffman_table default_huffman_tables[4]
static void skip_marker_content(uint8_t **image)
static int read_marker(uint8_t **image)
static bool check_rtp_compatibility(const struct jpeg_info *info)
static const uint8_t lum_ac_symbols[]
Definition jpeg_reader.c:65
#define read_2byte(image)
static const uint8_t lum_dc_symbols[]
Definition jpeg_reader.c:57
static int read_dri(struct jpeg_info *param, uint8_t **image)
static int read_dht(struct jpeg_info *param, uint8_t **image)
static int read_sos(struct jpeg_info *param, uint8_t **image)
static int read_adobe_app14(struct jpeg_info *param, uint8_t **image)
static const uint8_t chm_dc_codelens[]
Definition jpeg_reader.c:89
static const uint8_t lum_dc_codelens[]
Definition jpeg_reader.c:53
static bool check_huff_tables(const struct jpeg_info *param)
static const char * jpeg_marker_name(enum jpeg_marker_code code)
static const uint8_t chm_ac_symbols[]
static const uint8_t chm_ac_codelens[]
Definition jpeg_reader.c:97
static int read_dqt(struct jpeg_info *param, uint8_t **image)
int jpeg_read_info(uint8_t *image, int len, struct jpeg_info *info)
#define read_byte(image)
static int read_sof0(struct jpeg_info *param, uint8_t **image)
jpeg_marker_code
@ JPEG_MARKER_COM
@ JPEG_MARKER_SOF14
@ JPEG_MARKER_APP12
@ JPEG_MARKER_APP4
@ JPEG_MARKER_APP0
@ JPEG_MARKER_SOF11
@ JPEG_MARKER_APP1
@ JPEG_MARKER_DNL
@ JPEG_MARKER_RST2
@ JPEG_MARKER_RST0
@ JPEG_MARKER_DHT
@ JPEG_MARKER_SOF15
@ JPEG_MARKER_EOI
@ JPEG_MARKER_SOF7
@ JPEG_MARKER_JPG
@ JPEG_MARKER_APP14
@ JPEG_MARKER_EXP
@ JPEG_MARKER_RST3
@ JPEG_MARKER_SOF13
@ JPEG_MARKER_DRI
@ JPEG_MARKER_JPG0
@ JPEG_MARKER_APP7
@ JPEG_MARKER_APP5
@ JPEG_MARKER_SOF6
@ JPEG_MARKER_RST6
@ JPEG_MARKER_JPG13
@ JPEG_MARKER_APP3
@ JPEG_MARKER_SOF5
@ JPEG_MARKER_RST1
@ JPEG_MARKER_SOF1
@ JPEG_MARKER_DQT
@ JPEG_MARKER_APP15
@ JPEG_MARKER_TEM
@ JPEG_MARKER_RST5
@ JPEG_MARKER_SOF2
@ JPEG_MARKER_APP8
@ JPEG_MARKER_SOF10
@ JPEG_MARKER_APP2
@ JPEG_MARKER_SOF3
@ JPEG_MARKER_RST4
@ JPEG_MARKER_SOF0
@ JPEG_MARKER_DAC
@ JPEG_MARKER_ERROR
@ JPEG_MARKER_APP9
@ JPEG_MARKER_SOS
@ JPEG_MARKER_APP13
@ JPEG_MARKER_RST7
@ JPEG_MARKER_DHP
@ JPEG_MARKER_SOI
@ JPEG_MARKER_APP6
@ JPEG_MARKER_SOF9
@ JPEG_MARKER_APP11
@ JPEG_MARKER_APP10
bool jpeg_get_rtp_hdr_data(uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
static const uint8_t lum_ac_codelens[]
Definition jpeg_reader.c:61
@ JPEG_COLOR_SPEC_YCBCR
Definition jpeg_reader.h:52
@ JPEG_COLOR_SPEC_CMYK
Definition jpeg_reader.h:54
@ JPEG_COLOR_SPEC_RGB
Definition jpeg_reader.h:53
@ JPEG_COLOR_SPEC_YCCK
Definition jpeg_reader.h:55
@ JPEG_MAX_COMPONENT_COUNT
Definition jpeg_reader.h:59
struct __attribute__((packed))
Definition rtp.h:88
const char * param
Definition settings.cpp:195
int comp_table_quantization_map[JPEG_MAX_COMPONENT_COUNT]
mapping component -> index to table_quantization
Definition jpeg_reader.h:71
int sampling_factor_h[JPEG_MAX_COMPONENT_COUNT]
Definition jpeg_reader.h:67
uint8_t * quantization_tables[JPEG_MAX_COMPONENT_COUNT]
Definition jpeg_reader.h:69
int restart_interval
Definition jpeg_reader.h:68
int sampling_factor_v[JPEG_MAX_COMPONENT_COUNT]
Definition jpeg_reader.h:66
uint8_t * data
Definition jpeg_reader.h:72
char com[65536 - 2+1]
Definition jpeg_reader.h:73
uint8_t * data
Definition jpeg_reader.h:86
uint8_t * quantization_tables[2]
Definition jpeg_reader.h:85