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