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