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