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