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