jpegdec: Fix compilation
[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  * Copyright (C) 2012 Collabora Ltd.
5  *      Author : Edward Hervey <edward@collabora.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:element-jpegdec
25  *
26  * Decodes jpeg images.
27  *
28  * <refsect2>
29  * <title>Example launch line</title>
30  * |[
31  * gst-launch -v v4l2src ! jpegdec ! ffmpegcolorspace ! xvimagesink
32  * ]| The above pipeline reads a motion JPEG stream from a v4l2 camera
33  * and renders it to the screen.
34  * </refsect2>
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include <string.h>
41
42 #include "gstjpegdec.h"
43 #include "gstjpeg.h"
44 #include <gst/video/video.h>
45 #include <gst/video/gstvideometa.h>
46 #include <gst/video/gstvideopool.h>
47 #include "gst/gst-i18n-plugin.h"
48 #include <jerror.h>
49
50 #define MIN_WIDTH  1
51 #define MAX_WIDTH  65535
52 #define MIN_HEIGHT 1
53 #define MAX_HEIGHT 65535
54
55 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
56         (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
57
58 #define JPEG_DEFAULT_IDCT_METHOD        JDCT_FASTEST
59 #define JPEG_DEFAULT_MAX_ERRORS         0
60
61 enum
62 {
63   PROP_0,
64   PROP_IDCT_METHOD,
65   PROP_MAX_ERRORS
66 };
67
68 /* *INDENT-OFF* */
69 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
70 GST_STATIC_PAD_TEMPLATE ("src",
71     GST_PAD_SRC,
72     GST_PAD_ALWAYS,
73     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
74         ("{ I420, RGB, BGR, RGBx, xRGB, BGRx, xBGR, GRAY8 }"))
75     );
76 /* *INDENT-ON* */
77
78 /* FIXME: sof-marker is for IJG libjpeg 8, should be different for 6.2 */
79 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
80 GST_STATIC_PAD_TEMPLATE ("sink",
81     GST_PAD_SINK,
82     GST_PAD_ALWAYS,
83     GST_STATIC_CAPS ("image/jpeg, "
84         "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
85         " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
86         G_STRINGIFY (MAX_HEIGHT) " ], framerate = (fraction) [ 0/1, MAX ], "
87         "sof-marker = (int) { 0, 1, 2, 5, 6, 7, 9, 10, 13, 14 }")
88     );
89
90 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
91 #define GST_CAT_DEFAULT jpeg_dec_debug
92 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
93
94 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
95     const GValue * value, GParamSpec * pspec);
96 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
97     GValue * value, GParamSpec * pspec);
98
99 static gboolean gst_jpeg_dec_set_format (GstVideoDecoder * dec,
100     GstVideoCodecState * state);
101 static gboolean gst_jpeg_dec_start (GstVideoDecoder * bdec);
102 static gboolean gst_jpeg_dec_stop (GstVideoDecoder * bdec);
103 static gboolean gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard);
104 static GstFlowReturn gst_jpeg_dec_parse (GstVideoDecoder * bdec,
105     GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
106 static GstFlowReturn gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec,
107     GstVideoCodecFrame * frame);
108 static gboolean gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec,
109     GstQuery * query);
110
111 #define gst_jpeg_dec_parent_class parent_class
112 G_DEFINE_TYPE (GstJpegDec, gst_jpeg_dec, GST_TYPE_VIDEO_DECODER);
113
114 static void
115 gst_jpeg_dec_finalize (GObject * object)
116 {
117   GstJpegDec *dec = GST_JPEG_DEC (object);
118
119   jpeg_destroy_decompress (&dec->cinfo);
120
121   G_OBJECT_CLASS (parent_class)->finalize (object);
122 }
123
124 static void
125 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
126 {
127   GObjectClass *gobject_class;
128   GstElementClass *element_class;
129   GstVideoDecoderClass *vdec_class;
130
131   gobject_class = (GObjectClass *) klass;
132   element_class = (GstElementClass *) klass;
133   vdec_class = (GstVideoDecoderClass *) klass;
134
135   parent_class = g_type_class_peek_parent (klass);
136
137   gobject_class->finalize = gst_jpeg_dec_finalize;
138   gobject_class->set_property = gst_jpeg_dec_set_property;
139   gobject_class->get_property = gst_jpeg_dec_get_property;
140
141   g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
142       g_param_spec_enum ("idct-method", "IDCT Method",
143           "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
144           JPEG_DEFAULT_IDCT_METHOD,
145           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
146
147   /**
148    * GstJpegDec:max-errors
149    *
150    * Error out after receiving N consecutive decoding errors
151    * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
152    *
153    * Since: 0.10.27
154    **/
155   g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
156       g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
157           "Error out after receiving N consecutive decoding errors "
158           "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
159           -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
160           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161
162   gst_element_class_add_pad_template (element_class,
163       gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
164   gst_element_class_add_pad_template (element_class,
165       gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
166   gst_element_class_set_details_simple (element_class, "JPEG image decoder",
167       "Codec/Decoder/Image",
168       "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
169
170   vdec_class->start = gst_jpeg_dec_start;
171   vdec_class->stop = gst_jpeg_dec_stop;
172   vdec_class->reset = gst_jpeg_dec_reset;
173   vdec_class->parse = gst_jpeg_dec_parse;
174   vdec_class->set_format = gst_jpeg_dec_set_format;
175   vdec_class->handle_frame = gst_jpeg_dec_handle_frame;
176   vdec_class->decide_allocation = gst_jpeg_dec_decide_allocation;
177
178   GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
179   GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
180 }
181
182 static void
183 gst_jpeg_dec_clear_error (GstJpegDec * dec)
184 {
185   g_free (dec->error_msg);
186   dec->error_msg = NULL;
187   dec->error_line = 0;
188   dec->error_func = NULL;
189 }
190
191 static void
192 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
193     const gchar * debug_msg_format, va_list args)
194 {
195 #ifndef GST_DISABLE_GST_DEBUG
196   gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
197       line, (GObject *) dec, debug_msg_format, args);
198 #endif
199
200   g_free (dec->error_msg);
201   if (debug_msg_format)
202     dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
203   else
204     dec->error_msg = NULL;
205
206   dec->error_line = line;
207   dec->error_func = func;
208 }
209
210 static void
211 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
212     const gchar * debug_msg_format, ...)
213 {
214   va_list va;
215
216   va_start (va, debug_msg_format);
217   gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
218   va_end (va);
219 }
220
221 static GstFlowReturn
222 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
223 {
224   GstFlowReturn ret;
225   int max_errors;
226
227   ++dec->error_count;
228   max_errors = g_atomic_int_get (&dec->max_errors);
229
230   if (max_errors < 0) {
231     ret = GST_FLOW_OK;
232   } else if (max_errors == 0) {
233     /* FIXME: do something more clever in "automatic mode" */
234     if (gst_video_decoder_get_packetized (GST_VIDEO_DECODER (dec))) {
235       ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
236     } else {
237       ret = GST_FLOW_ERROR;
238     }
239   } else {
240     ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
241   }
242
243   GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
244       max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
245
246   gst_element_message_full (GST_ELEMENT (dec),
247       (ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
248       GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
249       g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
250       __FILE__, dec->error_func, dec->error_line);
251
252   dec->error_msg = NULL;
253   gst_jpeg_dec_clear_error (dec);
254   return ret;
255 }
256
257 static boolean
258 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
259 {
260   GstJpegDec *dec;
261
262   dec = CINFO_GET_JPEGDEC (cinfo);
263   g_return_val_if_fail (dec != NULL, FALSE);
264   g_return_val_if_fail (dec->current_frame != NULL, FALSE);
265   g_return_val_if_fail (dec->current_frame_map.data != NULL, FALSE);
266
267   cinfo->src->next_input_byte = dec->current_frame_map.data;
268   cinfo->src->bytes_in_buffer = dec->current_frame_map.size;
269
270   return TRUE;
271 }
272
273 static void
274 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
275 {
276   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
277 }
278
279
280 static void
281 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
282 {
283   GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
284
285   GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
286
287   if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
288     cinfo->src->next_input_byte += (size_t) num_bytes;
289     cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
290   }
291 #if 0
292   else if (num_bytes > 0) {
293     gint available;
294
295     num_bytes -= cinfo->src->bytes_in_buffer;
296     cinfo->src->next_input_byte += (size_t) cinfo->src->bytes_in_buffer;
297     cinfo->src->bytes_in_buffer = 0;
298
299     available = gst_adapter_available (dec->adapter);
300     if (available < num_bytes || available < dec->rem_img_len) {
301       GST_WARNING_OBJECT (dec, "Less bytes to skip than available in the "
302           "adapter or the remaining image length %ld < %d or %u",
303           num_bytes, available, dec->rem_img_len);
304     }
305     num_bytes = MIN (MIN (num_bytes, available), dec->rem_img_len);
306     gst_adapter_flush (dec->adapter, num_bytes);
307     dec->rem_img_len -= num_bytes;
308   }
309 #endif
310 }
311
312 static boolean
313 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
314 {
315   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
316   return TRUE;
317 }
318
319 static void
320 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
321 {
322   GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
323   return;
324 }
325
326 METHODDEF (void)
327     gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
328 {
329   return;                       /* do nothing */
330 }
331
332 METHODDEF (void)
333     gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
334 {
335   /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
336   return;
337 }
338
339 METHODDEF (void)
340     gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
341 {
342   struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
343
344   (*cinfo->err->output_message) (cinfo);
345   longjmp (err_mgr->setjmp_buffer, 1);
346 }
347
348 static void
349 gst_jpeg_dec_init (GstJpegDec * dec)
350 {
351   GST_DEBUG ("initializing");
352
353 #if 0
354   /* create the sink and src pads */
355   dec->sinkpad =
356       gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
357       "sink");
358   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
359   gst_pad_set_setcaps_function (dec->sinkpad,
360       GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
361
362   dec->srcpad =
363       gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
364   gst_pad_use_fixed_caps (dec->srcpad);
365   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
366 #endif
367
368   /* setup jpeglib */
369   memset (&dec->cinfo, 0, sizeof (dec->cinfo));
370   memset (&dec->jerr, 0, sizeof (dec->jerr));
371   dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
372   dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
373   dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
374   dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
375
376   jpeg_create_decompress (&dec->cinfo);
377
378   dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
379   dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
380   dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
381   dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
382   dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
383   dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
384   dec->jsrc.dec = dec;
385
386   /* init properties */
387   dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
388   dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
389 }
390
391 #if 0
392 static gboolean
393 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
394 {
395   gint av;
396   gint offset;
397
398   av = gst_adapter_available (dec->adapter);
399   /* we expect at least 4 bytes, first of which start marker */
400   offset = gst_adapter_masked_scan_uint32 (dec->adapter, 0xffffff00, 0xffd8ff00,
401       0, av);
402   if (G_UNLIKELY (offset < 0)) {
403     GST_DEBUG_OBJECT (dec, "No JPEG header in current buffer");
404     /* not found */
405     if (av > 4)
406       gst_adapter_flush (dec->adapter, av - 4);
407     return FALSE;
408   }
409
410   if (offset > 0) {
411     GST_LOG_OBJECT (dec, "Skipping %u bytes.", offset);
412     gst_adapter_flush (dec->adapter, offset);
413   }
414   GST_DEBUG_OBJECT (dec, "Found JPEG header");
415
416   return TRUE;
417 }
418 #endif
419
420 static inline gboolean
421 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
422 {
423   if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
424     return TRUE;
425   return FALSE;
426 }
427
428 static GstFlowReturn
429 gst_jpeg_dec_parse (GstVideoDecoder * bdec, GstVideoCodecFrame * frame,
430     GstAdapter * adapter, gboolean at_eos)
431 {
432   guint size;
433   gint toadd = 0;
434   gboolean resync;
435   gint offset = 0, noffset;
436   GstJpegDec *dec = (GstJpegDec *) bdec;
437
438   /* FIXME : The overhead of using scan_uint32 is massive */
439
440   size = gst_adapter_available (adapter);
441   GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
442
443   if (at_eos) {
444     GST_DEBUG ("Flushing all data out");
445     toadd = size;
446
447     /* If we have leftover data, throw it away */
448     if (!dec->saw_header)
449       goto drop_frame;
450     goto have_full_frame;
451   }
452
453   if (size < 8)
454     goto need_more_data;
455
456   if (!dec->saw_header) {
457     gint ret;
458     /* we expect at least 4 bytes, first of which start marker */
459     ret =
460         gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0,
461         size - 4);
462
463     GST_DEBUG ("ret:%d", ret);
464     if (ret < 0)
465       goto need_more_data;
466
467     if (ret) {
468       gst_adapter_flush (adapter, ret);
469       size -= ret;
470     }
471     dec->saw_header = TRUE;
472   }
473
474   while (1) {
475     guint frame_len;
476     guint32 value;
477
478     GST_DEBUG ("offset:%d, size:%d", offset, size);
479
480     noffset =
481         gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
482         offset, size - offset, &value);
483
484     /* lost sync if 0xff marker not where expected */
485     if ((resync = (noffset != offset))) {
486       GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
487     }
488     /* may have marker, but could have been resyncng */
489     resync = resync || dec->parse_resync;
490     /* Skip over extra 0xff */
491     while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
492       noffset++;
493       noffset =
494           gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
495           noffset, size - noffset, &value);
496     }
497     /* enough bytes left for marker? (we need 0xNN after the 0xff) */
498     if (noffset < 0) {
499       GST_DEBUG ("at end of input and no EOI marker found, need more data");
500       goto need_more_data;
501     }
502
503     /* now lock on the marker we found */
504     offset = noffset;
505     value = value & 0xff;
506     if (value == 0xd9) {
507       GST_DEBUG ("0x%08x: EOI marker", offset + 2);
508       /* clear parse state */
509       dec->saw_header = FALSE;
510       dec->parse_resync = FALSE;
511       toadd = offset + 4;
512       goto have_full_frame;
513     }
514     if (value == 0xd8) {
515       /* Skip this frame if we found another SOI marker */
516       GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
517       dec->parse_resync = FALSE;
518       /* FIXME : Need to skip data */
519       toadd -= offset + 2;
520       goto have_full_frame;
521     }
522
523
524     if (value >= 0xd0 && value <= 0xd7)
525       frame_len = 0;
526     else {
527       /* peek tag and subsequent length */
528       if (offset + 2 + 4 > size)
529         goto need_more_data;
530       else
531         gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
532             &frame_len);
533       frame_len = frame_len & 0xffff;
534     }
535     GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
536     /* the frame length includes the 2 bytes for the length; here we want at
537      * least 2 more bytes at the end for an end marker */
538     if (offset + 2 + 2 + frame_len + 2 > size) {
539       goto need_more_data;
540     }
541
542     if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
543       guint eseglen = dec->parse_entropy_len;
544
545       GST_DEBUG ("0x%08x: finding entropy segment length (eseglen:%d)",
546           offset + 2, eseglen);
547       if (size < offset + 2 + frame_len + eseglen)
548         goto need_more_data;
549       noffset = offset + 2 + frame_len + dec->parse_entropy_len;
550       while (1) {
551         GST_DEBUG ("noffset:%d, size:%d, size - noffset:%d",
552             noffset, size, size - noffset);
553         noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
554             0x0000ff00, noffset, size - noffset, &value);
555         if (noffset < 0) {
556           /* need more data */
557           dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
558           goto need_more_data;
559         }
560         if ((value & 0xff) != 0x00) {
561           eseglen = noffset - offset - frame_len - 2;
562           break;
563         }
564         noffset++;
565       }
566       dec->parse_entropy_len = 0;
567       frame_len += eseglen;
568       GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
569           frame_len);
570     }
571     if (resync) {
572       /* check if we will still be in sync if we interpret
573        * this as a sync point and skip this frame */
574       noffset = offset + frame_len + 2;
575       noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
576           noffset, 4);
577       if (noffset < 0) {
578         /* ignore and continue resyncing until we hit the end
579          * of our data or find a sync point that looks okay */
580         offset++;
581         continue;
582       }
583       GST_DEBUG ("found sync at 0x%x", offset + 2);
584     }
585
586     /* Add current data to output buffer */
587     toadd += frame_len + 2;
588     offset += frame_len + 2;
589   }
590
591 need_more_data:
592   if (toadd)
593     gst_video_decoder_add_to_frame (bdec, toadd);
594   return GST_VIDEO_DECODER_FLOW_NEED_DATA;
595
596 have_full_frame:
597   if (toadd)
598     gst_video_decoder_add_to_frame (bdec, toadd);
599   return gst_video_decoder_have_frame (bdec);
600
601 drop_frame:
602   gst_adapter_flush (adapter, size);
603   return GST_FLOW_OK;
604 }
605
606
607 /* shamelessly ripped from jpegutils.c in mjpegtools */
608 static void
609 add_huff_table (j_decompress_ptr dinfo,
610     JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
611 /* Define a Huffman table */
612 {
613   int nsymbols, len;
614
615   if (*htblptr == NULL)
616     *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
617
618   g_assert (*htblptr);
619
620   /* Copy the number-of-symbols-of-each-code-length counts */
621   memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
622
623   /* Validate the counts.  We do this here mainly so we can copy the right
624    * number of symbols from the val[] array, without risking marching off
625    * the end of memory.  jchuff.c will do a more thorough test later.
626    */
627   nsymbols = 0;
628   for (len = 1; len <= 16; len++)
629     nsymbols += bits[len];
630   if (nsymbols < 1 || nsymbols > 256)
631     g_error ("jpegutils.c:  add_huff_table failed badly. ");
632
633   memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
634 }
635
636
637
638 static void
639 std_huff_tables (j_decompress_ptr dinfo)
640 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
641 /* IMPORTANT: these are only valid for 8-bit data precision! */
642 {
643   static const UINT8 bits_dc_luminance[17] =
644       { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
645   static const UINT8 val_dc_luminance[] =
646       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
647
648   static const UINT8 bits_dc_chrominance[17] =
649       { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
650   static const UINT8 val_dc_chrominance[] =
651       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
652
653   static const UINT8 bits_ac_luminance[17] =
654       { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
655   static const UINT8 val_ac_luminance[] =
656       { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
657     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
658     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
659     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
660     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
661     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
662     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
663     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
664     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
665     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
666     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
667     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
668     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
669     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
670     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
671     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
672     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
673     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
674     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
675     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
676     0xf9, 0xfa
677   };
678
679   static const UINT8 bits_ac_chrominance[17] =
680       { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
681   static const UINT8 val_ac_chrominance[] =
682       { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
683     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
684     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
685     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
686     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
687     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
688     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
689     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
690     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
691     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
692     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
693     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
694     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
695     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
696     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
697     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
698     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
699     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
700     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
701     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
702     0xf9, 0xfa
703   };
704
705   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
706       bits_dc_luminance, val_dc_luminance);
707   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
708       bits_ac_luminance, val_ac_luminance);
709   add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
710       bits_dc_chrominance, val_dc_chrominance);
711   add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
712       bits_ac_chrominance, val_ac_chrominance);
713 }
714
715
716
717 static void
718 guarantee_huff_tables (j_decompress_ptr dinfo)
719 {
720   if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
721       (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
722       (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
723       (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
724     GST_DEBUG ("Generating standard Huffman tables for this frame.");
725     std_huff_tables (dinfo);
726   }
727 }
728
729 static gboolean
730 gst_jpeg_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
731 {
732   GstJpegDec *jpeg = GST_JPEG_DEC (dec);
733   GstVideoInfo *info = &state->info;
734
735   /* FIXME : previously jpegdec would handled input as packetized
736    * if the framerate was present. Here we consider it packetized if
737    * the fps is != 1/1 */
738   if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1)
739     gst_video_decoder_set_packetized (dec, TRUE);
740   else
741     gst_video_decoder_set_packetized (dec, FALSE);
742
743   if (jpeg->input_state)
744     gst_video_codec_state_unref (jpeg->input_state);
745   jpeg->input_state = gst_video_codec_state_ref (state);
746
747   return TRUE;
748 }
749
750
751 /* yuk */
752 static void
753 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
754 {
755   gint i;
756
757   for (i = 0; i < len; ++i) {
758     /* equivalent to: dest[i] = src[i << 1] */
759     *dest = *src;
760     ++dest;
761     ++src;
762     ++src;
763   }
764 }
765
766 static void
767 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
768 {
769   gint i;
770
771   for (i = 0; i < 16; i++) {
772     g_free (dec->idr_y[i]);
773     g_free (dec->idr_u[i]);
774     g_free (dec->idr_v[i]);
775     dec->idr_y[i] = NULL;
776     dec->idr_u[i] = NULL;
777     dec->idr_v[i] = NULL;
778   }
779
780   dec->idr_width_allocated = 0;
781 }
782
783 static inline gboolean
784 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
785 {
786   gint i;
787
788   if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
789     return TRUE;
790
791   /* FIXME: maybe just alloc one or three blocks altogether? */
792   for (i = 0; i < 16; i++) {
793     dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
794     dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
795     dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
796
797     if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
798       GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
799       return FALSE;
800     }
801   }
802
803   dec->idr_width_allocated = maxrowbytes;
804   GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
805   return TRUE;
806 }
807
808 static void
809 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, GstVideoFrame * frame)
810 {
811   guchar *rows[16];
812   guchar **scanarray[1] = { rows };
813   gint i, j, k;
814   gint lines;
815   guint8 *base[1];
816   gint width, height;
817   gint pstride, rstride;
818
819   GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
820
821   width = GST_VIDEO_FRAME_WIDTH (frame);
822   height = GST_VIDEO_FRAME_HEIGHT (frame);
823
824   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
825     return;
826
827   base[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
828   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
829   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
830
831   memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
832
833   i = 0;
834   while (i < height) {
835     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
836     if (G_LIKELY (lines > 0)) {
837       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
838         gint p;
839
840         p = 0;
841         for (k = 0; k < width; k++) {
842           base[0][p] = rows[j][k];
843           p += pstride;
844         }
845         base[0] += rstride;
846       }
847     } else {
848       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
849     }
850   }
851 }
852
853 static void
854 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, GstVideoFrame * frame)
855 {
856   guchar *r_rows[16], *g_rows[16], *b_rows[16];
857   guchar **scanarray[3] = { r_rows, g_rows, b_rows };
858   gint i, j, k;
859   gint lines;
860   guint8 *base[3];
861   guint pstride, rstride;
862   gint width, height;
863
864   GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
865
866   width = GST_VIDEO_FRAME_WIDTH (frame);
867   height = GST_VIDEO_FRAME_HEIGHT (frame);
868
869   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
870     return;
871
872   for (i = 0; i < 3; i++)
873     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
874
875   pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
876   rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
877
878   memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
879   memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
880   memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
881
882   i = 0;
883   while (i < height) {
884     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
885     if (G_LIKELY (lines > 0)) {
886       for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
887         gint p;
888
889         p = 0;
890         for (k = 0; k < width; k++) {
891           base[0][p] = r_rows[j][k];
892           base[1][p] = g_rows[j][k];
893           base[2][p] = b_rows[j][k];
894           p += pstride;
895         }
896         base[0] += rstride;
897         base[1] += rstride;
898         base[2] += rstride;
899       }
900     } else {
901       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
902     }
903   }
904 }
905
906 static void
907 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame, gint r_v,
908     gint r_h, gint comp)
909 {
910   guchar *y_rows[16], *u_rows[16], *v_rows[16];
911   guchar **scanarray[3] = { y_rows, u_rows, v_rows };
912   gint i, j, k;
913   gint lines;
914   guchar *base[3], *last[3];
915   gint stride[3];
916   gint width, height;
917
918   GST_DEBUG_OBJECT (dec,
919       "unadvantageous width or r_h, taking slow route involving memcpy");
920
921   width = GST_VIDEO_FRAME_WIDTH (frame);
922   height = GST_VIDEO_FRAME_HEIGHT (frame);
923
924   if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
925     return;
926
927   for (i = 0; i < 3; i++) {
928     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
929     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
930     /* make sure we don't make jpeglib write beyond our buffer,
931      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
932     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
933         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
934   }
935
936   memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
937   memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
938   memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
939
940   /* fill chroma components for grayscale */
941   if (comp == 1) {
942     GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
943     for (i = 0; i < 16; i++) {
944       memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
945       memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
946     }
947   }
948
949   for (i = 0; i < height; i += r_v * DCTSIZE) {
950     lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
951     if (G_LIKELY (lines > 0)) {
952       for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
953         if (G_LIKELY (base[0] <= last[0])) {
954           memcpy (base[0], y_rows[j], stride[0]);
955           base[0] += stride[0];
956         }
957         if (r_v == 2) {
958           if (G_LIKELY (base[0] <= last[0])) {
959             memcpy (base[0], y_rows[j + 1], stride[0]);
960             base[0] += stride[0];
961           }
962         }
963         if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
964           if (r_h == 2) {
965             memcpy (base[1], u_rows[k], stride[1]);
966             memcpy (base[2], v_rows[k], stride[2]);
967           } else if (r_h == 1) {
968             hresamplecpy1 (base[1], u_rows[k], stride[1]);
969             hresamplecpy1 (base[2], v_rows[k], stride[2]);
970           } else {
971             /* FIXME: implement (at least we avoid crashing by doing nothing) */
972           }
973         }
974
975         if (r_v == 2 || (k & 1) != 0) {
976           base[1] += stride[1];
977           base[2] += stride[2];
978         }
979       }
980     } else {
981       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
982     }
983   }
984 }
985
986 static GstFlowReturn
987 gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame)
988 {
989   guchar **line[3];             /* the jpeg line buffer         */
990   guchar *y[4 * DCTSIZE] = { NULL, };   /* alloc enough for the lines   */
991   guchar *u[4 * DCTSIZE] = { NULL, };   /* r_v will be <4               */
992   guchar *v[4 * DCTSIZE] = { NULL, };
993   gint i, j;
994   gint lines, v_samp[3];
995   guchar *base[3], *last[3];
996   gint stride[3];
997   guint height;
998
999   line[0] = y;
1000   line[1] = u;
1001   line[2] = v;
1002
1003   v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1004   v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1005   v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1006
1007   if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1008     goto format_not_supported;
1009
1010   height = GST_VIDEO_FRAME_HEIGHT (frame);
1011
1012   for (i = 0; i < 3; i++) {
1013     base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
1014     stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
1015     /* make sure we don't make jpeglib write beyond our buffer,
1016      * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1017     last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
1018         (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
1019   }
1020
1021   /* let jpeglib decode directly into our final buffer */
1022   GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1023
1024   for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1025     for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1026       /* Y */
1027       line[0][j] = base[0] + (i + j) * stride[0];
1028       if (G_UNLIKELY (line[0][j] > last[0]))
1029         line[0][j] = last[0];
1030       /* U */
1031       if (v_samp[1] == v_samp[0]) {
1032         line[1][j] = base[1] + ((i + j) / 2) * stride[1];
1033       } else if (j < (v_samp[1] * DCTSIZE)) {
1034         line[1][j] = base[1] + ((i / 2) + j) * stride[1];
1035       }
1036       if (G_UNLIKELY (line[1][j] > last[1]))
1037         line[1][j] = last[1];
1038       /* V */
1039       if (v_samp[2] == v_samp[0]) {
1040         line[2][j] = base[2] + ((i + j) / 2) * stride[2];
1041       } else if (j < (v_samp[2] * DCTSIZE)) {
1042         line[2][j] = base[2] + ((i / 2) + j) * stride[2];
1043       }
1044       if (G_UNLIKELY (line[2][j] > last[2]))
1045         line[2][j] = last[2];
1046     }
1047
1048     lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1049     if (G_UNLIKELY (!lines)) {
1050       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1051     }
1052   }
1053   return GST_FLOW_OK;
1054
1055 format_not_supported:
1056   {
1057     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1058         "Unsupported subsampling schema: v_samp factors: %u %u %u",
1059         v_samp[0], v_samp[1], v_samp[2]);
1060     return GST_FLOW_ERROR;
1061   }
1062 }
1063
1064 static void
1065 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1066 {
1067   GstVideoCodecState *outstate;
1068   GstVideoInfo *info;
1069   GstVideoFormat format;
1070
1071   switch (clrspc) {
1072     case JCS_RGB:
1073       format = GST_VIDEO_FORMAT_RGB;
1074       break;
1075     case JCS_GRAYSCALE:
1076       format = GST_VIDEO_FORMAT_GRAY8;
1077       break;
1078     default:
1079       format = GST_VIDEO_FORMAT_I420;
1080       break;
1081   }
1082
1083   /* Compare to currently configured output state */
1084   outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
1085   if (outstate) {
1086     info = &outstate->info;
1087
1088     if (width == GST_VIDEO_INFO_WIDTH (info) &&
1089         height == GST_VIDEO_INFO_HEIGHT (info) &&
1090         format == GST_VIDEO_INFO_FORMAT (info)) {
1091       gst_video_codec_state_unref (outstate);
1092       return;
1093     }
1094     gst_video_codec_state_unref (outstate);
1095   }
1096
1097   outstate =
1098       gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format,
1099       width, height, dec->input_state);
1100
1101   gst_video_codec_state_unref (outstate);
1102
1103   GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1104   GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1105 }
1106
1107 static GstFlowReturn
1108 gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
1109 {
1110   GstFlowReturn ret = GST_FLOW_OK;
1111   GstJpegDec *dec = (GstJpegDec *) bdec;
1112   GstVideoFrame vframe;
1113   gint width, height;
1114   gint r_h, r_v;
1115   guint code, hdr_ok;
1116   gboolean need_unmap = TRUE;
1117   GstVideoCodecState *state = NULL;
1118
1119 #if 0
1120 again:
1121   if (!gst_jpeg_dec_ensure_header (dec))
1122     goto need_more_data;
1123
1124   /* If we know that each input buffer contains data
1125    * for a whole jpeg image (e.g. MJPEG streams), just 
1126    * do some sanity checking instead of parsing all of 
1127    * the jpeg data */
1128   if (dec->packetized) {
1129     img_len = gst_adapter_available (dec->adapter);
1130   } else {
1131     /* Parse jpeg image to handle jpeg input that
1132      * is not aligned to buffer boundaries */
1133     img_len = gst_jpeg_dec_parse_image_data (dec);
1134
1135     if (img_len == 0) {
1136       goto need_more_data;
1137     } else if (img_len < 0) {
1138       gst_adapter_flush (dec->adapter, -img_len);
1139       goto again;
1140     }
1141   }
1142 #endif
1143
1144   dec->current_frame = frame;
1145   gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
1146   gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1147
1148   if (setjmp (dec->jerr.setjmp_buffer)) {
1149     code = dec->jerr.pub.msg_code;
1150
1151     if (code == JERR_INPUT_EOF) {
1152       GST_DEBUG ("jpeg input EOF error, we probably need more data");
1153       goto need_more_data;
1154     }
1155     goto decode_error;
1156   }
1157
1158   /* read header */
1159   hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1160   if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1161     GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1162   }
1163
1164   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1165   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1166
1167   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1168     goto components_not_supported;
1169
1170   r_h = dec->cinfo.comp_info[0].h_samp_factor;
1171   r_v = dec->cinfo.comp_info[0].v_samp_factor;
1172
1173   GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1174
1175   if (dec->cinfo.num_components > 3)
1176     goto components_not_supported;
1177
1178   /* verify color space expectation to avoid going *boom* or bogus output */
1179   if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1180       dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1181       dec->cinfo.jpeg_color_space != JCS_RGB)
1182     goto unsupported_colorspace;
1183
1184 #ifndef GST_DISABLE_GST_DEBUG
1185   {
1186     gint i;
1187
1188     for (i = 0; i < dec->cinfo.num_components; ++i) {
1189       GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1190           i, dec->cinfo.comp_info[i].h_samp_factor,
1191           dec->cinfo.comp_info[i].v_samp_factor,
1192           dec->cinfo.comp_info[i].component_id);
1193     }
1194   }
1195 #endif
1196
1197   /* prepare for raw output */
1198   dec->cinfo.do_fancy_upsampling = FALSE;
1199   dec->cinfo.do_block_smoothing = FALSE;
1200   dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1201   dec->cinfo.dct_method = dec->idct_method;
1202   dec->cinfo.raw_data_out = TRUE;
1203
1204   GST_LOG_OBJECT (dec, "starting decompress");
1205   guarantee_huff_tables (&dec->cinfo);
1206   if (!jpeg_start_decompress (&dec->cinfo)) {
1207     GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1208   }
1209
1210   /* sanity checks to get safe and reasonable output */
1211   switch (dec->cinfo.jpeg_color_space) {
1212     case JCS_GRAYSCALE:
1213       if (dec->cinfo.num_components != 1)
1214         goto invalid_yuvrgbgrayscale;
1215       break;
1216     case JCS_RGB:
1217       if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1218           dec->cinfo.max_h_samp_factor > 1)
1219         goto invalid_yuvrgbgrayscale;
1220       break;
1221     case JCS_YCbCr:
1222       if (dec->cinfo.num_components != 3 ||
1223           r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1224           r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1225           r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1226           r_h < dec->cinfo.comp_info[1].h_samp_factor)
1227         goto invalid_yuvrgbgrayscale;
1228       break;
1229     default:
1230       g_assert_not_reached ();
1231       break;
1232   }
1233
1234   width = dec->cinfo.output_width;
1235   height = dec->cinfo.output_height;
1236
1237   if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1238           height < MIN_HEIGHT || height > MAX_HEIGHT))
1239     goto wrong_size;
1240
1241   gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1242
1243   state = gst_video_decoder_get_output_state (bdec);
1244   ret = gst_video_decoder_alloc_output_frame (bdec, frame);
1245   if (G_UNLIKELY (ret != GST_FLOW_OK))
1246     goto alloc_failed;
1247
1248   if (!gst_video_frame_map (&vframe, &state->info, frame->output_buffer,
1249           GST_MAP_READWRITE))
1250     goto alloc_failed;
1251
1252   GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1253
1254   if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1255     gst_jpeg_dec_decode_rgb (dec, &vframe);
1256   } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1257     gst_jpeg_dec_decode_grayscale (dec, &vframe);
1258   } else {
1259     GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1260         dec->cinfo.rec_outbuf_height);
1261
1262     /* For some widths jpeglib requires more horizontal padding than I420 
1263      * provides. In those cases we need to decode into separate buffers and then
1264      * copy over the data into our final picture buffer, otherwise jpeglib might
1265      * write over the end of a line into the beginning of the next line,
1266      * resulting in blocky artifacts on the left side of the picture. */
1267     if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1268             || dec->cinfo.comp_info[0].h_samp_factor != 2
1269             || dec->cinfo.comp_info[1].h_samp_factor != 1
1270             || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1271       GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1272           "indirect decoding using extra buffer copy");
1273       gst_jpeg_dec_decode_indirect (dec, &vframe, r_v, r_h,
1274           dec->cinfo.num_components);
1275     } else {
1276       ret = gst_jpeg_dec_decode_direct (dec, &vframe);
1277
1278       if (G_UNLIKELY (ret != GST_FLOW_OK))
1279         goto decode_direct_failed;
1280     }
1281   }
1282
1283   gst_video_frame_unmap (&vframe);
1284
1285   GST_LOG_OBJECT (dec, "decompressing finished");
1286   jpeg_finish_decompress (&dec->cinfo);
1287
1288   /* reset error count on successful decode */
1289   dec->error_count = 0;
1290
1291   gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1292   ret = gst_video_decoder_finish_frame (bdec, frame);
1293   need_unmap = FALSE;
1294
1295 done:
1296
1297 exit:
1298
1299   if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1300     jpeg_abort_decompress (&dec->cinfo);
1301     ret = gst_jpeg_dec_post_error_or_warning (dec);
1302   }
1303
1304   if (need_unmap)
1305     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1306
1307   if (state)
1308     gst_video_codec_state_unref (state);
1309
1310   return ret;
1311
1312   /* special cases */
1313 need_more_data:
1314   {
1315     GST_LOG_OBJECT (dec, "we need more data");
1316     ret = GST_FLOW_OK;
1317     goto exit;
1318   }
1319   /* ERRORS */
1320 wrong_size:
1321   {
1322     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1323         "Picture is too small or too big (%ux%u)", width, height);
1324     ret = GST_FLOW_ERROR;
1325     goto done;
1326   }
1327 decode_error:
1328   {
1329     gchar err_msg[JMSG_LENGTH_MAX];
1330
1331     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1332
1333     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1334         "Decode error #%u: %s", code, err_msg);
1335
1336     gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1337     gst_video_decoder_drop_frame (bdec, frame);
1338     need_unmap = FALSE;
1339
1340     ret = GST_FLOW_ERROR;
1341     goto done;
1342   }
1343 decode_direct_failed:
1344   {
1345     /* already posted an error message */
1346     jpeg_abort_decompress (&dec->cinfo);
1347     goto done;
1348   }
1349 alloc_failed:
1350   {
1351     const gchar *reason;
1352
1353     reason = gst_flow_get_name (ret);
1354
1355     GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1356     /* Reset for next time */
1357     jpeg_abort_decompress (&dec->cinfo);
1358     if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1359         ret != GST_FLOW_NOT_LINKED) {
1360       gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1361           "Buffer allocation failed, reason: %s", reason);
1362     }
1363     goto exit;
1364   }
1365 components_not_supported:
1366   {
1367     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1368         "number of components not supported: %d (max 3)",
1369         dec->cinfo.num_components);
1370     ret = GST_FLOW_ERROR;
1371     goto done;
1372   }
1373 unsupported_colorspace:
1374   {
1375     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1376         "Picture has unknown or unsupported colourspace");
1377     ret = GST_FLOW_ERROR;
1378     goto done;
1379   }
1380 invalid_yuvrgbgrayscale:
1381   {
1382     gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1383         "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1384     ret = GST_FLOW_ERROR;
1385     goto done;
1386   }
1387 }
1388
1389 static gboolean
1390 gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
1391 {
1392   GstBufferPool *pool;
1393   GstStructure *config;
1394
1395   if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
1396     return FALSE;
1397
1398   g_assert (gst_query_get_n_allocation_pools (query) > 0);
1399   gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
1400   g_assert (pool != NULL);
1401
1402   config = gst_buffer_pool_get_config (pool);
1403   if (gst_query_has_allocation_meta (query, GST_VIDEO_META_API_TYPE)) {
1404     gst_buffer_pool_config_add_option (config,
1405         GST_BUFFER_POOL_OPTION_VIDEO_META);
1406   }
1407   gst_buffer_pool_set_config (pool, config);
1408   gst_object_unref (pool);
1409
1410   return TRUE;
1411 }
1412
1413 static gboolean
1414 gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard)
1415 {
1416   GstJpegDec *dec = (GstJpegDec *) bdec;
1417
1418   jpeg_abort_decompress (&dec->cinfo);
1419   dec->parse_entropy_len = 0;
1420   dec->parse_resync = FALSE;
1421   dec->saw_header = FALSE;
1422
1423   return TRUE;
1424 }
1425
1426 static void
1427 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1428     const GValue * value, GParamSpec * pspec)
1429 {
1430   GstJpegDec *dec;
1431
1432   dec = GST_JPEG_DEC (object);
1433
1434   switch (prop_id) {
1435     case PROP_IDCT_METHOD:
1436       dec->idct_method = g_value_get_enum (value);
1437       break;
1438     case PROP_MAX_ERRORS:
1439       g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1440       break;
1441
1442     default:
1443       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1444       break;
1445   }
1446 }
1447
1448 static void
1449 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1450     GParamSpec * pspec)
1451 {
1452   GstJpegDec *dec;
1453
1454   dec = GST_JPEG_DEC (object);
1455
1456   switch (prop_id) {
1457     case PROP_IDCT_METHOD:
1458       g_value_set_enum (value, dec->idct_method);
1459       break;
1460     case PROP_MAX_ERRORS:
1461       g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1462       break;
1463
1464     default:
1465       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1466       break;
1467   }
1468 }
1469
1470 static gboolean
1471 gst_jpeg_dec_start (GstVideoDecoder * bdec)
1472 {
1473   GstJpegDec *dec = (GstJpegDec *) bdec;
1474
1475   dec->error_count = 0;
1476   dec->parse_entropy_len = 0;
1477   dec->parse_resync = FALSE;
1478
1479   return TRUE;
1480 }
1481
1482 static gboolean
1483 gst_jpeg_dec_stop (GstVideoDecoder * bdec)
1484 {
1485   GstJpegDec *dec = (GstJpegDec *) bdec;
1486
1487   gst_jpeg_dec_free_buffers (dec);
1488
1489   return TRUE;
1490 }