gst_element_class_set_details => gst_element_class_set_details_simple
[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 ! jpegddec ! 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  16
47 #define MAX_WIDTH  65535
48 #define MIN_HEIGHT 8
49 #define MAX_HEIGHT 65535
50
51 #define JPEG_DEFAULT_IDCT_METHOD        JDCT_FASTEST
52
53 enum
54 {
55   PROP_0,
56   PROP_IDCT_METHOD
57 };
58
59 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
60 GST_STATIC_PAD_TEMPLATE ("src",
61     GST_PAD_SRC,
62     GST_PAD_ALWAYS,
63     GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
64     );
65
66 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
67 GST_STATIC_PAD_TEMPLATE ("sink",
68     GST_PAD_SINK,
69     GST_PAD_ALWAYS,
70     GST_STATIC_CAPS ("image/jpeg, "
71         "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
72         " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
73         G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (fraction) [ 0/1, MAX ]")
74     );
75
76 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
77 #define GST_CAT_DEFAULT jpeg_dec_debug
78 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
79
80 /* These macros are adapted from videotestsrc.c 
81  *  and/or gst-plugins/gst/games/gstvideoimage.c */
82 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
83 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
84 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
85
86 #define I420_Y_OFFSET(w,h) (0)
87 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
88 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
89
90 #define I420_SIZE(w,h)     (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
91
92 static GstElementClass *parent_class;   /* NULL */
93
94 static void gst_jpeg_dec_base_init (gpointer g_class);
95 static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
96 static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
97
98 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
99     const GValue * value, GParamSpec * pspec);
100 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
101     GValue * value, GParamSpec * pspec);
102
103 static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
104 static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
105 static gboolean gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event);
106 static gboolean gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event);
107 static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
108     GstStateChange transition);
109 static void gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
110     GstClockTimeDiff diff, GstClockTime ts);
111 static void gst_jpeg_dec_reset_qos (GstJpegDec * dec);
112 static void gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
113     GstClockTime * time);
114
115 GType
116 gst_jpeg_dec_get_type (void)
117 {
118   static GType type = 0;
119
120   if (!type) {
121     static const GTypeInfo jpeg_dec_info = {
122       sizeof (GstJpegDecClass),
123       (GBaseInitFunc) gst_jpeg_dec_base_init,
124       NULL,
125       (GClassInitFunc) gst_jpeg_dec_class_init,
126       NULL,
127       NULL,
128       sizeof (GstJpegDec),
129       0,
130       (GInstanceInitFunc) gst_jpeg_dec_init,
131     };
132
133     type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
134         &jpeg_dec_info, 0);
135   }
136   return type;
137 }
138
139 static void
140 gst_jpeg_dec_finalize (GObject * object)
141 {
142   GstJpegDec *dec = GST_JPEG_DEC (object);
143
144   jpeg_destroy_decompress (&dec->cinfo);
145
146   if (dec->tempbuf)
147     gst_buffer_unref (dec->tempbuf);
148
149   G_OBJECT_CLASS (parent_class)->finalize (object);
150 }
151
152 static void
153 gst_jpeg_dec_base_init (gpointer g_class)
154 {
155   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
156
157   gst_element_class_add_pad_template (element_class,
158       gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
159   gst_element_class_add_pad_template (element_class,
160       gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
161   gst_element_class_set_details_simple (element_class, "JPEG image decoder",
162       "Codec/Decoder/Image",
163       "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
164 }
165
166 static void
167 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
168 {
169   GstElementClass *gstelement_class;
170   GObjectClass *gobject_class;
171
172   gstelement_class = (GstElementClass *) klass;
173   gobject_class = (GObjectClass *) klass;
174
175   parent_class = g_type_class_peek_parent (klass);
176
177   gobject_class->finalize = gst_jpeg_dec_finalize;
178   gobject_class->set_property = gst_jpeg_dec_set_property;
179   gobject_class->get_property = gst_jpeg_dec_get_property;
180
181   g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
182       g_param_spec_enum ("idct-method", "IDCT Method",
183           "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
184           JPEG_DEFAULT_IDCT_METHOD, G_PARAM_READWRITE));
185
186   gstelement_class->change_state =
187       GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
188
189   GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
190   GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
191 }
192
193 static boolean
194 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
195 {
196 /*
197   struct GstJpegDecSourceMgr *src_mgr;
198   GstJpegDec *dec;
199
200   src_mgr = (struct GstJpegDecSourceMgr*) &cinfo->src;
201   dec = GST_JPEG_DEC (src_mgr->dec);
202 */
203   GST_DEBUG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "fill_input_buffer");
204 /*
205   g_return_val_if_fail (dec != NULL, TRUE);
206
207   src_mgr->pub.next_input_byte = GST_BUFFER_DATA (dec->tempbuf);
208   src_mgr->pub.bytes_in_buffer = GST_BUFFER_SIZE (dec->tempbuf);
209 */
210   return TRUE;
211 }
212
213 static void
214 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
215 {
216   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
217 }
218
219
220 static void
221 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
222 {
223   GST_DEBUG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "skip %ld bytes", num_bytes);
224
225   if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
226     cinfo->src->next_input_byte += (size_t) num_bytes;
227     cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
228   }
229 }
230
231 static boolean
232 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
233 {
234   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
235   return TRUE;
236 }
237
238 static void
239 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
240 {
241   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
242   return;
243 }
244
245 METHODDEF (void)
246     gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
247 {
248   return;                       /* do nothing */
249 }
250
251 METHODDEF (void)
252     gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
253 {
254   /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
255   return;
256 }
257
258 METHODDEF (void)
259     gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
260 {
261   struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
262
263   (*cinfo->err->output_message) (cinfo);
264   longjmp (err_mgr->setjmp_buffer, 1);
265 }
266
267 static void
268 gst_jpeg_dec_init (GstJpegDec * dec)
269 {
270   GST_DEBUG ("initializing");
271
272   /* create the sink and src pads */
273   dec->sinkpad =
274       gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
275       "sink");
276   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
277   gst_pad_set_setcaps_function (dec->sinkpad,
278       GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
279   gst_pad_set_chain_function (dec->sinkpad,
280       GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
281   gst_pad_set_event_function (dec->sinkpad,
282       GST_DEBUG_FUNCPTR (gst_jpeg_dec_sink_event));
283
284   dec->srcpad =
285       gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
286   gst_pad_set_event_function (dec->srcpad,
287       GST_DEBUG_FUNCPTR (gst_jpeg_dec_src_event));
288   gst_pad_use_fixed_caps (dec->srcpad);
289   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
290
291   /* setup jpeglib */
292   memset (&dec->cinfo, 0, sizeof (dec->cinfo));
293   memset (&dec->jerr, 0, sizeof (dec->jerr));
294   dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
295   dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
296   dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
297   dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
298
299   jpeg_create_decompress (&dec->cinfo);
300
301   dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
302   dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
303   dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
304   dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
305   dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
306   dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
307   dec->jsrc.dec = dec;
308
309   /* init properties */
310   dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
311 }
312
313 static inline gboolean
314 is_jpeg_start_marker (const guint8 * data)
315 {
316   return (data[0] == 0xff && data[1] == 0xd8);
317 }
318
319 static gboolean
320 gst_jpeg_dec_find_jpeg_header (GstJpegDec * dec)
321 {
322   const guint8 *data;
323   guint size;
324
325   data = GST_BUFFER_DATA (dec->tempbuf);
326   size = GST_BUFFER_SIZE (dec->tempbuf);
327
328   g_return_val_if_fail (size >= 2, FALSE);
329
330   while (!is_jpeg_start_marker (data) || data[2] != 0xff) {
331     const guint8 *marker;
332     GstBuffer *tmp;
333     guint off;
334
335     marker = memchr (data + 1, 0xff, size - 1 - 2);
336     if (marker == NULL) {
337       off = size - 1;           /* keep last byte */
338     } else {
339       off = marker - data;
340     }
341
342     tmp = gst_buffer_create_sub (dec->tempbuf, off, size - off);
343     gst_buffer_unref (dec->tempbuf);
344     dec->tempbuf = tmp;
345
346     data = GST_BUFFER_DATA (dec->tempbuf);
347     size = GST_BUFFER_SIZE (dec->tempbuf);
348
349     if (size < 2)
350       return FALSE;             /* wait for more data */
351   }
352
353   return TRUE;                  /* got header */
354 }
355
356 static gboolean
357 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
358 {
359   g_return_val_if_fail (dec->tempbuf != NULL, FALSE);
360
361 check_header:
362
363   /* we need at least a start marker (0xff 0xd8)
364    *   and an end marker (0xff 0xd9) */
365   if (GST_BUFFER_SIZE (dec->tempbuf) <= 4) {
366     GST_DEBUG ("Not enough data");
367     return FALSE;               /* we need more data */
368   }
369
370   if (!is_jpeg_start_marker (GST_BUFFER_DATA (dec->tempbuf))) {
371     GST_DEBUG ("Not a JPEG header, resyncing to header...");
372     if (!gst_jpeg_dec_find_jpeg_header (dec)) {
373       GST_DEBUG ("No JPEG header in current buffer");
374       return FALSE;             /* we need more data */
375     }
376     GST_DEBUG ("Found JPEG header");
377     goto check_header;          /* buffer might have changed */
378   }
379
380   return TRUE;
381 }
382
383 #if 0
384 static gboolean
385 gst_jpeg_dec_have_end_marker (GstJpegDec * dec)
386 {
387   guint8 *data = GST_BUFFER_DATA (dec->tempbuf);
388   guint size = GST_BUFFER_SIZE (dec->tempbuf);
389
390   return (size > 2 && data && is_jpeg_end_marker (data + size - 2));
391 }
392 #endif
393
394 static inline gboolean
395 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
396 {
397   if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
398     return TRUE;
399   return FALSE;
400 }
401
402 /* returns image length in bytes if parsed 
403  * successfully, otherwise 0 */
404 static guint
405 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
406 {
407   guint8 *start, *data, *end;
408   guint size;
409
410   size = GST_BUFFER_SIZE (dec->tempbuf);
411   start = GST_BUFFER_DATA (dec->tempbuf);
412   end = start + size;
413   data = start;
414
415   g_return_val_if_fail (is_jpeg_start_marker (data), 0);
416
417   GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
418
419   /* skip start marker */
420   data += 2;
421
422   while (1) {
423     guint frame_len;
424     gboolean resync;
425
426     /* do we need to resync? */
427     resync = (*data != 0xff);
428     if (resync) {
429       GST_DEBUG ("Lost sync at 0x%08" G_GINT64_MODIFIER "x, resyncing",
430           (gint64) (data - start));
431       /* at the very least we expect 0xff 0xNN, thus end-1 */
432       while (*data != 0xff && data < end - 1)
433         ++data;
434       if (G_UNLIKELY (*data != 0xff)) {
435         GST_DEBUG ("at end of input and no next marker found, need more data");
436         return 0;
437       }
438     }
439     /* Skip over extra 0xff */
440     while (*data == 0xff && data < end)
441       ++data;
442     /* enough bytes left for marker? (we need 0xNN after the 0xff) */
443     if (data >= end) {
444       GST_DEBUG ("at end of input and no EOI marker found, need more data");
445       return 0;
446     }
447
448     if (*data == 0xd9) {
449       GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: EOI marker",
450           (gint64) (data - start));
451       return (data - start + 1);
452     }
453
454     if (*data >= 0xd0 && *data <= 0xd7)
455       frame_len = 0;
456     else if (data >= end - 2)
457       return 0;
458     else
459       frame_len = GST_READ_UINT16_BE (data + 1);
460     GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: tag %02x, frame_len=%u",
461         (gint64) (data - start - 1), *data, frame_len);
462     /* the frame length includes the 2 bytes for the length; here we want at
463      * least 2 more bytes at the end for an end marker, thus end-2 */
464     if (data + 1 + frame_len >= end - 2) {
465       if (resync) {
466         GST_DEBUG ("not a valid sync (not enough data).");
467         /* Since *data != 0xff, the next iteration will go into resync again. */
468         continue;
469       }
470       /* theoretically we could have lost sync and not really need more
471        * data, but that's just tough luck and a broken image then */
472       GST_DEBUG ("at end of input and no EOI marker found, need more data");
473       return 0;
474     }
475
476     if (gst_jpeg_dec_parse_tag_has_entropy_segment (*data)) {
477       guint8 *d2 = data + 1 + frame_len;
478       guint eseglen = 0;
479
480       GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: finding entropy segment length",
481           (gint64) (data - start - 1));
482       while (1) {
483         if (d2 + eseglen >= end - 1)
484           return 0;             /* need more data */
485         if (d2[eseglen] == 0xff && d2[eseglen + 1] != 0x00)
486           break;
487         ++eseglen;
488       }
489       frame_len += eseglen;
490       GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
491           frame_len);
492     }
493     if (resync) {
494       /* check if we will still be in sync if we interpret
495        * this as a sync point and skip this frame */
496       if (data[2 + frame_len] != 0xff) {
497         /* ignore and continue resyncing until we hit the end
498          * of our data or find a sync point that looks okay */
499         continue;
500       }
501       GST_DEBUG ("found sync at %p", data - size);
502     }
503
504     data += 1 + frame_len;
505   }
506 }
507
508 /* shamelessly ripped from jpegutils.c in mjpegtools */
509 static void
510 add_huff_table (j_decompress_ptr dinfo,
511     JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
512 /* Define a Huffman table */
513 {
514   int nsymbols, len;
515
516   if (*htblptr == NULL)
517     *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
518
519   g_assert (*htblptr);
520
521   /* Copy the number-of-symbols-of-each-code-length counts */
522   memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
523
524   /* Validate the counts.  We do this here mainly so we can copy the right
525    * number of symbols from the val[] array, without risking marching off
526    * the end of memory.  jchuff.c will do a more thorough test later.
527    */
528   nsymbols = 0;
529   for (len = 1; len <= 16; len++)
530     nsymbols += bits[len];
531   if (nsymbols < 1 || nsymbols > 256)
532     g_error ("jpegutils.c:  add_huff_table failed badly. ");
533
534   memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
535 }
536
537
538
539 static void
540 std_huff_tables (j_decompress_ptr dinfo)
541 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
542 /* IMPORTANT: these are only valid for 8-bit data precision! */
543 {
544   static const UINT8 bits_dc_luminance[17] =
545       { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
546   static const UINT8 val_dc_luminance[] =
547       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
548
549   static const UINT8 bits_dc_chrominance[17] =
550       { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
551   static const UINT8 val_dc_chrominance[] =
552       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
553
554   static const UINT8 bits_ac_luminance[17] =
555       { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
556   static const UINT8 val_ac_luminance[] =
557       { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
558     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
559     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
560     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
561     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
562     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
563     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
564     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
565     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
566     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
567     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
568     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
569     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
570     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
571     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
572     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
573     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
574     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
575     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
576     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
577     0xf9, 0xfa
578   };
579
580   static const UINT8 bits_ac_chrominance[17] =
581       { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
582   static const UINT8 val_ac_chrominance[] =
583       { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
584     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
585     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
586     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
587     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
588     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
589     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
590     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
591     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
592     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
593     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
594     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
595     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
596     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
597     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
598     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
599     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
600     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
601     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
602     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
603     0xf9, 0xfa
604   };
605
606   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
607       bits_dc_luminance, val_dc_luminance);
608   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
609       bits_ac_luminance, val_ac_luminance);
610   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
611       bits_dc_chrominance, val_dc_chrominance);
612   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
613       bits_ac_chrominance, val_ac_chrominance);
614 }
615
616
617
618 static void
619 guarantee_huff_tables (j_decompress_ptr dinfo)
620 {
621   if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
622       (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
623       (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
624       (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
625     GST_DEBUG ("Generating standard Huffman tables for this frame.");
626     std_huff_tables (dinfo);
627   }
628 }
629
630 static gboolean
631 gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
632 {
633   GstStructure *s;
634   GstJpegDec *dec;
635   const GValue *framerate;
636
637   dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
638   s = gst_caps_get_structure (caps, 0);
639
640   if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
641     dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
642     dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
643     dec->packetized = TRUE;
644     GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
645         dec->framerate_numerator, dec->framerate_denominator);
646   }
647
648   /* do not extract width/height here. we do that in the chain
649    * function on a per-frame basis (including the line[] array
650    * setup) */
651
652   /* But we can take the framerate values and set them on the src pad */
653
654   return TRUE;
655 }
656
657 /* yuk */
658 static void
659 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
660 {
661   gint i;
662
663   for (i = 0; i < len; ++i) {
664     /* equivalent to: dest[i] = src[i << 1] */
665     *dest = *src;
666     ++dest;
667     ++src;
668     ++src;
669   }
670 }
671
672 static void
673 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
674 {
675   gint i;
676
677   for (i = 0; i < 16; i++) {
678     g_free (dec->idr_y[i]);
679     g_free (dec->idr_u[i]);
680     g_free (dec->idr_v[i]);
681     dec->idr_y[i] = NULL;
682     dec->idr_u[i] = NULL;
683     dec->idr_v[i] = NULL;
684   }
685
686   dec->idr_width_allocated = 0;
687 }
688
689 static inline gboolean
690 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
691 {
692   gint i;
693
694   if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
695     return TRUE;
696
697   /* FIXME: maybe just alloc one or three blocks altogether? */
698   for (i = 0; i < 16; i++) {
699     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
700     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
701     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
702
703     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
704       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
705       return FALSE;
706     }
707   }
708
709   dec->idr_width_allocated = maxrowbytes;
710   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
711   return TRUE;
712 }
713
714 static void
715 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
716     guchar * last[3], guint width, guint height, gint r_v, gint r_h)
717 {
718   guchar *y_rows[16], *u_rows[16], *v_rows[16];
719   guchar **scanarray[3] = { y_rows, u_rows, v_rows };
720   gint i, j, k;
721   gint lines;
722
723   GST_DEBUG_OBJECT (dec,
724       "unadvantageous width or r_h, taking slow route involving memcpy");
725
726   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
727     return;
728
729   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
730   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
731   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
732
733   for (i = 0; i < height; i += r_v * DCTSIZE) {
734     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
735     if (G_LIKELY (lines > 0)) {
736       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
737         memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
738         if (G_LIKELY (base[0] < last[0]))
739           base[0] += I420_Y_ROWSTRIDE (width);
740         if (r_v == 2) {
741           memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
742           if (G_LIKELY (base[0] < last[0]))
743             base[0] += I420_Y_ROWSTRIDE (width);
744         }
745         if (r_h == 2) {
746           memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
747           memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
748         } else if (r_h == 1) {
749           hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
750           hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
751         } else {
752           /* FIXME: implement (at least we avoid crashing by doing nothing) */
753         }
754
755         if (r_v == 2 || (k & 1) != 0) {
756           if (G_LIKELY (base[1] < last[1] && base[2] < last[2])) {
757             base[1] += I420_U_ROWSTRIDE (width);
758             base[2] += I420_V_ROWSTRIDE (width);
759           }
760         }
761       }
762     } else {
763       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
764     }
765   }
766 }
767
768 #ifndef GST_DISABLE_GST_DEBUG
769 static inline void
770 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
771 {
772   int j;
773
774   for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
775     GST_LOG ("[%02d]  %5d  %5d  %5d", j,
776         (line[0][j] >= base[0]) ?
777         (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
778         (line[1][j] >= base[1]) ?
779         (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
780         (line[2][j] >= base[2]) ?
781         (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
782   }
783 }
784 #endif
785
786 static GstFlowReturn
787 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
788     guchar * last[3], guint width, guint height)
789 {
790   guchar **line[3];             /* the jpeg line buffer         */
791   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
792   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
793   guchar *v[4 * DCTSIZE] = { NULL, };
794   gint i, j;
795   gint lines, v_samp[3];
796
797   line[0] = y;
798   line[1] = u;
799   line[2] = v;
800
801   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
802   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
803   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
804
805   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
806     goto format_not_supported;
807
808   /* let jpeglib decode directly into our final buffer */
809   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
810
811   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
812     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
813       /* Y */
814       line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
815       if (G_UNLIKELY (line[0][j] > last[0]))
816         line[0][j] = last[0];
817       /* U */
818       if (v_samp[1] == v_samp[0]) {
819         line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
820       } else if (j < (v_samp[1] * DCTSIZE)) {
821         line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
822       }
823       if (G_UNLIKELY (line[1][j] > last[1]))
824         line[1][j] = last[1];
825       /* V */
826       if (v_samp[2] == v_samp[0]) {
827         line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
828       } else if (j < (v_samp[2] * DCTSIZE)) {
829         line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
830       }
831       if (G_UNLIKELY (line[2][j] > last[2]))
832         line[2][j] = last[2];
833     }
834
835     /* dump_lines (base, line, v_samp[0], width); */
836
837     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
838     if (G_UNLIKELY (!lines)) {
839       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
840     }
841   }
842   return GST_FLOW_OK;
843
844 format_not_supported:
845   {
846     GST_ELEMENT_ERROR (dec, STREAM, DECODE,
847         (_("Failed to decode JPEG image")),
848         ("Unsupported subsampling schema: v_samp factors: %u %u %u",
849             v_samp[0], v_samp[1], v_samp[2]));
850     return GST_FLOW_ERROR;
851   }
852 }
853
854 static void
855 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
856     GstClockTimeDiff diff, GstClockTime ts)
857 {
858   GST_OBJECT_LOCK (dec);
859   dec->proportion = proportion;
860   if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
861     if (G_UNLIKELY (diff > 0))
862       dec->earliest_time = ts + 2 * diff + dec->qos_duration;
863     else
864       dec->earliest_time = ts + diff;
865   } else {
866     dec->earliest_time = GST_CLOCK_TIME_NONE;
867   }
868   GST_OBJECT_UNLOCK (dec);
869 }
870
871 static void
872 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
873 {
874   gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
875 }
876
877 static void
878 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
879     GstClockTime * time)
880 {
881   GST_OBJECT_LOCK (dec);
882   *proportion = dec->proportion;
883   *time = dec->earliest_time;
884   GST_OBJECT_UNLOCK (dec);
885 }
886
887 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
888  * frame should be decoded, FALSE if the frame can be dropped entirely */
889 static gboolean
890 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
891 {
892   GstClockTime qostime, earliest_time;
893   gdouble proportion;
894
895   /* no timestamp, can't do QoS => decode frame */
896   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
897     GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
898     return TRUE;
899   }
900
901   /* get latest QoS observation values */
902   gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
903
904   /* skip qos if we have no observation (yet) => decode frame */
905   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
906     GST_LOG_OBJECT (dec, "no observation yet, decode frame");
907     return TRUE;
908   }
909
910   /* qos is done on running time */
911   qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
912       timestamp);
913
914   /* see how our next timestamp relates to the latest qos timestamp */
915   GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
916       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
917
918   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
919     GST_DEBUG_OBJECT (dec, "we are late, drop frame");
920     return FALSE;
921   }
922
923   GST_LOG_OBJECT (dec, "decode frame");
924   return TRUE;
925 }
926
927 static GstFlowReturn
928 gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
929 {
930   GstFlowReturn ret = GST_FLOW_OK;
931   GstJpegDec *dec;
932   GstBuffer *outbuf = NULL;
933   guchar *data, *outdata;
934   guchar *base[3], *last[3];
935   guint img_len, outsize;
936   gint width, height;
937   gint r_h, r_v;
938   guint code, hdr_ok;
939   GstClockTime timestamp, duration;
940
941   dec = GST_JPEG_DEC (GST_PAD_PARENT (pad));
942
943   timestamp = GST_BUFFER_TIMESTAMP (buf);
944   duration = GST_BUFFER_DURATION (buf);
945
946   if (GST_CLOCK_TIME_IS_VALID (timestamp))
947     dec->next_ts = timestamp;
948
949   if (GST_BUFFER_IS_DISCONT (buf)) {
950     GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
951     dec->discont = TRUE;
952     if (!dec->packetized && dec->tempbuf != NULL) {
953       GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
954       gst_buffer_replace (&dec->tempbuf, NULL);
955     }
956   }
957
958   if (dec->tempbuf) {
959     dec->tempbuf = gst_buffer_join (dec->tempbuf, buf);
960   } else {
961     dec->tempbuf = buf;
962   }
963   buf = NULL;
964
965   /* If we are non-packetized and know the total incoming size in bytes,
966    * just wait until we have enough before doing any processing. */
967
968   if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
969       (dec->segment.stop != -1) &&
970       (GST_BUFFER_SIZE (dec->tempbuf) < dec->segment.stop)) {
971     /* We assume that non-packetized input in bytes is *one* single jpeg image */
972     GST_DEBUG ("Non-packetized mode. Got %d bytes, need %" G_GINT64_FORMAT,
973         GST_BUFFER_SIZE (dec->tempbuf), dec->segment.stop);
974     goto need_more_data;
975   }
976
977   if (!gst_jpeg_dec_ensure_header (dec))
978     goto need_more_data;
979
980   /* If we know that each input buffer contains data
981    * for a whole jpeg image (e.g. MJPEG streams), just 
982    * do some sanity checking instead of parsing all of 
983    * the jpeg data */
984   if (dec->packetized) {
985     img_len = GST_BUFFER_SIZE (dec->tempbuf);
986   } else {
987     /* Parse jpeg image to handle jpeg input that
988      * is not aligned to buffer boundaries */
989     img_len = gst_jpeg_dec_parse_image_data (dec);
990
991     if (img_len == 0)
992       goto need_more_data;
993   }
994
995   /* QoS: if we're too late anyway, skip decoding */
996   if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
997     goto skip_decoding;
998
999   data = (guchar *) GST_BUFFER_DATA (dec->tempbuf);
1000   GST_LOG_OBJECT (dec, "image size = %u", img_len);
1001
1002   dec->jsrc.pub.next_input_byte = data;
1003   dec->jsrc.pub.bytes_in_buffer = img_len;
1004
1005   if (setjmp (dec->jerr.setjmp_buffer)) {
1006     code = dec->jerr.pub.msg_code;
1007
1008     if (code == JERR_INPUT_EOF) {
1009       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1010       goto need_more_data;
1011     }
1012     goto decode_error;
1013   }
1014
1015   GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1016       data[2], data[3]);
1017
1018   /* read header */
1019   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1020   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1021     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1022   }
1023
1024   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1025   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1026
1027   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1028   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1029   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1030
1031 #ifndef GST_DISABLE_GST_DEBUG
1032   {
1033     gint i;
1034
1035     for (i = 0; i < dec->cinfo.num_components; ++i) {
1036       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1037           i, dec->cinfo.comp_info[i].h_samp_factor,
1038           dec->cinfo.comp_info[i].v_samp_factor,
1039           dec->cinfo.comp_info[i].component_id);
1040     }
1041   }
1042 #endif
1043
1044   /* prepare for raw output */
1045   dec->cinfo.do_fancy_upsampling = FALSE;
1046   dec->cinfo.do_block_smoothing = FALSE;
1047   dec->cinfo.out_color_space = JCS_YCbCr;
1048   dec->cinfo.dct_method = dec->idct_method;
1049   dec->cinfo.raw_data_out = TRUE;
1050
1051   GST_LOG_OBJECT (dec, "starting decompress");
1052   guarantee_huff_tables (&dec->cinfo);
1053   if (!jpeg_start_decompress (&dec->cinfo)) {
1054     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1055   }
1056
1057   width = dec->cinfo.output_width;
1058   height = dec->cinfo.output_height;
1059
1060   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1061           height < MIN_HEIGHT || height > MAX_HEIGHT))
1062     goto wrong_size;
1063
1064   if (G_UNLIKELY (width != dec->caps_width || height != dec->caps_height ||
1065           dec->framerate_numerator != dec->caps_framerate_numerator ||
1066           dec->framerate_denominator != dec->caps_framerate_denominator)) {
1067     GstCaps *caps;
1068
1069     /* framerate == 0/1 is a still frame */
1070     if (dec->framerate_denominator == 0) {
1071       dec->framerate_numerator = 0;
1072       dec->framerate_denominator = 1;
1073     }
1074
1075     /* calculate or assume an average frame duration for QoS purposes */
1076     GST_OBJECT_LOCK (dec);
1077     if (dec->framerate_numerator != 0) {
1078       dec->qos_duration = gst_util_uint64_scale (GST_SECOND,
1079           dec->framerate_denominator, dec->framerate_numerator);
1080     } else {
1081       /* if not set just use 25fps */
1082       dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1083     }
1084     GST_OBJECT_UNLOCK (dec);
1085
1086     caps = gst_caps_new_simple ("video/x-raw-yuv",
1087         "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
1088         "width", G_TYPE_INT, width,
1089         "height", G_TYPE_INT, height,
1090         "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
1091         dec->framerate_denominator, NULL);
1092
1093     GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1094     GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d",
1095         dec->cinfo.max_v_samp_factor);
1096     GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d",
1097         dec->cinfo.max_h_samp_factor);
1098
1099     gst_pad_set_caps (dec->srcpad, caps);
1100     gst_caps_unref (caps);
1101
1102     dec->caps_width = width;
1103     dec->caps_height = height;
1104     dec->caps_framerate_numerator = dec->framerate_numerator;
1105     dec->caps_framerate_denominator = dec->framerate_denominator;
1106     dec->outsize = I420_SIZE (width, height);
1107   }
1108
1109   ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
1110       dec->outsize, GST_PAD_CAPS (dec->srcpad), &outbuf);
1111   if (G_UNLIKELY (ret != GST_FLOW_OK))
1112     goto alloc_failed;
1113
1114   outdata = GST_BUFFER_DATA (outbuf);
1115   outsize = GST_BUFFER_SIZE (outbuf);
1116
1117   GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
1118       width, height, outsize, dec->outsize);
1119
1120   GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1121
1122   if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1123     if (GST_CLOCK_TIME_IS_VALID (duration)) {
1124       /* use duration from incoming buffer for outgoing buffer */
1125       dec->next_ts += duration;
1126     } else if (dec->framerate_numerator != 0) {
1127       duration = gst_util_uint64_scale (GST_SECOND,
1128           dec->framerate_denominator, dec->framerate_numerator);
1129       dec->next_ts += duration;
1130     } else {
1131       duration = GST_CLOCK_TIME_NONE;
1132       dec->next_ts = GST_CLOCK_TIME_NONE;
1133     }
1134   } else {
1135     duration = GST_CLOCK_TIME_NONE;
1136     dec->next_ts = GST_CLOCK_TIME_NONE;
1137   }
1138   GST_BUFFER_DURATION (outbuf) = duration;
1139
1140   /* mind the swap, jpeglib outputs blue chroma first
1141    * ensonic: I see no swap?
1142    */
1143   base[0] = outdata + I420_Y_OFFSET (width, height);
1144   base[1] = outdata + I420_U_OFFSET (width, height);
1145   base[2] = outdata + I420_V_OFFSET (width, height);
1146
1147   /* make sure we don't make jpeglib write beyond our buffer,
1148    * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1149   last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1150   last[1] =
1151       base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1152           1));
1153   last[2] =
1154       base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1155           1));
1156
1157   GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1158       dec->cinfo.rec_outbuf_height);
1159
1160   /* For some widths jpeglib requires more horizontal padding than I420 
1161    * provides. In those cases we need to decode into separate buffers and then
1162    * copy over the data into our final picture buffer, otherwise jpeglib might
1163    * write over the end of a line into the beginning of the next line,
1164    * resulting in blocky artifacts on the left side of the picture. */
1165   if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1166           || dec->cinfo.comp_info[0].h_samp_factor != 2
1167           || dec->cinfo.comp_info[1].h_samp_factor != 1
1168           || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1169     GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1170         "indirect decoding using extra buffer copy");
1171     gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h);
1172   } else {
1173     ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1174
1175     if (G_UNLIKELY (ret != GST_FLOW_OK))
1176       goto decode_direct_failed;
1177   }
1178
1179   GST_LOG_OBJECT (dec, "decompressing finished");
1180   jpeg_finish_decompress (&dec->cinfo);
1181
1182   /* Clipping */
1183   if (dec->segment.format == GST_FORMAT_TIME) {
1184     gint64 start, stop, clip_start, clip_stop;
1185
1186     GST_LOG_OBJECT (dec, "Attempting clipping");
1187
1188     start = GST_BUFFER_TIMESTAMP (outbuf);
1189     if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1190       stop = start;
1191     else
1192       stop = start + GST_BUFFER_DURATION (outbuf);
1193
1194     if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1195             start, stop, &clip_start, &clip_stop)) {
1196       GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1197           GST_TIME_ARGS (clip_start));
1198       GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1199       if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1200         GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1201             GST_TIME_ARGS (clip_stop - clip_start));
1202         GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1203       }
1204     } else
1205       goto drop_buffer;
1206   }
1207
1208   GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1209       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1210       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1211
1212   ret = gst_pad_push (dec->srcpad, outbuf);
1213
1214 skip_decoding:
1215 done:
1216   if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) {
1217     gst_buffer_unref (dec->tempbuf);
1218     dec->tempbuf = NULL;
1219   } else {
1220     GstBuffer *buf = gst_buffer_create_sub (dec->tempbuf, img_len,
1221         GST_BUFFER_SIZE (dec->tempbuf) - img_len);
1222
1223     gst_buffer_unref (dec->tempbuf);
1224     dec->tempbuf = buf;
1225   }
1226
1227 exit:
1228
1229   return ret;
1230
1231   /* special cases */
1232 need_more_data:
1233   {
1234     GST_LOG_OBJECT (dec, "we need more data");
1235     if (outbuf) {
1236       gst_buffer_unref (outbuf);
1237       outbuf = NULL;
1238     }
1239     ret = GST_FLOW_OK;
1240     goto exit;
1241   }
1242   /* ERRORS */
1243 wrong_size:
1244   {
1245     GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1246         ("Picture is too small or too big (%ux%u)", width, height),
1247         ("Picture is too small or too big (%ux%u)", width, height));
1248     ret = GST_FLOW_ERROR;
1249     goto done;
1250   }
1251 decode_error:
1252   {
1253     gchar err_msg[JMSG_LENGTH_MAX];
1254
1255     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1256
1257     GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1258         (_("Failed to decode JPEG image")), ("Error #%u: %s", code, err_msg));
1259     if (outbuf) {
1260       gst_buffer_unref (outbuf);
1261       outbuf = NULL;
1262     }
1263     ret = GST_FLOW_ERROR;
1264     goto done;
1265   }
1266 decode_direct_failed:
1267   {
1268     /* already posted an error message */
1269     jpeg_abort_decompress (&dec->cinfo);
1270     gst_buffer_replace (&outbuf, NULL);
1271     goto done;
1272   }
1273 alloc_failed:
1274   {
1275     const gchar *reason;
1276
1277     reason = gst_flow_get_name (ret);
1278
1279     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1280     /* Reset for next time */
1281     jpeg_abort_decompress (&dec->cinfo);
1282     if (GST_FLOW_IS_FATAL (ret)) {
1283       GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1284           ("Buffer allocation failed, reason: %s", reason),
1285           ("Buffer allocation failed, reason: %s", reason));
1286     }
1287     goto exit;
1288   }
1289 drop_buffer:
1290   {
1291     GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1292     gst_buffer_unref (outbuf);
1293     ret = GST_FLOW_OK;
1294     goto exit;
1295   }
1296 }
1297
1298 static gboolean
1299 gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
1300 {
1301   GstJpegDec *dec;
1302   gboolean res;
1303
1304   dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
1305
1306   switch (GST_EVENT_TYPE (event)) {
1307     case GST_EVENT_QOS:{
1308       GstClockTimeDiff diff;
1309       GstClockTime timestamp;
1310       gdouble proportion;
1311
1312       gst_event_parse_qos (event, &proportion, &diff, &timestamp);
1313       gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1314       break;
1315     }
1316     default:
1317       break;
1318   }
1319
1320   res = gst_pad_push_event (dec->sinkpad, event);
1321
1322   gst_object_unref (dec);
1323   return res;
1324 }
1325
1326 static gboolean
1327 gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event)
1328 {
1329   gboolean ret = TRUE;
1330   GstJpegDec *dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
1331
1332   GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1333
1334   switch (GST_EVENT_TYPE (event)) {
1335     case GST_EVENT_FLUSH_STOP:
1336       GST_DEBUG_OBJECT (dec, "Aborting decompress");
1337       jpeg_abort_decompress (&dec->cinfo);
1338       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1339       gst_jpeg_dec_reset_qos (dec);
1340       break;
1341     case GST_EVENT_NEWSEGMENT:{
1342       gboolean update;
1343       gdouble rate, applied_rate;
1344       GstFormat format;
1345       gint64 start, stop, position;
1346
1347       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1348           &format, &start, &stop, &position);
1349
1350       GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
1351           " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
1352           GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
1353           GST_TIME_ARGS (position));
1354
1355       gst_segment_set_newsegment_full (&dec->segment, update, rate,
1356           applied_rate, format, start, stop, position);
1357
1358       break;
1359     }
1360     default:
1361       break;
1362   }
1363
1364   ret = gst_pad_push_event (dec->srcpad, event);
1365
1366   return ret;
1367 }
1368
1369 static void
1370 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1371     const GValue * value, GParamSpec * pspec)
1372 {
1373   GstJpegDec *dec;
1374
1375   dec = GST_JPEG_DEC (object);
1376
1377   switch (prop_id) {
1378     case PROP_IDCT_METHOD:
1379       dec->idct_method = g_value_get_enum (value);
1380       break;
1381
1382     default:
1383       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1384       break;
1385   }
1386 }
1387
1388 static void
1389 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1390     GParamSpec * pspec)
1391 {
1392   GstJpegDec *dec;
1393
1394   dec = GST_JPEG_DEC (object);
1395
1396   switch (prop_id) {
1397     case PROP_IDCT_METHOD:
1398       g_value_set_enum (value, dec->idct_method);
1399       break;
1400
1401     default:
1402       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1403       break;
1404   }
1405 }
1406
1407 static GstStateChangeReturn
1408 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1409 {
1410   GstStateChangeReturn ret;
1411   GstJpegDec *dec;
1412
1413   dec = GST_JPEG_DEC (element);
1414
1415   switch (transition) {
1416     case GST_STATE_CHANGE_READY_TO_PAUSED:
1417       dec->framerate_numerator = 0;
1418       dec->framerate_denominator = 1;
1419       dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
1420       dec->caps_width = -1;
1421       dec->caps_height = -1;
1422       dec->packetized = FALSE;
1423       dec->next_ts = 0;
1424       dec->discont = TRUE;
1425       gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1426       gst_jpeg_dec_reset_qos (dec);
1427     default:
1428       break;
1429   }
1430
1431   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1432   if (ret != GST_STATE_CHANGE_SUCCESS)
1433     return ret;
1434
1435   switch (transition) {
1436     case GST_STATE_CHANGE_PAUSED_TO_READY:
1437       if (dec->tempbuf) {
1438         gst_buffer_unref (dec->tempbuf);
1439         dec->tempbuf = NULL;
1440       }
1441       gst_jpeg_dec_free_buffers (dec);
1442       break;
1443     default:
1444       break;
1445   }
1446
1447   return ret;
1448 }