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