codecparsers: jpeg: track valid quantization and Huffman tables.

Add valid flag to GstJpegQuantTable and GstJpegHuffmanTable so that
to determine whether a table actually changed since the last user
synchronization point. That way, this makes it possible for some
hardware accelerated decoding solution to upload only those tables
that changed.
This commit is contained in:
Gwenole Beauchesne 2012-06-21 16:06:47 +02:00
parent e61f4c4445
commit 326a229636
3 changed files with 104 additions and 83 deletions

View file

@ -101,37 +101,39 @@ static gboolean jpeg_parse_to_next_marker (GstByteReader * reader,
guint8 * marker);
/* CCITT T.81, Annex K.1 Quantization tables for luminance and chrominance components */
/* only for 8-bit per sample image*/
static const GstJpegQuantTable
default_quant_tables_zigzag[GST_JPEG_MAX_SCAN_COMPONENTS] = {
/* luma */
{0, { 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x27,
0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0xa8,
0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0xb5, 0x57,
0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 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 } },
/* 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, }
/* only for 8-bit per sample image */
static const GstJpegQuantTables
default_quant_tables_zigzag = {
.quant_tables = {
/* luma */
{0, { 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x27,
0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0xa8,
0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0xb5, 0x57,
0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63 }, TRUE },
/* 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 }, TRUE },
/* 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 }, TRUE },
{0, }
}
};
/* Table K.3: typical Huffman tables for 8-bit precision luminance and chrominance */
@ -141,30 +143,33 @@ GST_JPEG_MAX_SCAN_COMPONENTS...GST_JPEG_MAX_SCAN_COMPONENTS*2-1, AC huffman tabl
*/
static const
GstJpegHuffmanTables default_huf_tables = {
{
.dc_tables = {
/* DC luma */
{ { 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b }
0x08, 0x09, 0x0a, 0x0b },
TRUE
},
/* DC chroma */
{ { 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b }
0x08, 0x09, 0x0a, 0x0b },
TRUE
},
/* DC chroma */
{ { 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b }
0x08, 0x09, 0x0a, 0x0b },
TRUE
},
{ { 0x0 },
{ 0x0 }
}
},
{
.ac_tables = {
/* AC luma */
{ { 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d },
@ -188,7 +193,8 @@ GstJpegHuffmanTables default_huf_tables = {
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa}
0xf9, 0xfa},
TRUE
},
/* AC chroma */
{ { 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
@ -213,7 +219,8 @@ GstJpegHuffmanTables default_huf_tables = {
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 }
0xf9, 0xfa },
TRUE
},
/* AC chroma */
{ { 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
@ -238,7 +245,8 @@ GstJpegHuffmanTables default_huf_tables = {
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 }
0xf9, 0xfa },
TRUE
},
{ { 0x00 },
{ 0x00 }
@ -373,6 +381,7 @@ gst_jpeg_parse_huffman_table (
for (i = 0; i < 16; i++)
value_count += huf_table->huf_bits[i];
READ_BYTES (&bytes_reader, huf_table->huf_values, value_count);
huf_table->valid = TRUE;
}
return GST_JPEG_PARSER_OK;
@ -385,7 +394,7 @@ wrong_state:
GstJpegParserResult
gst_jpeg_parse_quant_table (
GstJpegQuantTable *quant_tables, guint num_quant_tables,
GstJpegQuantTables *quant_tables,
const guint8 * data, gsize size, guint offset)
{
GstByteReader bytes_reader = GST_BYTE_READER_INIT (data + offset, size - offset);
@ -395,13 +404,13 @@ gst_jpeg_parse_quant_table (
guint8 table_index;
guint i;
g_assert (quant_tables && num_quant_tables && data && size);
g_assert (quant_tables && data && size);
while (gst_byte_reader_get_remaining (&bytes_reader)) {
U_READ_UINT8 (&bytes_reader, val);
table_index = (val & 0x0f);
CHECK_FAILED (table_index < GST_JPEG_MAX_SCAN_COMPONENTS && table_index < num_quant_tables,
CHECK_FAILED (table_index < GST_JPEG_MAX_SCAN_COMPONENTS,
GST_JPEG_PARSER_BROKEN_DATA);
quant_table = &quant_tables[table_index];
quant_table = &quant_tables->quant_tables[table_index];
quant_table->quant_precision = ((val >> 4) & 0x0f);
CHECK_FAILED (gst_byte_reader_get_remaining(&bytes_reader) >= GST_JPEG_MAX_QUANT_ELEMENTS * (1 + !!quant_table->quant_precision),
@ -414,6 +423,7 @@ gst_jpeg_parse_quant_table (
U_READ_UINT16 (&bytes_reader, quant_table->quant_table[i]);
}
}
quant_table->valid = TRUE;
}
return GST_JPEG_PARSER_OK;
@ -438,23 +448,18 @@ failed:
}
void
gst_jpeg_get_default_huffman_table (GstJpegHuffmanTables *huf_tables)
gst_jpeg_get_default_huffman_tables (GstJpegHuffmanTables *huf_tables)
{
g_assert(huf_tables);
memcpy(huf_tables,
&default_huf_tables,
sizeof(GstJpegHuffmanTables));
g_assert (huf_tables);
memcpy (huf_tables, &default_huf_tables, sizeof (GstJpegHuffmanTables));
}
void
gst_jpeg_get_default_quantization_table (GstJpegQuantTable *quant_tables, guint num_quant_tables)
gst_jpeg_get_default_quantization_tables (GstJpegQuantTables *quant_tables)
{
int i = 1;
g_assert(quant_tables && num_quant_tables);
for (i = 0; i < num_quant_tables && i < GST_JPEG_MAX_SCAN_COMPONENTS; i++)
memcpy(&quant_tables[i],
&default_quant_tables_zigzag[i],
sizeof(GstJpegQuantTable));
g_assert (quant_tables);
memcpy (quant_tables, &default_quant_tables_zigzag, sizeof (GstJpegQuantTables));
}
static gint32

View file

@ -53,6 +53,7 @@ G_BEGIN_DECLS
#define GST_JPEG_MAX_QUANT_ELEMENTS 64
typedef struct _GstJpegQuantTable GstJpegQuantTable;
typedef struct _GstJpegQuantTables GstJpegQuantTables;
typedef struct _GstJpegHuffmanTable GstJpegHuffmanTable;
typedef struct _GstJpegHuffmanTables GstJpegHuffmanTables;
typedef struct _GstJpegScanComponent GstJpegScanComponent;
@ -139,6 +140,8 @@ typedef enum {
* GstJpegQuantTable:
* @quant_precision: Quantization table element precision (Pq)
* @quant_table: Quantization table elements (Qk)
* @valid: If the quantization table is valid, which means it has
* already been parsed
*
* Quantization table.
*/
@ -146,12 +149,27 @@ struct _GstJpegQuantTable
{
guint8 quant_precision;
guint16 quant_table[GST_JPEG_MAX_QUANT_ELEMENTS];
gboolean valid;
};
/**
* GstJpegQuantTables:
* @quant_tables: All quantization tables
*
* Helper data structure that holds all quantization tables used to
* decode an image.
*/
struct _GstJpegQuantTables
{
GstJpegQuantTable quant_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
};
/**
* GstJpegHuffmanTable:
* @huf_bits: Number of Huffman codes of length i + 1 (Li)
* @huf_vales: Value associated with each Huffman code (Vij)
* @valid: If the Huffman table is valid, which means it has already
* been parsed
*
* Huffman table.
*/
@ -159,6 +177,7 @@ struct _GstJpegHuffmanTable
{
guint8 huf_bits[16];
guint8 huf_values[256];
gboolean valid;
};
/**
@ -334,17 +353,15 @@ GstJpegParserResult gst_jpeg_parse_scan_hdr (GstJpegScanHdr * hdr,
*
* Parses the JPEG quantization table structure members from @data.
*
* Note: @quant_tables represents the user-allocated quantization
* tables based on the number of scan components. That is, the parser
* writes the output quantization table at the index specified by the
* quantization table destination identifier (Tq). So, the array of
* quantization tables shall be large enough to hold the table for the
* last component.
* Note: @quant_tables represents the complete set of possible
* quantization tables. However, the parser will only write to the
* quantization table specified by the table destination identifier
* (Tq). While doing so, the @valid flag of the specified quantization
* table will also be set to %TRUE.
*
* Returns: a #GstJpegParserResult
*/
GstJpegParserResult gst_jpeg_parse_quant_table (GstJpegQuantTable *quant_tables,
guint num_quant_tables,
GstJpegParserResult gst_jpeg_parse_quant_table (GstJpegQuantTables *quant_tables,
const guint8 * data,
gsize size,
guint offset);
@ -360,7 +377,9 @@ GstJpegParserResult gst_jpeg_parse_quant_table (GstJpegQuantTable *quan
*
* Note: @huf_tables represents the complete set of possible Huffman
* tables. However, the parser will only write to the Huffman table
* specified by the table destination identifier (Th).
* specified by the table destination identifier (Th). While doing so,
* the @valid flag of the specified Huffman table will also be set to
* %TRUE;
*
* Returns: a #GstJpegParserResult
*/
@ -384,24 +403,23 @@ GstJpegParserResult gst_jpeg_parse_restart_interval (guint * interval,
guint offset);
/**
* gst_jpeg_get_default_huffman_table:
* @huf_tables: (out): The default dc/ac hufman tables to fill in
* gst_jpeg_get_default_huffman_tables:
* @huf_tables: (out): The default DC/AC Huffman tables to fill in
*
* Returns: void
* Fills in @huf_tables with the default AC/DC Huffman tables, as
* specified by the JPEG standard.
*/
void gst_jpeg_get_default_huffman_table (
void gst_jpeg_get_default_huffman_tables (
GstJpegHuffmanTables *huf_tables);
/**
* 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);
void gst_jpeg_get_default_quantization_tables (GstJpegQuantTables *quant_tables);
G_END_DECLS

View file

@ -52,7 +52,7 @@ struct _GstVaapiDecoderJpegPrivate {
GstVaapiPicture *current_picture;
GstJpegFrameHdr frame_hdr;
GstJpegHuffmanTables huf_tables;
GstJpegQuantTable quant_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
GstJpegQuantTables quant_tables;
gboolean has_huf_table;
gboolean has_quant_table;
guint mcu_restart;
@ -225,22 +225,24 @@ fill_quantization_table(
guint i, j;
if (!priv->has_quant_table)
gst_jpeg_get_default_quantization_table(priv->quant_tables, GST_JPEG_MAX_SCAN_COMPONENTS);
gst_jpeg_get_default_quantization_tables(&priv->quant_tables);
picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEG, decoder);
g_assert(picture->iq_matrix);
iq_matrix = picture->iq_matrix->param;
memset(iq_matrix, 0, sizeof(VAIQMatrixBufferJPEG));
for (i = 0; i < GST_JPEG_MAX_SCAN_COMPONENTS; i++) {
iq_matrix->precision[i] = priv->quant_tables[i].quant_precision;
GstJpegQuantTable * const quant_table =
&priv->quant_tables.quant_tables[i];
iq_matrix->precision[i] = quant_table->quant_precision;
if (iq_matrix->precision[i] == 0) /* 8-bit values */
for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++) {
iq_matrix->quantiser_matrix[i][j] =
priv->quant_tables[i].quant_table[j];
quant_table->quant_table[j];
}
else
memcpy(iq_matrix->quantiser_matrix[i],
priv->quant_tables[i].quant_table,
quant_table->quant_table,
128);
}
return TRUE;
@ -257,7 +259,7 @@ fill_huffman_table(
guint i;
if (!priv->has_huf_table)
gst_jpeg_get_default_huffman_table(&priv->huf_tables);
gst_jpeg_get_default_huffman_tables(&priv->huf_tables);
picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEG, decoder);
g_assert(picture->huf_table);
@ -399,11 +401,7 @@ decode_quant_table(
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
);
result = gst_jpeg_parse_quant_table(&priv->quant_tables, buf, buf_size, 0);
if (result != GST_JPEG_PARSER_OK) {
GST_DEBUG("failed to parse quantization table");
return get_status(result);
@ -651,7 +649,7 @@ gst_vaapi_decoder_jpeg_init(GstVaapiDecoderJpeg *decoder)
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));
memset(&priv->quant_tables, 0, sizeof(priv->quant_tables));
}
/**