Tizen 2.1 base
[framework/multimedia/gstreamer-vaapi.git] / gst-libs / gst / codecparsers / gstjpegparser.c
1 /*
2  *  gstjpegparser.c - JPEG parser
3  *
4  *  Copyright (C) 2011-2012 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include <string.h>
23 #include <gst/base/gstbytereader.h>
24 #include "gstjpegparser.h"
25
26 #ifndef GST_DISABLE_GST_DEBUG
27
28 #define GST_CAT_DEFAULT ensure_debug_category()
29
30 static GstDebugCategory *
31 ensure_debug_category (void)
32 {
33   static gsize cat_gonce = 0;
34
35   if (g_once_init_enter (&cat_gonce)) {
36     gsize cat_done;
37
38     cat_done = (gsize) _gst_debug_category_new ("codecparsers_jpeg", 0,
39         "GstJpegCodecParser");
40
41     g_once_init_leave (&cat_gonce, cat_done);
42   }
43
44   return (GstDebugCategory *) cat_gonce;
45 }
46 #else
47
48 #define ensure_debug_category() /* NOOP */
49
50 #endif /* GST_DISABLE_GST_DEBUG */
51
52 #define DEBUG_PRINT_COMMENT 0
53
54 #define READ_UINT8(reader, val) G_STMT_START {                  \
55     if (!gst_byte_reader_get_uint8 ((reader), &(val))) {        \
56       GST_WARNING ("failed to read uint8");                     \
57       goto failed;                                              \
58     }                                                           \
59   } G_STMT_END
60
61 #define READ_UINT16(reader, val) G_STMT_START {                 \
62     if (!gst_byte_reader_get_uint16_be ((reader), &(val))) {    \
63       GST_WARNING ("failed to read uint16");                    \
64       goto failed;                                              \
65     }                                                           \
66   } G_STMT_END
67
68 #define READ_BYTES(reader, buf, length) G_STMT_START {          \
69     const guint8 *vals;                                         \
70     if (!gst_byte_reader_get_data (reader, length, &vals)) {    \
71       GST_WARNING ("failed to read bytes, size:%d", length);    \
72       goto failed;                                              \
73     }                                                           \
74     memcpy (buf, vals, length);                                 \
75   } G_STMT_END
76
77 #define U_READ_UINT8(reader, val) G_STMT_START {                \
78     (val) = gst_byte_reader_get_uint8_unchecked(reader);        \
79   } G_STMT_END
80
81 #define U_READ_UINT16(reader, val) G_STMT_START {               \
82     (val) = gst_byte_reader_get_uint16_be_unchecked(reader);    \
83   } G_STMT_END
84
85
86 /* Table used to address an 8x8 matrix in zig-zag order */
87 /* *INDENT-OFF* */
88 static const guint8 zigzag_index[64] = {
89   0,   1,  8, 16,  9,  2,  3, 10,
90   17, 24, 32, 25, 18, 11,  4,  5,
91   12, 19, 26, 33, 40, 48, 41, 34,
92   27, 20, 13,  6,  7, 14, 21, 28,
93   35, 42, 49, 56, 57, 50, 43, 36,
94   29, 22, 15, 23, 30, 37, 44, 51,
95   58, 59, 52, 45, 38, 31, 39, 46,
96   53, 60, 61, 54, 47, 55, 62, 63
97 };
98 /* *INDENT-ON* */
99
100 /* Table K.1 - Luminance quantization table */
101 /* *INDENT-OFF* */
102 static const guint8 default_luminance_quant_table[64] = {
103   16,  11,  10,  16,  24,  40,  51,  61,
104   12,  12,  14,  19,  26,  58,  60,  55,
105   14,  13,  16,  24,  40,  57,  69,  56,
106   14,  17,  22,  29,  51,  87,  80,  62,
107   18,  22,  37,  56,  68, 109, 103,  77,
108   24,  35,  55,  64,  81, 104, 113,  92,
109   49,  64,  78,  87, 103, 121, 120, 101,
110   72,  92,  95,  98, 112, 100, 103,  99
111 };
112 /* *INDENT-ON* */
113
114 /* Table K.2 - Chrominance quantization table */
115 /* *INDENT-OFF* */
116 static const guint8 default_chrominance_quant_table[64] = {
117   17,  18,  24,  47,  99,  99,  99,  99,
118   18,  21,  26,  66,  99,  99,  99,  99,
119   24,  26,  56,  99,  99,  99,  99,  99,
120   47,  66,  99,  99,  99,  99,  99,  99,
121   99,  99,  99,  99,  99,  99,  99,  99,
122   99,  99,  99,  99,  99,  99,  99,  99,
123   99,  99,  99,  99,  99,  99,  99,  99,
124   99,  99,  99,  99,  99,  99,  99,  99
125 };
126 /* *INDENT-ON* */
127
128 typedef struct _GstJpegHuffmanTableEntry GstJpegHuffmanTableEntry;
129 struct _GstJpegHuffmanTableEntry
130 {
131   guint8 value;                 /* category */
132   guint8 length;                /* code length in bits */
133 };
134
135 /* Table K.3 - Table for luminance DC coefficient differences */
136 static const GstJpegHuffmanTableEntry default_luminance_dc_table[] = {
137   {0x00, 2}, {0x01, 3}, {0x02, 3}, {0x03, 3}, {0x04, 3}, {0x05, 3},
138   {0x06, 4}, {0x07, 5}, {0x08, 6}, {0x09, 7}, {0x0a, 8}, {0x0b, 9}
139 };
140
141 /* Table K.4 - Table for chrominance DC coefficient differences */
142 static const GstJpegHuffmanTableEntry default_chrominance_dc_table[] = {
143   {0x00, 2}, {0x01, 2}, {0x02, 2}, {0x03, 3}, {0x04, 4}, {0x05, 5},
144   {0x06, 6}, {0x07, 7}, {0x08, 8}, {0x09, 9}, {0x0a, 10}, {0x0b, 11}
145 };
146
147 /* Table K.5 - Table for luminance AC coefficients */
148 /* *INDENT-OFF* */
149 static const GstJpegHuffmanTableEntry default_luminance_ac_table[] = {
150   {0x00,  4}, {0x01,  2}, {0x02,  2}, {0x03,  3}, {0x04,  4}, {0x05,  5},
151   {0x06,  7}, {0x07,  8}, {0x08, 10}, {0x09, 16}, {0x0a, 16}, {0x11,  4},
152   {0x12,  5}, {0x13,  7}, {0x14,  9}, {0x15, 11}, {0x16, 16}, {0x17, 16},
153   {0x18, 16}, {0x19, 16}, {0x1a, 16}, {0x21,  5}, {0x22,  8}, {0x23, 10},
154   {0x24, 12}, {0x25, 16}, {0x26, 16}, {0x27, 16}, {0x28, 16}, {0x29, 16},
155   {0x2a, 16}, {0x31,  6}, {0x32,  9}, {0x33, 12}, {0x34, 16}, {0x35, 16},
156   {0x36, 16}, {0x37, 16}, {0x38, 16}, {0x39, 16}, {0x3a, 16}, {0x41,  6},
157   {0x42, 10}, {0x43, 16}, {0x44, 16}, {0x45, 16}, {0x46, 16}, {0x47, 16},
158   {0x48, 16}, {0x49, 16}, {0x4a, 16}, {0x51,  7}, {0x52, 11}, {0x53, 16},
159   {0x54, 16}, {0x55, 16}, {0x56, 16}, {0x57, 16}, {0x58, 16}, {0x59, 16},
160   {0x5a, 16}, {0x61,  7}, {0x62, 12}, {0x63, 16}, {0x64, 16}, {0x65, 16},
161   {0x66, 16}, {0x67, 16}, {0x68, 16}, {0x69, 16}, {0x6a, 16}, {0x71,  8},
162   {0x72, 12}, {0x73, 16}, {0x74, 16}, {0x75, 16}, {0x76, 16}, {0x77, 16},
163   {0x78, 16}, {0x79, 16}, {0x7a, 16}, {0x81,  9}, {0x82, 15}, {0x83, 16},
164   {0x84, 16}, {0x85, 16}, {0x86, 16}, {0x87, 16}, {0x88, 16}, {0x89, 16},
165   {0x8a, 16}, {0x91,  9}, {0x92, 16}, {0x93, 16}, {0x94, 16}, {0x95, 16},
166   {0x96, 16}, {0x97, 16}, {0x98, 16}, {0x99, 16}, {0x9a, 16}, {0xa1,  9},
167   {0xa2, 16}, {0xa3, 16}, {0xa4, 16}, {0xa5, 16}, {0xa6, 16}, {0xa7, 16},
168   {0xa8, 16}, {0xa9, 16}, {0xaa, 16}, {0xb1, 10}, {0xb2, 16}, {0xb3, 16},
169   {0xb4, 16}, {0xb5, 16}, {0xb6, 16}, {0xb7, 16}, {0xb8, 16}, {0xb9, 16},
170   {0xba, 16}, {0xc1, 10}, {0xc2, 16}, {0xc3, 16}, {0xc4, 16}, {0xc5, 16},
171   {0xc6, 16}, {0xc7, 16}, {0xc8, 16}, {0xc9, 16}, {0xca, 16}, {0xd1, 11},
172   {0xd2, 16}, {0xd3, 16}, {0xd4, 16}, {0xd5, 16}, {0xd6, 16}, {0xd7, 16},
173   {0xd8, 16}, {0xd9, 16}, {0xda, 16}, {0xe1, 16}, {0xe2, 16}, {0xe3, 16},
174   {0xe4, 16}, {0xe5, 16}, {0xe6, 16}, {0xe7, 16}, {0xe8, 16}, {0xe9, 16},
175   {0xea, 16}, {0xf0, 11}, {0xf1, 16}, {0xf2, 16}, {0xf3, 16}, {0xf4, 16},
176   {0xf5, 16}, {0xf6, 16}, {0xf7, 16}, {0xf8, 16}, {0xf9, 16}, {0xfa, 16}
177 };
178 /* *INDENT-ON* */
179
180 /* Table K.6 - Table for chrominance AC coefficients */
181 /* *INDENT-OFF* */
182 static const GstJpegHuffmanTableEntry default_chrominance_ac_table[] = {
183   {0x00,  2}, {0x01,  2}, {0x02,  3}, {0x03,  4}, {0x04,  5}, {0x05,  5},
184   {0x06,  6}, {0x07,  7}, {0x08,  9}, {0x09, 10}, {0x0a, 12}, {0x11,  4},
185   {0x12,  6}, {0x13,  8}, {0x14,  9}, {0x15, 11}, {0x16, 12}, {0x17, 16},
186   {0x18, 16}, {0x19, 16}, {0x1a, 16}, {0x21,  5}, {0x22,  8}, {0x23, 10},
187   {0x24, 12}, {0x25, 15}, {0x26, 16}, {0x27, 16}, {0x28, 16}, {0x29, 16},
188   {0x2a, 16}, {0x31,  5}, {0x32,  8}, {0x33, 10}, {0x34, 12}, {0x35, 16},
189   {0x36, 16}, {0x37, 16}, {0x38, 16}, {0x39, 16}, {0x3a, 16}, {0x41,  6},
190   {0x42,  9}, {0x43, 16}, {0x44, 16}, {0x45, 16}, {0x46, 16}, {0x47, 16},
191   {0x48, 16}, {0x49, 16}, {0x4a, 16}, {0x51,  6}, {0x52, 10}, {0x53, 16},
192   {0x54, 16}, {0x55, 16}, {0x56, 16}, {0x57, 16}, {0x58, 16}, {0x59, 16},
193   {0x5a, 16}, {0x61,  7}, {0x62, 11}, {0x63, 16}, {0x64, 16}, {0x65, 16},
194   {0x66, 16}, {0x67, 16}, {0x68, 16}, {0x69, 16}, {0x6a, 16}, {0x71,  7},
195   {0x72, 11}, {0x73, 16}, {0x74, 16}, {0x75, 16}, {0x76, 16}, {0x77, 16},
196   {0x78, 16}, {0x79, 16}, {0x7a, 16}, {0x81,  8}, {0x82, 16}, {0x83, 16},
197   {0x84, 16}, {0x85, 16}, {0x86, 16}, {0x87, 16}, {0x88, 16}, {0x89, 16},
198   {0x8a, 16}, {0x91,  9}, {0x92, 16}, {0x93, 16}, {0x94, 16}, {0x95, 16},
199   {0x96, 16}, {0x97, 16}, {0x98, 16}, {0x99, 16}, {0x9a, 16}, {0xa1,  9},
200   {0xa2, 16}, {0xa3, 16}, {0xa4, 16}, {0xa5, 16}, {0xa6, 16}, {0xa7, 16},
201   {0xa8, 16}, {0xa9, 16}, {0xaa, 16}, {0xb1,  9}, {0xb2, 16}, {0xb3, 16},
202   {0xb4, 16}, {0xb5, 16}, {0xb6, 16}, {0xb7, 16}, {0xb8, 16}, {0xb9, 16},
203   {0xba, 16}, {0xc1,  9}, {0xc2, 16}, {0xc3, 16}, {0xc4, 16}, {0xc5, 16},
204   {0xc6, 16}, {0xc7, 16}, {0xc8, 16}, {0xc9, 16}, {0xca, 16}, {0xd1, 11},
205   {0xd2, 16}, {0xd3, 16}, {0xd4, 16}, {0xd5, 16}, {0xd6, 16}, {0xd7, 16},
206   {0xd8, 16}, {0xd9, 16}, {0xda, 16}, {0xe1, 14}, {0xe2, 16}, {0xe3, 16},
207   {0xe4, 16}, {0xe5, 16}, {0xe6, 16}, {0xe7, 16}, {0xe8, 16}, {0xe9, 16},
208   {0xea, 16}, {0xf0, 10}, {0xf1, 15}, {0xf2, 16}, {0xf3, 16}, {0xf4, 16},
209   {0xf5, 16}, {0xf6, 16}, {0xf7, 16}, {0xf8, 16}, {0xf9, 16}, {0xfa, 16}
210 };
211 /* *INDENT-ON* */
212
213 static inline gboolean
214 jpeg_parse_to_next_marker (GstByteReader * br, guint8 * marker)
215 {
216   gint ofs;
217
218   ofs = gst_jpeg_scan_for_marker_code (br->data, br->size, br->byte);
219   if (ofs < 0)
220     return FALSE;
221
222   if (marker)
223     *marker = br->data[ofs + 1];
224   gst_byte_reader_skip (br, ofs - br->byte + 2);
225   return TRUE;
226 }
227
228 gint
229 gst_jpeg_scan_for_marker_code (const guint8 * data, gsize size, guint offset)
230 {
231   guint i;
232
233   g_return_val_if_fail (data != NULL, -1);
234   g_return_val_if_fail (size > offset, -1);
235
236   for (i = offset; i < size - 1;) {
237     if (data[i] != 0xff)
238       i++;
239     else {
240       const guint8 v = data[i + 1];
241       if (v >= 0xc0 && v <= 0xfe)
242         return i;
243       i += 2;
244     }
245   }
246   return -1;
247 }
248
249 gboolean
250 gst_jpeg_parse_frame_hdr (GstJpegFrameHdr * frame_hdr,
251     const guint8 * data, gsize size, guint offset)
252 {
253   GstByteReader br;
254   guint16 length;
255   guint8 val;
256   guint i;
257
258   g_return_val_if_fail (frame_hdr != NULL, FALSE);
259   g_return_val_if_fail (data != NULL, FALSE);
260   g_return_val_if_fail (size > offset, FALSE);
261
262   size -= offset;
263   gst_byte_reader_init (&br, &data[offset], size);
264   g_return_val_if_fail (size >= 8, FALSE);
265
266   U_READ_UINT16 (&br, length);  /* Lf */
267   g_return_val_if_fail (size >= length, FALSE);
268
269   U_READ_UINT8 (&br, frame_hdr->sample_precision);
270   U_READ_UINT16 (&br, frame_hdr->height);
271   U_READ_UINT16 (&br, frame_hdr->width);
272   U_READ_UINT8 (&br, frame_hdr->num_components);
273   g_return_val_if_fail (frame_hdr->num_components <=
274       GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
275
276   length -= 8;
277   g_return_val_if_fail (length >= 3 * frame_hdr->num_components, FALSE);
278   for (i = 0; i < frame_hdr->num_components; i++) {
279     U_READ_UINT8 (&br, frame_hdr->components[i].identifier);
280     U_READ_UINT8 (&br, val);
281     frame_hdr->components[i].horizontal_factor = (val >> 4) & 0x0F;
282     frame_hdr->components[i].vertical_factor = (val & 0x0F);
283     U_READ_UINT8 (&br, frame_hdr->components[i].quant_table_selector);
284     g_return_val_if_fail ((frame_hdr->components[i].horizontal_factor <= 4 &&
285             frame_hdr->components[i].vertical_factor <= 4 &&
286             frame_hdr->components[i].quant_table_selector < 4), FALSE);
287     length -= 3;
288   }
289
290   g_assert (length == 0);
291   return TRUE;
292 }
293
294 gboolean
295 gst_jpeg_parse_scan_hdr (GstJpegScanHdr * scan_hdr,
296     const guint8 * data, gsize size, guint offset)
297 {
298   GstByteReader br;
299   guint16 length;
300   guint8 val;
301   guint i;
302
303   g_return_val_if_fail (scan_hdr != NULL, FALSE);
304   g_return_val_if_fail (data != NULL, FALSE);
305   g_return_val_if_fail (size > offset, FALSE);
306
307   size -= offset;
308   gst_byte_reader_init (&br, &data[offset], size);
309   g_return_val_if_fail (size >= 3, FALSE);
310
311   U_READ_UINT16 (&br, length);  /* Ls */
312   g_return_val_if_fail (size >= length, FALSE);
313
314   U_READ_UINT8 (&br, scan_hdr->num_components);
315   g_return_val_if_fail (scan_hdr->num_components <=
316       GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
317
318   length -= 3;
319   g_return_val_if_fail (length >= 2 * scan_hdr->num_components, FALSE);
320   for (i = 0; i < scan_hdr->num_components; i++) {
321     U_READ_UINT8 (&br, scan_hdr->components[i].component_selector);
322     U_READ_UINT8 (&br, val);
323     scan_hdr->components[i].dc_selector = (val >> 4) & 0x0F;
324     scan_hdr->components[i].ac_selector = val & 0x0F;
325     g_return_val_if_fail ((scan_hdr->components[i].dc_selector < 4 &&
326             scan_hdr->components[i].ac_selector < 4), FALSE);
327     length -= 2;
328   }
329
330   /* FIXME: Ss, Se, Ah, Al */
331   g_assert (length == 3);
332   return TRUE;
333 }
334
335 gboolean
336 gst_jpeg_parse_huffman_table (GstJpegHuffmanTables * huf_tables,
337     const guint8 * data, gsize size, guint offset)
338 {
339   GstByteReader br;
340   GstJpegHuffmanTable *huf_table;
341   guint16 length;
342   guint8 val, table_class, table_index;
343   guint32 value_count;
344   guint i;
345
346   g_return_val_if_fail (huf_tables != NULL, FALSE);
347   g_return_val_if_fail (data != NULL, FALSE);
348   g_return_val_if_fail (size > offset, FALSE);
349
350   size -= offset;
351   gst_byte_reader_init (&br, &data[offset], size);
352   g_return_val_if_fail (size >= 2, FALSE);
353
354   U_READ_UINT16 (&br, length);  /* Lh */
355   g_return_val_if_fail (size >= length, FALSE);
356
357   while (gst_byte_reader_get_remaining (&br)) {
358     U_READ_UINT8 (&br, val);
359     table_class = ((val >> 4) & 0x0F);
360     table_index = (val & 0x0F);
361     g_return_val_if_fail (table_index < GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
362     if (table_class == 0) {
363       huf_table = &huf_tables->dc_tables[table_index];
364     } else {
365       huf_table = &huf_tables->ac_tables[table_index];
366     }
367     READ_BYTES (&br, huf_table->huf_bits, 16);
368     value_count = 0;
369     for (i = 0; i < 16; i++)
370       value_count += huf_table->huf_bits[i];
371     READ_BYTES (&br, huf_table->huf_values, value_count);
372     huf_table->valid = TRUE;
373   }
374   return TRUE;
375
376 failed:
377   return FALSE;
378 }
379
380 gboolean
381 gst_jpeg_parse_quant_table (GstJpegQuantTables * quant_tables,
382     const guint8 * data, gsize size, guint offset)
383 {
384   GstByteReader br;
385   GstJpegQuantTable *quant_table;
386   guint16 length;
387   guint8 val, table_index;
388   guint i;
389
390   g_return_val_if_fail (quant_tables != NULL, FALSE);
391   g_return_val_if_fail (data != NULL, FALSE);
392   g_return_val_if_fail (size > offset, FALSE);
393
394   size -= offset;
395   gst_byte_reader_init (&br, &data[offset], size);
396   g_return_val_if_fail (size >= 2, FALSE);
397
398   U_READ_UINT16 (&br, length);  /* Lq */
399   g_return_val_if_fail (size >= length, FALSE);
400
401   while (gst_byte_reader_get_remaining (&br)) {
402     U_READ_UINT8 (&br, val);
403     table_index = (val & 0x0f);
404     g_return_val_if_fail (table_index < GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
405     quant_table = &quant_tables->quant_tables[table_index];
406     quant_table->quant_precision = ((val >> 4) & 0x0f);
407
408     g_return_val_if_fail (gst_byte_reader_get_remaining (&br) >=
409         GST_JPEG_MAX_QUANT_ELEMENTS * (1 + ! !quant_table->quant_precision),
410         FALSE);
411     for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
412       if (!quant_table->quant_precision) {      /* 8-bit values */
413         U_READ_UINT8 (&br, val);
414         quant_table->quant_table[i] = val;
415       } else {                  /* 16-bit values */
416         U_READ_UINT16 (&br, quant_table->quant_table[i]);
417       }
418     }
419     quant_table->valid = TRUE;
420   }
421   return TRUE;
422 }
423
424 gboolean
425 gst_jpeg_parse_restart_interval (guint * interval,
426     const guint8 * data, gsize size, guint offset)
427 {
428   GstByteReader br;
429   guint16 length, val;
430
431   g_return_val_if_fail (interval != NULL, FALSE);
432   g_return_val_if_fail (data != NULL, FALSE);
433   g_return_val_if_fail (size > offset, FALSE);
434
435   size -= offset;
436   gst_byte_reader_init (&br, &data[offset], size);
437   g_return_val_if_fail (size >= 4, FALSE);
438
439   U_READ_UINT16 (&br, length);  /* Lr */
440   g_return_val_if_fail (size >= length, FALSE);
441
442   U_READ_UINT16 (&br, val);
443   *interval = val;
444   return TRUE;
445 }
446
447 static int
448 compare_huffman_table_entry (const void *a, const void *b)
449 {
450   const GstJpegHuffmanTableEntry *const e1 = *(GstJpegHuffmanTableEntry **) a;
451   const GstJpegHuffmanTableEntry *const e2 = *(GstJpegHuffmanTableEntry **) b;
452
453   if (e1->length == e2->length)
454     return (gint) e1->value - (gint) e2->value;
455   return (gint) e1->length - (gint) e2->length;
456 }
457
458 static void
459 build_huffman_table (GstJpegHuffmanTable * huf_table,
460     const GstJpegHuffmanTableEntry * entries, guint num_entries)
461 {
462   const GstJpegHuffmanTableEntry *sorted_entries[256];
463   guint i, j, n;
464
465   g_assert (num_entries <= G_N_ELEMENTS (sorted_entries));
466
467   for (i = 0; i < num_entries; i++)
468     sorted_entries[i] = &entries[i];
469   qsort (sorted_entries, num_entries, sizeof (sorted_entries[0]),
470       compare_huffman_table_entry);
471
472   for (i = 0, j = 1, n = 0; i < num_entries; i++) {
473     const GstJpegHuffmanTableEntry *const e = sorted_entries[i];
474     if (e->length != j) {
475       huf_table->huf_bits[j++ - 1] = n;
476       for (; j < e->length; j++)
477         huf_table->huf_bits[j - 1] = 0;
478       n = 0;
479     }
480     huf_table->huf_values[i] = e->value;
481     n++;
482   }
483
484   for (; j < G_N_ELEMENTS (huf_table->huf_bits); j++)
485     huf_table->huf_bits[j] = 0;
486   for (; i < G_N_ELEMENTS (huf_table->huf_values); i++)
487     huf_table->huf_values[i] = 0;
488   huf_table->valid = TRUE;
489 }
490
491 void
492 gst_jpeg_get_default_huffman_tables (GstJpegHuffmanTables * huf_tables)
493 {
494   g_assert (huf_tables);
495
496   /* Build DC tables */
497   build_huffman_table (&huf_tables->dc_tables[0], default_luminance_dc_table,
498       G_N_ELEMENTS (default_luminance_dc_table));
499   build_huffman_table (&huf_tables->dc_tables[1], default_chrominance_dc_table,
500       G_N_ELEMENTS (default_chrominance_dc_table));
501   memcpy (&huf_tables->dc_tables[2], &huf_tables->dc_tables[1],
502       sizeof (huf_tables->dc_tables[2]));
503
504   /* Build AC tables */
505   build_huffman_table (&huf_tables->ac_tables[0], default_luminance_ac_table,
506       G_N_ELEMENTS (default_luminance_ac_table));
507   build_huffman_table (&huf_tables->ac_tables[1], default_chrominance_ac_table,
508       G_N_ELEMENTS (default_chrominance_ac_table));
509   memcpy (&huf_tables->ac_tables[2], &huf_tables->ac_tables[1],
510       sizeof (huf_tables->ac_tables[2]));
511 }
512
513 static void
514 build_quant_table (GstJpegQuantTable * quant_table, const guint8 values[64])
515 {
516   guint i;
517
518   for (i = 0; i < 64; i++)
519     quant_table->quant_table[i] = values[zigzag_index[i]];
520   quant_table->quant_precision = 0;     /* Pq = 0 (8-bit precision) */
521   quant_table->valid = TRUE;
522 }
523
524 void
525 gst_jpeg_get_default_quantization_tables (GstJpegQuantTables * quant_tables)
526 {
527   g_assert (quant_tables);
528
529   build_quant_table (&quant_tables->quant_tables[0],
530       default_luminance_quant_table);
531   build_quant_table (&quant_tables->quant_tables[1],
532       default_chrominance_quant_table);
533   build_quant_table (&quant_tables->quant_tables[2],
534       default_chrominance_quant_table);
535 }
536
537 gboolean
538 gst_jpeg_parse (GstJpegMarkerSegment * seg,
539     const guint8 * data, gsize size, guint offset)
540 {
541   GstByteReader br;
542   guint16 length;
543
544   g_return_val_if_fail (seg != NULL, FALSE);
545
546   if (size <= offset) {
547     GST_DEBUG ("failed to parse from offset %u, buffer is too small", offset);
548     return FALSE;
549   }
550
551   size -= offset;
552   gst_byte_reader_init (&br, &data[offset], size);
553
554   if (!jpeg_parse_to_next_marker (&br, &seg->marker)) {
555     GST_DEBUG ("failed to find marker code");
556     return FALSE;
557   }
558
559   seg->offset = offset + gst_byte_reader_get_pos (&br);
560   seg->size = -1;
561
562   /* Try to find end of segment */
563   switch (seg->marker) {
564     case GST_JPEG_MARKER_SOI:
565     case GST_JPEG_MARKER_EOI:
566     fixed_size_segment:
567       seg->size = 2;
568       break;
569
570     case (GST_JPEG_MARKER_SOF_MIN + 0):        /* Lf */
571     case (GST_JPEG_MARKER_SOF_MIN + 1):        /* Lf */
572     case (GST_JPEG_MARKER_SOF_MIN + 2):        /* Lf */
573     case (GST_JPEG_MARKER_SOF_MIN + 3):        /* Lf */
574     case (GST_JPEG_MARKER_SOF_MIN + 9):        /* Lf */
575     case (GST_JPEG_MARKER_SOF_MIN + 10):       /* Lf */
576     case (GST_JPEG_MARKER_SOF_MIN + 11):       /* Lf */
577     case GST_JPEG_MARKER_SOS:  /* Ls */
578     case GST_JPEG_MARKER_DQT:  /* Lq */
579     case GST_JPEG_MARKER_DHT:  /* Lh */
580     case GST_JPEG_MARKER_DAC:  /* La */
581     case GST_JPEG_MARKER_DRI:  /* Lr */
582     case GST_JPEG_MARKER_COM:  /* Lc */
583     case GST_JPEG_MARKER_DNL:  /* Ld */
584     variable_size_segment:
585       READ_UINT16 (&br, length);
586       seg->size = length;
587       break;
588
589     default:
590       /* Application data segment length (Lp) */
591       if (seg->marker >= GST_JPEG_MARKER_APP_MIN &&
592           seg->marker <= GST_JPEG_MARKER_APP_MAX)
593         goto variable_size_segment;
594
595       /* Restart markers (fixed size, two bytes only) */
596       if (seg->marker >= GST_JPEG_MARKER_RST_MIN &&
597           seg->marker <= GST_JPEG_MARKER_RST_MAX)
598         goto fixed_size_segment;
599
600       /* Fallback: scan for next marker */
601       if (!jpeg_parse_to_next_marker (&br, NULL))
602         goto failed;
603       seg->size = gst_byte_reader_get_pos (&br) - seg->offset;
604       break;
605   }
606   return TRUE;
607
608 failed:
609   return FALSE;
610 }