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