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