UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
jpeg_reader.h File Reference
#include <cstddef>
#include <cstdint>
Include dependency graph for jpeg_reader.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  huffman_table
 
struct  jpeg_info
 
struct  jpeg_rtp_data
 

Enumerations

enum  { JPEG_MAX_COMPONENT_COUNT = 4 }
 
enum  huff_type { LUM_DC = 0 , LUM_AC = 1 , CHR_DC = 2 , CHR_AC = 3 }
 
enum  jpeg_color_spec {
  JPEG_COLOR_SPEC_NONE = 0 , JPEG_COLOR_SPEC_YCBCR , JPEG_COLOR_SPEC_RGB , JPEG_COLOR_SPEC_CMYK ,
  JPEG_COLOR_SPEC_YCCK
}
 

Functions

bool jpeg_get_rtp_hdr_data (uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
 
int jpeg_read_info (uint8_t *image, int len, struct jpeg_info *info)
 

Variables

const struct huffman_table default_huffman_tables [4]
 

Detailed Description

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

Definition in file jpeg_reader.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
JPEG_MAX_COMPONENT_COUNT 

Definition at line 58 of file jpeg_reader.h.

58 {
60};
@ JPEG_MAX_COMPONENT_COUNT
Definition jpeg_reader.h:59

◆ huff_type

enum huff_type
Enumerator
LUM_DC 

order of tables in default_huffman_tables

LUM_AC 
CHR_DC 
CHR_AC 

Definition at line 101 of file jpeg_reader.h.

101 {
102 LUM_DC = 0,
103 LUM_AC = 1,
104 CHR_DC = 2,
105 CHR_AC = 3,
106};
@ CHR_DC
@ CHR_AC
@ LUM_DC
order of tables in default_huffman_tables
@ LUM_AC

◆ jpeg_color_spec

Enumerator
JPEG_COLOR_SPEC_NONE 
JPEG_COLOR_SPEC_YCBCR 
JPEG_COLOR_SPEC_RGB 
JPEG_COLOR_SPEC_CMYK 
JPEG_COLOR_SPEC_YCCK 

Definition at line 50 of file jpeg_reader.h.

50 {
56};
@ 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_NONE
Definition jpeg_reader.h:51
@ JPEG_COLOR_SPEC_YCCK
Definition jpeg_reader.h:55

Function Documentation

◆ jpeg_get_rtp_hdr_data()

bool jpeg_get_rtp_hdr_data ( uint8_t * jpeg_data,
int len,
struct jpeg_rtp_data * hdr_data )

Definition at line 775 of file jpeg_reader.c.

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;
790 hdr_data->restart_interval = i.restart_interval;
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] =
821 i.quantization_tables[i.comp_table_quantization_map[0]];
822 hdr_data->quantization_tables[1] = // shared Cb/Cr table
823 i.quantization_tables[i.comp_table_quantization_map[1]];
824 }
825
826 return true;
827}
int void size_t * len
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
static bool arr_eq3(const int *a1, const int *a2)
static bool check_rtp_compatibility(const struct jpeg_info *info)
int jpeg_read_info(uint8_t *image, int len, struct jpeg_info *info)
uint8_t * data
Definition jpeg_reader.h:86
uint8_t * quantization_tables[2]
Definition jpeg_reader.h:85

References arr_eq3(), check_rtp_compatibility(), jpeg_info::com, jpeg_info::comp_table_quantization_map, jpeg_info::data, jpeg_rtp_data::data, jpeg_info::height, jpeg_rtp_data::height, jpeg_read_info(), len, LOG_LEVEL_ERROR, log_msg(), MSG, jpeg_rtp_data::q, jpeg_info::quantization_tables, jpeg_rtp_data::quantization_tables, jpeg_info::restart_interval, jpeg_rtp_data::restart_interval, jpeg_info::sampling_factor_h, jpeg_info::sampling_factor_v, jpeg_rtp_data::type, jpeg_info::width, and jpeg_rtp_data::width.

Referenced by tx_send_jpeg().

Here is the call graph for this function:

◆ jpeg_read_info()

int jpeg_read_info ( uint8_t * image,
int len,
struct jpeg_info * info )

This function reads values from JPEG file.

Return values
0ok
-1general error
-2incomplete file (required markers missing)

Definition at line 551 of file jpeg_reader.c.

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}
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
static int read_com(struct jpeg_info *param, uint8_t **image)
static void skip_marker_content(uint8_t **image)
static int read_marker(uint8_t **image)
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 char * jpeg_marker_name(enum jpeg_marker_code code)
static int read_dqt(struct jpeg_info *param, uint8_t **image)
static int read_sof0(struct jpeg_info *param, uint8_t **image)
jpeg_marker_code
@ JPEG_MARKER_COM
@ JPEG_MARKER_RST2
@ JPEG_MARKER_RST0
@ JPEG_MARKER_DHT
@ JPEG_MARKER_EOI
@ JPEG_MARKER_APP14
@ JPEG_MARKER_RST3
@ JPEG_MARKER_DRI
@ JPEG_MARKER_RST6
@ JPEG_MARKER_RST1
@ JPEG_MARKER_DQT
@ JPEG_MARKER_RST5
@ JPEG_MARKER_RST4
@ JPEG_MARKER_SOF0
@ JPEG_MARKER_SOS
@ JPEG_MARKER_RST7
@ JPEG_MARKER_SOI

References JPEG_COLOR_SPEC_CMYK, JPEG_COLOR_SPEC_RGB, JPEG_COLOR_SPEC_YCBCR, JPEG_MARKER_APP14, JPEG_MARKER_COM, JPEG_MARKER_DHT, JPEG_MARKER_DQT, JPEG_MARKER_DRI, JPEG_MARKER_EOI, jpeg_marker_name(), JPEG_MARKER_RST0, JPEG_MARKER_RST1, JPEG_MARKER_RST2, JPEG_MARKER_RST3, JPEG_MARKER_RST4, JPEG_MARKER_RST5, JPEG_MARKER_RST6, JPEG_MARKER_RST7, JPEG_MARKER_SOF0, JPEG_MARKER_SOI, JPEG_MARKER_SOS, len, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), read_adobe_app14(), read_com(), read_dht(), read_dqt(), read_dri(), read_marker(), read_sof0(), read_sos(), and skip_marker_content().

Referenced by jpeg_get_rtp_hdr_data().

Here is the call graph for this function:

Variable Documentation

◆ default_huffman_tables

const struct huffman_table default_huffman_tables[4]
extern

Definition at line 125 of file jpeg_reader.c.

125 {
130};
static const uint8_t chm_dc_symbols[]
Definition jpeg_reader.c:93
static const uint8_t lum_ac_symbols[]
Definition jpeg_reader.c:65
static const uint8_t lum_dc_symbols[]
Definition jpeg_reader.c:57
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 const uint8_t chm_ac_symbols[]
static const uint8_t chm_ac_codelens[]
Definition jpeg_reader.c:97
static const uint8_t lum_ac_codelens[]
Definition jpeg_reader.c:61

Referenced by jpeg_writer_write_dhts().