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