Merge commit '38516ad367128d83f9e156529018adb4433cd328' into 0.11
[platform/upstream/gst-plugins-good.git] / ext / jpeg / gstjpegdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:element-jpegdec
23  *
24  * Decodes jpeg images.
25  *
26  * <refsect2>
27  * <title>Example launch line</title>
28  * |[
29  * gst-launch -v v4l2src ! jpegdec ! ffmpegcolorspace ! xvimagesink
30  * ]| The above pipeline reads a motion JPEG stream from a v4l2 camera
31  * and renders it to the screen.
32  * </refsect2>
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 #include <string.h>
39
40 #include "gstjpegdec.h"
41 #include "gstjpeg.h"
42 #include <gst/video/video.h>
43 #include "gst/gst-i18n-plugin.h"
44 #include <jerror.h>
45
46 #define MIN_WIDTH  1
47 #define MAX_WIDTH  65535
48 #define MIN_HEIGHT 1
49 #define MAX_HEIGHT 65535
50
51 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
52         (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
53
54 #define JPEG_DEFAULT_IDCT_METHOD        JDCT_FASTEST
55 #define JPEG_DEFAULT_MAX_ERRORS         0
56
57 enum
58 {
59   PROP_0,
60   PROP_IDCT_METHOD,
61   PROP_MAX_ERRORS
62 };
63
64 /* *INDENT-OFF* */
65 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
66 GST_STATIC_PAD_TEMPLATE ("src",
67     GST_PAD_SRC,
68     GST_PAD_ALWAYS,
69     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
70         ("{ I420, RGB, BGR, RGBx, xRGB, BGRx, xBGR, GRAY8 }"))
71     );
72
73 /* *INDENT-ON* */
74
75 /* 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
737   dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
738
739   if (gst_pad_has_current_caps (pad))
740     return gst_pad_get_current_caps (pad);
741
742   peer = gst_pad_get_peer (dec->srcpad);
743
744   if (peer) {
745     GstCaps *peer_caps;
746     const GstCaps *templ_caps;
747     GstStructure *s;
748     guint i, n;
749
750     peer_caps = gst_pad_query_caps (peer, filter);
751
752     /* Translate peercaps to image/jpeg */
753     peer_caps = gst_caps_make_writable (peer_caps);
754     n = gst_caps_get_size (peer_caps);
755     for (i = 0; i < n; i++) {
756       s = gst_caps_get_structure (peer_caps, i);
757
758       gst_structure_set_name (s, "image/jpeg");
759     }
760
761     templ_caps = gst_pad_get_pad_template_caps (pad);
762     caps = gst_caps_intersect_full (peer_caps, templ_caps,
763         GST_CAPS_INTERSECT_FIRST);
764     gst_caps_unref (peer_caps);
765     gst_object_unref (peer);
766   } else {
767     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
768   }
769
770   return caps;
771 }
772
773
774 /* yuk */
775 static void
776 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
777 {
778   gint i;
779
780   for (i = 0; i < len; ++i) {
781     /* equivalent to: dest[i] = src[i << 1] */
782     *dest = *src;
783     ++dest;
784     ++src;
785     ++src;
786   }
787 }
788
789 static void
790 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
791 {
792   gint i;
793
794   for (i = 0; i < 16; i++) {
795     g_free (dec->idr_y[i]);
796     g_free (dec->idr_u[i]);
797     g_free (dec->idr_v[i]);
798     dec->idr_y[i] = NULL;
799     dec->idr_u[i] = NULL;
800     dec->idr_v[i] = NULL;
801   }
802
803   dec->idr_width_allocated = 0;
804 }
805
806 static inline gboolean
807 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
808 {
809   gint i;
810
811   if (G_LIKELY (dec->idr_width_allocated >= maxrowbytes))
812     return TRUE;
813
814   /* FIXME: maybe just alloc one or three blocks altogether? */
815   for (i = 0; i < 16; i++) {
816     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
817     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
818     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
819
820     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
821       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
822       return FALSE;
823     }
824   }
825
826   dec->idr_width_allocated = maxrowbytes;
827   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
828   return TRUE;
829 }
830
831 static void
832 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, GstVideoFrame * frame)
833 {
834   guchar *rows[16];
835   guchar **scanarray[1] = { rows };
836   gint i, j, k;
837   gint lines;
838   guint8 *base[1];
839   gint width, height;
840   gint pstride, rstride;
841
842   GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
843
844   width = GST_VIDEO_FRAME_WIDTH (frame);
845   height = GST_VIDEO_FRAME_HEIGHT (frame);
846
847   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
848     return;
849
850   base[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
851   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
852   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
853
854   memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
855
856   i = 0;
857   while (i < height) {
858     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
859     if (G_LIKELY (lines > 0)) {
860       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
861         gint p;
862
863         p = 0;
864         for (k = 0; k < width; k++) {
865           base[0][p] = rows[j][k];
866           p += pstride;
867         }
868         base[0] += rstride;
869       }
870     } else {
871       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
872     }
873   }
874 }
875
876 static void
877 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, GstVideoFrame * frame)
878 {
879   guchar *r_rows[16], *g_rows[16], *b_rows[16];
880   guchar **scanarray[3] = { r_rows, g_rows, b_rows };
881   gint i, j, k;
882   gint lines;
883   guint8 *base[3];
884   guint pstride, rstride;
885   gint width, height;
886
887   GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
888
889   width = GST_VIDEO_FRAME_WIDTH (frame);
890   height = GST_VIDEO_FRAME_HEIGHT (frame);
891
892   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
893     return;
894
895   for (i = 0; i < 3; i++)
896     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
897
898   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
899   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
900
901   memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
902   memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
903   memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
904
905   i = 0;
906   while (i < height) {
907     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
908     if (G_LIKELY (lines > 0)) {
909       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
910         gint p;
911
912         p = 0;
913         for (k = 0; k < width; k++) {
914           base[0][p] = r_rows[j][k];
915           base[1][p] = g_rows[j][k];
916           base[2][p] = b_rows[j][k];
917           p += pstride;
918         }
919         base[0] += rstride;
920         base[1] += rstride;
921         base[2] += rstride;
922       }
923     } else {
924       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
925     }
926   }
927 }
928
929 static void
930 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame,
931     gint r_v, gint r_h, gint comp)
932 {
933   guchar *y_rows[16], *u_rows[16], *v_rows[16];
934   guchar **scanarray[3] = { y_rows, u_rows, v_rows };
935   gint i, j, k;
936   gint lines;
937   guchar *base[3], *last[3];
938   gint stride[3];
939   gint width, height;
940
941   GST_DEBUG_OBJECT (dec,
942       "unadvantageous width or r_h, taking slow route involving memcpy");
943
944   width = GST_VIDEO_FRAME_WIDTH (frame);
945   height = GST_VIDEO_FRAME_HEIGHT (frame);
946
947   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
948     return;
949
950   for (i = 0; i < 3; i++) {
951     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
952     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
953     /* make sure we don't make jpeglib write beyond our buffer,
954      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
955     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
956         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
957   }
958
959   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
960   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
961   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
962
963   /* fill chroma components for grayscale */
964   if (comp == 1) {
965     GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
966     for (i = 0; i < 16; i++) {
967       memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
968       memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
969     }
970   }
971
972   for (i = 0; i < height; i += r_v * DCTSIZE) {
973     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
974     if (G_LIKELY (lines > 0)) {
975       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
976         if (G_LIKELY (base[0] <= last[0])) {
977           memcpy (base[0], y_rows[j], stride[0]);
978           base[0] += stride[0];
979         }
980         if (r_v == 2) {
981           if (G_LIKELY (base[0] <= last[0])) {
982             memcpy (base[0], y_rows[j + 1], stride[0]);
983             base[0] += stride[0];
984           }
985         }
986         if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
987           if (r_h == 2) {
988             memcpy (base[1], u_rows[k], stride[1]);
989             memcpy (base[2], v_rows[k], stride[2]);
990           } else if (r_h == 1) {
991             hresamplecpy1 (base[1], u_rows[k], stride[1]);
992             hresamplecpy1 (base[2], v_rows[k], stride[2]);
993           } else {
994             /* FIXME: implement (at least we avoid crashing by doing nothing) */
995           }
996         }
997
998         if (r_v == 2 || (k & 1) != 0) {
999           base[1] += stride[1];
1000           base[2] += stride[2];
1001         }
1002       }
1003     } else {
1004       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1005     }
1006   }
1007 }
1008
1009 static GstFlowReturn
1010 gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame)
1011 {
1012   guchar **line[3];             /* the jpeg line buffer         */
1013   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
1014   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
1015   guchar *v[4 * DCTSIZE] = { NULL, };
1016   gint i, j;
1017   gint lines, v_samp[3];
1018   guchar *base[3], *last[3];
1019   gint stride[3];
1020   guint height;
1021
1022   line[0] = y;
1023   line[1] = u;
1024   line[2] = v;
1025
1026   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1027   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1028   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1029
1030   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1031     goto format_not_supported;
1032
1033   height = GST_VIDEO_FRAME_HEIGHT (frame);
1034
1035   for (i = 0; i < 3; i++) {
1036     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
1037     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
1038     /* make sure we don't make jpeglib write beyond our buffer,
1039      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1040     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
1041         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
1042   }
1043
1044   /* let jpeglib decode directly into our final buffer */
1045   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1046
1047   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1048     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1049       /* Y */
1050       line[0][j] = base[0] + (i + j) * stride[0];
1051       if (G_UNLIKELY (line[0][j] > last[0]))
1052         line[0][j] = last[0];
1053       /* U */
1054       if (v_samp[1] == v_samp[0]) {
1055         line[1][j] = base[1] + ((i + j) / 2) * stride[1];
1056       } else if (j < (v_samp[1] * DCTSIZE)) {
1057         line[1][j] = base[1] + ((i / 2) + j) * stride[1];
1058       }
1059       if (G_UNLIKELY (line[1][j] > last[1]))
1060         line[1][j] = last[1];
1061       /* V */
1062       if (v_samp[2] == v_samp[0]) {
1063         line[2][j] = base[2] + ((i + j) / 2) * stride[2];
1064       } else if (j < (v_samp[2] * DCTSIZE)) {
1065         line[2][j] = base[2] + ((i / 2) + j) * stride[2];
1066       }
1067       if (G_UNLIKELY (line[2][j] > last[2]))
1068         line[2][j] = last[2];
1069     }
1070
1071     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1072     if (G_UNLIKELY (!lines)) {
1073       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1074     }
1075   }
1076   return GST_FLOW_OK;
1077
1078 format_not_supported:
1079   {
1080     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1081         "Unsupported subsampling schema: v_samp factors: %u %u %u",
1082         v_samp[0], v_samp[1], v_samp[2]);
1083     return GST_FLOW_ERROR;
1084   }
1085 }
1086
1087 static void
1088 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
1089     GstClockTimeDiff diff, GstClockTime ts)
1090 {
1091   GST_OBJECT_LOCK (dec);
1092   dec->proportion = proportion;
1093   if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
1094     if (G_UNLIKELY (diff > dec->qos_duration))
1095       dec->earliest_time = ts + 2 * diff + dec->qos_duration;
1096     else
1097       dec->earliest_time = ts + diff;
1098   } else {
1099     dec->earliest_time = GST_CLOCK_TIME_NONE;
1100   }
1101   GST_OBJECT_UNLOCK (dec);
1102 }
1103
1104 static void
1105 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
1106 {
1107   gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
1108 }
1109
1110 static void
1111 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
1112     GstClockTime * time)
1113 {
1114   GST_OBJECT_LOCK (dec);
1115   *proportion = dec->proportion;
1116   *time = dec->earliest_time;
1117   GST_OBJECT_UNLOCK (dec);
1118 }
1119
1120 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
1121  * frame should be decoded, FALSE if the frame can be dropped entirely */
1122 static gboolean
1123 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
1124 {
1125   GstClockTime qostime, earliest_time;
1126   gdouble proportion;
1127
1128   /* no timestamp, can't do QoS => decode frame */
1129   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1130     GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
1131     return TRUE;
1132   }
1133
1134   /* get latest QoS observation values */
1135   gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
1136
1137   /* skip qos if we have no observation (yet) => decode frame */
1138   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1139     GST_LOG_OBJECT (dec, "no observation yet, decode frame");
1140     return TRUE;
1141   }
1142
1143   /* qos is done on running time */
1144   qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
1145       timestamp);
1146
1147   /* see how our next timestamp relates to the latest qos timestamp */
1148   GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
1149       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1150
1151   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1152     GST_DEBUG_OBJECT (dec, "we are late, drop frame");
1153     return FALSE;
1154   }
1155
1156   GST_LOG_OBJECT (dec, "decode frame");
1157   return TRUE;
1158 }
1159
1160 static gboolean
1161 gst_jpeg_dec_buffer_pool (GstJpegDec * dec, GstCaps * caps)
1162 {
1163   GstQuery *query;
1164   GstBufferPool *pool = NULL;
1165   guint size, min, max, prefix, alignment;
1166   GstStructure *config;
1167
1168   GST_DEBUG_OBJECT (dec, "setting up bufferpool");
1169
1170   /* find a pool for the negotiated caps now */
1171   query = gst_query_new_allocation (caps, TRUE);
1172
1173   if (gst_pad_peer_query (dec->srcpad, query)) {
1174     /* we got configuration from our peer, parse them */
1175     gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
1176         &alignment, &pool);
1177     size = MAX (size, dec->info.size);
1178   } else {
1179     GST_DEBUG_OBJECT (dec, "peer query failed, using defaults");
1180     size = dec->info.size;
1181     min = max = 0;
1182     prefix = 0;
1183     alignment = 15;
1184   }
1185   gst_query_unref (query);
1186
1187   if (pool == NULL) {
1188     /* we did not get a pool, make one ourselves then */
1189     pool = gst_buffer_pool_new ();
1190   }
1191
1192   config = gst_buffer_pool_get_config (pool);
1193   gst_buffer_pool_config_set (config, caps, size, min, max, prefix,
1194       alignment | 15);
1195   /* and store */
1196   gst_buffer_pool_set_config (pool, config);
1197
1198   if (dec->pool) {
1199     gst_buffer_pool_set_active (dec->pool, FALSE);
1200     gst_object_unref (dec->pool);
1201   }
1202   dec->pool = pool;
1203
1204   /* and activate */
1205   gst_buffer_pool_set_active (pool, TRUE);
1206
1207   return TRUE;
1208 }
1209
1210 static gboolean
1211 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1212 {
1213   GstCaps *caps;
1214   GstVideoFormat format;
1215   GstVideoInfo info;
1216
1217   if (G_UNLIKELY (width == dec->info.width && height == dec->info.height &&
1218           dec->in_fps_n == dec->info.fps_n && dec->in_fps_d == dec->info.fps_d
1219           && clrspc == dec->clrspc))
1220     return TRUE;
1221
1222   gst_video_info_init (&info);
1223
1224   /* framerate == 0/1 is a still frame */
1225   if (dec->in_fps_d == 0) {
1226     info.fps_n = 0;
1227     info.fps_d = 1;
1228   } else {
1229     info.fps_n = dec->in_fps_n;
1230     info.fps_d = dec->in_fps_d;
1231   }
1232
1233   /* calculate or assume an average frame duration for QoS purposes */
1234   GST_OBJECT_LOCK (dec);
1235   if (info.fps_n != 0) {
1236     dec->qos_duration =
1237         gst_util_uint64_scale (GST_SECOND, info.fps_d, info.fps_n);
1238     dec->duration = dec->qos_duration;
1239   } else {
1240     /* if not set just use 25fps */
1241     dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1242     dec->duration = GST_CLOCK_TIME_NONE;
1243   }
1244   GST_OBJECT_UNLOCK (dec);
1245
1246   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1247     gint i;
1248     GstCaps *allowed_caps;
1249     GstVideoInfo tmpinfo;
1250
1251     GST_DEBUG_OBJECT (dec, "selecting RGB format");
1252     /* retrieve allowed caps, and find the first one that reasonably maps
1253      * to the parameters of the colourspace */
1254     caps = gst_pad_get_allowed_caps (dec->srcpad);
1255     if (!caps) {
1256       GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1257       /* need to copy because get_allowed_caps returns a ref,
1258        * and get_pad_template_caps doesn't */
1259       caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
1260     }
1261     /* avoid lists of formats, etc */
1262     allowed_caps = gst_caps_normalize (caps);
1263     gst_caps_unref (caps);
1264     caps = NULL;
1265     GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1266
1267     for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1268       if (caps)
1269         gst_caps_unref (caps);
1270       caps = gst_caps_copy_nth (allowed_caps, i);
1271       /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1272       gst_caps_fixate (caps);
1273       GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1274
1275       if (!gst_video_info_from_caps (&tmpinfo, caps))
1276         continue;
1277       /* we'll settle for the first (preferred) downstream rgb format */
1278       if (GST_VIDEO_INFO_IS_RGB (&tmpinfo))
1279         break;
1280       /* default fall-back */
1281       format = GST_VIDEO_FORMAT_RGB;
1282     }
1283     if (caps)
1284       gst_caps_unref (caps);
1285     gst_caps_unref (allowed_caps);
1286   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1287     /* TODO is anything else then 8bit supported in jpeg? */
1288     format = GST_VIDEO_FORMAT_GRAY8;
1289   } else {
1290     /* go for plain and simple I420 */
1291     /* TODO other YUV cases ? */
1292     format = GST_VIDEO_FORMAT_I420;
1293   }
1294
1295   gst_video_info_set_format (&info, format, width, height);
1296   caps = gst_video_info_to_caps (&info);
1297
1298   GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1299   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1300   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1301
1302   gst_pad_set_caps (dec->srcpad, caps);
1303
1304   dec->info = info;
1305   dec->clrspc = clrspc;
1306
1307   gst_jpeg_dec_buffer_pool (dec, caps);
1308   gst_caps_unref (caps);
1309
1310   return TRUE;
1311 }
1312
1313 static GstFlowReturn
1314 gst_jpeg_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1315 {
1316   GstFlowReturn ret = GST_FLOW_OK;
1317   GstJpegDec *dec;
1318   GstBuffer *outbuf = NULL;
1319   gint img_len;
1320   gint width, height;
1321   gint r_h, r_v;
1322   guint code, hdr_ok;
1323   GstClockTime timestamp, duration;
1324   GstVideoFrame frame;
1325
1326   dec = GST_JPEG_DEC (parent);
1327
1328   timestamp = GST_BUFFER_TIMESTAMP (buf);
1329   duration = GST_BUFFER_DURATION (buf);
1330
1331   if (GST_CLOCK_TIME_IS_VALID (timestamp))
1332     dec->next_ts = timestamp;
1333
1334   if (GST_BUFFER_IS_DISCONT (buf)) {
1335     GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1336     dec->discont = TRUE;
1337     if (!dec->packetized && gst_adapter_available (dec->adapter)) {
1338       GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1339       gst_adapter_clear (dec->adapter);
1340     }
1341   }
1342
1343   gst_adapter_push (dec->adapter, buf);
1344   buf = NULL;
1345
1346   /* If we are non-packetized and know the total incoming size in bytes,
1347    * just wait until we have enough before doing any processing. */
1348
1349   if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1350       (dec->segment.stop != -1) &&
1351       (gst_adapter_available (dec->adapter) < dec->segment.stop)) {
1352     /* We assume that non-packetized input in bytes is *one* single jpeg image */
1353     GST_DEBUG ("Non-packetized mode. Got %" G_GSIZE_FORMAT " bytes, "
1354         "need %" G_GINT64_FORMAT, gst_adapter_available (dec->adapter),
1355         dec->segment.stop);
1356     goto need_more_data;
1357   }
1358
1359 again:
1360   if (!gst_jpeg_dec_ensure_header (dec))
1361     goto need_more_data;
1362
1363   /* If we know that each input buffer contains data
1364    * for a whole jpeg image (e.g. MJPEG streams), just 
1365    * do some sanity checking instead of parsing all of 
1366    * the jpeg data */
1367   if (dec->packetized) {
1368     img_len = gst_adapter_available (dec->adapter);
1369   } else {
1370     /* Parse jpeg image to handle jpeg input that
1371      * is not aligned to buffer boundaries */
1372     img_len = gst_jpeg_dec_parse_image_data (dec);
1373
1374     if (img_len == 0) {
1375       goto need_more_data;
1376     } else if (img_len < 0) {
1377       gst_adapter_flush (dec->adapter, -img_len);
1378       goto again;
1379     }
1380   }
1381
1382   dec->rem_img_len = img_len;
1383
1384   GST_LOG_OBJECT (dec, "image size = %u", img_len);
1385
1386   /* QoS: if we're too late anyway, skip decoding */
1387   if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1388     goto skip_decoding;
1389
1390 #ifndef GST_DISABLE_GST_DEBUG
1391   {
1392     guchar data[4];
1393
1394     gst_adapter_copy (dec->adapter, data, 0, 4);
1395     GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1396         data[2], data[3]);
1397   }
1398 #endif
1399
1400   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1401
1402   if (setjmp (dec->jerr.setjmp_buffer)) {
1403     code = dec->jerr.pub.msg_code;
1404
1405     if (code == JERR_INPUT_EOF) {
1406       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1407       goto need_more_data;
1408     }
1409     goto decode_error;
1410   }
1411
1412   /* read header */
1413   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1414   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1415     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1416   }
1417
1418   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1419   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1420
1421   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1422     goto components_not_supported;
1423
1424   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1425   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1426
1427   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1428
1429   if (dec->cinfo.num_components > 3)
1430     goto components_not_supported;
1431
1432   /* verify color space expectation to avoid going *boom* or bogus output */
1433   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1434       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1435       dec->cinfo.jpeg_color_space != JCS_RGB)
1436     goto unsupported_colorspace;
1437
1438 #ifndef GST_DISABLE_GST_DEBUG
1439   {
1440     gint i;
1441
1442     for (i = 0; i < dec->cinfo.num_components; ++i) {
1443       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1444           i, dec->cinfo.comp_info[i].h_samp_factor,
1445           dec->cinfo.comp_info[i].v_samp_factor,
1446           dec->cinfo.comp_info[i].component_id);
1447     }
1448   }
1449 #endif
1450
1451   /* prepare for raw output */
1452   dec->cinfo.do_fancy_upsampling = FALSE;
1453   dec->cinfo.do_block_smoothing = FALSE;
1454   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1455   dec->cinfo.dct_method = dec->idct_method;
1456   dec->cinfo.raw_data_out = TRUE;
1457
1458   GST_LOG_OBJECT (dec, "starting decompress");
1459   guarantee_huff_tables (&dec->cinfo);
1460   if (!jpeg_start_decompress (&dec->cinfo)) {
1461     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1462   }
1463
1464   /* sanity checks to get safe and reasonable output */
1465   switch (dec->cinfo.jpeg_color_space) {
1466     case JCS_GRAYSCALE:
1467       if (dec->cinfo.num_components != 1)
1468         goto invalid_yuvrgbgrayscale;
1469       break;
1470     case JCS_RGB:
1471       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1472           dec->cinfo.max_h_samp_factor > 1)
1473         goto invalid_yuvrgbgrayscale;
1474       break;
1475     case JCS_YCbCr:
1476       if (dec->cinfo.num_components != 3 ||
1477           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1478           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1479           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1480           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1481         goto invalid_yuvrgbgrayscale;
1482       break;
1483     default:
1484       g_assert_not_reached ();
1485       break;
1486   }
1487
1488   width = dec->cinfo.output_width;
1489   height = dec->cinfo.output_height;
1490
1491   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1492           height < MIN_HEIGHT || height > MAX_HEIGHT))
1493     goto wrong_size;
1494
1495   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1496
1497   ret = gst_buffer_pool_acquire_buffer (dec->pool, &outbuf, NULL);
1498   if (G_UNLIKELY (ret != GST_FLOW_OK))
1499     goto alloc_failed;
1500
1501   if (!gst_video_frame_map (&frame, &dec->info, outbuf, GST_MAP_READWRITE))
1502     goto invalid_frame;
1503
1504   GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1505
1506   GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1507
1508   if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1509     if (GST_CLOCK_TIME_IS_VALID (duration)) {
1510       /* use duration from incoming buffer for outgoing buffer */
1511       dec->next_ts += duration;
1512     } else if (GST_CLOCK_TIME_IS_VALID (dec->duration)) {
1513       duration = dec->duration;
1514       dec->next_ts += dec->duration;
1515     } else {
1516       duration = GST_CLOCK_TIME_NONE;
1517       dec->next_ts = GST_CLOCK_TIME_NONE;
1518     }
1519   } else {
1520     duration = GST_CLOCK_TIME_NONE;
1521     dec->next_ts = GST_CLOCK_TIME_NONE;
1522   }
1523   GST_BUFFER_DURATION (outbuf) = duration;
1524
1525   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1526     gst_jpeg_dec_decode_rgb (dec, &frame);
1527   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1528     gst_jpeg_dec_decode_grayscale (dec, &frame);
1529   } else {
1530     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1531         dec->cinfo.rec_outbuf_height);
1532
1533     /* For some widths jpeglib requires more horizontal padding than I420 
1534      * provides. In those cases we need to decode into separate buffers and then
1535      * copy over the data into our final picture buffer, otherwise jpeglib might
1536      * write over the end of a line into the beginning of the next line,
1537      * resulting in blocky artifacts on the left side of the picture. */
1538     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1539             || dec->cinfo.comp_info[0].h_samp_factor != 2
1540             || dec->cinfo.comp_info[1].h_samp_factor != 1
1541             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1542       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1543           "indirect decoding using extra buffer copy");
1544       gst_jpeg_dec_decode_indirect (dec, &frame, r_v, r_h,
1545           dec->cinfo.num_components);
1546     } else {
1547       ret = gst_jpeg_dec_decode_direct (dec, &frame);
1548       if (G_UNLIKELY (ret != GST_FLOW_OK))
1549         goto decode_direct_failed;
1550     }
1551   }
1552
1553   GST_LOG_OBJECT (dec, "decompressing finished");
1554   jpeg_finish_decompress (&dec->cinfo);
1555
1556   gst_video_frame_unmap (&frame);
1557
1558   /* Clipping */
1559   if (dec->segment.format == GST_FORMAT_TIME) {
1560     guint64 start, stop, clip_start, clip_stop;
1561
1562     GST_LOG_OBJECT (dec, "Attempting clipping");
1563
1564     start = GST_BUFFER_TIMESTAMP (outbuf);
1565     if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1566       stop = start;
1567     else
1568       stop = start + GST_BUFFER_DURATION (outbuf);
1569
1570     if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1571             start, stop, &clip_start, &clip_stop)) {
1572       GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1573           GST_TIME_ARGS (clip_start));
1574       GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1575       if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1576         GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1577             GST_TIME_ARGS (clip_stop - clip_start));
1578         GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1579       }
1580     } else
1581       goto drop_buffer;
1582   }
1583
1584   /* reset error count on successful decode */
1585   dec->error_count = 0;
1586
1587   ++dec->good_count;
1588
1589   GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1590       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1591       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1592
1593   ret = gst_pad_push (dec->srcpad, outbuf);
1594
1595 skip_decoding:
1596 done:
1597   gst_adapter_flush (dec->adapter, dec->rem_img_len);
1598
1599 exit:
1600
1601   if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1602     jpeg_abort_decompress (&dec->cinfo);
1603     ret = gst_jpeg_dec_post_error_or_warning (dec);
1604   }
1605
1606   return ret;
1607
1608   /* special cases */
1609 need_more_data:
1610   {
1611     GST_LOG_OBJECT (dec, "we need more data");
1612     if (outbuf) {
1613       gst_buffer_unref (outbuf);
1614       outbuf = NULL;
1615     }
1616     ret = GST_FLOW_OK;
1617     goto exit;
1618   }
1619   /* ERRORS */
1620 wrong_size:
1621   {
1622     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1623         "Picture is too small or too big (%ux%u)", width, height);
1624     ret = GST_FLOW_ERROR;
1625     goto done;
1626   }
1627 decode_error:
1628   {
1629     gchar err_msg[JMSG_LENGTH_MAX];
1630
1631     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1632
1633     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1634         "Decode error #%u: %s", code, err_msg);
1635
1636     if (outbuf) {
1637       gst_buffer_unref (outbuf);
1638       outbuf = NULL;
1639     }
1640     ret = GST_FLOW_ERROR;
1641     goto done;
1642   }
1643 decode_direct_failed:
1644   {
1645     /* already posted an error message */
1646     jpeg_abort_decompress (&dec->cinfo);
1647     gst_buffer_replace (&outbuf, NULL);
1648     goto done;
1649   }
1650 alloc_failed:
1651   {
1652     const gchar *reason;
1653
1654     reason = gst_flow_get_name (ret);
1655
1656     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1657     /* Reset for next time */
1658     jpeg_abort_decompress (&dec->cinfo);
1659     if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1660         ret != GST_FLOW_NOT_LINKED) {
1661       gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1662           "Buffer allocation failed, reason: %s", reason);
1663     }
1664     goto exit;
1665   }
1666 invalid_frame:
1667   {
1668     jpeg_abort_decompress (&dec->cinfo);
1669     gst_buffer_unref (outbuf);
1670     ret = GST_FLOW_OK;
1671     goto exit;
1672   }
1673 drop_buffer:
1674   {
1675     GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1676     gst_buffer_unref (outbuf);
1677     ret = GST_FLOW_OK;
1678     goto exit;
1679   }
1680 components_not_supported:
1681   {
1682     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1683         "number of components not supported: %d (max 3)",
1684         dec->cinfo.num_components);
1685     ret = GST_FLOW_ERROR;
1686     goto done;
1687   }
1688 unsupported_colorspace:
1689   {
1690     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1691         "Picture has unknown or unsupported colourspace");
1692     ret = GST_FLOW_ERROR;
1693     goto done;
1694   }
1695 invalid_yuvrgbgrayscale:
1696   {
1697     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1698         "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1699     ret = GST_FLOW_ERROR;
1700     goto done;
1701   }
1702 }
1703
1704 static gboolean
1705 gst_jpeg_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1706 {
1707   GstJpegDec *dec;
1708   gboolean res;
1709
1710   dec = GST_JPEG_DEC (parent);
1711
1712   switch (GST_EVENT_TYPE (event)) {
1713     case GST_EVENT_QOS:{
1714       GstQOSType type;
1715       GstClockTimeDiff diff;
1716       GstClockTime timestamp;
1717       gdouble proportion;
1718
1719       gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
1720       gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1721       break;
1722     }
1723     default:
1724       break;
1725   }
1726
1727   res = gst_pad_push_event (dec->sinkpad, event);
1728
1729   return res;
1730 }
1731
1732 static gboolean
1733 gst_jpeg_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1734 {
1735   gboolean ret = TRUE, forward = TRUE;
1736   GstJpegDec *dec = GST_JPEG_DEC (parent);
1737
1738   GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1739
1740   switch (GST_EVENT_TYPE (event)) {
1741     case GST_EVENT_FLUSH_STOP:
1742       GST_DEBUG_OBJECT (dec, "Aborting decompress");
1743       jpeg_abort_decompress (&dec->cinfo);
1744       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1745       gst_adapter_clear (dec->adapter);
1746       g_free (dec->cur_buf);
1747       dec->cur_buf = NULL;
1748       dec->parse_offset = 0;
1749       dec->parse_entropy_len = 0;
1750       dec->parse_resync = FALSE;
1751       gst_jpeg_dec_reset_qos (dec);
1752       break;
1753     case GST_EVENT_SEGMENT:
1754       gst_event_copy_segment (event, &dec->segment);
1755       GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT,
1756           &dec->segment);
1757       break;
1758     case GST_EVENT_CAPS:
1759     {
1760       GstCaps *caps;
1761
1762       gst_event_parse_caps (event, &caps);
1763       ret = gst_jpeg_dec_setcaps (dec, caps);
1764       forward = FALSE;
1765       break;
1766     }
1767     default:
1768       break;
1769   }
1770
1771   if (forward)
1772     ret = gst_pad_push_event (dec->srcpad, event);
1773   else
1774     gst_event_unref (event);
1775
1776   return ret;
1777 }
1778
1779 static gboolean
1780 gst_jpeg_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
1781 {
1782   gboolean res = FALSE;
1783
1784   switch (GST_QUERY_TYPE (query)) {
1785     case GST_QUERY_CAPS:
1786     {
1787       GstCaps *filter, *caps;
1788
1789       gst_query_parse_caps (query, &filter);
1790       caps = gst_jpeg_dec_getcaps (pad, filter);
1791       gst_query_set_caps_result (query, caps);
1792       gst_caps_unref (caps);
1793       res = TRUE;
1794       break;
1795     }
1796     default:
1797       res = gst_pad_query_default (pad, parent, query);
1798       break;
1799   }
1800   return res;
1801 }
1802
1803 static void
1804 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1805     const GValue * value, GParamSpec * pspec)
1806 {
1807   GstJpegDec *dec;
1808
1809   dec = GST_JPEG_DEC (object);
1810
1811   switch (prop_id) {
1812     case PROP_IDCT_METHOD:
1813       dec->idct_method = g_value_get_enum (value);
1814       break;
1815     case PROP_MAX_ERRORS:
1816       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1817       break;
1818
1819     default:
1820       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1821       break;
1822   }
1823 }
1824
1825 static void
1826 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1827     GParamSpec * pspec)
1828 {
1829   GstJpegDec *dec;
1830
1831   dec = GST_JPEG_DEC (object);
1832
1833   switch (prop_id) {
1834     case PROP_IDCT_METHOD:
1835       g_value_set_enum (value, dec->idct_method);
1836       break;
1837     case PROP_MAX_ERRORS:
1838       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1839       break;
1840
1841     default:
1842       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1843       break;
1844   }
1845 }
1846
1847 static GstStateChangeReturn
1848 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1849 {
1850   GstStateChangeReturn ret;
1851   GstJpegDec *dec;
1852
1853   dec = GST_JPEG_DEC (element);
1854
1855   switch (transition) {
1856     case GST_STATE_CHANGE_READY_TO_PAUSED:
1857       dec->error_count = 0;
1858       dec->good_count = 0;
1859       dec->in_fps_n = 0;
1860       dec->in_fps_d = 1;
1861       gst_video_info_init (&dec->info);
1862       dec->clrspc = -1;
1863       dec->packetized = FALSE;
1864       dec->next_ts = 0;
1865       dec->discont = TRUE;
1866       dec->parse_offset = 0;
1867       dec->parse_entropy_len = 0;
1868       dec->parse_resync = FALSE;
1869       dec->cur_buf = NULL;
1870       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1871       gst_jpeg_dec_reset_qos (dec);
1872     default:
1873       break;
1874   }
1875
1876   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1877   if (ret != GST_STATE_CHANGE_SUCCESS)
1878     return ret;
1879
1880   switch (transition) {
1881     case GST_STATE_CHANGE_PAUSED_TO_READY:
1882       gst_adapter_clear (dec->adapter);
1883       g_free (dec->cur_buf);
1884       dec->cur_buf = NULL;
1885       gst_jpeg_dec_free_buffers (dec);
1886       if (dec->pool) {
1887         gst_buffer_pool_set_active (dec->pool, FALSE);
1888         gst_object_unref (dec->pool);
1889       }
1890       dec->pool = NULL;
1891       break;
1892     default:
1893       break;
1894   }
1895
1896   return ret;
1897 }