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