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