Use new gst_element_class_set_static_metadata()
[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 /* 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_static_metadata (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;
1167   guint size, min, max;
1168   GstStructure *config;
1169   static GstAllocationParams params = { 0, 0, 0, 15, };
1170
1171   GST_DEBUG_OBJECT (dec, "setting up bufferpool");
1172
1173   /* find a pool for the negotiated caps now */
1174   query = gst_query_new_allocation (caps, TRUE);
1175
1176   if (!gst_pad_peer_query (dec->srcpad, query)) {
1177     GST_DEBUG_OBJECT (dec, "peer query failed, using defaults");
1178   }
1179
1180   if (gst_query_get_n_allocation_pools (query) > 0) {
1181     /* we got configuration from our peer, parse them */
1182     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
1183     size = MAX (size, dec->info.size);
1184   } else {
1185     pool = NULL;
1186     size = dec->info.size;
1187     min = max = 0;
1188   }
1189   gst_query_unref (query);
1190
1191   if (pool == NULL) {
1192     /* we did not get a pool, make one ourselves then */
1193     pool = gst_buffer_pool_new ();
1194   }
1195
1196   config = gst_buffer_pool_get_config (pool);
1197   gst_buffer_pool_config_set_params (config, caps, size, min, max);
1198   gst_buffer_pool_config_set_allocator (config, NULL, &params);
1199   /* and store */
1200   gst_buffer_pool_set_config (pool, config);
1201
1202   if (dec->pool) {
1203     gst_buffer_pool_set_active (dec->pool, FALSE);
1204     gst_object_unref (dec->pool);
1205   }
1206   dec->pool = pool;
1207
1208   /* and activate */
1209   gst_buffer_pool_set_active (pool, TRUE);
1210
1211   return TRUE;
1212 }
1213
1214 static gboolean
1215 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1216 {
1217   GstCaps *caps;
1218   GstVideoFormat format;
1219   GstVideoInfo info;
1220
1221   if (G_UNLIKELY (width == dec->info.width && height == dec->info.height &&
1222           dec->in_fps_n == dec->info.fps_n && dec->in_fps_d == dec->info.fps_d
1223           && clrspc == dec->clrspc))
1224     return TRUE;
1225
1226   gst_video_info_init (&info);
1227
1228   /* framerate == 0/1 is a still frame */
1229   if (dec->in_fps_d == 0) {
1230     info.fps_n = 0;
1231     info.fps_d = 1;
1232   } else {
1233     info.fps_n = dec->in_fps_n;
1234     info.fps_d = dec->in_fps_d;
1235   }
1236
1237   /* calculate or assume an average frame duration for QoS purposes */
1238   GST_OBJECT_LOCK (dec);
1239   if (info.fps_n != 0) {
1240     dec->qos_duration =
1241         gst_util_uint64_scale (GST_SECOND, info.fps_d, info.fps_n);
1242     dec->duration = dec->qos_duration;
1243   } else {
1244     /* if not set just use 25fps */
1245     dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1246     dec->duration = GST_CLOCK_TIME_NONE;
1247   }
1248   GST_OBJECT_UNLOCK (dec);
1249
1250   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1251     gint i;
1252     GstCaps *allowed_caps;
1253     GstVideoInfo tmpinfo;
1254
1255     GST_DEBUG_OBJECT (dec, "selecting RGB format");
1256     /* retrieve allowed caps, and find the first one that reasonably maps
1257      * to the parameters of the colourspace */
1258     caps = gst_pad_get_allowed_caps (dec->srcpad);
1259     if (!caps) {
1260       GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1261       /* need to copy because get_allowed_caps returns a ref,
1262        * and get_pad_template_caps doesn't */
1263       caps = gst_pad_get_pad_template_caps (dec->srcpad);
1264     }
1265     /* avoid lists of formats, etc */
1266     allowed_caps = gst_caps_normalize (caps);
1267     caps = NULL;
1268     GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1269
1270     for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1271       if (caps)
1272         gst_caps_unref (caps);
1273       caps = gst_caps_copy_nth (allowed_caps, i);
1274       /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1275       caps = gst_caps_fixate (caps);
1276       GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1277
1278       if (!gst_video_info_from_caps (&tmpinfo, caps))
1279         continue;
1280       /* we'll settle for the first (preferred) downstream rgb format */
1281       if (GST_VIDEO_INFO_IS_RGB (&tmpinfo))
1282         break;
1283       /* default fall-back */
1284       format = GST_VIDEO_FORMAT_RGB;
1285     }
1286     if (caps)
1287       gst_caps_unref (caps);
1288     gst_caps_unref (allowed_caps);
1289   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1290     /* TODO is anything else then 8bit supported in jpeg? */
1291     format = GST_VIDEO_FORMAT_GRAY8;
1292   } else {
1293     /* go for plain and simple I420 */
1294     /* TODO other YUV cases ? */
1295     format = GST_VIDEO_FORMAT_I420;
1296   }
1297
1298   gst_video_info_set_format (&info, format, width, height);
1299   caps = gst_video_info_to_caps (&info);
1300
1301   GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1302   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1303   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1304
1305   gst_pad_set_caps (dec->srcpad, caps);
1306
1307   dec->info = info;
1308   dec->clrspc = clrspc;
1309
1310   gst_jpeg_dec_buffer_pool (dec, caps);
1311   gst_caps_unref (caps);
1312
1313   return TRUE;
1314 }
1315
1316 static GstFlowReturn
1317 gst_jpeg_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1318 {
1319   GstFlowReturn ret = GST_FLOW_OK;
1320   GstJpegDec *dec;
1321   GstBuffer *outbuf = NULL;
1322   gint img_len;
1323   gint width, height;
1324   gint r_h, r_v;
1325   guint code, hdr_ok;
1326   GstClockTime timestamp, duration;
1327   GstVideoFrame frame;
1328
1329   dec = GST_JPEG_DEC (parent);
1330
1331   timestamp = GST_BUFFER_TIMESTAMP (buf);
1332   duration = GST_BUFFER_DURATION (buf);
1333
1334   if (GST_CLOCK_TIME_IS_VALID (timestamp))
1335     dec->next_ts = timestamp;
1336
1337   if (GST_BUFFER_IS_DISCONT (buf)) {
1338     GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1339     dec->discont = TRUE;
1340     if (!dec->packetized && gst_adapter_available (dec->adapter)) {
1341       GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1342       gst_adapter_clear (dec->adapter);
1343     }
1344   }
1345
1346   gst_adapter_push (dec->adapter, buf);
1347   buf = NULL;
1348
1349   /* If we are non-packetized and know the total incoming size in bytes,
1350    * just wait until we have enough before doing any processing. */
1351
1352   if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1353       (dec->segment.stop != -1) &&
1354       (gst_adapter_available (dec->adapter) < dec->segment.stop)) {
1355     /* We assume that non-packetized input in bytes is *one* single jpeg image */
1356     GST_DEBUG ("Non-packetized mode. Got %" G_GSIZE_FORMAT " bytes, "
1357         "need %" G_GINT64_FORMAT, gst_adapter_available (dec->adapter),
1358         dec->segment.stop);
1359     goto need_more_data;
1360   }
1361
1362 again:
1363   if (!gst_jpeg_dec_ensure_header (dec))
1364     goto need_more_data;
1365
1366   /* If we know that each input buffer contains data
1367    * for a whole jpeg image (e.g. MJPEG streams), just 
1368    * do some sanity checking instead of parsing all of 
1369    * the jpeg data */
1370   if (dec->packetized) {
1371     img_len = gst_adapter_available (dec->adapter);
1372   } else {
1373     /* Parse jpeg image to handle jpeg input that
1374      * is not aligned to buffer boundaries */
1375     img_len = gst_jpeg_dec_parse_image_data (dec);
1376
1377     if (img_len == 0) {
1378       goto need_more_data;
1379     } else if (img_len < 0) {
1380       gst_adapter_flush (dec->adapter, -img_len);
1381       goto again;
1382     }
1383   }
1384
1385   dec->rem_img_len = img_len;
1386
1387   GST_LOG_OBJECT (dec, "image size = %u", img_len);
1388
1389   /* QoS: if we're too late anyway, skip decoding */
1390   if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1391     goto skip_decoding;
1392
1393 #ifndef GST_DISABLE_GST_DEBUG
1394   {
1395     guchar data[4];
1396
1397     gst_adapter_copy (dec->adapter, data, 0, 4);
1398     GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1399         data[2], data[3]);
1400   }
1401 #endif
1402
1403   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1404
1405   if (setjmp (dec->jerr.setjmp_buffer)) {
1406     code = dec->jerr.pub.msg_code;
1407
1408     if (code == JERR_INPUT_EOF) {
1409       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1410       goto need_more_data;
1411     }
1412     goto decode_error;
1413   }
1414
1415   /* read header */
1416   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1417   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1418     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1419   }
1420
1421   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1422   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1423
1424   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1425     goto components_not_supported;
1426
1427   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1428   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1429
1430   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1431
1432   if (dec->cinfo.num_components > 3)
1433     goto components_not_supported;
1434
1435   /* verify color space expectation to avoid going *boom* or bogus output */
1436   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1437       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1438       dec->cinfo.jpeg_color_space != JCS_RGB)
1439     goto unsupported_colorspace;
1440
1441 #ifndef GST_DISABLE_GST_DEBUG
1442   {
1443     gint i;
1444
1445     for (i = 0; i < dec->cinfo.num_components; ++i) {
1446       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1447           i, dec->cinfo.comp_info[i].h_samp_factor,
1448           dec->cinfo.comp_info[i].v_samp_factor,
1449           dec->cinfo.comp_info[i].component_id);
1450     }
1451   }
1452 #endif
1453
1454   /* prepare for raw output */
1455   dec->cinfo.do_fancy_upsampling = FALSE;
1456   dec->cinfo.do_block_smoothing = FALSE;
1457   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1458   dec->cinfo.dct_method = dec->idct_method;
1459   dec->cinfo.raw_data_out = TRUE;
1460
1461   GST_LOG_OBJECT (dec, "starting decompress");
1462   guarantee_huff_tables (&dec->cinfo);
1463   if (!jpeg_start_decompress (&dec->cinfo)) {
1464     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1465   }
1466
1467   /* sanity checks to get safe and reasonable output */
1468   switch (dec->cinfo.jpeg_color_space) {
1469     case JCS_GRAYSCALE:
1470       if (dec->cinfo.num_components != 1)
1471         goto invalid_yuvrgbgrayscale;
1472       break;
1473     case JCS_RGB:
1474       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1475           dec->cinfo.max_h_samp_factor > 1)
1476         goto invalid_yuvrgbgrayscale;
1477       break;
1478     case JCS_YCbCr:
1479       if (dec->cinfo.num_components != 3 ||
1480           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1481           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1482           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1483           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1484         goto invalid_yuvrgbgrayscale;
1485       break;
1486     default:
1487       g_assert_not_reached ();
1488       break;
1489   }
1490
1491   width = dec->cinfo.output_width;
1492   height = dec->cinfo.output_height;
1493
1494   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1495           height < MIN_HEIGHT || height > MAX_HEIGHT))
1496     goto wrong_size;
1497
1498   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1499
1500   ret = gst_buffer_pool_acquire_buffer (dec->pool, &outbuf, NULL);
1501   if (G_UNLIKELY (ret != GST_FLOW_OK))
1502     goto alloc_failed;
1503
1504   if (!gst_video_frame_map (&frame, &dec->info, outbuf, GST_MAP_READWRITE))
1505     goto invalid_frame;
1506
1507   GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1508
1509   GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1510
1511   if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1512     if (GST_CLOCK_TIME_IS_VALID (duration)) {
1513       /* use duration from incoming buffer for outgoing buffer */
1514       dec->next_ts += duration;
1515     } else if (GST_CLOCK_TIME_IS_VALID (dec->duration)) {
1516       duration = dec->duration;
1517       dec->next_ts += dec->duration;
1518     } else {
1519       duration = GST_CLOCK_TIME_NONE;
1520       dec->next_ts = GST_CLOCK_TIME_NONE;
1521     }
1522   } else {
1523     duration = GST_CLOCK_TIME_NONE;
1524     dec->next_ts = GST_CLOCK_TIME_NONE;
1525   }
1526   GST_BUFFER_DURATION (outbuf) = duration;
1527
1528   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1529     gst_jpeg_dec_decode_rgb (dec, &frame);
1530   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1531     gst_jpeg_dec_decode_grayscale (dec, &frame);
1532   } else {
1533     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1534         dec->cinfo.rec_outbuf_height);
1535
1536     /* For some widths jpeglib requires more horizontal padding than I420 
1537      * provides. In those cases we need to decode into separate buffers and then
1538      * copy over the data into our final picture buffer, otherwise jpeglib might
1539      * write over the end of a line into the beginning of the next line,
1540      * resulting in blocky artifacts on the left side of the picture. */
1541     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1542             || dec->cinfo.comp_info[0].h_samp_factor != 2
1543             || dec->cinfo.comp_info[1].h_samp_factor != 1
1544             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1545       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1546           "indirect decoding using extra buffer copy");
1547       gst_jpeg_dec_decode_indirect (dec, &frame, r_v, r_h,
1548           dec->cinfo.num_components);
1549     } else {
1550       ret = gst_jpeg_dec_decode_direct (dec, &frame);
1551       if (G_UNLIKELY (ret != GST_FLOW_OK))
1552         goto decode_direct_failed;
1553     }
1554   }
1555
1556   GST_LOG_OBJECT (dec, "decompressing finished");
1557   jpeg_finish_decompress (&dec->cinfo);
1558
1559   gst_video_frame_unmap (&frame);
1560
1561   /* Clipping */
1562   if (dec->segment.format == GST_FORMAT_TIME) {
1563     guint64 start, stop, clip_start, clip_stop;
1564
1565     GST_LOG_OBJECT (dec, "Attempting clipping");
1566
1567     start = GST_BUFFER_TIMESTAMP (outbuf);
1568     if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1569       stop = start;
1570     else
1571       stop = start + GST_BUFFER_DURATION (outbuf);
1572
1573     if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1574             start, stop, &clip_start, &clip_stop)) {
1575       GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1576           GST_TIME_ARGS (clip_start));
1577       GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1578       if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1579         GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1580             GST_TIME_ARGS (clip_stop - clip_start));
1581         GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1582       }
1583     } else
1584       goto drop_buffer;
1585   }
1586
1587   /* reset error count on successful decode */
1588   dec->error_count = 0;
1589
1590   ++dec->good_count;
1591
1592   GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1593       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1594       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1595
1596   ret = gst_pad_push (dec->srcpad, outbuf);
1597
1598 skip_decoding:
1599 done:
1600   gst_adapter_flush (dec->adapter, dec->rem_img_len);
1601
1602 exit:
1603
1604   if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1605     jpeg_abort_decompress (&dec->cinfo);
1606     ret = gst_jpeg_dec_post_error_or_warning (dec);
1607   }
1608
1609   return ret;
1610
1611   /* special cases */
1612 need_more_data:
1613   {
1614     GST_LOG_OBJECT (dec, "we need more data");
1615     if (outbuf) {
1616       gst_buffer_unref (outbuf);
1617       outbuf = NULL;
1618     }
1619     ret = GST_FLOW_OK;
1620     goto exit;
1621   }
1622   /* ERRORS */
1623 wrong_size:
1624   {
1625     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1626         "Picture is too small or too big (%ux%u)", width, height);
1627     ret = GST_FLOW_ERROR;
1628     goto done;
1629   }
1630 decode_error:
1631   {
1632     gchar err_msg[JMSG_LENGTH_MAX];
1633
1634     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1635
1636     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1637         "Decode error #%u: %s", code, err_msg);
1638
1639     if (outbuf) {
1640       gst_buffer_unref (outbuf);
1641       outbuf = NULL;
1642     }
1643     ret = GST_FLOW_ERROR;
1644     goto done;
1645   }
1646 decode_direct_failed:
1647   {
1648     /* already posted an error message */
1649     jpeg_abort_decompress (&dec->cinfo);
1650     gst_buffer_replace (&outbuf, NULL);
1651     goto done;
1652   }
1653 alloc_failed:
1654   {
1655     const gchar *reason;
1656
1657     reason = gst_flow_get_name (ret);
1658
1659     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1660     /* Reset for next time */
1661     jpeg_abort_decompress (&dec->cinfo);
1662     if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1663         ret != GST_FLOW_NOT_LINKED) {
1664       gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1665           "Buffer allocation failed, reason: %s", reason);
1666     }
1667     goto exit;
1668   }
1669 invalid_frame:
1670   {
1671     jpeg_abort_decompress (&dec->cinfo);
1672     gst_buffer_unref (outbuf);
1673     ret = GST_FLOW_OK;
1674     goto exit;
1675   }
1676 drop_buffer:
1677   {
1678     GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1679     gst_buffer_unref (outbuf);
1680     ret = GST_FLOW_OK;
1681     goto exit;
1682   }
1683 components_not_supported:
1684   {
1685     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1686         "number of components not supported: %d (max 3)",
1687         dec->cinfo.num_components);
1688     ret = GST_FLOW_ERROR;
1689     goto done;
1690   }
1691 unsupported_colorspace:
1692   {
1693     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1694         "Picture has unknown or unsupported colourspace");
1695     ret = GST_FLOW_ERROR;
1696     goto done;
1697   }
1698 invalid_yuvrgbgrayscale:
1699   {
1700     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1701         "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1702     ret = GST_FLOW_ERROR;
1703     goto done;
1704   }
1705 }
1706
1707 static gboolean
1708 gst_jpeg_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1709 {
1710   GstJpegDec *dec;
1711   gboolean res;
1712
1713   dec = GST_JPEG_DEC (parent);
1714
1715   switch (GST_EVENT_TYPE (event)) {
1716     case GST_EVENT_QOS:{
1717       GstQOSType type;
1718       GstClockTimeDiff diff;
1719       GstClockTime timestamp;
1720       gdouble proportion;
1721
1722       gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
1723       gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1724       break;
1725     }
1726     default:
1727       break;
1728   }
1729
1730   res = gst_pad_push_event (dec->sinkpad, event);
1731
1732   return res;
1733 }
1734
1735 static gboolean
1736 gst_jpeg_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1737 {
1738   gboolean ret = TRUE, forward = TRUE;
1739   GstJpegDec *dec = GST_JPEG_DEC (parent);
1740
1741   GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1742
1743   switch (GST_EVENT_TYPE (event)) {
1744     case GST_EVENT_FLUSH_STOP:
1745       GST_DEBUG_OBJECT (dec, "Aborting decompress");
1746       jpeg_abort_decompress (&dec->cinfo);
1747       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1748       gst_adapter_clear (dec->adapter);
1749       g_free (dec->cur_buf);
1750       dec->cur_buf = NULL;
1751       dec->parse_offset = 0;
1752       dec->parse_entropy_len = 0;
1753       dec->parse_resync = FALSE;
1754       gst_jpeg_dec_reset_qos (dec);
1755       break;
1756     case GST_EVENT_SEGMENT:
1757       gst_event_copy_segment (event, &dec->segment);
1758       GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT,
1759           &dec->segment);
1760       break;
1761     case GST_EVENT_CAPS:
1762     {
1763       GstCaps *caps;
1764
1765       gst_event_parse_caps (event, &caps);
1766       ret = gst_jpeg_dec_setcaps (dec, caps);
1767       forward = FALSE;
1768       break;
1769     }
1770     default:
1771       break;
1772   }
1773
1774   if (forward)
1775     ret = gst_pad_push_event (dec->srcpad, event);
1776   else
1777     gst_event_unref (event);
1778
1779   return ret;
1780 }
1781
1782 static gboolean
1783 gst_jpeg_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
1784 {
1785   gboolean res = FALSE;
1786
1787   switch (GST_QUERY_TYPE (query)) {
1788     case GST_QUERY_CAPS:
1789     {
1790       GstCaps *filter, *caps;
1791
1792       gst_query_parse_caps (query, &filter);
1793       caps = gst_jpeg_dec_getcaps (pad, filter);
1794       gst_query_set_caps_result (query, caps);
1795       gst_caps_unref (caps);
1796       res = TRUE;
1797       break;
1798     }
1799     default:
1800       res = gst_pad_query_default (pad, parent, query);
1801       break;
1802   }
1803   return res;
1804 }
1805
1806 static void
1807 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1808     const GValue * value, GParamSpec * pspec)
1809 {
1810   GstJpegDec *dec;
1811
1812   dec = GST_JPEG_DEC (object);
1813
1814   switch (prop_id) {
1815     case PROP_IDCT_METHOD:
1816       dec->idct_method = g_value_get_enum (value);
1817       break;
1818     case PROP_MAX_ERRORS:
1819       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1820       break;
1821
1822     default:
1823       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1824       break;
1825   }
1826 }
1827
1828 static void
1829 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1830     GParamSpec * pspec)
1831 {
1832   GstJpegDec *dec;
1833
1834   dec = GST_JPEG_DEC (object);
1835
1836   switch (prop_id) {
1837     case PROP_IDCT_METHOD:
1838       g_value_set_enum (value, dec->idct_method);
1839       break;
1840     case PROP_MAX_ERRORS:
1841       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1842       break;
1843
1844     default:
1845       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1846       break;
1847   }
1848 }
1849
1850 static GstStateChangeReturn
1851 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1852 {
1853   GstStateChangeReturn ret;
1854   GstJpegDec *dec;
1855
1856   dec = GST_JPEG_DEC (element);
1857
1858   switch (transition) {
1859     case GST_STATE_CHANGE_READY_TO_PAUSED:
1860       dec->error_count = 0;
1861       dec->good_count = 0;
1862       dec->in_fps_n = 0;
1863       dec->in_fps_d = 1;
1864       gst_video_info_init (&dec->info);
1865       dec->clrspc = -1;
1866       dec->packetized = FALSE;
1867       dec->next_ts = 0;
1868       dec->discont = TRUE;
1869       dec->parse_offset = 0;
1870       dec->parse_entropy_len = 0;
1871       dec->parse_resync = FALSE;
1872       dec->cur_buf = NULL;
1873       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1874       gst_jpeg_dec_reset_qos (dec);
1875     default:
1876       break;
1877   }
1878
1879   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1880   if (ret != GST_STATE_CHANGE_SUCCESS)
1881     return ret;
1882
1883   switch (transition) {
1884     case GST_STATE_CHANGE_PAUSED_TO_READY:
1885       gst_adapter_clear (dec->adapter);
1886       g_free (dec->cur_buf);
1887       dec->cur_buf = NULL;
1888       gst_jpeg_dec_free_buffers (dec);
1889       if (dec->pool) {
1890         gst_buffer_pool_set_active (dec->pool, FALSE);
1891         gst_object_unref (dec->pool);
1892       }
1893       dec->pool = NULL;
1894       break;
1895     default:
1896       break;
1897   }
1898
1899   return ret;
1900 }