jpegdec: Use base class error handling function instead of replicating it here
[platform/upstream/gst-plugins-good.git] / ext / jpeg / gstjpegdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2012 Collabora Ltd.
5  *      Author : Edward Hervey <edward@collabora.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:element-jpegdec
25  *
26  * Decodes jpeg images.
27  *
28  * <refsect2>
29  * <title>Example launch line</title>
30  * |[
31  * gst-launch-1.0 -v filesrc location=mjpeg.avi ! avidemux !  queue ! jpegdec ! videoconvert ! videoscale ! autovideosink
32  * ]| The above pipeline decode the mjpeg stream and renders it to the screen.
33  * </refsect2>
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 #include <string.h>
40
41 #include "gstjpegdec.h"
42 #include "gstjpeg.h"
43 #include <gst/video/video.h>
44 #include <gst/video/gstvideometa.h>
45 #include <gst/video/gstvideopool.h>
46 #include "gst/gst-i18n-plugin.h"
47 #include <jerror.h>
48
49 #define MIN_WIDTH  1
50 #define MAX_WIDTH  65535
51 #define MIN_HEIGHT 1
52 #define MAX_HEIGHT 65535
53
54 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
55         (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
56
57 #define JPEG_DEFAULT_IDCT_METHOD        JDCT_FASTEST
58 #define JPEG_DEFAULT_MAX_ERRORS         0
59
60 enum
61 {
62   PROP_0,
63   PROP_IDCT_METHOD,
64   PROP_MAX_ERRORS
65 };
66
67 /* *INDENT-OFF* */
68 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
69 GST_STATIC_PAD_TEMPLATE ("src",
70     GST_PAD_SRC,
71     GST_PAD_ALWAYS,
72     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
73         ("{ I420, RGB, BGR, RGBx, xRGB, BGRx, xBGR, GRAY8 }"))
74     );
75 /* *INDENT-ON* */
76
77 /* FIXME: sof-marker is for IJG libjpeg 8, should be different for 6.2 */
78 /* FIXME: add back "sof-marker = (int) { 0, 1, 2, 5, 6, 7, 9, 10, 13, 14 }"
79  * once we have a parser and/or demuxer set caps properly */
80 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
81 GST_STATIC_PAD_TEMPLATE ("sink",
82     GST_PAD_SINK,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS ("image/jpeg, "
85         "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
86         " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
87         G_STRINGIFY (MAX_HEIGHT) " ] ")
88     );
89
90 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
91 #define GST_CAT_DEFAULT jpeg_dec_debug
92 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
93
94 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
95     const GValue * value, GParamSpec * pspec);
96 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
97     GValue * value, GParamSpec * pspec);
98
99 static gboolean gst_jpeg_dec_set_format (GstVideoDecoder * dec,
100     GstVideoCodecState * state);
101 static gboolean gst_jpeg_dec_stop (GstVideoDecoder * bdec);
102 static gboolean gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard);
103 static GstFlowReturn gst_jpeg_dec_parse (GstVideoDecoder * bdec,
104     GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
105 static GstFlowReturn gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec,
106     GstVideoCodecFrame * frame);
107 static gboolean gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec,
108     GstQuery * query);
109
110 #define gst_jpeg_dec_parent_class parent_class
111 G_DEFINE_TYPE (GstJpegDec, gst_jpeg_dec, GST_TYPE_VIDEO_DECODER);
112
113 static void
114 gst_jpeg_dec_finalize (GObject * object)
115 {
116   GstJpegDec *dec = GST_JPEG_DEC (object);
117
118   jpeg_destroy_decompress (&dec->cinfo);
119   if (dec->input_state)
120     gst_video_codec_state_unref (dec->input_state);
121
122   G_OBJECT_CLASS (parent_class)->finalize (object);
123 }
124
125 static void
126 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
127 {
128   GObjectClass *gobject_class;
129   GstElementClass *element_class;
130   GstVideoDecoderClass *vdec_class;
131
132   gobject_class = (GObjectClass *) klass;
133   element_class = (GstElementClass *) klass;
134   vdec_class = (GstVideoDecoderClass *) klass;
135
136   parent_class = g_type_class_peek_parent (klass);
137
138   gobject_class->finalize = gst_jpeg_dec_finalize;
139   gobject_class->set_property = gst_jpeg_dec_set_property;
140   gobject_class->get_property = gst_jpeg_dec_get_property;
141
142   g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
143       g_param_spec_enum ("idct-method", "IDCT Method",
144           "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
145           JPEG_DEFAULT_IDCT_METHOD,
146           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
147
148   /**
149    * GstJpegDec:max-errors
150    *
151    * Error out after receiving N consecutive decoding errors
152    * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
153    *
154    * Since: 0.10.27
155    **/
156   g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
157       g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
158           "Error out after receiving N consecutive decoding errors "
159           "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
160           -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
161           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162
163   gst_element_class_add_pad_template (element_class,
164       gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
165   gst_element_class_add_pad_template (element_class,
166       gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
167   gst_element_class_set_static_metadata (element_class, "JPEG image decoder",
168       "Codec/Decoder/Image",
169       "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
170
171   vdec_class->stop = gst_jpeg_dec_stop;
172   vdec_class->reset = gst_jpeg_dec_reset;
173   vdec_class->parse = gst_jpeg_dec_parse;
174   vdec_class->set_format = gst_jpeg_dec_set_format;
175   vdec_class->handle_frame = gst_jpeg_dec_handle_frame;
176   vdec_class->decide_allocation = gst_jpeg_dec_decide_allocation;
177
178   GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
179   GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
180 }
181
182 static boolean
183 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
184 {
185   GstJpegDec *dec;
186
187   dec = CINFO_GET_JPEGDEC (cinfo);
188   g_return_val_if_fail (dec != NULL, FALSE);
189   g_return_val_if_fail (dec->current_frame != NULL, FALSE);
190   g_return_val_if_fail (dec->current_frame_map.data != NULL, FALSE);
191
192   cinfo->src->next_input_byte = dec->current_frame_map.data;
193   cinfo->src->bytes_in_buffer = dec->current_frame_map.size;
194
195   return TRUE;
196 }
197
198 static void
199 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
200 {
201   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
202 }
203
204
205 static void
206 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
207 {
208   GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
209
210   GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
211
212   if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
213     cinfo->src->next_input_byte += (size_t) num_bytes;
214     cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
215   }
216 }
217
218 static boolean
219 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
220 {
221   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
222   return TRUE;
223 }
224
225 static void
226 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
227 {
228   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
229   return;
230 }
231
232 METHODDEF (void)
233     gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
234 {
235   return;                       /* do nothing */
236 }
237
238 METHODDEF (void)
239     gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
240 {
241   /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
242   return;
243 }
244
245 METHODDEF (void)
246     gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
247 {
248   struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
249
250   (*cinfo->err->output_message) (cinfo);
251   longjmp (err_mgr->setjmp_buffer, 1);
252 }
253
254 static void
255 gst_jpeg_dec_init (GstJpegDec * dec)
256 {
257   GST_DEBUG ("initializing");
258
259   /* setup jpeglib */
260   memset (&dec->cinfo, 0, sizeof (dec->cinfo));
261   memset (&dec->jerr, 0, sizeof (dec->jerr));
262   dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
263   dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
264   dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
265   dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
266
267   jpeg_create_decompress (&dec->cinfo);
268
269   dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
270   dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
271   dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
272   dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
273   dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
274   dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
275   dec->jsrc.dec = dec;
276
277   /* init properties */
278   dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
279   dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
280 }
281
282 static inline gboolean
283 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
284 {
285   if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
286     return TRUE;
287   return FALSE;
288 }
289
290 static GstFlowReturn
291 gst_jpeg_dec_parse (GstVideoDecoder * bdec, GstVideoCodecFrame * frame,
292     GstAdapter * adapter, gboolean at_eos)
293 {
294   guint size;
295   gint toadd = 0;
296   gboolean resync;
297   gint offset = 0, noffset;
298   GstJpegDec *dec = (GstJpegDec *) bdec;
299
300   /* FIXME : The overhead of using scan_uint32 is massive */
301
302   size = gst_adapter_available (adapter);
303   GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
304
305   if (at_eos) {
306     GST_DEBUG ("Flushing all data out");
307     toadd = size;
308
309     /* If we have leftover data, throw it away */
310     if (!dec->saw_header)
311       goto drop_frame;
312     goto have_full_frame;
313   }
314
315   if (size < 8)
316     goto need_more_data;
317
318   if (!dec->saw_header) {
319     gint ret;
320     /* we expect at least 4 bytes, first of which start marker */
321     ret =
322         gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0,
323         size - 4);
324
325     GST_DEBUG ("ret:%d", ret);
326     if (ret < 0)
327       goto need_more_data;
328
329     if (ret) {
330       gst_adapter_flush (adapter, ret);
331       size -= ret;
332     }
333     dec->saw_header = TRUE;
334   }
335
336   while (1) {
337     guint frame_len;
338     guint32 value;
339
340     GST_DEBUG ("offset:%d, size:%d", offset, size);
341
342     noffset =
343         gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
344         offset, size - offset, &value);
345
346     /* lost sync if 0xff marker not where expected */
347     if ((resync = (noffset != offset))) {
348       GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
349     }
350     /* may have marker, but could have been resyncng */
351     resync = resync || dec->parse_resync;
352     /* Skip over extra 0xff */
353     while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
354       noffset++;
355       noffset =
356           gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
357           noffset, size - noffset, &value);
358     }
359     /* enough bytes left for marker? (we need 0xNN after the 0xff) */
360     if (noffset < 0) {
361       GST_DEBUG ("at end of input and no EOI marker found, need more data");
362       goto need_more_data;
363     }
364
365     /* now lock on the marker we found */
366     offset = noffset;
367     value = value & 0xff;
368     if (value == 0xd9) {
369       GST_DEBUG ("0x%08x: EOI marker", offset + 2);
370       /* clear parse state */
371       dec->saw_header = FALSE;
372       dec->parse_resync = FALSE;
373       toadd = offset + 4;
374       goto have_full_frame;
375     }
376     if (value == 0xd8) {
377       /* Skip this frame if we found another SOI marker */
378       GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
379       dec->parse_resync = FALSE;
380       /* FIXME : Need to skip data */
381       toadd -= offset + 2;
382       goto have_full_frame;
383     }
384
385
386     if (value >= 0xd0 && value <= 0xd7)
387       frame_len = 0;
388     else {
389       /* peek tag and subsequent length */
390       if (offset + 2 + 4 > size)
391         goto need_more_data;
392       else
393         gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
394             &frame_len);
395       frame_len = frame_len & 0xffff;
396     }
397     GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
398     /* the frame length includes the 2 bytes for the length; here we want at
399      * least 2 more bytes at the end for an end marker */
400     if (offset + 2 + 2 + frame_len + 2 > size) {
401       goto need_more_data;
402     }
403
404     if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
405       guint eseglen = dec->parse_entropy_len;
406
407       GST_DEBUG ("0x%08x: finding entropy segment length (eseglen:%d)",
408           offset + 2, eseglen);
409       if (size < offset + 2 + frame_len + eseglen)
410         goto need_more_data;
411       noffset = offset + 2 + frame_len + dec->parse_entropy_len;
412       while (1) {
413         GST_DEBUG ("noffset:%d, size:%d, size - noffset:%d",
414             noffset, size, size - noffset);
415         noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
416             0x0000ff00, noffset, size - noffset, &value);
417         if (noffset < 0) {
418           /* need more data */
419           dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
420           goto need_more_data;
421         }
422         if ((value & 0xff) != 0x00) {
423           eseglen = noffset - offset - frame_len - 2;
424           break;
425         }
426         noffset++;
427       }
428       dec->parse_entropy_len = 0;
429       frame_len += eseglen;
430       GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
431           frame_len);
432     }
433     if (resync) {
434       /* check if we will still be in sync if we interpret
435        * this as a sync point and skip this frame */
436       noffset = offset + frame_len + 2;
437       noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
438           noffset, 4);
439       if (noffset < 0) {
440         /* ignore and continue resyncing until we hit the end
441          * of our data or find a sync point that looks okay */
442         offset++;
443         continue;
444       }
445       GST_DEBUG ("found sync at 0x%x", offset + 2);
446     }
447
448     /* Add current data to output buffer */
449     toadd += frame_len + 2;
450     offset += frame_len + 2;
451   }
452
453 need_more_data:
454   if (toadd)
455     gst_video_decoder_add_to_frame (bdec, toadd);
456   return GST_VIDEO_DECODER_FLOW_NEED_DATA;
457
458 have_full_frame:
459   if (toadd)
460     gst_video_decoder_add_to_frame (bdec, toadd);
461   return gst_video_decoder_have_frame (bdec);
462
463 drop_frame:
464   gst_adapter_flush (adapter, size);
465   return GST_FLOW_OK;
466 }
467
468
469 /* shamelessly ripped from jpegutils.c in mjpegtools */
470 static void
471 add_huff_table (j_decompress_ptr dinfo,
472     JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
473 /* Define a Huffman table */
474 {
475   int nsymbols, len;
476
477   if (*htblptr == NULL)
478     *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
479
480   g_assert (*htblptr);
481
482   /* Copy the number-of-symbols-of-each-code-length counts */
483   memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
484
485   /* Validate the counts.  We do this here mainly so we can copy the right
486    * number of symbols from the val[] array, without risking marching off
487    * the end of memory.  jchuff.c will do a more thorough test later.
488    */
489   nsymbols = 0;
490   for (len = 1; len <= 16; len++)
491     nsymbols += bits[len];
492   if (nsymbols < 1 || nsymbols > 256)
493     g_error ("jpegutils.c:  add_huff_table failed badly. ");
494
495   memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
496 }
497
498
499
500 static void
501 std_huff_tables (j_decompress_ptr dinfo)
502 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
503 /* IMPORTANT: these are only valid for 8-bit data precision! */
504 {
505   static const UINT8 bits_dc_luminance[17] =
506       { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
507   static const UINT8 val_dc_luminance[] =
508       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
509
510   static const UINT8 bits_dc_chrominance[17] =
511       { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
512   static const UINT8 val_dc_chrominance[] =
513       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
514
515   static const UINT8 bits_ac_luminance[17] =
516       { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
517   static const UINT8 val_ac_luminance[] =
518       { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
519     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
520     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
521     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
522     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
523     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
524     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
525     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
526     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
527     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
528     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
529     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
530     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
531     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
532     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
533     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
534     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
535     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
536     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
537     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
538     0xf9, 0xfa
539   };
540
541   static const UINT8 bits_ac_chrominance[17] =
542       { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
543   static const UINT8 val_ac_chrominance[] =
544       { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
545     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
546     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
547     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
548     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
549     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
550     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
551     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
552     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
553     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
554     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
555     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
556     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
557     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
558     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
559     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
560     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
561     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
562     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
563     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
564     0xf9, 0xfa
565   };
566
567   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
568       bits_dc_luminance, val_dc_luminance);
569   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
570       bits_ac_luminance, val_ac_luminance);
571   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
572       bits_dc_chrominance, val_dc_chrominance);
573   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
574       bits_ac_chrominance, val_ac_chrominance);
575 }
576
577
578
579 static void
580 guarantee_huff_tables (j_decompress_ptr dinfo)
581 {
582   if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
583       (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
584       (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
585       (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
586     GST_DEBUG ("Generating standard Huffman tables for this frame.");
587     std_huff_tables (dinfo);
588   }
589 }
590
591 static gboolean
592 gst_jpeg_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
593 {
594   GstJpegDec *jpeg = GST_JPEG_DEC (dec);
595   GstVideoInfo *info = &state->info;
596
597   /* FIXME : previously jpegdec would handled input as packetized
598    * if the framerate was present. Here we consider it packetized if
599    * the fps is != 1/1 */
600   if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1)
601     gst_video_decoder_set_packetized (dec, TRUE);
602   else
603     gst_video_decoder_set_packetized (dec, FALSE);
604
605   if (jpeg->input_state)
606     gst_video_codec_state_unref (jpeg->input_state);
607   jpeg->input_state = gst_video_codec_state_ref (state);
608
609   return TRUE;
610 }
611
612
613 /* yuk */
614 static void
615 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
616 {
617   gint i;
618
619   for (i = 0; i < len; ++i) {
620     /* equivalent to: dest[i] = src[i << 1] */
621     *dest = *src;
622     ++dest;
623     ++src;
624     ++src;
625   }
626 }
627
628 static void
629 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
630 {
631   gint i;
632
633   for (i = 0; i < 16; i++) {
634     g_free (dec->idr_y[i]);
635     g_free (dec->idr_u[i]);
636     g_free (dec->idr_v[i]);
637     dec->idr_y[i] = NULL;
638     dec->idr_u[i] = NULL;
639     dec->idr_v[i] = NULL;
640   }
641
642   dec->idr_width_allocated = 0;
643 }
644
645 static inline gboolean
646 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
647 {
648   gint i;
649
650   if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
651     return TRUE;
652
653   /* FIXME: maybe just alloc one or three blocks altogether? */
654   for (i = 0; i < 16; i++) {
655     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
656     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
657     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
658
659     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
660       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
661       return FALSE;
662     }
663   }
664
665   dec->idr_width_allocated = maxrowbytes;
666   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
667   return TRUE;
668 }
669
670 static void
671 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, GstVideoFrame * frame)
672 {
673   guchar *rows[16];
674   guchar **scanarray[1] = { rows };
675   gint i, j, k;
676   gint lines;
677   guint8 *base[1];
678   gint width, height;
679   gint pstride, rstride;
680
681   GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
682
683   width = GST_VIDEO_FRAME_WIDTH (frame);
684   height = GST_VIDEO_FRAME_HEIGHT (frame);
685
686   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
687     return;
688
689   base[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
690   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
691   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
692
693   memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
694
695   i = 0;
696   while (i < height) {
697     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
698     if (G_LIKELY (lines > 0)) {
699       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
700         gint p;
701
702         p = 0;
703         for (k = 0; k < width; k++) {
704           base[0][p] = rows[j][k];
705           p += pstride;
706         }
707         base[0] += rstride;
708       }
709     } else {
710       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
711     }
712   }
713 }
714
715 static void
716 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, GstVideoFrame * frame)
717 {
718   guchar *r_rows[16], *g_rows[16], *b_rows[16];
719   guchar **scanarray[3] = { r_rows, g_rows, b_rows };
720   gint i, j, k;
721   gint lines;
722   guint8 *base[3];
723   guint pstride, rstride;
724   gint width, height;
725
726   GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
727
728   width = GST_VIDEO_FRAME_WIDTH (frame);
729   height = GST_VIDEO_FRAME_HEIGHT (frame);
730
731   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
732     return;
733
734   for (i = 0; i < 3; i++)
735     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
736
737   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
738   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
739
740   memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
741   memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
742   memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
743
744   i = 0;
745   while (i < height) {
746     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
747     if (G_LIKELY (lines > 0)) {
748       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
749         gint p;
750
751         p = 0;
752         for (k = 0; k < width; k++) {
753           base[0][p] = r_rows[j][k];
754           base[1][p] = g_rows[j][k];
755           base[2][p] = b_rows[j][k];
756           p += pstride;
757         }
758         base[0] += rstride;
759         base[1] += rstride;
760         base[2] += rstride;
761       }
762     } else {
763       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
764     }
765   }
766 }
767
768 static void
769 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame, gint r_v,
770     gint r_h, gint comp)
771 {
772   guchar *y_rows[16], *u_rows[16], *v_rows[16];
773   guchar **scanarray[3] = { y_rows, u_rows, v_rows };
774   gint i, j, k;
775   gint lines;
776   guchar *base[3], *last[3];
777   gint stride[3];
778   gint width, height;
779
780   GST_DEBUG_OBJECT (dec,
781       "unadvantageous width or r_h, taking slow route involving memcpy");
782
783   width = GST_VIDEO_FRAME_WIDTH (frame);
784   height = GST_VIDEO_FRAME_HEIGHT (frame);
785
786   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
787     return;
788
789   for (i = 0; i < 3; i++) {
790     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
791     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
792     /* make sure we don't make jpeglib write beyond our buffer,
793      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
794     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
795         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
796   }
797
798   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
799   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
800   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
801
802   /* fill chroma components for grayscale */
803   if (comp == 1) {
804     GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
805     for (i = 0; i < 16; i++) {
806       memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
807       memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
808     }
809   }
810
811   for (i = 0; i < height; i += r_v * DCTSIZE) {
812     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
813     if (G_LIKELY (lines > 0)) {
814       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
815         if (G_LIKELY (base[0] <= last[0])) {
816           memcpy (base[0], y_rows[j], stride[0]);
817           base[0] += stride[0];
818         }
819         if (r_v == 2) {
820           if (G_LIKELY (base[0] <= last[0])) {
821             memcpy (base[0], y_rows[j + 1], stride[0]);
822             base[0] += stride[0];
823           }
824         }
825         if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
826           if (r_h == 2) {
827             memcpy (base[1], u_rows[k], stride[1]);
828             memcpy (base[2], v_rows[k], stride[2]);
829           } else if (r_h == 1) {
830             hresamplecpy1 (base[1], u_rows[k], stride[1]);
831             hresamplecpy1 (base[2], v_rows[k], stride[2]);
832           } else {
833             /* FIXME: implement (at least we avoid crashing by doing nothing) */
834           }
835         }
836
837         if (r_v == 2 || (k & 1) != 0) {
838           base[1] += stride[1];
839           base[2] += stride[2];
840         }
841       }
842     } else {
843       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
844     }
845   }
846 }
847
848 static GstFlowReturn
849 gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame)
850 {
851   guchar **line[3];             /* the jpeg line buffer         */
852   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
853   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
854   guchar *v[4 * DCTSIZE] = { NULL, };
855   gint i, j;
856   gint lines, v_samp[3];
857   guchar *base[3], *last[3];
858   gint stride[3];
859   guint height;
860
861   line[0] = y;
862   line[1] = u;
863   line[2] = v;
864
865   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
866   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
867   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
868
869   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
870     goto format_not_supported;
871
872   height = GST_VIDEO_FRAME_HEIGHT (frame);
873
874   for (i = 0; i < 3; i++) {
875     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
876     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
877     /* make sure we don't make jpeglib write beyond our buffer,
878      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
879     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
880         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
881   }
882
883   /* let jpeglib decode directly into our final buffer */
884   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
885
886   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
887     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
888       /* Y */
889       line[0][j] = base[0] + (i + j) * stride[0];
890       if (G_UNLIKELY (line[0][j] > last[0]))
891         line[0][j] = last[0];
892       /* U */
893       if (v_samp[1] == v_samp[0]) {
894         line[1][j] = base[1] + ((i + j) / 2) * stride[1];
895       } else if (j < (v_samp[1] * DCTSIZE)) {
896         line[1][j] = base[1] + ((i / 2) + j) * stride[1];
897       }
898       if (G_UNLIKELY (line[1][j] > last[1]))
899         line[1][j] = last[1];
900       /* V */
901       if (v_samp[2] == v_samp[0]) {
902         line[2][j] = base[2] + ((i + j) / 2) * stride[2];
903       } else if (j < (v_samp[2] * DCTSIZE)) {
904         line[2][j] = base[2] + ((i / 2) + j) * stride[2];
905       }
906       if (G_UNLIKELY (line[2][j] > last[2]))
907         line[2][j] = last[2];
908     }
909
910     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
911     if (G_UNLIKELY (!lines)) {
912       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
913     }
914   }
915   return GST_FLOW_OK;
916
917 format_not_supported:
918   {
919     gboolean ret = GST_FLOW_OK;
920
921     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
922         (_("Failed to decode JPEG image")),
923         ("Unsupported subsampling schema: v_samp factors: %u %u %u", v_samp[0],
924             v_samp[1], v_samp[2]), ret);
925
926     return ret;
927   }
928 }
929
930 static void
931 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
932 {
933   GstVideoCodecState *outstate;
934   GstVideoInfo *info;
935   GstVideoFormat format;
936
937   switch (clrspc) {
938     case JCS_RGB:
939       format = GST_VIDEO_FORMAT_RGB;
940       break;
941     case JCS_GRAYSCALE:
942       format = GST_VIDEO_FORMAT_GRAY8;
943       break;
944     default:
945       format = GST_VIDEO_FORMAT_I420;
946       break;
947   }
948
949   /* Compare to currently configured output state */
950   outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
951   if (outstate) {
952     info = &outstate->info;
953
954     if (width == GST_VIDEO_INFO_WIDTH (info) &&
955         height == GST_VIDEO_INFO_HEIGHT (info) &&
956         format == GST_VIDEO_INFO_FORMAT (info)) {
957       gst_video_codec_state_unref (outstate);
958       return;
959     }
960     gst_video_codec_state_unref (outstate);
961   }
962
963   outstate =
964       gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format,
965       width, height, dec->input_state);
966
967   switch (clrspc) {
968     case JCS_RGB:
969     case JCS_GRAYSCALE:
970       break;
971     default:
972       outstate->info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
973       outstate->info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
974       outstate->info.colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
975       outstate->info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
976       break;
977   }
978
979   gst_video_codec_state_unref (outstate);
980
981   gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec));
982
983   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
984   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
985 }
986
987 static GstFlowReturn
988 gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
989 {
990   GstFlowReturn ret = GST_FLOW_OK;
991   GstJpegDec *dec = (GstJpegDec *) bdec;
992   GstVideoFrame vframe;
993   gint width, height;
994   gint r_h, r_v;
995   guint code, hdr_ok;
996   gboolean need_unmap = TRUE;
997   GstVideoCodecState *state = NULL;
998
999   dec->current_frame = frame;
1000   gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
1001   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1002
1003   if (setjmp (dec->jerr.setjmp_buffer)) {
1004     code = dec->jerr.pub.msg_code;
1005
1006     if (code == JERR_INPUT_EOF) {
1007       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1008       goto need_more_data;
1009     }
1010     goto decode_error;
1011   }
1012
1013   /* read header */
1014   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1015   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1016     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1017   }
1018
1019   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1020   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1021
1022   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1023     goto components_not_supported;
1024
1025   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1026   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1027
1028   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1029
1030   if (dec->cinfo.num_components > 3)
1031     goto components_not_supported;
1032
1033   /* verify color space expectation to avoid going *boom* or bogus output */
1034   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1035       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1036       dec->cinfo.jpeg_color_space != JCS_RGB)
1037     goto unsupported_colorspace;
1038
1039 #ifndef GST_DISABLE_GST_DEBUG
1040   {
1041     gint i;
1042
1043     for (i = 0; i < dec->cinfo.num_components; ++i) {
1044       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1045           i, dec->cinfo.comp_info[i].h_samp_factor,
1046           dec->cinfo.comp_info[i].v_samp_factor,
1047           dec->cinfo.comp_info[i].component_id);
1048     }
1049   }
1050 #endif
1051
1052   /* prepare for raw output */
1053   dec->cinfo.do_fancy_upsampling = FALSE;
1054   dec->cinfo.do_block_smoothing = FALSE;
1055   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1056   dec->cinfo.dct_method = dec->idct_method;
1057   dec->cinfo.raw_data_out = TRUE;
1058
1059   GST_LOG_OBJECT (dec, "starting decompress");
1060   guarantee_huff_tables (&dec->cinfo);
1061   if (!jpeg_start_decompress (&dec->cinfo)) {
1062     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1063   }
1064
1065   /* sanity checks to get safe and reasonable output */
1066   switch (dec->cinfo.jpeg_color_space) {
1067     case JCS_GRAYSCALE:
1068       if (dec->cinfo.num_components != 1)
1069         goto invalid_yuvrgbgrayscale;
1070       break;
1071     case JCS_RGB:
1072       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1073           dec->cinfo.max_h_samp_factor > 1)
1074         goto invalid_yuvrgbgrayscale;
1075       break;
1076     case JCS_YCbCr:
1077       if (dec->cinfo.num_components != 3 ||
1078           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1079           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1080           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1081           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1082         goto invalid_yuvrgbgrayscale;
1083       break;
1084     default:
1085       g_assert_not_reached ();
1086       break;
1087   }
1088
1089   width = dec->cinfo.output_width;
1090   height = dec->cinfo.output_height;
1091
1092   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1093           height < MIN_HEIGHT || height > MAX_HEIGHT))
1094     goto wrong_size;
1095
1096   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1097
1098   state = gst_video_decoder_get_output_state (bdec);
1099   ret = gst_video_decoder_allocate_output_frame (bdec, frame);
1100   if (G_UNLIKELY (ret != GST_FLOW_OK))
1101     goto alloc_failed;
1102
1103   if (!gst_video_frame_map (&vframe, &state->info, frame->output_buffer,
1104           GST_MAP_READWRITE))
1105     goto alloc_failed;
1106
1107   GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1108
1109   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1110     gst_jpeg_dec_decode_rgb (dec, &vframe);
1111   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1112     gst_jpeg_dec_decode_grayscale (dec, &vframe);
1113   } else {
1114     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1115         dec->cinfo.rec_outbuf_height);
1116
1117     /* For some widths jpeglib requires more horizontal padding than I420 
1118      * provides. In those cases we need to decode into separate buffers and then
1119      * copy over the data into our final picture buffer, otherwise jpeglib might
1120      * write over the end of a line into the beginning of the next line,
1121      * resulting in blocky artifacts on the left side of the picture. */
1122     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1123             || dec->cinfo.comp_info[0].h_samp_factor != 2
1124             || dec->cinfo.comp_info[1].h_samp_factor != 1
1125             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1126       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1127           "indirect decoding using extra buffer copy");
1128       gst_jpeg_dec_decode_indirect (dec, &vframe, r_v, r_h,
1129           dec->cinfo.num_components);
1130     } else {
1131       ret = gst_jpeg_dec_decode_direct (dec, &vframe);
1132
1133       if (G_UNLIKELY (ret != GST_FLOW_OK))
1134         goto decode_direct_failed;
1135     }
1136   }
1137
1138   gst_video_frame_unmap (&vframe);
1139
1140   GST_LOG_OBJECT (dec, "decompressing finished");
1141   jpeg_finish_decompress (&dec->cinfo);
1142
1143   gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1144   ret = gst_video_decoder_finish_frame (bdec, frame);
1145   need_unmap = FALSE;
1146
1147 done:
1148
1149 exit:
1150
1151   if (need_unmap)
1152     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1153
1154   if (state)
1155     gst_video_codec_state_unref (state);
1156
1157   return ret;
1158
1159   /* special cases */
1160 need_more_data:
1161   {
1162     GST_LOG_OBJECT (dec, "we need more data");
1163     ret = GST_FLOW_OK;
1164     goto exit;
1165   }
1166   /* ERRORS */
1167 wrong_size:
1168   {
1169     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1170         (_("Failed to decode JPEG image")),
1171         ("Picture is too small or too big (%ux%u)", width, height), ret);
1172     ret = GST_FLOW_ERROR;
1173     goto done;
1174   }
1175 decode_error:
1176   {
1177     gchar err_msg[JMSG_LENGTH_MAX];
1178
1179     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1180
1181     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1182         (_("Failed to decode JPEG image")), ("Decode error #%u: %s", code,
1183             err_msg), ret);
1184
1185     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1186     gst_video_decoder_drop_frame (bdec, frame);
1187     need_unmap = FALSE;
1188     jpeg_abort_decompress (&dec->cinfo);
1189
1190     ret = GST_FLOW_ERROR;
1191     goto done;
1192   }
1193 decode_direct_failed:
1194   {
1195     /* already posted an error message */
1196     jpeg_abort_decompress (&dec->cinfo);
1197     goto done;
1198   }
1199 alloc_failed:
1200   {
1201     const gchar *reason;
1202
1203     reason = gst_flow_get_name (ret);
1204
1205     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1206     /* Reset for next time */
1207     jpeg_abort_decompress (&dec->cinfo);
1208     if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1209         ret != GST_FLOW_NOT_LINKED) {
1210       GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1211           (_("Failed to decode JPEG image")),
1212           ("Buffer allocation failed, reason: %s", reason), ret);
1213       jpeg_abort_decompress (&dec->cinfo);
1214     }
1215     goto exit;
1216   }
1217 components_not_supported:
1218   {
1219     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1220         (_("Failed to decode JPEG image")),
1221         ("number of components not supported: %d (max 3)",
1222             dec->cinfo.num_components), ret);
1223     jpeg_abort_decompress (&dec->cinfo);
1224     goto done;
1225   }
1226 unsupported_colorspace:
1227   {
1228     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1229         (_("Failed to decode JPEG image")),
1230         ("Picture has unknown or unsupported colourspace"), ret);
1231     jpeg_abort_decompress (&dec->cinfo);
1232     goto done;
1233   }
1234 invalid_yuvrgbgrayscale:
1235   {
1236     GST_VIDEO_DECODER_ERROR (dec, 1, STREAM, DECODE,
1237         (_("Failed to decode JPEG image")),
1238         ("Picture is corrupt or unhandled YUV/RGB/grayscale layout"), ret);
1239     jpeg_abort_decompress (&dec->cinfo);
1240     goto done;
1241   }
1242 }
1243
1244 static gboolean
1245 gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
1246 {
1247   GstBufferPool *pool = NULL;
1248   GstStructure *config;
1249
1250   if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
1251     return FALSE;
1252
1253   if (gst_query_get_n_allocation_pools (query) > 0)
1254     gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
1255
1256   if (pool == NULL)
1257     return FALSE;
1258
1259   config = gst_buffer_pool_get_config (pool);
1260   if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
1261     gst_buffer_pool_config_add_option (config,
1262         GST_BUFFER_POOL_OPTION_VIDEO_META);
1263   }
1264   gst_buffer_pool_set_config (pool, config);
1265   gst_object_unref (pool);
1266
1267   return TRUE;
1268 }
1269
1270 static gboolean
1271 gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard)
1272 {
1273   GstJpegDec *dec = (GstJpegDec *) bdec;
1274
1275   jpeg_abort_decompress (&dec->cinfo);
1276   dec->parse_entropy_len = 0;
1277   dec->parse_resync = FALSE;
1278   dec->saw_header = FALSE;
1279
1280   if (hard) {
1281     dec->parse_entropy_len = 0;
1282     dec->parse_resync = FALSE;
1283
1284     gst_video_decoder_set_packetized (bdec, FALSE);
1285   }
1286
1287   return TRUE;
1288 }
1289
1290 static void
1291 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1292     const GValue * value, GParamSpec * pspec)
1293 {
1294   GstJpegDec *dec;
1295
1296   dec = GST_JPEG_DEC (object);
1297
1298   switch (prop_id) {
1299     case PROP_IDCT_METHOD:
1300       dec->idct_method = g_value_get_enum (value);
1301       break;
1302     case PROP_MAX_ERRORS:
1303       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1304       break;
1305
1306     default:
1307       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1308       break;
1309   }
1310 }
1311
1312 static void
1313 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1314     GParamSpec * pspec)
1315 {
1316   GstJpegDec *dec;
1317
1318   dec = GST_JPEG_DEC (object);
1319
1320   switch (prop_id) {
1321     case PROP_IDCT_METHOD:
1322       g_value_set_enum (value, dec->idct_method);
1323       break;
1324     case PROP_MAX_ERRORS:
1325       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1326       break;
1327
1328     default:
1329       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1330       break;
1331   }
1332 }
1333
1334 static gboolean
1335 gst_jpeg_dec_stop (GstVideoDecoder * bdec)
1336 {
1337   GstJpegDec *dec = (GstJpegDec *) bdec;
1338
1339   gst_jpeg_dec_free_buffers (dec);
1340
1341   return TRUE;
1342 }