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