jpegdec: Only parse for SOI when we didn't see it before
[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 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
447     /* If we have leftover data, throw it away */
448     if (!dec->saw_header)
449       goto drop_frame;
450     goto have_full_frame;
451   }
452
453   if (size < 8)
454     goto need_more_data;
455
456   if (!dec->saw_header) {
457     gint ret;
458     /* we expect at least 4 bytes, first of which start marker */
459     ret =
460         gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0,
461         size - 4);
462
463     GST_DEBUG ("ret:%d", ret);
464     if (ret < 0)
465       goto need_more_data;
466
467     if (ret) {
468       gst_adapter_flush (adapter, ret);
469       size -= ret;
470     }
471     dec->saw_header = TRUE;
472   }
473
474   while (1) {
475     guint frame_len;
476     guint32 value;
477
478     GST_DEBUG ("offset:%d, size:%d", offset, size);
479
480     noffset =
481         gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
482         offset, size - offset, &value);
483
484     /* lost sync if 0xff marker not where expected */
485     if ((resync = (noffset != offset))) {
486       GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
487     }
488     /* may have marker, but could have been resyncng */
489     resync = resync || dec->parse_resync;
490     /* Skip over extra 0xff */
491     while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
492       noffset++;
493       noffset =
494           gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
495           noffset, size - noffset, &value);
496     }
497     /* enough bytes left for marker? (we need 0xNN after the 0xff) */
498     if (noffset < 0) {
499       GST_DEBUG ("at end of input and no EOI marker found, need more data");
500       goto need_more_data;
501     }
502
503     /* now lock on the marker we found */
504     offset = noffset;
505     value = value & 0xff;
506     if (value == 0xd9) {
507       GST_DEBUG ("0x%08x: EOI marker", offset + 2);
508       /* clear parse state */
509       dec->saw_header = FALSE;
510       dec->parse_resync = FALSE;
511       dec->parse_offset = 0;
512       toadd = offset + 4;
513       goto have_full_frame;
514     }
515     if (value == 0xd8) {
516       /* Skip this frame if we found another SOI marker */
517       GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
518       dec->parse_resync = FALSE;
519       dec->parse_offset = 0;
520       /* FIXME : Need to skip data */
521       toadd -= offset + 2;
522       goto have_full_frame;
523     }
524
525
526     if (value >= 0xd0 && value <= 0xd7)
527       frame_len = 0;
528     else {
529       /* peek tag and subsequent length */
530       if (offset + 2 + 4 > size)
531         goto need_more_data;
532       else
533         gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
534             &frame_len);
535       frame_len = frame_len & 0xffff;
536     }
537     GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
538     /* the frame length includes the 2 bytes for the length; here we want at
539      * least 2 more bytes at the end for an end marker */
540     if (offset + 2 + 2 + frame_len + 2 > size) {
541       goto need_more_data;
542     }
543
544     if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
545       guint eseglen = dec->parse_entropy_len;
546
547       GST_DEBUG ("0x%08x: finding entropy segment length (eseglen:%d)",
548           offset + 2, eseglen);
549       if (size < offset + 2 + frame_len + eseglen)
550         goto need_more_data;
551       noffset = offset + 2 + frame_len + dec->parse_entropy_len;
552       while (1) {
553         GST_DEBUG ("noffset:%d, size:%d, size - noffset:%d",
554             noffset, size, size - noffset);
555         noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
556             0x0000ff00, noffset, size - noffset, &value);
557         if (noffset < 0) {
558           /* need more data */
559           dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
560           goto need_more_data;
561         }
562         if ((value & 0xff) != 0x00) {
563           eseglen = noffset - offset - frame_len - 2;
564           break;
565         }
566         noffset++;
567       }
568       dec->parse_entropy_len = 0;
569       frame_len += eseglen;
570       GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
571           frame_len);
572     }
573     if (resync) {
574       /* check if we will still be in sync if we interpret
575        * this as a sync point and skip this frame */
576       noffset = offset + frame_len + 2;
577       noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
578           noffset, 4);
579       if (noffset < 0) {
580         /* ignore and continue resyncing until we hit the end
581          * of our data or find a sync point that looks okay */
582         offset++;
583         continue;
584       }
585       GST_DEBUG ("found sync at 0x%x", offset + 2);
586     }
587
588     /* Add current data to output buffer */
589     toadd += frame_len + 2;
590     offset += frame_len + 2;
591   }
592
593 need_more_data:
594   if (toadd)
595     gst_video_decoder_add_to_frame (bdec, toadd);
596   return GST_VIDEO_DECODER_FLOW_NEED_DATA;
597
598 have_full_frame:
599   if (toadd)
600     gst_video_decoder_add_to_frame (bdec, toadd);
601   return gst_video_decoder_have_frame (bdec);
602
603 drop_frame:
604   return GST_VIDEO_DECODER_FLOW_DROPPED;
605 }
606
607
608 /* shamelessly ripped from jpegutils.c in mjpegtools */
609 static void
610 add_huff_table (j_decompress_ptr dinfo,
611     JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
612 /* Define a Huffman table */
613 {
614   int nsymbols, len;
615
616   if (*htblptr == NULL)
617     *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
618
619   g_assert (*htblptr);
620
621   /* Copy the number-of-symbols-of-each-code-length counts */
622   memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
623
624   /* Validate the counts.  We do this here mainly so we can copy the right
625    * number of symbols from the val[] array, without risking marching off
626    * the end of memory.  jchuff.c will do a more thorough test later.
627    */
628   nsymbols = 0;
629   for (len = 1; len <= 16; len++)
630     nsymbols += bits[len];
631   if (nsymbols < 1 || nsymbols > 256)
632     g_error ("jpegutils.c:  add_huff_table failed badly. ");
633
634   memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
635 }
636
637
638
639 static void
640 std_huff_tables (j_decompress_ptr dinfo)
641 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
642 /* IMPORTANT: these are only valid for 8-bit data precision! */
643 {
644   static const UINT8 bits_dc_luminance[17] =
645       { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
646   static const UINT8 val_dc_luminance[] =
647       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
648
649   static const UINT8 bits_dc_chrominance[17] =
650       { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
651   static const UINT8 val_dc_chrominance[] =
652       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
653
654   static const UINT8 bits_ac_luminance[17] =
655       { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
656   static const UINT8 val_ac_luminance[] =
657       { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
658     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
659     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
660     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
661     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
662     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
663     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
664     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
665     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
666     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
667     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
668     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
669     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
670     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
671     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
672     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
673     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
674     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
675     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
676     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
677     0xf9, 0xfa
678   };
679
680   static const UINT8 bits_ac_chrominance[17] =
681       { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
682   static const UINT8 val_ac_chrominance[] =
683       { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
684     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
685     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
686     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
687     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
688     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
689     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
690     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
691     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
692     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
693     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
694     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
695     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
696     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
697     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
698     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
699     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
700     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
701     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
702     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
703     0xf9, 0xfa
704   };
705
706   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
707       bits_dc_luminance, val_dc_luminance);
708   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
709       bits_ac_luminance, val_ac_luminance);
710   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
711       bits_dc_chrominance, val_dc_chrominance);
712   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
713       bits_ac_chrominance, val_ac_chrominance);
714 }
715
716
717
718 static void
719 guarantee_huff_tables (j_decompress_ptr dinfo)
720 {
721   if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
722       (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
723       (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
724       (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
725     GST_DEBUG ("Generating standard Huffman tables for this frame.");
726     std_huff_tables (dinfo);
727   }
728 }
729
730 static gboolean
731 gst_jpeg_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
732 {
733   GstJpegDec *jpeg = GST_JPEG_DEC (dec);
734   GstVideoInfo *info = &state->info;
735
736   /* FIXME : previously jpegdec would handled input as packetized
737    * if the framerate was present. Here we consider it packetized if
738    * the fps is != 1/1 */
739   if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1)
740     gst_video_decoder_set_packetized (dec, TRUE);
741   else
742     gst_video_decoder_set_packetized (dec, FALSE);
743
744   if (jpeg->input_state)
745     gst_video_codec_state_unref (jpeg->input_state);
746   jpeg->input_state = gst_video_codec_state_ref (state);
747
748   return TRUE;
749 }
750
751
752 /* yuk */
753 static void
754 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
755 {
756   gint i;
757
758   for (i = 0; i < len; ++i) {
759     /* equivalent to: dest[i] = src[i << 1] */
760     *dest = *src;
761     ++dest;
762     ++src;
763     ++src;
764   }
765 }
766
767 static void
768 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
769 {
770   gint i;
771
772   for (i = 0; i < 16; i++) {
773     g_free (dec->idr_y[i]);
774     g_free (dec->idr_u[i]);
775     g_free (dec->idr_v[i]);
776     dec->idr_y[i] = NULL;
777     dec->idr_u[i] = NULL;
778     dec->idr_v[i] = NULL;
779   }
780
781   dec->idr_width_allocated = 0;
782 }
783
784 static inline gboolean
785 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
786 {
787   gint i;
788
789   if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
790     return TRUE;
791
792   /* FIXME: maybe just alloc one or three blocks altogether? */
793   for (i = 0; i < 16; i++) {
794     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
795     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
796     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
797
798     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
799       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
800       return FALSE;
801     }
802   }
803
804   dec->idr_width_allocated = maxrowbytes;
805   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
806   return TRUE;
807 }
808
809 static void
810 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, GstVideoFrame * frame)
811 {
812   guchar *rows[16];
813   guchar **scanarray[1] = { rows };
814   gint i, j, k;
815   gint lines;
816   guint8 *base[1];
817   gint width, height;
818   gint pstride, rstride;
819
820   GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
821
822   width = GST_VIDEO_FRAME_WIDTH (frame);
823   height = GST_VIDEO_FRAME_HEIGHT (frame);
824
825   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
826     return;
827
828   base[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
829   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
830   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
831
832   memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
833
834   i = 0;
835   while (i < height) {
836     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
837     if (G_LIKELY (lines > 0)) {
838       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
839         gint p;
840
841         p = 0;
842         for (k = 0; k < width; k++) {
843           base[0][p] = rows[j][k];
844           p += pstride;
845         }
846         base[0] += rstride;
847       }
848     } else {
849       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
850     }
851   }
852 }
853
854 static void
855 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, GstVideoFrame * frame)
856 {
857   guchar *r_rows[16], *g_rows[16], *b_rows[16];
858   guchar **scanarray[3] = { r_rows, g_rows, b_rows };
859   gint i, j, k;
860   gint lines;
861   guint8 *base[3];
862   guint pstride, rstride;
863   gint width, height;
864
865   GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
866
867   width = GST_VIDEO_FRAME_WIDTH (frame);
868   height = GST_VIDEO_FRAME_HEIGHT (frame);
869
870   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
871     return;
872
873   for (i = 0; i < 3; i++)
874     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
875
876   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
877   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
878
879   memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
880   memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
881   memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
882
883   i = 0;
884   while (i < height) {
885     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
886     if (G_LIKELY (lines > 0)) {
887       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
888         gint p;
889
890         p = 0;
891         for (k = 0; k < width; k++) {
892           base[0][p] = r_rows[j][k];
893           base[1][p] = g_rows[j][k];
894           base[2][p] = b_rows[j][k];
895           p += pstride;
896         }
897         base[0] += rstride;
898         base[1] += rstride;
899         base[2] += rstride;
900       }
901     } else {
902       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
903     }
904   }
905 }
906
907 static void
908 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame, gint r_v,
909     gint r_h, gint comp)
910 {
911   guchar *y_rows[16], *u_rows[16], *v_rows[16];
912   guchar **scanarray[3] = { y_rows, u_rows, v_rows };
913   gint i, j, k;
914   gint lines;
915   guchar *base[3], *last[3];
916   gint stride[3];
917   gint width, height;
918
919   GST_DEBUG_OBJECT (dec,
920       "unadvantageous width or r_h, taking slow route involving memcpy");
921
922   width = GST_VIDEO_FRAME_WIDTH (frame);
923   height = GST_VIDEO_FRAME_HEIGHT (frame);
924
925   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
926     return;
927
928   for (i = 0; i < 3; i++) {
929     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
930     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
931     /* make sure we don't make jpeglib write beyond our buffer,
932      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
933     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
934         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
935   }
936
937   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
938   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
939   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
940
941   /* fill chroma components for grayscale */
942   if (comp == 1) {
943     GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
944     for (i = 0; i < 16; i++) {
945       memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
946       memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
947     }
948   }
949
950   for (i = 0; i < height; i += r_v * DCTSIZE) {
951     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
952     if (G_LIKELY (lines > 0)) {
953       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
954         if (G_LIKELY (base[0] <= last[0])) {
955           memcpy (base[0], y_rows[j], stride[0]);
956           base[0] += stride[0];
957         }
958         if (r_v == 2) {
959           if (G_LIKELY (base[0] <= last[0])) {
960             memcpy (base[0], y_rows[j + 1], stride[0]);
961             base[0] += stride[0];
962           }
963         }
964         if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
965           if (r_h == 2) {
966             memcpy (base[1], u_rows[k], stride[1]);
967             memcpy (base[2], v_rows[k], stride[2]);
968           } else if (r_h == 1) {
969             hresamplecpy1 (base[1], u_rows[k], stride[1]);
970             hresamplecpy1 (base[2], v_rows[k], stride[2]);
971           } else {
972             /* FIXME: implement (at least we avoid crashing by doing nothing) */
973           }
974         }
975
976         if (r_v == 2 || (k & 1) != 0) {
977           base[1] += stride[1];
978           base[2] += stride[2];
979         }
980       }
981     } else {
982       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
983     }
984   }
985 }
986
987 static GstFlowReturn
988 gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame)
989 {
990   guchar **line[3];             /* the jpeg line buffer         */
991   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
992   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
993   guchar *v[4 * DCTSIZE] = { NULL, };
994   gint i, j;
995   gint lines, v_samp[3];
996   guchar *base[3], *last[3];
997   gint stride[3];
998   guint height;
999
1000   line[0] = y;
1001   line[1] = u;
1002   line[2] = v;
1003
1004   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1005   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1006   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1007
1008   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1009     goto format_not_supported;
1010
1011   height = GST_VIDEO_FRAME_HEIGHT (frame);
1012
1013   for (i = 0; i < 3; i++) {
1014     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
1015     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
1016     /* make sure we don't make jpeglib write beyond our buffer,
1017      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1018     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
1019         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
1020   }
1021
1022   /* let jpeglib decode directly into our final buffer */
1023   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1024
1025   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1026     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1027       /* Y */
1028       line[0][j] = base[0] + (i + j) * stride[0];
1029       if (G_UNLIKELY (line[0][j] > last[0]))
1030         line[0][j] = last[0];
1031       /* U */
1032       if (v_samp[1] == v_samp[0]) {
1033         line[1][j] = base[1] + ((i + j) / 2) * stride[1];
1034       } else if (j < (v_samp[1] * DCTSIZE)) {
1035         line[1][j] = base[1] + ((i / 2) + j) * stride[1];
1036       }
1037       if (G_UNLIKELY (line[1][j] > last[1]))
1038         line[1][j] = last[1];
1039       /* V */
1040       if (v_samp[2] == v_samp[0]) {
1041         line[2][j] = base[2] + ((i + j) / 2) * stride[2];
1042       } else if (j < (v_samp[2] * DCTSIZE)) {
1043         line[2][j] = base[2] + ((i / 2) + j) * stride[2];
1044       }
1045       if (G_UNLIKELY (line[2][j] > last[2]))
1046         line[2][j] = last[2];
1047     }
1048
1049     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1050     if (G_UNLIKELY (!lines)) {
1051       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1052     }
1053   }
1054   return GST_FLOW_OK;
1055
1056 format_not_supported:
1057   {
1058     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1059         "Unsupported subsampling schema: v_samp factors: %u %u %u",
1060         v_samp[0], v_samp[1], v_samp[2]);
1061     return GST_FLOW_ERROR;
1062   }
1063 }
1064
1065 static void
1066 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1067 {
1068   GstVideoCodecState *outstate;
1069   GstVideoInfo *info;
1070   GstVideoFormat format;
1071
1072   switch (clrspc) {
1073     case JCS_RGB:
1074       format = GST_VIDEO_FORMAT_RGB;
1075       break;
1076     case JCS_GRAYSCALE:
1077       format = GST_VIDEO_FORMAT_GRAY8;
1078       break;
1079     default:
1080       format = GST_VIDEO_FORMAT_I420;
1081       break;
1082   }
1083
1084   /* Compare to currently configured output state */
1085   outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
1086   if (outstate) {
1087     info = &outstate->info;
1088
1089     if (width == GST_VIDEO_INFO_WIDTH (info) &&
1090         height == GST_VIDEO_INFO_HEIGHT (info) &&
1091         format == GST_VIDEO_INFO_FORMAT (info)) {
1092       gst_video_codec_state_unref (outstate);
1093       return;
1094     }
1095     gst_video_codec_state_unref (outstate);
1096   }
1097
1098   outstate =
1099       gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format,
1100       width, height, dec->input_state);
1101
1102   gst_video_codec_state_unref (outstate);
1103
1104   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1105   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1106 }
1107
1108 static GstFlowReturn
1109 gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
1110 {
1111   GstFlowReturn ret = GST_FLOW_OK;
1112   GstJpegDec *dec = (GstJpegDec *) bdec;
1113   GstVideoFrame vframe;
1114   gint width, height;
1115   gint r_h, r_v;
1116   guint code, hdr_ok;
1117   gboolean need_unmap = TRUE;
1118   GstVideoCodecState *state = NULL;
1119
1120 #if 0
1121 again:
1122   if (!gst_jpeg_dec_ensure_header (dec))
1123     goto need_more_data;
1124
1125   /* If we know that each input buffer contains data
1126    * for a whole jpeg image (e.g. MJPEG streams), just 
1127    * do some sanity checking instead of parsing all of 
1128    * the jpeg data */
1129   if (dec->packetized) {
1130     img_len = gst_adapter_available (dec->adapter);
1131   } else {
1132     /* Parse jpeg image to handle jpeg input that
1133      * is not aligned to buffer boundaries */
1134     img_len = gst_jpeg_dec_parse_image_data (dec);
1135
1136     if (img_len == 0) {
1137       goto need_more_data;
1138     } else if (img_len < 0) {
1139       gst_adapter_flush (dec->adapter, -img_len);
1140       goto again;
1141     }
1142   }
1143 #endif
1144
1145   dec->current_frame = frame;
1146   gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
1147   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1148
1149   if (setjmp (dec->jerr.setjmp_buffer)) {
1150     code = dec->jerr.pub.msg_code;
1151
1152     if (code == JERR_INPUT_EOF) {
1153       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1154       goto need_more_data;
1155     }
1156     goto decode_error;
1157   }
1158
1159   /* read header */
1160   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1161   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1162     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1163   }
1164
1165   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1166   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1167
1168   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1169     goto components_not_supported;
1170
1171   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1172   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1173
1174   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1175
1176   if (dec->cinfo.num_components > 3)
1177     goto components_not_supported;
1178
1179   /* verify color space expectation to avoid going *boom* or bogus output */
1180   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1181       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1182       dec->cinfo.jpeg_color_space != JCS_RGB)
1183     goto unsupported_colorspace;
1184
1185 #ifndef GST_DISABLE_GST_DEBUG
1186   {
1187     gint i;
1188
1189     for (i = 0; i < dec->cinfo.num_components; ++i) {
1190       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1191           i, dec->cinfo.comp_info[i].h_samp_factor,
1192           dec->cinfo.comp_info[i].v_samp_factor,
1193           dec->cinfo.comp_info[i].component_id);
1194     }
1195   }
1196 #endif
1197
1198   /* prepare for raw output */
1199   dec->cinfo.do_fancy_upsampling = FALSE;
1200   dec->cinfo.do_block_smoothing = FALSE;
1201   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1202   dec->cinfo.dct_method = dec->idct_method;
1203   dec->cinfo.raw_data_out = TRUE;
1204
1205   GST_LOG_OBJECT (dec, "starting decompress");
1206   guarantee_huff_tables (&dec->cinfo);
1207   if (!jpeg_start_decompress (&dec->cinfo)) {
1208     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1209   }
1210
1211   /* sanity checks to get safe and reasonable output */
1212   switch (dec->cinfo.jpeg_color_space) {
1213     case JCS_GRAYSCALE:
1214       if (dec->cinfo.num_components != 1)
1215         goto invalid_yuvrgbgrayscale;
1216       break;
1217     case JCS_RGB:
1218       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1219           dec->cinfo.max_h_samp_factor > 1)
1220         goto invalid_yuvrgbgrayscale;
1221       break;
1222     case JCS_YCbCr:
1223       if (dec->cinfo.num_components != 3 ||
1224           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1225           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1226           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1227           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1228         goto invalid_yuvrgbgrayscale;
1229       break;
1230     default:
1231       g_assert_not_reached ();
1232       break;
1233   }
1234
1235   width = dec->cinfo.output_width;
1236   height = dec->cinfo.output_height;
1237
1238   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1239           height < MIN_HEIGHT || height > MAX_HEIGHT))
1240     goto wrong_size;
1241
1242   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1243
1244   state = gst_video_decoder_get_output_state (bdec);
1245   ret = gst_video_decoder_alloc_output_frame (bdec, frame);
1246   if (G_UNLIKELY (ret != GST_FLOW_OK))
1247     goto alloc_failed;
1248
1249   if (!gst_video_frame_map (&vframe, &state->info, frame->output_buffer,
1250           GST_MAP_READWRITE))
1251     goto alloc_failed;
1252
1253   GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1254
1255   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1256     gst_jpeg_dec_decode_rgb (dec, &vframe);
1257   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1258     gst_jpeg_dec_decode_grayscale (dec, &vframe);
1259   } else {
1260     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1261         dec->cinfo.rec_outbuf_height);
1262
1263     /* For some widths jpeglib requires more horizontal padding than I420 
1264      * provides. In those cases we need to decode into separate buffers and then
1265      * copy over the data into our final picture buffer, otherwise jpeglib might
1266      * write over the end of a line into the beginning of the next line,
1267      * resulting in blocky artifacts on the left side of the picture. */
1268     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1269             || dec->cinfo.comp_info[0].h_samp_factor != 2
1270             || dec->cinfo.comp_info[1].h_samp_factor != 1
1271             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1272       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1273           "indirect decoding using extra buffer copy");
1274       gst_jpeg_dec_decode_indirect (dec, &vframe, r_v, r_h,
1275           dec->cinfo.num_components);
1276     } else {
1277       ret = gst_jpeg_dec_decode_direct (dec, &vframe);
1278
1279       if (G_UNLIKELY (ret != GST_FLOW_OK))
1280         goto decode_direct_failed;
1281     }
1282   }
1283
1284   gst_video_frame_unmap (&vframe);
1285
1286   GST_LOG_OBJECT (dec, "decompressing finished");
1287   jpeg_finish_decompress (&dec->cinfo);
1288
1289   /* reset error count on successful decode */
1290   dec->error_count = 0;
1291
1292   gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1293   ret = gst_video_decoder_finish_frame (bdec, frame);
1294   need_unmap = FALSE;
1295
1296 done:
1297
1298 exit:
1299
1300   if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1301     jpeg_abort_decompress (&dec->cinfo);
1302     ret = gst_jpeg_dec_post_error_or_warning (dec);
1303   }
1304
1305   if (need_unmap)
1306     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1307
1308   if (state)
1309     gst_video_codec_state_unref (state);
1310
1311   return ret;
1312
1313   /* special cases */
1314 need_more_data:
1315   {
1316     GST_LOG_OBJECT (dec, "we need more data");
1317     ret = GST_FLOW_OK;
1318     goto exit;
1319   }
1320   /* ERRORS */
1321 wrong_size:
1322   {
1323     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1324         "Picture is too small or too big (%ux%u)", width, height);
1325     ret = GST_FLOW_ERROR;
1326     goto done;
1327   }
1328 decode_error:
1329   {
1330     gchar err_msg[JMSG_LENGTH_MAX];
1331
1332     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1333
1334     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1335         "Decode error #%u: %s", code, err_msg);
1336
1337     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1338     gst_video_decoder_drop_frame (bdec, frame);
1339     need_unmap = FALSE;
1340
1341     ret = GST_FLOW_ERROR;
1342     goto done;
1343   }
1344 decode_direct_failed:
1345   {
1346     /* already posted an error message */
1347     jpeg_abort_decompress (&dec->cinfo);
1348     goto done;
1349   }
1350 alloc_failed:
1351   {
1352     const gchar *reason;
1353
1354     reason = gst_flow_get_name (ret);
1355
1356     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1357     /* Reset for next time */
1358     jpeg_abort_decompress (&dec->cinfo);
1359     if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1360         ret != GST_FLOW_NOT_LINKED) {
1361       gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1362           "Buffer allocation failed, reason: %s", reason);
1363     }
1364     goto exit;
1365   }
1366 components_not_supported:
1367   {
1368     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1369         "number of components not supported: %d (max 3)",
1370         dec->cinfo.num_components);
1371     ret = GST_FLOW_ERROR;
1372     goto done;
1373   }
1374 unsupported_colorspace:
1375   {
1376     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1377         "Picture has unknown or unsupported colourspace");
1378     ret = GST_FLOW_ERROR;
1379     goto done;
1380   }
1381 invalid_yuvrgbgrayscale:
1382   {
1383     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1384         "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1385     ret = GST_FLOW_ERROR;
1386     goto done;
1387   }
1388 }
1389
1390 static gboolean
1391 gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
1392 {
1393   GstBufferPool *pool;
1394   GstStructure *config;
1395
1396   if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
1397     return FALSE;
1398
1399   g_assert (gst_query_get_n_allocation_pools (query) > 0);
1400   gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
1401   g_assert (pool != NULL);
1402
1403   config = gst_buffer_pool_get_config (pool);
1404   if (gst_query_has_allocation_meta (query, GST_VIDEO_META_API_TYPE)) {
1405     gst_buffer_pool_config_add_option (config,
1406         GST_BUFFER_POOL_OPTION_VIDEO_META);
1407   }
1408   gst_buffer_pool_set_config (pool, config);
1409   gst_object_unref (pool);
1410
1411   return TRUE;
1412 }
1413
1414 static gboolean
1415 gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard)
1416 {
1417   GstJpegDec *dec = (GstJpegDec *) bdec;
1418
1419   jpeg_abort_decompress (&dec->cinfo);
1420   dec->parse_offset = 0;
1421   dec->parse_entropy_len = 0;
1422   dec->parse_resync = FALSE;
1423   dec->saw_header = FALSE;
1424
1425   return TRUE;
1426 }
1427
1428 static void
1429 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1430     const GValue * value, GParamSpec * pspec)
1431 {
1432   GstJpegDec *dec;
1433
1434   dec = GST_JPEG_DEC (object);
1435
1436   switch (prop_id) {
1437     case PROP_IDCT_METHOD:
1438       dec->idct_method = g_value_get_enum (value);
1439       break;
1440     case PROP_MAX_ERRORS:
1441       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1442       break;
1443
1444     default:
1445       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1446       break;
1447   }
1448 }
1449
1450 static void
1451 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1452     GParamSpec * pspec)
1453 {
1454   GstJpegDec *dec;
1455
1456   dec = GST_JPEG_DEC (object);
1457
1458   switch (prop_id) {
1459     case PROP_IDCT_METHOD:
1460       g_value_set_enum (value, dec->idct_method);
1461       break;
1462     case PROP_MAX_ERRORS:
1463       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1464       break;
1465
1466     default:
1467       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1468       break;
1469   }
1470 }
1471
1472 static gboolean
1473 gst_jpeg_dec_start (GstVideoDecoder * bdec)
1474 {
1475   GstJpegDec *dec = (GstJpegDec *) bdec;
1476
1477   dec->error_count = 0;
1478   dec->parse_offset = 0;
1479   dec->parse_entropy_len = 0;
1480   dec->parse_resync = FALSE;
1481
1482   return TRUE;
1483 }
1484
1485 static gboolean
1486 gst_jpeg_dec_stop (GstVideoDecoder * bdec)
1487 {
1488   GstJpegDec *dec = (GstJpegDec *) bdec;
1489
1490   gst_jpeg_dec_free_buffers (dec);
1491
1492   return TRUE;
1493 }