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