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