jpeg: update to match latest parser API.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
Wind Yuan 2012-04-19 23:50:14 +08:00 committed by Gwenole Beauchesne
parent 0cf06cdbcb
commit 53cbdcc1e6
3 changed files with 629 additions and 530 deletions

View file

@ -65,15 +65,15 @@ ensure_debug_category (void)
} \ } \
} G_STMT_END } G_STMT_END
#define READ_UINT8(reader, val) G_STMT_START { \ #define READ_UINT8(reader, val) G_STMT_START { \
if (!gst_byte_reader_get_uint8 ((reader), &val)) { \ if (!gst_byte_reader_get_uint8 ((reader), &(val))) { \
GST_WARNING ("failed to read uint8"); \ GST_WARNING ("failed to read uint8"); \
goto failed; \ goto failed; \
} \ } \
} G_STMT_END } G_STMT_END
#define READ_UINT16(reader, val) G_STMT_START { \ #define READ_UINT16(reader, val) G_STMT_START { \
if (!gst_byte_reader_get_uint16_be ((reader), &val)) { \ if (!gst_byte_reader_get_uint16_be ((reader), &(val))) { \
GST_WARNING ("failed to read uint16"); \ GST_WARNING ("failed to read uint16"); \
goto failed; \ goto failed; \
} \ } \
@ -88,123 +88,149 @@ ensure_debug_category (void)
memcpy(buf, vals, length); \ memcpy(buf, vals, length); \
} G_STMT_END } G_STMT_END
/* Table B.1: marker code assignments */
enum JPEG_MARKER
{
GST_JPEG_SOF0 = 0xC0, /* Frame Profile, Baseline */
GST_JPEG_SOFF = 0xCF,
GST_JPEG_DHT = 0xC4, /* Define Huffman Table */
GST_JPEG_DAC = 0xCC, /* Define Arithmetic Coding conditioning */
GST_JPEG_RST0 = 0xD0, /* Restart with modulo 8 */
GST_JPEG_RST7 = 0xD7,
GST_JPEG_SOI = 0xD8, /* Start Of Image */
GST_JPEG_EOI = 0xD9, /* End Of Image */
GST_JPEG_SOS = 0xDA, /* Start Of Scan */
GST_JPEG_DQT = 0xDB, /* Define Quantization Table */
GST_JPEG_DNL = 0xDC, /* Define Num of Lines */
GST_JPEG_DRI = 0xDD, /* Define Restart Interval */
GST_JPEG_APP0 = 0xE0, /* Application segments */
GST_JPEG_APPF = 0xEF,
GST_JPEG_COM = 0xFE, /* Comments */
};
static gboolean jpeg_parse_to_next_marker (GstByteReader * reader, static gboolean jpeg_parse_to_next_marker (GstByteReader * reader,
guint8 * marker); guint8 * marker);
/* CCITT T.81, Annex K.1 Quantization tables for luminance and chrominance components */ /* CCITT T.81, Annex K.1 Quantization tables for luminance and chrominance components */
/* only for 8-bit per sample image*/ /* only for 8-bit per sample image*/
static const guint8 default_quant_luma_zigzag[64] = { static const GstJpegQuantTable
0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, default_quant_tables_zigzag[GST_JPEG_MAX_SCAN_COMPONENTS] = {
0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x27, /* luma */
0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, {0, { 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x27,
0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0xa8, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0xb5, 0x57, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0xa8,
0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0xb5, 0x57,
}; 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63 } },
static const guint8 default_quant_chroma_zigzag[64] = { /* chroma */
0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, {0, { 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 } },
/* chroma */
{0, { 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 } },
{0, }
}; };
/* Table K.3: typical Huffman tables for 8-bit precision luminance and chrominance */ /* Table K.3: typical Huffman tables for 8-bit precision luminance and chrominance */
static const guint8 default_dc_luma_bits[16] = { /*
0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 0..GST_JPEG_MAX_SCAN_COMPONENTS -1, DC huffman tables
}; GST_JPEG_MAX_SCAN_COMPONENTS...GST_JPEG_MAX_SCAN_COMPONENTS*2-1, AC huffman tables
*/
static const guint8 default_dc_luma_vals[16] = { static const
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 GstJpegHuffmanTable default_huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2] = {
}; /* DC luma */
{ { 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
static const guint8 default_dc_chroma_bits[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
}; 0x08, 0x09, 0x0a, 0x0b }
},
static const guint8 default_dc_chroma_vals[16] = { /* DC chroma */
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 { { 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
}; 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
static const guint8 default_ac_luma_bits[16] = { 0x08, 0x09, 0x0a, 0x0b }
0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 },
}; /* DC chroma */
{ { 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
static const guint8 default_ac_luma_vals[256] = { 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x08, 0x09, 0x0a, 0x0b }
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, },
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, { { 0 },
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, { 0 }
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, },
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* AC luma */
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, { { 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d },
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0xf9, 0xfa 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
}; 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
static const guint8 default_ac_chroma_bits[16] = { 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
}; 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
static const guint8 default_ac_chroma_vals[256] = { 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0xf9, 0xfa}
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, },
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, /* AC chroma */
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, { { 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77 },
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xf9, 0xfa 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa }
},
/* AC chroma */
{ { 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77 },
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa }
},
{ { 0 },
{ 0 }
}
}; };
static gboolean static gboolean
@ -228,98 +254,101 @@ failed:
return FALSE; return FALSE;
} }
static GstJpegParserResult GstJpegParserResult
jpeg_parse_frame (GstJpegImage * image, const guint8 * buf, guint32 length) gst_jpeg_parse_frame_hdr (GstJpegFrameHdr * frame_hdr,
const guint8 * data, gsize size, guint offset)
{ {
GstByteReader bytes_reader = GST_BYTE_READER_INIT (buf, length); GstByteReader bytes_reader = GST_BYTE_READER_INIT (data + offset, size - offset);
GstJpegParserResult result = GST_JPEG_PARSER_OK; GstJpegParserResult result = GST_JPEG_PARSER_OK;
guint8 val; guint8 val;
u_int i; u_int i;
g_assert (image && buf && length); g_assert (frame_hdr && data && size);
READ_UINT8 (&bytes_reader, image->sample_precision); READ_UINT8 (&bytes_reader, frame_hdr->sample_precision);
READ_UINT16 (&bytes_reader, image->height); READ_UINT16 (&bytes_reader, frame_hdr->height);
READ_UINT16 (&bytes_reader, image->width); READ_UINT16 (&bytes_reader, frame_hdr->width);
READ_UINT8 (&bytes_reader, image->num_components); READ_UINT8 (&bytes_reader, frame_hdr->num_components);
CHECK_FAILED (image->num_components <= GST_JPEG_MAX_COMPONENTS, CHECK_FAILED (frame_hdr->num_components <= GST_JPEG_MAX_SCAN_COMPONENTS,
GST_JPEG_PARSER_FRAME_ERROR); GST_JPEG_PARSER_ERROR);
for (i = 0; i < image->num_components; i++) { for (i = 0; i < frame_hdr->num_components; i++) {
READ_UINT8 (&bytes_reader, image->components[i].identifier); READ_UINT8 (&bytes_reader, frame_hdr->components[i].identifier);
READ_UINT8 (&bytes_reader, val); READ_UINT8 (&bytes_reader, val);
image->components[i].horizontal_factor = (val >> 4) & 0x0F; frame_hdr->components[i].horizontal_factor = (val >> 4) & 0x0F;
image->components[i].vertical_factor = (val & 0x0F); frame_hdr->components[i].vertical_factor = (val & 0x0F);
READ_UINT8 (&bytes_reader, image->components[i].quant_table_selector); READ_UINT8 (&bytes_reader, frame_hdr->components[i].quant_table_selector);
CHECK_FAILED ((image->components[i].horizontal_factor <= 4 && CHECK_FAILED ((frame_hdr->components[i].horizontal_factor <= 4 &&
image->components[i].vertical_factor <= 4 && frame_hdr->components[i].vertical_factor <= 4 &&
image->components[i].quant_table_selector < 4), frame_hdr->components[i].quant_table_selector < 4),
GST_JPEG_PARSER_FRAME_ERROR); GST_JPEG_PARSER_ERROR);
} }
return GST_JPEG_PARSER_OK; return GST_JPEG_PARSER_OK;
failed: failed:
return GST_JPEG_PARSER_FRAME_ERROR; return GST_JPEG_PARSER_ERROR;
wrong_state: wrong_state:
return result; return result;
} }
static GstJpegParserResult GstJpegParserResult
jpeg_parse_scan (GstJpegImage * image, const guint8 * buf, guint32 length) gst_jpeg_parse_scan_hdr (GstJpegScanHdr * scan_hdr,
const guint8 * data, gsize size, guint offset)
{ {
GstByteReader bytes_reader = GST_BYTE_READER_INIT (buf, length); GstByteReader bytes_reader = GST_BYTE_READER_INIT (data + offset, size - offset);
GstJpegParserResult result = GST_JPEG_PARSER_OK; GstJpegParserResult result = GST_JPEG_PARSER_OK;
guint8 val; guint8 val;
u_int i; u_int i;
g_assert (image && buf && length); g_assert (scan_hdr && data && size);
READ_UINT8 (&bytes_reader, image->current_scan.num_components); READ_UINT8 (&bytes_reader, scan_hdr->num_components);
CHECK_FAILED (image->current_scan.num_components <= GST_JPEG_MAX_COMPONENTS, CHECK_FAILED (scan_hdr->num_components <= GST_JPEG_MAX_SCAN_COMPONENTS,
GST_JPEG_PARSER_SCAN_ERROR); GST_JPEG_PARSER_BROKEN_DATA);
for (i = 0; i < image->current_scan.num_components; i++) { for (i = 0; i < scan_hdr->num_components; i++) {
READ_UINT8 (&bytes_reader, READ_UINT8 (&bytes_reader,
image->current_scan.components[i].component_selector); scan_hdr->components[i].component_selector);
READ_UINT8 (&bytes_reader, val); READ_UINT8 (&bytes_reader, val);
image->current_scan.components[i].dc_selector = (val >> 4) & 0x0F; scan_hdr->components[i].dc_selector = (val >> 4) & 0x0F;
image->current_scan.components[i].ac_selector = val & 0x0F; scan_hdr->components[i].ac_selector = val & 0x0F;
g_assert (image->current_scan.components[i].dc_selector < 4 && g_assert (scan_hdr->components[i].dc_selector < 4 &&
image->current_scan.components[i].ac_selector < 4); scan_hdr->components[i].ac_selector < 4);
CHECK_FAILED ((image->current_scan.components[i].dc_selector < 4 && CHECK_FAILED ((scan_hdr->components[i].dc_selector < 4 &&
image->current_scan.components[i].ac_selector < 4), scan_hdr->components[i].ac_selector < 4),
GST_JPEG_PARSER_SCAN_ERROR); GST_JPEG_PARSER_BROKEN_DATA);
} }
return GST_JPEG_PARSER_OK; return GST_JPEG_PARSER_OK;
failed: failed:
return GST_JPEG_PARSER_SCAN_ERROR; return GST_JPEG_PARSER_ERROR;
wrong_state: wrong_state:
return result; return result;
} }
static GstJpegParserResult GstJpegParserResult
jpeg_parse_huffman_tables (GstJpegImage * image, const guint8 * buf, gst_jpeg_parse_huffman_table (
guint32 length) GstJpegHuffmanTable huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2],
const guint8 * data, gsize size, guint offset)
{ {
GstByteReader bytes_reader = GST_BYTE_READER_INIT (buf, length); GstByteReader bytes_reader = GST_BYTE_READER_INIT (data+offset, size-offset);
GstJpegParserResult result = GST_JPEG_PARSER_OK; GstJpegParserResult result = GST_JPEG_PARSER_OK;
GstJpegHuffmanTable *huf_table; GstJpegHuffmanTable * huf_table;
guint8 tmp_val; guint8 tmp_val;
gboolean is_dc; gboolean is_dc;
guint8 table_index; guint8 table_index;
guint32 value_count; guint32 value_count;
u_int i; u_int i;
g_assert (image && buf && length); g_assert (huf_tables && data && size);
while (gst_byte_reader_get_remaining (&bytes_reader)) { while (gst_byte_reader_get_remaining (&bytes_reader)) {
READ_UINT8 (&bytes_reader, tmp_val); READ_UINT8 (&bytes_reader, tmp_val);
is_dc = !((tmp_val >> 4) & 0x0F); is_dc = !((tmp_val >> 4) & 0x0F);
table_index = (tmp_val & 0x0F); table_index = (tmp_val & 0x0F);
CHECK_FAILED (table_index < GST_JPEG_MAX_COMPONENTS, CHECK_FAILED (table_index < GST_JPEG_MAX_SCAN_COMPONENTS,
GST_JPEG_PARSER_HUFFMAN_ERROR); GST_JPEG_PARSER_BROKEN_DATA);
if (is_dc) { if (is_dc) {
huf_table = &image->dc_huf_tables[table_index]; huf_table = &huf_tables[table_index];
} else { } else {
huf_table = &image->ac_huf_tables[table_index]; huf_table = &huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS + table_index];
} }
READ_BYTES (&bytes_reader, huf_table->huf_bits, 16); READ_BYTES (&bytes_reader, huf_table->huf_bits, 16);
value_count = 0; value_count = 0;
@ -330,296 +359,133 @@ jpeg_parse_huffman_tables (GstJpegImage * image, const guint8 * buf,
return GST_JPEG_PARSER_OK; return GST_JPEG_PARSER_OK;
failed: failed:
return GST_JPEG_PARSER_HUFFMAN_ERROR; return GST_JPEG_PARSER_ERROR;
wrong_state: wrong_state:
return result; return result;
} }
static GstJpegParserResult GstJpegParserResult
jpeg_parse_quantization_table (GstJpegImage * image, const guint8 * buf, gst_jpeg_parse_quant_table (
guint32 length) GstJpegQuantTable *quant_tables, guint num_quant_tables,
const guint8 * data, gsize size, guint offset)
{ {
GstByteReader bytes_reader = GST_BYTE_READER_INIT (buf, length); GstByteReader bytes_reader = GST_BYTE_READER_INIT (data + offset, size - offset);
GstJpegParserResult result = GST_JPEG_PARSER_OK; GstJpegParserResult result = GST_JPEG_PARSER_OK;
GstJpegQuantTable *quant_table; GstJpegQuantTable *quant_table;
guint8 val; guint8 val;
guint8 table_index; guint8 table_index;
guint i;
g_assert (image && buf && length); g_assert (quant_tables && num_quant_tables && data && size);
while (gst_byte_reader_get_remaining (&bytes_reader)) { while (gst_byte_reader_get_remaining (&bytes_reader)) {
READ_UINT8 (&bytes_reader, val); READ_UINT8 (&bytes_reader, val);
table_index = (val & 0x0f); table_index = (val & 0x0f);
CHECK_FAILED (table_index < GST_JPEG_MAX_COMPONENTS, CHECK_FAILED (table_index < GST_JPEG_MAX_SCAN_COMPONENTS && table_index < num_quant_tables,
GST_JPEG_PARSER_QUANT_ERROR); GST_JPEG_PARSER_BROKEN_DATA);
quant_table = &(image->quant_tables[table_index]); quant_table = &quant_tables[table_index];
quant_table->quant_precision = ((val >> 4) & 0x0f); quant_table->quant_precision = ((val >> 4) & 0x0f);
if (!quant_table->quant_precision) { /* 8-bit values */ for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
READ_BYTES (&bytes_reader, quant_table->quant_table, 64); if (!quant_table->quant_precision) { /* 8-bit values */
} else { /* 16-bit values */ READ_UINT8(&bytes_reader, val);
READ_BYTES (&bytes_reader, quant_table->quant_table, 128); quant_table->quant_table[i] = val;
} else { /* 16-bit values */
READ_UINT16(&bytes_reader, quant_table->quant_table[i]);
}
} }
} }
return GST_JPEG_PARSER_OK; return GST_JPEG_PARSER_OK;
failed: failed:
return GST_JPEG_PARSER_QUANT_ERROR; return GST_JPEG_PARSER_ERROR;
wrong_state: wrong_state:
return result; return result;
} }
static GstJpegParserResult GstJpegParserResult
jpeg_parse_restart_interval (GstJpegImage * image, const guint8 * buf, gst_jpeg_parse_restart_interval (guint * interval,
guint32 length) const guint8 * data, gsize size, guint offset)
{ {
GstByteReader bytes_reader = GST_BYTE_READER_INIT (buf, length); GstByteReader bytes_reader = GST_BYTE_READER_INIT (data + offset, size - offset);
guint16 interval; guint16 tmp;
g_assert (image && buf && length); g_assert (interval && data && size);
READ_UINT16 (&bytes_reader, interval); READ_UINT16 (&bytes_reader, tmp);
image->restart_interval = interval; *interval = tmp;
return GST_JPEG_PARSER_OK; return GST_JPEG_PARSER_OK;
failed: failed:
return GST_JPEG_PARSER_QUANT_ERROR; return GST_JPEG_PARSER_BROKEN_DATA;
} }
static GstJpegParserResult void
jpeg_parse_comments (GstJpegImage * image, const guint8 * buf, guint32 length) gst_jpeg_get_default_huffman_table (GstJpegHuffmanTable huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2])
{ {
g_assert (image); memcpy(huf_tables,
#if DEBUG_PRINT_COMMENT default_huf_tables,
char *comments = (char *) g_malloc0 (length + 1); sizeof(GstJpegHuffmanTable)*GST_JPEG_MAX_SCAN_COMPONENTS*2);
memcpy (comments, buf, length);
comments[length] = '\0';
GST_DEBUG ("jpeg comments:%s\n", comments);
g_free (comments);
#endif
return GST_JPEG_PARSER_OK;
} }
static void void
jpeg_set_default_huffman_tables (GstJpegImage * image) gst_jpeg_get_default_quantization_table (GstJpegQuantTable *quant_tables, guint num_quant_tables)
{ {
/* luma */ int i = 1;
memcpy (image->dc_huf_tables[0].huf_bits, default_dc_luma_bits, 16); g_assert(quant_tables && num_quant_tables);
memcpy (image->dc_huf_tables[0].huf_values, default_dc_luma_vals, 16); for (i = 0; i < num_quant_tables && i < GST_JPEG_MAX_SCAN_COMPONENTS; i++)
memcpy (image->ac_huf_tables[0].huf_bits, default_ac_luma_bits, 16); memcpy(&quant_tables[i],
memcpy (image->ac_huf_tables[0].huf_values, default_ac_luma_vals, 256); &default_quant_tables_zigzag[i],
sizeof(GstJpegQuantTable));
/* chroma */
memcpy (image->dc_huf_tables[1].huf_bits, default_dc_chroma_bits, 16);
memcpy (image->dc_huf_tables[1].huf_values, default_dc_chroma_vals, 16);
memcpy (image->ac_huf_tables[1].huf_bits, default_ac_chroma_bits, 16);
memcpy (image->ac_huf_tables[1].huf_values, default_ac_chroma_vals, 256);
} }
static void GList *
jpeg_set_default_quantization_tables (GstJpegImage * image) gst_jpeg_parse(const guint8 * data, gsize size, guint offset)
{
/* luma */
image->quant_tables[0].quant_precision = 0;
memcpy (image->quant_tables[0].quant_table, default_quant_luma_zigzag, 64);
/* chroma */
image->quant_tables[1].quant_precision = 0;
memcpy (image->quant_tables[1].quant_table, default_quant_chroma_zigzag, 64);
}
GstJpegParserResult
gst_jpeg_parse_image (GstJpegImage * image, const guint8 * buf, guint32 size)
{ {
GstByteReader bytes_reader; GstByteReader bytes_reader;
GstJpegParserResult result = GST_JPEG_PARSER_OK;
guint8 marker; guint8 marker;
guint16 header_length; guint16 header_length;
const guint8 *header_buf; GList *segments = NULL;
gboolean first_scan_reached = FALSE; GstJpegTypeOffsetSize *seg;
gboolean has_huffman_tables = FALSE, has_quant_tables = FALSE;
g_assert (image && buf && size); size -= offset;
memset (image, 0, sizeof (GstJpegImage));
gst_byte_reader_init (&bytes_reader, buf, size); if ((gssize)size <= 0) {
GST_DEBUG ("Can't parse from offset %d, buffer is too small", offset);
return NULL;
}
gst_byte_reader_init (&bytes_reader, &data[offset], size);
/* read SOI */ /* read SOI */
CHECK_FAILED (jpeg_parse_to_next_marker (&bytes_reader, &marker) if (!jpeg_parse_to_next_marker (&bytes_reader, &marker) ||
&& GST_JPEG_SOI == marker, GST_JPEG_PARSER_NOT_JPEG); marker != GST_JPEG_MARKER_SOI)
image->jpeg_begin = buf + gst_byte_reader_get_pos (&bytes_reader) - 2; goto failed;
image->jpeg_end = buf + size;
while (jpeg_parse_to_next_marker (&bytes_reader, &marker)) { while (jpeg_parse_to_next_marker (&bytes_reader, &marker)) {
if (marker >= GST_JPEG_SOF0 && marker <= GST_JPEG_SOFF if (marker == GST_JPEG_MARKER_EOI)
&& marker != GST_JPEG_DHT && marker != GST_JPEG_DAC) {
g_assert (marker == GST_JPEG_SOF0);
if (marker > GST_JPEG_SOF0) {
GST_WARNING ("codecparser_jpeg cannot support this image type:%02x",
marker);
result = GST_JPEG_PARSER_UNSUPPORTED_PROFILE;
goto wrong_state;
}
image->frame_type = marker;
marker = GST_JPEG_SOF0;
}
if (marker == GST_JPEG_EOI) {
image->jpeg_end = buf + gst_byte_reader_get_pos (&bytes_reader);
break; break;
} else {
READ_UINT16 (&bytes_reader, header_length);
CHECK_FAILED ((header_length >= 2 &&
gst_byte_reader_get_remaining (&bytes_reader) + 2 >=
header_length), GST_JPEG_PARSER_BROKEN_DATA);
header_length -= 2;
header_buf = buf + gst_byte_reader_get_pos (&bytes_reader);
}
switch (marker) {
case GST_JPEG_SOF0:
JPEG_RESULT_CHECK (result =
jpeg_parse_frame (image, header_buf, header_length));
break;
case GST_JPEG_DHT:
JPEG_RESULT_CHECK (result =
jpeg_parse_huffman_tables (image, header_buf, header_length));
has_huffman_tables = TRUE;
break;
case GST_JPEG_SOS:
JPEG_RESULT_CHECK (result =
jpeg_parse_scan (image, header_buf, header_length));
first_scan_reached = TRUE; /* read to first scan stop */
break;
case GST_JPEG_DQT:
JPEG_RESULT_CHECK (result =
jpeg_parse_quantization_table (image, header_buf, header_length));
has_quant_tables = TRUE;
break;
case GST_JPEG_DRI:
JPEG_RESULT_CHECK (result =
jpeg_parse_restart_interval (image, header_buf, header_length));
break;
case GST_JPEG_COM:
JPEG_RESULT_CHECK (result =
jpeg_parse_comments (image, header_buf, header_length));
break;
case GST_JPEG_DAC:
case GST_JPEG_DNL:
default:
/* Unsupported markers, skip them */
break;
}
gst_byte_reader_skip (&bytes_reader, header_length);
if (first_scan_reached)
break;
}
image->jpeg_pos = buf + gst_byte_reader_get_pos (&bytes_reader);
if (!first_scan_reached) {
GST_WARNING ("jpeg no scan was found\n");
return GST_JPEG_PARSER_NO_SCAN_FOUND;
}
if (!has_huffman_tables)
jpeg_set_default_huffman_tables (image);
if (!has_quant_tables)
jpeg_set_default_quantization_tables (image);
return GST_JPEG_PARSER_OK;
failed:
GST_WARNING ("jpeg parsing read broken data");
return GST_JPEG_PARSER_BROKEN_DATA;
wrong_state:
return result;
}
GstJpegParserResult
gst_jpeg_parse_next_scan (GstJpegImage * image)
{
GstByteReader bytes_reader;
GstJpegParserResult result = GST_JPEG_PARSER_OK;
guint8 marker;
guint16 header_length;
const guint8 *header_buf;
gboolean scan_found = FALSE;
g_assert (image->jpeg_begin && image->jpeg_end && image->jpeg_pos);
if (!image->jpeg_begin || !image->jpeg_end || !image->jpeg_pos
|| image->jpeg_pos >= image->jpeg_end)
return GST_JPEG_PARSER_NO_SCAN_FOUND;
gst_byte_reader_init (&bytes_reader, image->jpeg_pos,
image->jpeg_end - image->jpeg_pos);
while (jpeg_parse_to_next_marker (&bytes_reader, &marker)) {
if (marker == GST_JPEG_EOI) {
image->jpeg_end =
image->jpeg_pos + gst_byte_reader_get_pos (&bytes_reader);
break;
}
if (marker != GST_JPEG_SOS)
continue;
READ_UINT16 (&bytes_reader, header_length); READ_UINT16 (&bytes_reader, header_length);
CHECK_FAILED ((header_length >= 2 && if (header_length < 2 ||
gst_byte_reader_get_remaining (&bytes_reader) + 2 >= header_length), gst_byte_reader_get_remaining (&bytes_reader) < header_length - 2)
GST_JPEG_PARSER_SCAN_ERROR); goto failed;
header_length -= 2;
header_buf = image->jpeg_pos + gst_byte_reader_get_pos (&bytes_reader); seg = g_malloc (sizeof (GstJpegTypeOffsetSize));
JPEG_RESULT_CHECK (result = seg->type = marker;
jpeg_parse_scan (image, header_buf, header_length)); seg->offset = gst_byte_reader_get_pos(&bytes_reader) + offset;
scan_found = TRUE; seg->size = header_length - 2;
break; segments = g_list_prepend(segments, seg);
} gst_byte_reader_skip (&bytes_reader, header_length - 2);
image->jpeg_pos += gst_byte_reader_get_pos (&bytes_reader);
if (!scan_found) /* parser should stop at first scan */
return GST_JPEG_PARSER_NO_SCAN_FOUND; if (seg->type == GST_JPEG_MARKER_SOS)
break;
}
return g_list_reverse (segments);
return GST_JPEG_PARSER_OK;
failed: failed:
GST_WARNING ("jpeg parsing read broken data"); {
return GST_JPEG_PARSER_BROKEN_DATA; GST_WARNING ("Failed to parse");
return g_list_reverse (segments);
wrong_state:
return result;
}
guint32
gst_jpeg_skip_to_scan_end (GstJpegImage * image)
{
GstByteReader bytes_reader;
guint8 marker;
guint32 skip_bytes = 0;
gboolean next_marker_found = FALSE;
g_assert (image->jpeg_begin && image->jpeg_end && image->jpeg_pos);
if (!image->jpeg_begin || !image->jpeg_end || !image->jpeg_pos
|| image->jpeg_pos >= image->jpeg_end)
return 0;
gst_byte_reader_init (&bytes_reader, image->jpeg_pos,
image->jpeg_end - image->jpeg_pos);
while (jpeg_parse_to_next_marker (&bytes_reader, &marker)) {
if (marker >= GST_JPEG_RST0 && marker <= GST_JPEG_RST7)
continue;
next_marker_found = TRUE;
break;
} }
if (next_marker_found)
skip_bytes = gst_byte_reader_get_pos (&bytes_reader) - 2;
else
skip_bytes = gst_byte_reader_get_pos (&bytes_reader);
image->jpeg_pos += skip_bytes;
return skip_bytes;
}
const guint8 *
gst_jpeg_get_position (GstJpegImage * image)
{
return image->jpeg_pos;
}
guint32
gst_jpeg_get_left_size (GstJpegImage * image)
{
if (image->jpeg_end > image->jpeg_pos)
return image->jpeg_end - image->jpeg_pos;
return 0;
} }

View file

@ -317,7 +317,6 @@ GstJpegParserResult gst_jpeg_parse_quant_table (GstJpegQuantTable *quan
/** /**
* gst_jpeg_parse_huffman_table: * gst_jpeg_parse_huffman_table:
* @huf_tables: (out): The #GstJpegHuffmanTable structure to fill in * @huf_tables: (out): The #GstJpegHuffmanTable structure to fill in
* @num_huf_tables: The number of allocated Huffman tables in @huf_tables
* @data: The data from which to parse the Huffman table * @data: The data from which to parse the Huffman table
* @size: The size of @data * @size: The size of @data
* @offset: The offset in bytes from which to start parsing @data * @offset: The offset in bytes from which to start parsing @data
@ -327,13 +326,14 @@ GstJpegParserResult gst_jpeg_parse_quant_table (GstJpegQuantTable *quan
* Note: @huf_tables represents the user-allocated Huffman tables * Note: @huf_tables represents the user-allocated Huffman tables
* based on the number of scan components. That is, the parser writes * based on the number of scan components. That is, the parser writes
* the output Huffman table at the index specified by the Huffman * the output Huffman table at the index specified by the Huffman
* table destination identifier (Th). So, the array of Huffman tables * table destination identifier (Th). The first array of
* shall be large enough to hold the table for the last component. * <GST_JPEG_MAX_SCAN_COMPONENTS> Huffman tables are related
* to dc tables; The second array of <GST_JPEG_MAX_SCAN_COMPONENTS>
* of Huffman tables are related to ac tables.
* *
* Returns: a #GstJpegParserResult * Returns: a #GstJpegParserResult
*/ */
GstJpegParserResult gst_jpeg_parse_huffman_table (GstJpegHuffmanTable *huf_tables, GstJpegParserResult gst_jpeg_parse_huffman_table (GstJpegHuffmanTable huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2],
guint num_huf_tables,
const guint8 * data, const guint8 * data,
gsize size, gsize size,
guint offset); guint offset);
@ -352,6 +352,29 @@ GstJpegParserResult gst_jpeg_parse_restart_interval (guint * interval,
gsize size, gsize size,
guint offset); guint offset);
/**
* gst_jpeg_get_default_huffman_table:
* @huf_tables: (out): The default dc/ac hufman tables to fill in
*
* DC huffman tables fill in the first 4 arrays.
* AC huffman tables fill in the last 4 arrays.
*
* Returns: void
*/
void gst_jpeg_get_default_huffman_table (
GstJpegHuffmanTable huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2]);
/**
* gst_jpeg_get_default_quantization_table:
* @quant_tables: (out): The default luma/chroma quant-tables in zigzag mode
* @num_quant_tables: The number of allocated quantization tables in @quant_tables
*
* Fills in @quant_tables with the default quantization tables, as
* specified by the JPEG standard.
*/
void gst_jpeg_get_default_quantization_table (GstJpegQuantTable *quant_tables,
guint num_quant_tables);
G_END_DECLS G_END_DECLS
#endif /* GST_JPEG_PARSER_H */ #endif /* GST_JPEG_PARSER_H */

View file

@ -50,6 +50,12 @@ struct _GstVaapiDecoderJpegPrivate {
guint width; guint width;
guint height; guint height;
GstVaapiPicture *current_picture; GstVaapiPicture *current_picture;
GstJpegFrameHdr frame_hdr;
GstJpegHuffmanTable huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS*2];
GstJpegQuantTable quant_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
gboolean has_huf_table;
gboolean has_quant_table;
guint mcu_restart;
guint is_opened : 1; guint is_opened : 1;
guint profile_changed : 1; guint profile_changed : 1;
guint is_constructed : 1; guint is_constructed : 1;
@ -65,10 +71,8 @@ get_status(GstJpegParserResult result)
case GST_JPEG_PARSER_OK: case GST_JPEG_PARSER_OK:
status = GST_VAAPI_DECODER_STATUS_SUCCESS; status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break; break;
case GST_JPEG_PARSER_FRAME_ERROR: case GST_JPEG_PARSER_BROKEN_DATA:
case GST_JPEG_PARSER_SCAN_ERROR: case GST_JPEG_PARSER_NO_SCAN_FOUND:
case GST_JPEG_PARSER_HUFFMAN_ERROR:
case GST_JPEG_PARSER_QUANT_ERROR:
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER; status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
break; break;
default: default:
@ -178,7 +182,7 @@ static gboolean
fill_picture( fill_picture(
GstVaapiDecoderJpeg *decoder, GstVaapiDecoderJpeg *decoder,
GstVaapiPicture *picture, GstVaapiPicture *picture,
GstJpegImage *jpeg_image GstJpegFrameHdr *jpeg_frame_hdr
) )
{ {
VAPictureParameterBufferJPEG *pic_param = picture->param; VAPictureParameterBufferJPEG *pic_param = picture->param;
@ -187,23 +191,25 @@ fill_picture(
g_assert(pic_param); g_assert(pic_param);
memset(pic_param, 0, sizeof(VAPictureParameterBufferJPEG)); memset(pic_param, 0, sizeof(VAPictureParameterBufferJPEG));
pic_param->type = jpeg_image->frame_type; pic_param->type = jpeg_frame_hdr->profile;
pic_param->sample_precision = jpeg_image->sample_precision; pic_param->sample_precision = jpeg_frame_hdr->sample_precision;
pic_param->image_width = jpeg_image->width; pic_param->image_width = jpeg_frame_hdr->width;
pic_param->image_height = jpeg_image->height; pic_param->image_height = jpeg_frame_hdr->height;
/* XXX: ROI + rotation */ /* XXX: ROI + rotation */
pic_param->num_components = jpeg_image->num_components; pic_param->num_components = jpeg_frame_hdr->num_components;
if (jpeg_frame_hdr->num_components > 4)
return FALSE;
for (i = 0; i < pic_param->num_components; i++) { for (i = 0; i < pic_param->num_components; i++) {
pic_param->components[i].component_id = pic_param->components[i].component_id =
jpeg_image->components[i].identifier; jpeg_frame_hdr->components[i].identifier;
pic_param->components[i].h_sampling_factor = pic_param->components[i].h_sampling_factor =
jpeg_image->components[i].horizontal_factor; jpeg_frame_hdr->components[i].horizontal_factor;
pic_param->components[i].v_sampling_factor = pic_param->components[i].v_sampling_factor =
jpeg_image->components[i].vertical_factor; jpeg_frame_hdr->components[i].vertical_factor;
pic_param->components[i].quantiser_table_selector = pic_param->components[i].quantiser_table_selector =
jpeg_image->components[i].quant_table_selector; jpeg_frame_hdr->components[i].quant_table_selector;
} }
return TRUE; return TRUE;
} }
@ -211,23 +217,31 @@ fill_picture(
static gboolean static gboolean
fill_quantization_table( fill_quantization_table(
GstVaapiDecoderJpeg *decoder, GstVaapiDecoderJpeg *decoder,
GstVaapiPicture *picture, GstVaapiPicture *picture
GstJpegImage *jpeg_image
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
VAIQMatrixBufferJPEG *iq_matrix; VAIQMatrixBufferJPEG *iq_matrix;
int i = 0; guint i, j;
if (!priv->has_quant_table)
gst_jpeg_get_default_quantization_table(priv->quant_tables, GST_JPEG_MAX_SCAN_COMPONENTS);
picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEG, decoder); picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEG, decoder);
g_assert(picture->iq_matrix); g_assert(picture->iq_matrix);
iq_matrix = picture->iq_matrix->param; iq_matrix = picture->iq_matrix->param;
memset(iq_matrix, 0, sizeof(VAIQMatrixBufferJPEG)); memset(iq_matrix, 0, sizeof(VAIQMatrixBufferJPEG));
for (i = 0; i < GST_JPEG_MAX_COMPONENTS; i++) { for (i = 0; i < GST_JPEG_MAX_SCAN_COMPONENTS; i++) {
iq_matrix->precision[i] = jpeg_image->quant_tables[i].quant_precision; iq_matrix->precision[i] = priv->quant_tables[i].quant_precision;
if (iq_matrix->precision[i] == 0) /* 8-bit values*/ if (iq_matrix->precision[i] == 0) /* 8-bit values */
memcpy(iq_matrix->quantiser_matrix[i], jpeg_image->quant_tables[i].quant_table, 64); for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++) {
iq_matrix->quantiser_matrix[i][j] =
priv->quant_tables[i].quant_table[j];
}
else else
memcpy(iq_matrix->quantiser_matrix[i], jpeg_image->quant_tables[i].quant_table, 128); memcpy(iq_matrix->quantiser_matrix[i],
priv->quant_tables[i].quant_table,
128);
} }
return TRUE; return TRUE;
} }
@ -235,119 +249,65 @@ fill_quantization_table(
static gboolean static gboolean
fill_huffman_table( fill_huffman_table(
GstVaapiDecoderJpeg *decoder, GstVaapiDecoderJpeg *decoder,
GstVaapiPicture *picture, GstVaapiPicture *picture
GstJpegImage *jpeg_image
) )
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
VAHuffmanTableBufferJPEG *huffman_table; VAHuffmanTableBufferJPEG *huffman_table;
int i; guint i;
if (!priv->has_huf_table)
gst_jpeg_get_default_huffman_table(priv->huf_tables);
picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEG, decoder); picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEG, decoder);
g_assert(picture->huf_table); g_assert(picture->huf_table);
huffman_table = picture->huf_table->param; huffman_table = picture->huf_table->param;
memset(huffman_table, 0, sizeof(VAHuffmanTableBufferJPEG)); memset(huffman_table, 0, sizeof(VAHuffmanTableBufferJPEG));
for (i = 0; i < GST_JPEG_MAX_COMPONENTS; i++) { for (i = 0; i < GST_JPEG_MAX_SCAN_COMPONENTS; i++) {
memcpy(huffman_table->huffman_table[i].dc_bits, memcpy(huffman_table->huffman_table[i].dc_bits,
jpeg_image->dc_huf_tables[i].huf_bits, priv->huf_tables[i].huf_bits,
16); 16);
memcpy(huffman_table->huffman_table[i].dc_huffval, memcpy(huffman_table->huffman_table[i].dc_huffval,
jpeg_image->dc_huf_tables[i].huf_values, priv->huf_tables[i].huf_values,
16); 16);
memcpy(huffman_table->huffman_table[i].ac_bits, memcpy(huffman_table->huffman_table[i].ac_bits,
jpeg_image->ac_huf_tables[i].huf_bits, priv->huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS + i].huf_bits,
16); 16);
memcpy(huffman_table->huffman_table[i].ac_huffval, memcpy(huffman_table->huffman_table[i].ac_huffval,
jpeg_image->ac_huf_tables[i].huf_values, priv->huf_tables[GST_JPEG_MAX_SCAN_COMPONENTS + i].huf_values,
256); 256);
} }
return TRUE; return TRUE;
} }
static guint static guint
get_max_horizontal_samples(GstJpegImage *jpeg) get_max_horizontal_samples(GstJpegFrameHdr *frame_hdr)
{ {
guint i, max_factor = 0; guint i, max_factor = 0;
for (i = 0; i < jpeg->num_components; i++) { for (i = 0; i < frame_hdr->num_components; i++) {
if (jpeg->components[i].horizontal_factor > max_factor) if (frame_hdr->components[i].horizontal_factor > max_factor)
max_factor = jpeg->components[i].horizontal_factor; max_factor = frame_hdr->components[i].horizontal_factor;
} }
return max_factor; return max_factor;
} }
static guint static guint
get_max_vertical_samples(GstJpegImage *jpeg) get_max_vertical_samples(GstJpegFrameHdr *frame_hdr)
{ {
guint i, max_factor = 0; guint i, max_factor = 0;
for (i = 0; i < jpeg->num_components; i++) { for (i = 0; i < frame_hdr->num_components; i++) {
if (jpeg->components[i].vertical_factor > max_factor) if (frame_hdr->components[i].vertical_factor > max_factor)
max_factor = jpeg->components[i].vertical_factor; max_factor = frame_hdr->components[i].vertical_factor;
} }
return max_factor; return max_factor;
} }
static gboolean
fill_slices(
GstVaapiDecoderJpeg *decoder,
GstVaapiPicture *picture,
GstJpegImage *jpeg_image
)
{
VASliceParameterBufferJPEG *slice_param;
GstVaapiSlice *gst_slice;
int i;
const guint8 *sos_src;
guint32 sos_length;
guint total_h_samples, total_v_samples;
while (gst_jpeg_get_left_size(jpeg_image)) {
sos_src = gst_jpeg_get_position(jpeg_image);
sos_length = gst_jpeg_skip_to_scan_end(jpeg_image);
if (!sos_length)
break;
gst_slice = GST_VAAPI_SLICE_NEW(JPEG, decoder, sos_src, sos_length);
slice_param = gst_slice->param;
slice_param->num_components = jpeg_image->current_scan.num_components;
for (i = 0; i < slice_param->num_components; i++) {
slice_param->components[i].component_id = jpeg_image->current_scan.components[i].component_selector;
slice_param->components[i].dc_selector = jpeg_image->current_scan.components[i].dc_selector;
slice_param->components[i].ac_selector = jpeg_image->current_scan.components[i].ac_selector;
}
slice_param->restart_interval = jpeg_image->restart_interval;
if (jpeg_image->current_scan.num_components == 1) { /*non-interleaved*/
slice_param->slice_horizontal_position = 0;
slice_param->slice_vertical_position = 0;
/* Y mcu numbers*/
if (slice_param->components[0].component_id == jpeg_image->components[0].identifier) {
slice_param->num_mcus = (jpeg_image->width/8)*(jpeg_image->height/8);
} else { /*Cr, Cb mcu numbers*/
slice_param->num_mcus = (jpeg_image->width/16)*(jpeg_image->height/16);
}
} else { /* interleaved */
slice_param->slice_horizontal_position = 0;
slice_param->slice_vertical_position = 0;
total_v_samples = get_max_vertical_samples(jpeg_image);
total_h_samples = get_max_horizontal_samples(jpeg_image);
slice_param->num_mcus = ((jpeg_image->width + total_h_samples*8 - 1)/(total_h_samples*8)) *
((jpeg_image->height + total_v_samples*8 -1)/(total_v_samples*8));
}
gst_vaapi_picture_add_slice(picture, gst_slice);
if (!gst_jpeg_parse_next_scan(jpeg_image)) {
break;
}
}
if (picture->slices && picture->slices->len)
return TRUE;
return FALSE;
}
static GstVaapiDecoderStatus static GstVaapiDecoderStatus
decode_picture( decode_picture(
GstVaapiDecoderJpeg *decoder, GstVaapiDecoderJpeg *decoder,
guint8 profile,
guchar *buf, guchar *buf,
guint buf_size, guint buf_size,
GstClockTime pts GstClockTime pts
@ -355,29 +315,42 @@ decode_picture(
{ {
GstVaapiDecoderJpegPrivate * const priv = decoder->priv; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiPicture *picture = NULL; GstVaapiPicture *picture = NULL;
GstJpegFrameHdr *jpeg_frame_hdr = &priv->frame_hdr;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS; GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
GstJpegImage jpeg_image;
GstJpegParserResult result; GstJpegParserResult result;
/* parse jpeg */ /* parse jpeg */
memset(&jpeg_image, 0, sizeof(jpeg_image)); memset(jpeg_frame_hdr, 0, sizeof(GstJpegFrameHdr));
result = gst_jpeg_parse_image(&jpeg_image, buf, buf_size); switch (profile) {
case GST_JPEG_MARKER_SOF_MIN:
jpeg_frame_hdr->profile = GST_JPEG_MARKER_SOF_MIN;
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
break;
default:
GST_WARNING("Jpeg profile was not supported.");
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
result = gst_jpeg_parse_frame_hdr(jpeg_frame_hdr, buf, buf_size, 0);
if (result != GST_JPEG_PARSER_OK) { if (result != GST_JPEG_PARSER_OK) {
GST_ERROR("failed to parse image"); GST_ERROR("failed to parse image");
return get_status(result); return get_status(result);
} }
/* set info to va parameters in current picture*/ /* set info to va parameters in current picture*/
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE; priv->height = jpeg_frame_hdr->height;
priv->height = jpeg_image.height; priv->width = jpeg_frame_hdr->width;
priv->width = jpeg_image.width;
status = ensure_context(decoder); status = ensure_context(decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
GST_ERROR("failed to reset context"); GST_ERROR("failed to reset context");
return status; return status;
} }
if (priv->current_picture &&
(status = decode_current_picture(decoder)) != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
picture = GST_VAAPI_PICTURE_NEW(JPEG, decoder); picture = GST_VAAPI_PICTURE_NEW(JPEG, decoder);
if (!picture) { if (!picture) {
GST_ERROR("failed to allocate picture"); GST_ERROR("failed to allocate picture");
@ -386,36 +359,224 @@ decode_picture(
gst_vaapi_picture_replace(&priv->current_picture, picture); gst_vaapi_picture_replace(&priv->current_picture, picture);
gst_vaapi_picture_unref(picture); gst_vaapi_picture_unref(picture);
if (!fill_picture(decoder, picture, &jpeg_image)) if (!fill_picture(decoder, picture, jpeg_frame_hdr))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
if (!fill_quantization_table(decoder, picture, &jpeg_image)) {
GST_ERROR("failed to fill in quantization table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
if (!fill_huffman_table(decoder, picture, &jpeg_image)) {
GST_ERROR("failed to fill in huffman table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
if (!fill_slices(decoder, picture, &jpeg_image)) {
GST_ERROR("failed to fill in all scans");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
/* Update presentation time */ /* Update presentation time */
picture->pts = pts; picture->pts = pts;
return status; return status;
} }
static GstVaapiDecoderStatus
decode_huffman_table(
GstVaapiDecoderJpeg *decoder,
guchar *buf,
guint buf_size
)
{
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_huffman_table(
priv->huf_tables,
buf, buf_size, 0
);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse Huffman table");
return get_status(result);
}
priv->has_huf_table = TRUE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_quant_table(
GstVaapiDecoderJpeg *decoder,
guchar *buf,
guint buf_size
)
{
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_quant_table(
priv->quant_tables,
GST_JPEG_MAX_SCAN_COMPONENTS,
buf, buf_size, 0
);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse quantization table");
return get_status(result);
}
priv->has_quant_table = TRUE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_restart_interval(
GstVaapiDecoderJpeg *decoder,
guchar *buf,
guint buf_size
)
{
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstJpegParserResult result;
result = gst_jpeg_parse_restart_interval(
&priv->mcu_restart,
buf, buf_size, 0
);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse restart interval");
return get_status(result);
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static gint32
scan_to_end(const guint8 *start, guint32 size)
{
const guint8 *pos = start, *end = start + size;
for (; pos < end; ++pos) {
if (*pos != 0xFF)
continue;
while (*pos == 0xFF && pos + 1 < end)
++pos;
if (*pos == 0x00 || *pos == 0xFF ||
(*pos >= GST_JPEG_MARKER_RST_MIN && *pos <= GST_JPEG_MARKER_RST_MAX))
continue;
break;
}
if (pos >= end)
return size;
return pos - start - 1;
}
static gboolean
scan_to_next_scan(guint8 *data, guint32 size,
guint8 **scan, guint32 *scan_header_size, guint32 *scan_left_size)
{
GList *seg_list = NULL;
gboolean ret = FALSE;
if (!data || !size)
return FALSE;
seg_list = gst_jpeg_parse(data, size, 0);
for (; seg_list; seg_list = seg_list->next) {
GstJpegTypeOffsetSize * const seg = seg_list->data;
if (seg->type != GST_JPEG_MARKER_SOS)
continue;
*scan = seg->offset + data;
*scan_header_size = seg->size;
*scan_left_size = size - seg->offset - seg->size;
ret = TRUE;
break;
}
g_list_free_full(seg_list, g_free);
return ret;
}
static GstVaapiDecoderStatus
decode_scan(
GstVaapiDecoderJpeg *decoder,
guchar *scan,
guint scan_header_size,
guint scan_left_size)
{
GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiPicture *picture = priv->current_picture;
GstJpegParserResult result = GST_JPEG_PARSER_OK;
VASliceParameterBufferJPEG *slice_param;
GstVaapiSlice *gst_slice;
guint8 *mcu_start, *next_mark;
guint8 *buf_end = scan + scan_header_size + scan_left_size;
guint mcu_size;
guint total_h_samples, total_v_samples;
GstJpegScanHdr scan_hdr;
guint i;
if (!picture) {
GST_ERROR ("There is no VAPicture before decoding scan.");
return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE;
}
if (!fill_quantization_table(decoder, picture)) {
GST_ERROR("Failed to fill in quantization table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
if (!fill_huffman_table(decoder, picture)) {
GST_ERROR("Failed to fill in huffman table");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
mcu_size = scan_left_size;
while (scan_left_size) {
memset(&scan_hdr, 0, sizeof(scan_hdr));
result = gst_jpeg_parse_scan_hdr(&scan_hdr, scan, scan_header_size, 0);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("Jpeg parsed scan failed.");
return get_status(result);
}
mcu_start = scan + scan_header_size;
mcu_size = scan_to_end(mcu_start, scan_left_size);
gst_slice = GST_VAAPI_SLICE_NEW(JPEG, decoder, mcu_start, mcu_size);
gst_vaapi_picture_add_slice(picture, gst_slice);
slice_param = gst_slice->param;
slice_param->num_components = scan_hdr.num_components;
for (i = 0; i < scan_hdr.num_components; i++) {
slice_param->components[i].component_id = scan_hdr.components[i].component_selector;
slice_param->components[i].dc_selector = scan_hdr.components[i].dc_selector;
slice_param->components[i].ac_selector = scan_hdr.components[i].ac_selector;
}
slice_param->restart_interval = priv->mcu_restart;
if (scan_hdr.num_components == 1) { /*non-interleaved*/
slice_param->slice_horizontal_position = 0;
slice_param->slice_vertical_position = 0;
/* Y mcu numbers*/
if (slice_param->components[0].component_id == priv->frame_hdr.components[0].identifier) {
slice_param->num_mcus = (priv->frame_hdr.width/8)*(priv->frame_hdr.height/8);
} else { /*Cr, Cb mcu numbers*/
slice_param->num_mcus = (priv->frame_hdr.width/16)*(priv->frame_hdr.height/16);
}
} else { /* interleaved */
slice_param->slice_horizontal_position = 0;
slice_param->slice_vertical_position = 0;
total_v_samples = get_max_vertical_samples(&priv->frame_hdr);
total_h_samples = get_max_horizontal_samples(&priv->frame_hdr);
slice_param->num_mcus = ((priv->frame_hdr.width + total_h_samples*8 - 1)/(total_h_samples*8)) *
((priv->frame_hdr.height + total_v_samples*8 -1)/(total_v_samples*8));
}
next_mark = mcu_start + mcu_size;
scan_left_size = buf_end - next_mark;
if (scan_left_size < 4) /* Mark_code(2-bytes) + header_length(2-bytes)*/
break;
if (!scan_to_next_scan(next_mark, scan_left_size, &scan, &scan_header_size, &scan_left_size))
break;
}
if (picture->slices && picture->slices->len)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
static GstVaapiDecoderStatus static GstVaapiDecoderStatus
decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer) decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
{ {
GstVaapiDecoderStatus status; GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
GstClockTime pts; GstClockTime pts;
guchar *buf; guchar *buf;
guint buf_size; guint buf_size;
GList *seg_list = NULL;
gboolean scan_found = FALSE;
GstJpegTypeOffsetSize *seg;
buf = GST_BUFFER_DATA(buffer); buf = GST_BUFFER_DATA(buffer);
buf_size = GST_BUFFER_SIZE(buffer); buf_size = GST_BUFFER_SIZE(buffer);
@ -425,10 +586,53 @@ decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
pts = GST_BUFFER_TIMESTAMP(buffer); pts = GST_BUFFER_TIMESTAMP(buffer);
g_assert(GST_CLOCK_TIME_IS_VALID(pts)); g_assert(GST_CLOCK_TIME_IS_VALID(pts));
status = decode_picture(decoder, buf, buf_size, pts); priv->has_quant_table = FALSE;
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) priv->has_huf_table = FALSE;
return status; priv->mcu_restart = 0;
return decode_current_picture(decoder);
seg_list = gst_jpeg_parse(buf, buf_size, 0);
for (; seg_list && !scan_found; seg_list = seg_list->next) {
seg = seg_list->data;
g_assert(seg);
switch (seg->type) {
case GST_JPEG_MARKER_DHT:
status = decode_huffman_table(decoder, buf + seg->offset, seg->size);
break;
case GST_JPEG_MARKER_DAC:
GST_ERROR("unsupported arithmetic decoding");
status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
break;
case GST_JPEG_MARKER_DQT:
status = decode_quant_table(decoder, buf + seg->offset, seg->size);
break;
case GST_JPEG_MARKER_DRI:
status = decode_restart_interval(decoder, buf + seg->offset, seg->size);
break;
case GST_JPEG_MARKER_SOS:
status = decode_scan(decoder, buf + seg->offset, seg->size, buf_size - seg->offset - seg->size);
scan_found = TRUE;
break;
default:
if (seg->type >= GST_JPEG_MARKER_SOF_MIN &&
seg->type <= GST_JPEG_MARKER_SOF_MAX)
status = decode_picture(decoder, seg->type, buf + seg->offset, seg->size, pts);
else {
GST_WARNING("unsupported marker (0x%02x)", seg->type);
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
break;
}
}
/* clean seg_list */
g_list_free_full(seg_list, g_free);
if (status == GST_VAAPI_DECODER_STATUS_SUCCESS) {
if (scan_found)
return decode_current_picture(decoder);
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
return status;
} }
GstVaapiDecoderStatus GstVaapiDecoderStatus
@ -494,9 +698,15 @@ gst_vaapi_decoder_jpeg_init(GstVaapiDecoderJpeg *decoder)
priv->width = 0; priv->width = 0;
priv->height = 0; priv->height = 0;
priv->current_picture = NULL; priv->current_picture = NULL;
priv->has_huf_table = FALSE;
priv->has_quant_table = FALSE;
priv->mcu_restart = 0;
priv->is_opened = FALSE; priv->is_opened = FALSE;
priv->profile_changed = TRUE; priv->profile_changed = TRUE;
priv->is_constructed = FALSE; priv->is_constructed = FALSE;
memset(&priv->frame_hdr, 0, sizeof(priv->frame_hdr));
memset(priv->huf_tables, 0, sizeof(priv->huf_tables));
memset(priv->quant_tables, 0, sizeof(priv->quant_tables));
} }
/** /**