Merge branch 'master' into 0.11
[platform/upstream/gstreamer.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  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:element-jpegdec
23  *
24  * Decodes jpeg images.
25  *
26  * <refsect2>
27  * <title>Example launch line</title>
28  * |[
29  * gst-launch -v v4l2src ! jpegdec ! ffmpegcolorspace ! xvimagesink
30  * ]| The above pipeline reads a motion JPEG stream from a v4l2 camera
31  * and renders it to the screen.
32  * </refsect2>
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 #include <string.h>
39
40 #include "gstjpegdec.h"
41 #include "gstjpeg.h"
42 #include <gst/video/video.h>
43 #include "gst/gst-i18n-plugin.h"
44 #include <jerror.h>
45
46 #define MIN_WIDTH  1
47 #define MAX_WIDTH  65535
48 #define MIN_HEIGHT 1
49 #define MAX_HEIGHT 65535
50
51 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
52         (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
53
54 #define JPEG_DEFAULT_IDCT_METHOD        JDCT_FASTEST
55 #define JPEG_DEFAULT_MAX_ERRORS         0
56
57 enum
58 {
59   PROP_0,
60   PROP_IDCT_METHOD,
61   PROP_MAX_ERRORS
62 };
63
64 /* *INDENT-OFF* */
65 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
66 GST_STATIC_PAD_TEMPLATE ("src",
67     GST_PAD_SRC,
68     GST_PAD_ALWAYS,
69     GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") "; "
70         GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; "
71         GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; "
72         GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR "; "
73         GST_VIDEO_CAPS_GRAY8)
74     );
75 /* *INDENT-ON* */
76
77 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
78 GST_STATIC_PAD_TEMPLATE ("sink",
79     GST_PAD_SINK,
80     GST_PAD_ALWAYS,
81     GST_STATIC_CAPS ("image/jpeg, "
82         "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
83         " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
84         G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (fraction) [ 0/1, MAX ]")
85     );
86
87 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
88 #define GST_CAT_DEFAULT jpeg_dec_debug
89 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
90
91 /* These macros are adapted from videotestsrc.c 
92  *  and/or gst-plugins/gst/games/gstvideoimage.c */
93 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
94 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
95 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
96
97 #define I420_Y_OFFSET(w,h) (0)
98 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
99 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
100
101 #define I420_SIZE(w,h)     (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
102
103 static GstElementClass *parent_class;   /* NULL */
104
105 static void gst_jpeg_dec_base_init (gpointer g_class);
106 static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
107 static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
108
109 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
110     const GValue * value, GParamSpec * pspec);
111 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
112     GValue * value, GParamSpec * pspec);
113
114 static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
115 static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
116 static gboolean gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event);
117 static gboolean gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event);
118 static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
119     GstStateChange transition);
120 static void gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
121     GstClockTimeDiff diff, GstClockTime ts);
122 static void gst_jpeg_dec_reset_qos (GstJpegDec * dec);
123 static void gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
124     GstClockTime * time);
125
126 GType
127 gst_jpeg_dec_get_type (void)
128 {
129   static GType type = 0;
130
131   if (!type) {
132     static const GTypeInfo jpeg_dec_info = {
133       sizeof (GstJpegDecClass),
134       (GBaseInitFunc) gst_jpeg_dec_base_init,
135       NULL,
136       (GClassInitFunc) gst_jpeg_dec_class_init,
137       NULL,
138       NULL,
139       sizeof (GstJpegDec),
140       0,
141       (GInstanceInitFunc) gst_jpeg_dec_init,
142     };
143
144     type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
145         &jpeg_dec_info, 0);
146   }
147   return type;
148 }
149
150 static void
151 gst_jpeg_dec_finalize (GObject * object)
152 {
153   GstJpegDec *dec = GST_JPEG_DEC (object);
154
155   jpeg_destroy_decompress (&dec->cinfo);
156
157   g_object_unref (dec->adapter);
158
159   G_OBJECT_CLASS (parent_class)->finalize (object);
160 }
161
162 static void
163 gst_jpeg_dec_base_init (gpointer g_class)
164 {
165   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
166
167   gst_element_class_add_pad_template (element_class,
168       gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
169   gst_element_class_add_pad_template (element_class,
170       gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
171   gst_element_class_set_details_simple (element_class, "JPEG image decoder",
172       "Codec/Decoder/Image",
173       "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
174 }
175
176 static void
177 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
178 {
179   GstElementClass *gstelement_class;
180   GObjectClass *gobject_class;
181
182   gstelement_class = (GstElementClass *) klass;
183   gobject_class = (GObjectClass *) klass;
184
185   parent_class = g_type_class_peek_parent (klass);
186
187   gobject_class->finalize = gst_jpeg_dec_finalize;
188   gobject_class->set_property = gst_jpeg_dec_set_property;
189   gobject_class->get_property = gst_jpeg_dec_get_property;
190
191   g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
192       g_param_spec_enum ("idct-method", "IDCT Method",
193           "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
194           JPEG_DEFAULT_IDCT_METHOD,
195           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
196
197   /**
198    * GstJpegDec:max-errors
199    *
200    * Error out after receiving N consecutive decoding errors
201    * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
202    *
203    * Since: 0.10.27
204    **/
205   g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
206       g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
207           "Error out after receiving N consecutive decoding errors "
208           "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
209           -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
210           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
211
212   gstelement_class->change_state =
213       GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
214
215   GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
216   GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
217 }
218
219 static void
220 gst_jpeg_dec_clear_error (GstJpegDec * dec)
221 {
222   g_free (dec->error_msg);
223   dec->error_msg = NULL;
224   dec->error_line = 0;
225   dec->error_func = NULL;
226 }
227
228 static void
229 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
230     const gchar * debug_msg_format, va_list args)
231 {
232 #ifndef GST_DISABLE_GST_DEBUG
233   gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
234       line, (GObject *) dec, debug_msg_format, args);
235 #endif
236
237   g_free (dec->error_msg);
238   if (debug_msg_format)
239     dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
240   else
241     dec->error_msg = NULL;
242
243   dec->error_line = line;
244   dec->error_func = func;
245 }
246
247 static void
248 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
249     const gchar * debug_msg_format, ...)
250 {
251   va_list va;
252
253   va_start (va, debug_msg_format);
254   gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
255   va_end (va);
256 }
257
258 static GstFlowReturn
259 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
260 {
261   GstFlowReturn ret;
262   int max_errors;
263
264   ++dec->error_count;
265   max_errors = g_atomic_int_get (&dec->max_errors);
266
267   if (max_errors < 0) {
268     ret = GST_FLOW_OK;
269   } else if (max_errors == 0) {
270     /* FIXME: do something more clever in "automatic mode" */
271     if (dec->packetized) {
272       ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
273     } else {
274       ret = GST_FLOW_ERROR;
275     }
276   } else {
277     ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
278   }
279
280   GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
281       max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
282
283   gst_element_message_full (GST_ELEMENT (dec),
284       (ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
285       GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
286       g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
287       __FILE__, dec->error_func, dec->error_line);
288
289   dec->error_msg = NULL;
290   gst_jpeg_dec_clear_error (dec);
291   return ret;
292 }
293
294 static boolean
295 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
296 {
297   GstJpegDec *dec;
298   guint av;
299
300   dec = CINFO_GET_JPEGDEC (cinfo);
301   g_return_val_if_fail (dec != NULL, FALSE);
302
303   av = gst_adapter_available_fast (dec->adapter);
304   GST_DEBUG_OBJECT (dec, "fill_input_buffer: fast av=%u, remaining=%u", av,
305       dec->rem_img_len);
306
307   if (av == 0) {
308     GST_DEBUG_OBJECT (dec, "Out of data");
309     return FALSE;
310   }
311
312   if (dec->rem_img_len < av)
313     av = dec->rem_img_len;
314   dec->rem_img_len -= av;
315
316   g_free (dec->cur_buf);
317   dec->cur_buf = gst_adapter_take (dec->adapter, av);
318
319   cinfo->src->next_input_byte = dec->cur_buf;
320   cinfo->src->bytes_in_buffer = av;
321
322   return TRUE;
323 }
324
325 static void
326 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
327 {
328   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
329 }
330
331
332 static void
333 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
334 {
335   GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
336
337   GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
338
339   if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
340     cinfo->src->next_input_byte += (size_t) num_bytes;
341     cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
342   } else if (num_bytes > 0) {
343     gint available;
344
345     num_bytes -= cinfo->src->bytes_in_buffer;
346     cinfo->src->next_input_byte += (size_t) cinfo->src->bytes_in_buffer;
347     cinfo->src->bytes_in_buffer = 0;
348
349     available = gst_adapter_available (dec->adapter);
350     if (available < num_bytes || available < dec->rem_img_len) {
351       GST_WARNING_OBJECT (dec, "Less bytes to skip than available in the "
352           "adapter or the remaining image length %ld < %d or %u",
353           num_bytes, available, dec->rem_img_len);
354     }
355     num_bytes = MIN (MIN (num_bytes, available), dec->rem_img_len);
356     gst_adapter_flush (dec->adapter, num_bytes);
357     dec->rem_img_len -= num_bytes;
358   }
359 }
360
361 static boolean
362 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
363 {
364   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
365   return TRUE;
366 }
367
368 static void
369 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
370 {
371   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
372   return;
373 }
374
375 METHODDEF (void)
376     gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
377 {
378   return;                       /* do nothing */
379 }
380
381 METHODDEF (void)
382     gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
383 {
384   /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
385   return;
386 }
387
388 METHODDEF (void)
389     gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
390 {
391   struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
392
393   (*cinfo->err->output_message) (cinfo);
394   longjmp (err_mgr->setjmp_buffer, 1);
395 }
396
397 static void
398 gst_jpeg_dec_init (GstJpegDec * dec)
399 {
400   GST_DEBUG ("initializing");
401
402   /* create the sink and src pads */
403   dec->sinkpad =
404       gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
405       "sink");
406   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
407   gst_pad_set_setcaps_function (dec->sinkpad,
408       GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
409   gst_pad_set_chain_function (dec->sinkpad,
410       GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
411   gst_pad_set_event_function (dec->sinkpad,
412       GST_DEBUG_FUNCPTR (gst_jpeg_dec_sink_event));
413
414   dec->srcpad =
415       gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
416   gst_pad_set_event_function (dec->srcpad,
417       GST_DEBUG_FUNCPTR (gst_jpeg_dec_src_event));
418   gst_pad_use_fixed_caps (dec->srcpad);
419   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
420
421   /* setup jpeglib */
422   memset (&dec->cinfo, 0, sizeof (dec->cinfo));
423   memset (&dec->jerr, 0, sizeof (dec->jerr));
424   dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
425   dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
426   dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
427   dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
428
429   jpeg_create_decompress (&dec->cinfo);
430
431   dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
432   dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
433   dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
434   dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
435   dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
436   dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
437   dec->jsrc.dec = dec;
438
439   /* init properties */
440   dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
441   dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
442
443   dec->adapter = gst_adapter_new ();
444 }
445
446 static gboolean
447 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
448 {
449   gint av;
450   gint offset;
451
452   av = gst_adapter_available (dec->adapter);
453   /* we expect at least 4 bytes, first of which start marker */
454   offset = gst_adapter_masked_scan_uint32 (dec->adapter, 0xffffff00, 0xffd8ff00,
455       0, av);
456   if (G_UNLIKELY (offset < 0)) {
457     GST_DEBUG_OBJECT (dec, "No JPEG header in current buffer");
458     /* not found */
459     if (av > 4)
460       gst_adapter_flush (dec->adapter, av - 4);
461     return FALSE;
462   }
463
464   if (offset > 0) {
465     GST_LOG_OBJECT (dec, "Skipping %u bytes.", offset);
466     gst_adapter_flush (dec->adapter, offset);
467   }
468   GST_DEBUG_OBJECT (dec, "Found JPEG header");
469
470   return TRUE;
471 }
472
473 static inline gboolean
474 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
475 {
476   if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
477     return TRUE;
478   return FALSE;
479 }
480
481 /* returns image length in bytes if parsed successfully,
482  * otherwise 0 if more data needed,
483  * if < 0 the absolute value needs to be flushed */
484 static gint
485 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
486 {
487   guint size;
488   gboolean resync;
489   GstAdapter *adapter = dec->adapter;
490   gint offset, noffset;
491
492   size = gst_adapter_available (adapter);
493
494   /* we expect at least 4 bytes, first of which start marker */
495   if (gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0, 4))
496     return 0;
497
498   GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
499
500   GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d",
501       dec->parse_offset, dec->parse_resync, dec->parse_entropy_len);
502
503   /* offset is 2 less than actual offset;
504    * - adapter needs at least 4 bytes for scanning,
505    * - start and end marker ensure at least that much
506    */
507   /* resume from state offset */
508   offset = dec->parse_offset;
509
510   while (1) {
511     guint frame_len;
512     guint32 value;
513
514     noffset =
515         gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
516         offset, size - offset, &value);
517     /* lost sync if 0xff marker not where expected */
518     if ((resync = (noffset != offset))) {
519       GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
520     }
521     /* may have marker, but could have been resyncng */
522     resync = resync || dec->parse_resync;
523     /* Skip over extra 0xff */
524     while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
525       noffset++;
526       noffset =
527           gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
528           noffset, size - noffset, &value);
529     }
530     /* enough bytes left for marker? (we need 0xNN after the 0xff) */
531     if (noffset < 0) {
532       GST_DEBUG ("at end of input and no EOI marker found, need more data");
533       goto need_more_data;
534     }
535
536     /* now lock on the marker we found */
537     offset = noffset;
538     value = value & 0xff;
539     if (value == 0xd9) {
540       GST_DEBUG ("0x%08x: EOI marker", offset + 2);
541       /* clear parse state */
542       dec->parse_resync = FALSE;
543       dec->parse_offset = 0;
544       return (offset + 4);
545     } else if (value == 0xd8) {
546       /* Skip this frame if we found another SOI marker */
547       GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
548       dec->parse_resync = FALSE;
549       dec->parse_offset = 0;
550       return -(offset + 2);
551     }
552
553
554     if (value >= 0xd0 && value <= 0xd7)
555       frame_len = 0;
556     else {
557       /* peek tag and subsequent length */
558       if (offset + 2 + 4 > size)
559         goto need_more_data;
560       else
561         gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
562             &frame_len);
563       frame_len = frame_len & 0xffff;
564     }
565     GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
566     /* the frame length includes the 2 bytes for the length; here we want at
567      * least 2 more bytes at the end for an end marker */
568     if (offset + 2 + 2 + frame_len + 2 > size) {
569       goto need_more_data;
570     }
571
572     if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
573       guint eseglen = dec->parse_entropy_len;
574
575       GST_DEBUG ("0x%08x: finding entropy segment length", offset + 2);
576       noffset = offset + 2 + frame_len + dec->parse_entropy_len;
577       while (1) {
578         noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
579             0x0000ff00, noffset, size - noffset, &value);
580         if (noffset < 0) {
581           /* need more data */
582           dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
583           goto need_more_data;
584         }
585         if ((value & 0xff) != 0x00) {
586           eseglen = noffset - offset - frame_len - 2;
587           break;
588         }
589         noffset++;
590       }
591       dec->parse_entropy_len = 0;
592       frame_len += eseglen;
593       GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
594           frame_len);
595     }
596     if (resync) {
597       /* check if we will still be in sync if we interpret
598        * this as a sync point and skip this frame */
599       noffset = offset + frame_len + 2;
600       noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
601           noffset, 4);
602       if (noffset < 0) {
603         /* ignore and continue resyncing until we hit the end
604          * of our data or find a sync point that looks okay */
605         offset++;
606         continue;
607       }
608       GST_DEBUG ("found sync at 0x%x", offset + 2);
609     }
610
611     offset += frame_len + 2;
612   }
613
614   /* EXITS */
615 need_more_data:
616   {
617     dec->parse_offset = offset;
618     dec->parse_resync = resync;
619     return 0;
620   }
621 }
622
623 /* shamelessly ripped from jpegutils.c in mjpegtools */
624 static void
625 add_huff_table (j_decompress_ptr dinfo,
626     JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
627 /* Define a Huffman table */
628 {
629   int nsymbols, len;
630
631   if (*htblptr == NULL)
632     *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
633
634   g_assert (*htblptr);
635
636   /* Copy the number-of-symbols-of-each-code-length counts */
637   memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
638
639   /* Validate the counts.  We do this here mainly so we can copy the right
640    * number of symbols from the val[] array, without risking marching off
641    * the end of memory.  jchuff.c will do a more thorough test later.
642    */
643   nsymbols = 0;
644   for (len = 1; len <= 16; len++)
645     nsymbols += bits[len];
646   if (nsymbols < 1 || nsymbols > 256)
647     g_error ("jpegutils.c:  add_huff_table failed badly. ");
648
649   memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
650 }
651
652
653
654 static void
655 std_huff_tables (j_decompress_ptr dinfo)
656 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
657 /* IMPORTANT: these are only valid for 8-bit data precision! */
658 {
659   static const UINT8 bits_dc_luminance[17] =
660       { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
661   static const UINT8 val_dc_luminance[] =
662       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
663
664   static const UINT8 bits_dc_chrominance[17] =
665       { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
666   static const UINT8 val_dc_chrominance[] =
667       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
668
669   static const UINT8 bits_ac_luminance[17] =
670       { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
671   static const UINT8 val_ac_luminance[] =
672       { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
673     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
674     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
675     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
676     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
677     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
678     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
679     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
680     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
681     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
682     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
683     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
684     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
685     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
686     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
687     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
688     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
689     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
690     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
691     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
692     0xf9, 0xfa
693   };
694
695   static const UINT8 bits_ac_chrominance[17] =
696       { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
697   static const UINT8 val_ac_chrominance[] =
698       { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
699     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
700     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
701     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
702     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
703     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
704     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
705     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
706     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
707     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
708     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
709     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
710     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
711     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
712     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
713     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
714     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
715     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
716     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
717     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
718     0xf9, 0xfa
719   };
720
721   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
722       bits_dc_luminance, val_dc_luminance);
723   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
724       bits_ac_luminance, val_ac_luminance);
725   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
726       bits_dc_chrominance, val_dc_chrominance);
727   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
728       bits_ac_chrominance, val_ac_chrominance);
729 }
730
731
732
733 static void
734 guarantee_huff_tables (j_decompress_ptr dinfo)
735 {
736   if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
737       (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
738       (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
739       (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
740     GST_DEBUG ("Generating standard Huffman tables for this frame.");
741     std_huff_tables (dinfo);
742   }
743 }
744
745 static gboolean
746 gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
747 {
748   GstStructure *s;
749   GstJpegDec *dec;
750   const GValue *framerate;
751
752   dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
753   s = gst_caps_get_structure (caps, 0);
754
755   if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
756     dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
757     dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
758     dec->packetized = TRUE;
759     GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
760         dec->framerate_numerator, dec->framerate_denominator);
761   }
762
763   /* do not extract width/height here. we do that in the chain
764    * function on a per-frame basis (including the line[] array
765    * setup) */
766
767   /* But we can take the framerate values and set them on the src pad */
768
769   return TRUE;
770 }
771
772 /* yuk */
773 static void
774 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
775 {
776   gint i;
777
778   for (i = 0; i < len; ++i) {
779     /* equivalent to: dest[i] = src[i << 1] */
780     *dest = *src;
781     ++dest;
782     ++src;
783     ++src;
784   }
785 }
786
787 static void
788 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
789 {
790   gint i;
791
792   for (i = 0; i < 16; i++) {
793     g_free (dec->idr_y[i]);
794     g_free (dec->idr_u[i]);
795     g_free (dec->idr_v[i]);
796     dec->idr_y[i] = NULL;
797     dec->idr_u[i] = NULL;
798     dec->idr_v[i] = NULL;
799   }
800
801   dec->idr_width_allocated = 0;
802 }
803
804 static inline gboolean
805 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
806 {
807   gint i;
808
809   if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
810     return TRUE;
811
812   /* FIXME: maybe just alloc one or three blocks altogether? */
813   for (i = 0; i < 16; i++) {
814     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
815     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
816     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
817
818     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
819       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
820       return FALSE;
821     }
822   }
823
824   dec->idr_width_allocated = maxrowbytes;
825   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
826   return TRUE;
827 }
828
829 static void
830 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, guchar * base[1],
831     guint width, guint height, guint pstride, guint rstride)
832 {
833   guchar *rows[16];
834   guchar **scanarray[1] = { rows };
835   gint i, j, k;
836   gint lines;
837
838   GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
839
840   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
841     return;
842
843   memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
844
845   i = 0;
846   while (i < height) {
847     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
848     if (G_LIKELY (lines > 0)) {
849       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
850         gint p;
851
852         p = 0;
853         for (k = 0; k < width; k++) {
854           base[0][p] = rows[j][k];
855           p += pstride;
856         }
857         base[0] += rstride;
858       }
859     } else {
860       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
861     }
862   }
863 }
864
865 static void
866 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, guchar * base[3],
867     guint width, guint height, guint pstride, guint rstride)
868 {
869   guchar *r_rows[16], *g_rows[16], *b_rows[16];
870   guchar **scanarray[3] = { r_rows, g_rows, b_rows };
871   gint i, j, k;
872   gint lines;
873
874   GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
875
876   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
877     return;
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, guchar * base[3],
909     guchar * last[3], guint width, guint height, gint r_v, 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
916   GST_DEBUG_OBJECT (dec,
917       "unadvantageous width or r_h, taking slow route involving memcpy");
918
919   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
920     return;
921
922   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
923   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
924   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
925
926   /* fill chroma components for grayscale */
927   if (comp == 1) {
928     GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
929     for (i = 0; i < 16; i++) {
930       memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
931       memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
932     }
933   }
934
935   for (i = 0; i < height; i += r_v * DCTSIZE) {
936     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
937     if (G_LIKELY (lines > 0)) {
938       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
939         if (G_LIKELY (base[0] <= last[0])) {
940           memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
941           base[0] += I420_Y_ROWSTRIDE (width);
942         }
943         if (r_v == 2) {
944           if (G_LIKELY (base[0] <= last[0])) {
945             memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
946             base[0] += I420_Y_ROWSTRIDE (width);
947           }
948         }
949         if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
950           if (r_h == 2) {
951             memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
952             memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
953           } else if (r_h == 1) {
954             hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
955             hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
956           } else {
957             /* FIXME: implement (at least we avoid crashing by doing nothing) */
958           }
959         }
960
961         if (r_v == 2 || (k & 1) != 0) {
962           base[1] += I420_U_ROWSTRIDE (width);
963           base[2] += I420_V_ROWSTRIDE (width);
964         }
965       }
966     } else {
967       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
968     }
969   }
970 }
971
972 #ifndef GST_DISABLE_GST_DEBUG
973 static inline void
974 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
975 {
976   int j;
977
978   for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
979     GST_LOG ("[%02d]  %5d  %5d  %5d", j,
980         (line[0][j] >= base[0]) ?
981         (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
982         (line[1][j] >= base[1]) ?
983         (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
984         (line[2][j] >= base[2]) ?
985         (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
986   }
987 }
988 #endif
989
990 static GstFlowReturn
991 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
992     guchar * last[3], guint width, guint height)
993 {
994   guchar **line[3];             /* the jpeg line buffer         */
995   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
996   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
997   guchar *v[4 * DCTSIZE] = { NULL, };
998   gint i, j;
999   gint lines, v_samp[3];
1000
1001   line[0] = y;
1002   line[1] = u;
1003   line[2] = v;
1004
1005   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1006   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1007   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1008
1009   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1010     goto format_not_supported;
1011
1012   /* let jpeglib decode directly into our final buffer */
1013   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1014
1015   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1016     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1017       /* Y */
1018       line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
1019       if (G_UNLIKELY (line[0][j] > last[0]))
1020         line[0][j] = last[0];
1021       /* U */
1022       if (v_samp[1] == v_samp[0]) {
1023         line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
1024       } else if (j < (v_samp[1] * DCTSIZE)) {
1025         line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
1026       }
1027       if (G_UNLIKELY (line[1][j] > last[1]))
1028         line[1][j] = last[1];
1029       /* V */
1030       if (v_samp[2] == v_samp[0]) {
1031         line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
1032       } else if (j < (v_samp[2] * DCTSIZE)) {
1033         line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
1034       }
1035       if (G_UNLIKELY (line[2][j] > last[2]))
1036         line[2][j] = last[2];
1037     }
1038
1039     /* dump_lines (base, line, v_samp[0], width); */
1040
1041     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1042     if (G_UNLIKELY (!lines)) {
1043       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1044     }
1045   }
1046   return GST_FLOW_OK;
1047
1048 format_not_supported:
1049   {
1050     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1051         "Unsupported subsampling schema: v_samp factors: %u %u %u",
1052         v_samp[0], v_samp[1], v_samp[2]);
1053     return GST_FLOW_ERROR;
1054   }
1055 }
1056
1057 static void
1058 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
1059     GstClockTimeDiff diff, GstClockTime ts)
1060 {
1061   GST_OBJECT_LOCK (dec);
1062   dec->proportion = proportion;
1063   if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
1064     if (G_UNLIKELY (diff > dec->qos_duration))
1065       dec->earliest_time = ts + 2 * diff + dec->qos_duration;
1066     else
1067       dec->earliest_time = ts + diff;
1068   } else {
1069     dec->earliest_time = GST_CLOCK_TIME_NONE;
1070   }
1071   GST_OBJECT_UNLOCK (dec);
1072 }
1073
1074 static void
1075 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
1076 {
1077   gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
1078 }
1079
1080 static void
1081 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
1082     GstClockTime * time)
1083 {
1084   GST_OBJECT_LOCK (dec);
1085   *proportion = dec->proportion;
1086   *time = dec->earliest_time;
1087   GST_OBJECT_UNLOCK (dec);
1088 }
1089
1090 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
1091  * frame should be decoded, FALSE if the frame can be dropped entirely */
1092 static gboolean
1093 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
1094 {
1095   GstClockTime qostime, earliest_time;
1096   gdouble proportion;
1097
1098   /* no timestamp, can't do QoS => decode frame */
1099   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1100     GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
1101     return TRUE;
1102   }
1103
1104   /* get latest QoS observation values */
1105   gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
1106
1107   /* skip qos if we have no observation (yet) => decode frame */
1108   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1109     GST_LOG_OBJECT (dec, "no observation yet, decode frame");
1110     return TRUE;
1111   }
1112
1113   /* qos is done on running time */
1114   qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
1115       timestamp);
1116
1117   /* see how our next timestamp relates to the latest qos timestamp */
1118   GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
1119       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1120
1121   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1122     GST_DEBUG_OBJECT (dec, "we are late, drop frame");
1123     return FALSE;
1124   }
1125
1126   GST_LOG_OBJECT (dec, "decode frame");
1127   return TRUE;
1128 }
1129
1130 static void
1131 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1132 {
1133   GstCaps *caps;
1134   GstVideoFormat format;
1135
1136   if (G_UNLIKELY (width == dec->caps_width && height == dec->caps_height &&
1137           dec->framerate_numerator == dec->caps_framerate_numerator &&
1138           dec->framerate_denominator == dec->caps_framerate_denominator &&
1139           clrspc == dec->clrspc))
1140     return;
1141
1142   /* framerate == 0/1 is a still frame */
1143   if (dec->framerate_denominator == 0) {
1144     dec->framerate_numerator = 0;
1145     dec->framerate_denominator = 1;
1146   }
1147
1148   /* calculate or assume an average frame duration for QoS purposes */
1149   GST_OBJECT_LOCK (dec);
1150   if (dec->framerate_numerator != 0) {
1151     dec->qos_duration = gst_util_uint64_scale (GST_SECOND,
1152         dec->framerate_denominator, dec->framerate_numerator);
1153   } else {
1154     /* if not set just use 25fps */
1155     dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1156   }
1157   GST_OBJECT_UNLOCK (dec);
1158
1159   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1160     gint i;
1161     GstCaps *allowed_caps;
1162
1163     GST_DEBUG_OBJECT (dec, "selecting RGB format");
1164     /* retrieve allowed caps, and find the first one that reasonably maps
1165      * to the parameters of the colourspace */
1166     caps = gst_pad_get_allowed_caps (dec->srcpad);
1167     if (!caps) {
1168       GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1169       /* need to copy because get_allowed_caps returns a ref,
1170        * and get_pad_template_caps doesn't */
1171       caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
1172     }
1173     /* avoid lists of fourcc, etc */
1174     allowed_caps = gst_caps_normalize (caps);
1175     gst_caps_unref (caps);
1176     caps = NULL;
1177     GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1178
1179     for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1180       if (caps)
1181         gst_caps_unref (caps);
1182       caps = gst_caps_copy_nth (allowed_caps, i);
1183       /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1184       gst_pad_fixate_caps (dec->srcpad, caps);
1185       GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1186       if (!gst_video_format_parse_caps (caps, &format, NULL, NULL))
1187         continue;
1188       /* we'll settle for the first (preferred) downstream rgb format */
1189       if (gst_video_format_is_rgb (format))
1190         break;
1191       /* default fall-back */
1192       format = GST_VIDEO_FORMAT_RGB;
1193     }
1194     if (caps)
1195       gst_caps_unref (caps);
1196     gst_caps_unref (allowed_caps);
1197     caps = gst_video_format_new_caps (format, width, height,
1198         dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1199     dec->outsize = gst_video_format_get_size (format, width, height);
1200     /* some format info */
1201     dec->offset[0] =
1202         gst_video_format_get_component_offset (format, 0, width, height);
1203     dec->offset[1] =
1204         gst_video_format_get_component_offset (format, 1, width, height);
1205     dec->offset[2] =
1206         gst_video_format_get_component_offset (format, 2, width, height);
1207     /* equal for all components */
1208     dec->stride = gst_video_format_get_row_stride (format, 0, width);
1209     dec->inc = gst_video_format_get_pixel_stride (format, 0);
1210   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1211     /* TODO is anything else then 8bit supported in jpeg? */
1212     format = GST_VIDEO_FORMAT_GRAY8;
1213     caps = gst_video_format_new_caps (format, width, height,
1214         dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1215     dec->outsize = gst_video_format_get_size (format, width, height);
1216     dec->offset[0] =
1217         gst_video_format_get_component_offset (format, 0, width, height);
1218     dec->stride = gst_video_format_get_row_stride (format, 0, width);
1219     dec->inc = gst_video_format_get_pixel_stride (format, 0);
1220   } else {
1221     /* go for plain and simple I420 */
1222     /* TODO other YUV cases ? */
1223     caps = gst_caps_new_simple ("video/x-raw-yuv",
1224         "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
1225         "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
1226         "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
1227         dec->framerate_denominator, NULL);
1228     dec->outsize = I420_SIZE (width, height);
1229   }
1230
1231   GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1232   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1233   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1234
1235   gst_pad_set_caps (dec->srcpad, caps);
1236   gst_caps_unref (caps);
1237
1238   dec->caps_width = width;
1239   dec->caps_height = height;
1240   dec->caps_framerate_numerator = dec->framerate_numerator;
1241   dec->caps_framerate_denominator = dec->framerate_denominator;
1242 }
1243
1244 static GstFlowReturn
1245 gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
1246 {
1247   GstFlowReturn ret = GST_FLOW_OK;
1248   GstJpegDec *dec;
1249   GstBuffer *outbuf = NULL;
1250 #ifndef GST_DISABLE_GST_DEBUG
1251   guchar *data;
1252 #endif
1253   guchar *outdata;
1254   guchar *base[3], *last[3];
1255   gint img_len;
1256   guint outsize;
1257   gint width, height;
1258   gint r_h, r_v;
1259   guint code, hdr_ok;
1260   GstClockTime timestamp, duration;
1261
1262   dec = GST_JPEG_DEC (GST_PAD_PARENT (pad));
1263
1264   timestamp = GST_BUFFER_TIMESTAMP (buf);
1265   duration = GST_BUFFER_DURATION (buf);
1266
1267   if (GST_CLOCK_TIME_IS_VALID (timestamp))
1268     dec->next_ts = timestamp;
1269
1270   if (GST_BUFFER_IS_DISCONT (buf)) {
1271     GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1272     dec->discont = TRUE;
1273     if (!dec->packetized && gst_adapter_available (dec->adapter)) {
1274       GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1275       gst_adapter_clear (dec->adapter);
1276     }
1277   }
1278
1279   gst_adapter_push (dec->adapter, buf);
1280   buf = NULL;
1281
1282   /* If we are non-packetized and know the total incoming size in bytes,
1283    * just wait until we have enough before doing any processing. */
1284
1285   if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1286       (dec->segment.stop != -1) &&
1287       (gst_adapter_available (dec->adapter) < dec->segment.stop)) {
1288     /* We assume that non-packetized input in bytes is *one* single jpeg image */
1289     GST_DEBUG ("Non-packetized mode. Got %d bytes, need %" G_GINT64_FORMAT,
1290         gst_adapter_available (dec->adapter), dec->segment.stop);
1291     goto need_more_data;
1292   }
1293
1294 again:
1295   if (!gst_jpeg_dec_ensure_header (dec))
1296     goto need_more_data;
1297
1298   /* If we know that each input buffer contains data
1299    * for a whole jpeg image (e.g. MJPEG streams), just 
1300    * do some sanity checking instead of parsing all of 
1301    * the jpeg data */
1302   if (dec->packetized) {
1303     img_len = gst_adapter_available (dec->adapter);
1304   } else {
1305     /* Parse jpeg image to handle jpeg input that
1306      * is not aligned to buffer boundaries */
1307     img_len = gst_jpeg_dec_parse_image_data (dec);
1308
1309     if (img_len == 0) {
1310       goto need_more_data;
1311     } else if (img_len < 0) {
1312       gst_adapter_flush (dec->adapter, -img_len);
1313       goto again;
1314     }
1315   }
1316
1317   dec->rem_img_len = img_len;
1318
1319   GST_LOG_OBJECT (dec, "image size = %u", img_len);
1320
1321   /* QoS: if we're too late anyway, skip decoding */
1322   if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1323     goto skip_decoding;
1324
1325 #ifndef GST_DISABLE_GST_DEBUG
1326   data = (guint8 *) gst_adapter_peek (dec->adapter, 4);
1327   GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1328       data[2], data[3]);
1329 #endif
1330
1331   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1332
1333   if (setjmp (dec->jerr.setjmp_buffer)) {
1334     code = dec->jerr.pub.msg_code;
1335
1336     if (code == JERR_INPUT_EOF) {
1337       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1338       goto need_more_data;
1339     }
1340     goto decode_error;
1341   }
1342
1343   /* read header */
1344   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1345   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1346     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1347   }
1348
1349   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1350   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1351
1352   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1353     goto components_not_supported;
1354
1355   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1356   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1357
1358   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1359
1360   if (dec->cinfo.num_components > 3)
1361     goto components_not_supported;
1362
1363   /* verify color space expectation to avoid going *boom* or bogus output */
1364   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1365       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1366       dec->cinfo.jpeg_color_space != JCS_RGB)
1367     goto unsupported_colorspace;
1368
1369 #ifndef GST_DISABLE_GST_DEBUG
1370   {
1371     gint i;
1372
1373     for (i = 0; i < dec->cinfo.num_components; ++i) {
1374       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1375           i, dec->cinfo.comp_info[i].h_samp_factor,
1376           dec->cinfo.comp_info[i].v_samp_factor,
1377           dec->cinfo.comp_info[i].component_id);
1378     }
1379   }
1380 #endif
1381
1382   /* prepare for raw output */
1383   dec->cinfo.do_fancy_upsampling = FALSE;
1384   dec->cinfo.do_block_smoothing = FALSE;
1385   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1386   dec->cinfo.dct_method = dec->idct_method;
1387   dec->cinfo.raw_data_out = TRUE;
1388
1389   GST_LOG_OBJECT (dec, "starting decompress");
1390   guarantee_huff_tables (&dec->cinfo);
1391   if (!jpeg_start_decompress (&dec->cinfo)) {
1392     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1393   }
1394
1395   /* sanity checks to get safe and reasonable output */
1396   switch (dec->cinfo.jpeg_color_space) {
1397     case JCS_GRAYSCALE:
1398       if (dec->cinfo.num_components != 1)
1399         goto invalid_yuvrgbgrayscale;
1400       break;
1401     case JCS_RGB:
1402       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1403           dec->cinfo.max_h_samp_factor > 1)
1404         goto invalid_yuvrgbgrayscale;
1405       break;
1406     case JCS_YCbCr:
1407       if (dec->cinfo.num_components != 3 ||
1408           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1409           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1410           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1411           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1412         goto invalid_yuvrgbgrayscale;
1413       break;
1414     default:
1415       g_assert_not_reached ();
1416       break;
1417   }
1418
1419   width = dec->cinfo.output_width;
1420   height = dec->cinfo.output_height;
1421
1422   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1423           height < MIN_HEIGHT || height > MAX_HEIGHT))
1424     goto wrong_size;
1425
1426   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1427
1428   ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
1429       dec->outsize, GST_PAD_CAPS (dec->srcpad), &outbuf);
1430   if (G_UNLIKELY (ret != GST_FLOW_OK))
1431     goto alloc_failed;
1432
1433   outdata = GST_BUFFER_DATA (outbuf);
1434   outsize = GST_BUFFER_SIZE (outbuf);
1435
1436   GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
1437       width, height, outsize, dec->outsize);
1438
1439   GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1440
1441   if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1442     if (GST_CLOCK_TIME_IS_VALID (duration)) {
1443       /* use duration from incoming buffer for outgoing buffer */
1444       dec->next_ts += duration;
1445     } else if (dec->framerate_numerator != 0) {
1446       duration = gst_util_uint64_scale (GST_SECOND,
1447           dec->framerate_denominator, dec->framerate_numerator);
1448       dec->next_ts += duration;
1449     } else {
1450       duration = GST_CLOCK_TIME_NONE;
1451       dec->next_ts = GST_CLOCK_TIME_NONE;
1452     }
1453   } else {
1454     duration = GST_CLOCK_TIME_NONE;
1455     dec->next_ts = GST_CLOCK_TIME_NONE;
1456   }
1457   GST_BUFFER_DURATION (outbuf) = duration;
1458
1459   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1460     base[0] = outdata + dec->offset[0];
1461     base[1] = outdata + dec->offset[1];
1462     base[2] = outdata + dec->offset[2];
1463     gst_jpeg_dec_decode_rgb (dec, base, width, height, dec->inc, dec->stride);
1464   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1465     base[0] = outdata + dec->offset[0];
1466     gst_jpeg_dec_decode_grayscale (dec, base, width, height, dec->inc,
1467         dec->stride);
1468   } else {
1469     /* mind the swap, jpeglib outputs blue chroma first
1470      * ensonic: I see no swap?
1471      */
1472     base[0] = outdata + I420_Y_OFFSET (width, height);
1473     base[1] = outdata + I420_U_OFFSET (width, height);
1474     base[2] = outdata + I420_V_OFFSET (width, height);
1475
1476     /* make sure we don't make jpeglib write beyond our buffer,
1477      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1478     last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1479     last[1] =
1480         base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1481             1));
1482     last[2] =
1483         base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1484             1));
1485
1486     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1487         dec->cinfo.rec_outbuf_height);
1488
1489     /* For some widths jpeglib requires more horizontal padding than I420 
1490      * provides. In those cases we need to decode into separate buffers and then
1491      * copy over the data into our final picture buffer, otherwise jpeglib might
1492      * write over the end of a line into the beginning of the next line,
1493      * resulting in blocky artifacts on the left side of the picture. */
1494     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1495             || dec->cinfo.comp_info[0].h_samp_factor != 2
1496             || dec->cinfo.comp_info[1].h_samp_factor != 1
1497             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1498       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1499           "indirect decoding using extra buffer copy");
1500       gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h,
1501           dec->cinfo.num_components);
1502     } else {
1503       ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1504
1505       if (G_UNLIKELY (ret != GST_FLOW_OK))
1506         goto decode_direct_failed;
1507     }
1508   }
1509
1510   GST_LOG_OBJECT (dec, "decompressing finished");
1511   jpeg_finish_decompress (&dec->cinfo);
1512
1513   /* Clipping */
1514   if (dec->segment.format == GST_FORMAT_TIME) {
1515     gint64 start, stop, clip_start, clip_stop;
1516
1517     GST_LOG_OBJECT (dec, "Attempting clipping");
1518
1519     start = GST_BUFFER_TIMESTAMP (outbuf);
1520     if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1521       stop = start;
1522     else
1523       stop = start + GST_BUFFER_DURATION (outbuf);
1524
1525     if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1526             start, stop, &clip_start, &clip_stop)) {
1527       GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1528           GST_TIME_ARGS (clip_start));
1529       GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1530       if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1531         GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1532             GST_TIME_ARGS (clip_stop - clip_start));
1533         GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1534       }
1535     } else
1536       goto drop_buffer;
1537   }
1538
1539   /* reset error count on successful decode */
1540   dec->error_count = 0;
1541
1542   ++dec->good_count;
1543
1544   GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1545       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1546       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1547
1548   ret = gst_pad_push (dec->srcpad, outbuf);
1549
1550 skip_decoding:
1551 done:
1552   gst_adapter_flush (dec->adapter, dec->rem_img_len);
1553
1554 exit:
1555
1556   if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1557     jpeg_abort_decompress (&dec->cinfo);
1558     ret = gst_jpeg_dec_post_error_or_warning (dec);
1559   }
1560
1561   return ret;
1562
1563   /* special cases */
1564 need_more_data:
1565   {
1566     GST_LOG_OBJECT (dec, "we need more data");
1567     if (outbuf) {
1568       gst_buffer_unref (outbuf);
1569       outbuf = NULL;
1570     }
1571     ret = GST_FLOW_OK;
1572     goto exit;
1573   }
1574   /* ERRORS */
1575 wrong_size:
1576   {
1577     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1578         "Picture is too small or too big (%ux%u)", width, height);
1579     ret = GST_FLOW_ERROR;
1580     goto done;
1581   }
1582 decode_error:
1583   {
1584     gchar err_msg[JMSG_LENGTH_MAX];
1585
1586     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1587
1588     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1589         "Decode error #%u: %s", code, err_msg);
1590
1591     if (outbuf) {
1592       gst_buffer_unref (outbuf);
1593       outbuf = NULL;
1594     }
1595     ret = GST_FLOW_ERROR;
1596     goto done;
1597   }
1598 decode_direct_failed:
1599   {
1600     /* already posted an error message */
1601     jpeg_abort_decompress (&dec->cinfo);
1602     gst_buffer_replace (&outbuf, NULL);
1603     goto done;
1604   }
1605 alloc_failed:
1606   {
1607     const gchar *reason;
1608
1609     reason = gst_flow_get_name (ret);
1610
1611     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1612     /* Reset for next time */
1613     jpeg_abort_decompress (&dec->cinfo);
1614     if (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_WRONG_STATE &&
1615         ret != GST_FLOW_NOT_LINKED) {
1616       gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1617           "Buffer allocation failed, reason: %s", reason);
1618     }
1619     goto exit;
1620   }
1621 drop_buffer:
1622   {
1623     GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1624     gst_buffer_unref (outbuf);
1625     ret = GST_FLOW_OK;
1626     goto exit;
1627   }
1628 components_not_supported:
1629   {
1630     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1631         "number of components not supported: %d (max 3)",
1632         dec->cinfo.num_components);
1633     ret = GST_FLOW_ERROR;
1634     goto done;
1635   }
1636 unsupported_colorspace:
1637   {
1638     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1639         "Picture has unknown or unsupported colourspace");
1640     ret = GST_FLOW_ERROR;
1641     goto done;
1642   }
1643 invalid_yuvrgbgrayscale:
1644   {
1645     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1646         "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1647     ret = GST_FLOW_ERROR;
1648     goto done;
1649   }
1650 }
1651
1652 static gboolean
1653 gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
1654 {
1655   GstJpegDec *dec;
1656   gboolean res;
1657
1658   dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
1659   if (G_UNLIKELY (dec == NULL)) {
1660     gst_event_unref (event);
1661     return FALSE;
1662   }
1663
1664   switch (GST_EVENT_TYPE (event)) {
1665     case GST_EVENT_QOS:{
1666       GstClockTimeDiff diff;
1667       GstClockTime timestamp;
1668       gdouble proportion;
1669
1670       gst_event_parse_qos (event, &proportion, &diff, &timestamp);
1671       gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1672       break;
1673     }
1674     default:
1675       break;
1676   }
1677
1678   res = gst_pad_push_event (dec->sinkpad, event);
1679
1680   gst_object_unref (dec);
1681   return res;
1682 }
1683
1684 static gboolean
1685 gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event)
1686 {
1687   gboolean ret = TRUE;
1688   GstJpegDec *dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
1689
1690   GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1691
1692   switch (GST_EVENT_TYPE (event)) {
1693     case GST_EVENT_FLUSH_STOP:
1694       GST_DEBUG_OBJECT (dec, "Aborting decompress");
1695       jpeg_abort_decompress (&dec->cinfo);
1696       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1697       gst_adapter_clear (dec->adapter);
1698       g_free (dec->cur_buf);
1699       dec->cur_buf = NULL;
1700       dec->parse_offset = 0;
1701       dec->parse_entropy_len = 0;
1702       dec->parse_resync = FALSE;
1703       gst_jpeg_dec_reset_qos (dec);
1704       break;
1705     case GST_EVENT_NEWSEGMENT:{
1706       gboolean update;
1707       gdouble rate, applied_rate;
1708       GstFormat format;
1709       gint64 start, stop, position;
1710
1711       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1712           &format, &start, &stop, &position);
1713
1714       GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
1715           " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
1716           GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
1717           GST_TIME_ARGS (position));
1718
1719       gst_segment_set_newsegment_full (&dec->segment, update, rate,
1720           applied_rate, format, start, stop, position);
1721
1722       break;
1723     }
1724     default:
1725       break;
1726   }
1727
1728   ret = gst_pad_push_event (dec->srcpad, event);
1729
1730   return ret;
1731 }
1732
1733 static void
1734 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1735     const GValue * value, GParamSpec * pspec)
1736 {
1737   GstJpegDec *dec;
1738
1739   dec = GST_JPEG_DEC (object);
1740
1741   switch (prop_id) {
1742     case PROP_IDCT_METHOD:
1743       dec->idct_method = g_value_get_enum (value);
1744       break;
1745     case PROP_MAX_ERRORS:
1746       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1747       break;
1748
1749     default:
1750       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1751       break;
1752   }
1753 }
1754
1755 static void
1756 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1757     GParamSpec * pspec)
1758 {
1759   GstJpegDec *dec;
1760
1761   dec = GST_JPEG_DEC (object);
1762
1763   switch (prop_id) {
1764     case PROP_IDCT_METHOD:
1765       g_value_set_enum (value, dec->idct_method);
1766       break;
1767     case PROP_MAX_ERRORS:
1768       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1769       break;
1770
1771     default:
1772       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1773       break;
1774   }
1775 }
1776
1777 static GstStateChangeReturn
1778 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1779 {
1780   GstStateChangeReturn ret;
1781   GstJpegDec *dec;
1782
1783   dec = GST_JPEG_DEC (element);
1784
1785   switch (transition) {
1786     case GST_STATE_CHANGE_READY_TO_PAUSED:
1787       dec->error_count = 0;
1788       dec->good_count = 0;
1789       dec->framerate_numerator = 0;
1790       dec->framerate_denominator = 1;
1791       dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
1792       dec->caps_width = -1;
1793       dec->caps_height = -1;
1794       dec->clrspc = -1;
1795       dec->packetized = FALSE;
1796       dec->next_ts = 0;
1797       dec->discont = TRUE;
1798       dec->parse_offset = 0;
1799       dec->parse_entropy_len = 0;
1800       dec->parse_resync = FALSE;
1801       dec->cur_buf = NULL;
1802       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1803       gst_jpeg_dec_reset_qos (dec);
1804     default:
1805       break;
1806   }
1807
1808   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1809   if (ret != GST_STATE_CHANGE_SUCCESS)
1810     return ret;
1811
1812   switch (transition) {
1813     case GST_STATE_CHANGE_PAUSED_TO_READY:
1814       gst_adapter_clear (dec->adapter);
1815       g_free (dec->cur_buf);
1816       dec->cur_buf = NULL;
1817       gst_jpeg_dec_free_buffers (dec);
1818       break;
1819     default:
1820       break;
1821   }
1822
1823   return ret;
1824 }