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>
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.
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.
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.
24 * SECTION:element-jpegdec
26 * Decodes jpeg images.
29 * <title>Example launch line</title>
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.
42 #include "gstjpegdec.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"
51 #define MAX_WIDTH 65535
53 #define MAX_HEIGHT 65535
55 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
56 (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
58 #define JPEG_DEFAULT_IDCT_METHOD JDCT_FASTEST
59 #define JPEG_DEFAULT_MAX_ERRORS 0
69 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
70 GST_STATIC_PAD_TEMPLATE ("src",
73 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
74 ("{ I420, RGB, BGR, RGBx, xRGB, BGRx, xBGR, GRAY8 }"))
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",
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) " ], "
87 "sof-marker = (int) { 0, 1, 2, 5, 6, 7, 9, 10, 13, 14 }")
90 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
91 #define GST_CAT_DEFAULT jpeg_dec_debug
92 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
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);
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,
111 #define gst_jpeg_dec_parent_class parent_class
112 G_DEFINE_TYPE (GstJpegDec, gst_jpeg_dec, GST_TYPE_VIDEO_DECODER);
115 gst_jpeg_dec_finalize (GObject * object)
117 GstJpegDec *dec = GST_JPEG_DEC (object);
119 jpeg_destroy_decompress (&dec->cinfo);
121 G_OBJECT_CLASS (parent_class)->finalize (object);
125 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
127 GObjectClass *gobject_class;
128 GstElementClass *element_class;
129 GstVideoDecoderClass *vdec_class;
131 gobject_class = (GObjectClass *) klass;
132 element_class = (GstElementClass *) klass;
133 vdec_class = (GstVideoDecoderClass *) klass;
135 parent_class = g_type_class_peek_parent (klass);
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;
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));
148 * GstJpegDec:max-errors
150 * Error out after receiving N consecutive decoding errors
151 * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
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));
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>");
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;
178 GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
179 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
183 gst_jpeg_dec_clear_error (GstJpegDec * dec)
185 g_free (dec->error_msg);
186 dec->error_msg = NULL;
188 dec->error_func = NULL;
192 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
193 const gchar * debug_msg_format, va_list args)
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);
200 g_free (dec->error_msg);
201 if (debug_msg_format)
202 dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
204 dec->error_msg = NULL;
206 dec->error_line = line;
207 dec->error_func = func;
211 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
212 const gchar * debug_msg_format, ...)
216 va_start (va, debug_msg_format);
217 gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
222 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
228 max_errors = g_atomic_int_get (&dec->max_errors);
230 if (max_errors < 0) {
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;
237 ret = GST_FLOW_ERROR;
240 ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
243 GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
244 max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
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);
252 dec->error_msg = NULL;
253 gst_jpeg_dec_clear_error (dec);
258 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
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);
267 cinfo->src->next_input_byte = dec->current_frame_map.data;
268 cinfo->src->bytes_in_buffer = dec->current_frame_map.size;
274 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
276 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
281 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
283 GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
285 GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
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;
294 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
296 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
301 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
303 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
308 gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
310 return; /* do nothing */
314 gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
316 /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
321 gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
323 struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
325 (*cinfo->err->output_message) (cinfo);
326 longjmp (err_mgr->setjmp_buffer, 1);
330 gst_jpeg_dec_init (GstJpegDec * dec)
332 GST_DEBUG ("initializing");
335 memset (&dec->cinfo, 0, sizeof (dec->cinfo));
336 memset (&dec->jerr, 0, sizeof (dec->jerr));
337 dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
338 dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
339 dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
340 dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
342 jpeg_create_decompress (&dec->cinfo);
344 dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
345 dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
346 dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
347 dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
348 dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
349 dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
352 /* init properties */
353 dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
354 dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
357 static inline gboolean
358 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
360 if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
366 gst_jpeg_dec_parse (GstVideoDecoder * bdec, GstVideoCodecFrame * frame,
367 GstAdapter * adapter, gboolean at_eos)
372 gint offset = 0, noffset;
373 GstJpegDec *dec = (GstJpegDec *) bdec;
375 /* FIXME : The overhead of using scan_uint32 is massive */
377 size = gst_adapter_available (adapter);
378 GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
381 GST_DEBUG ("Flushing all data out");
384 /* If we have leftover data, throw it away */
385 if (!dec->saw_header)
387 goto have_full_frame;
393 if (!dec->saw_header) {
395 /* we expect at least 4 bytes, first of which start marker */
397 gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0,
400 GST_DEBUG ("ret:%d", ret);
405 gst_adapter_flush (adapter, ret);
408 dec->saw_header = TRUE;
415 GST_DEBUG ("offset:%d, size:%d", offset, size);
418 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
419 offset, size - offset, &value);
421 /* lost sync if 0xff marker not where expected */
422 if ((resync = (noffset != offset))) {
423 GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
425 /* may have marker, but could have been resyncng */
426 resync = resync || dec->parse_resync;
427 /* Skip over extra 0xff */
428 while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
431 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
432 noffset, size - noffset, &value);
434 /* enough bytes left for marker? (we need 0xNN after the 0xff) */
436 GST_DEBUG ("at end of input and no EOI marker found, need more data");
440 /* now lock on the marker we found */
442 value = value & 0xff;
444 GST_DEBUG ("0x%08x: EOI marker", offset + 2);
445 /* clear parse state */
446 dec->saw_header = FALSE;
447 dec->parse_resync = FALSE;
449 goto have_full_frame;
452 /* Skip this frame if we found another SOI marker */
453 GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
454 dec->parse_resync = FALSE;
455 /* FIXME : Need to skip data */
457 goto have_full_frame;
461 if (value >= 0xd0 && value <= 0xd7)
464 /* peek tag and subsequent length */
465 if (offset + 2 + 4 > size)
468 gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
470 frame_len = frame_len & 0xffff;
472 GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
473 /* the frame length includes the 2 bytes for the length; here we want at
474 * least 2 more bytes at the end for an end marker */
475 if (offset + 2 + 2 + frame_len + 2 > size) {
479 if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
480 guint eseglen = dec->parse_entropy_len;
482 GST_DEBUG ("0x%08x: finding entropy segment length (eseglen:%d)",
483 offset + 2, eseglen);
484 if (size < offset + 2 + frame_len + eseglen)
486 noffset = offset + 2 + frame_len + dec->parse_entropy_len;
488 GST_DEBUG ("noffset:%d, size:%d, size - noffset:%d",
489 noffset, size, size - noffset);
490 noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
491 0x0000ff00, noffset, size - noffset, &value);
494 dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
497 if ((value & 0xff) != 0x00) {
498 eseglen = noffset - offset - frame_len - 2;
503 dec->parse_entropy_len = 0;
504 frame_len += eseglen;
505 GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
509 /* check if we will still be in sync if we interpret
510 * this as a sync point and skip this frame */
511 noffset = offset + frame_len + 2;
512 noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
515 /* ignore and continue resyncing until we hit the end
516 * of our data or find a sync point that looks okay */
520 GST_DEBUG ("found sync at 0x%x", offset + 2);
523 /* Add current data to output buffer */
524 toadd += frame_len + 2;
525 offset += frame_len + 2;
530 gst_video_decoder_add_to_frame (bdec, toadd);
531 return GST_VIDEO_DECODER_FLOW_NEED_DATA;
535 gst_video_decoder_add_to_frame (bdec, toadd);
536 return gst_video_decoder_have_frame (bdec);
539 gst_adapter_flush (adapter, size);
544 /* shamelessly ripped from jpegutils.c in mjpegtools */
546 add_huff_table (j_decompress_ptr dinfo,
547 JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
548 /* Define a Huffman table */
552 if (*htblptr == NULL)
553 *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
557 /* Copy the number-of-symbols-of-each-code-length counts */
558 memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
560 /* Validate the counts. We do this here mainly so we can copy the right
561 * number of symbols from the val[] array, without risking marching off
562 * the end of memory. jchuff.c will do a more thorough test later.
565 for (len = 1; len <= 16; len++)
566 nsymbols += bits[len];
567 if (nsymbols < 1 || nsymbols > 256)
568 g_error ("jpegutils.c: add_huff_table failed badly. ");
570 memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
576 std_huff_tables (j_decompress_ptr dinfo)
577 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
578 /* IMPORTANT: these are only valid for 8-bit data precision! */
580 static const UINT8 bits_dc_luminance[17] =
581 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
582 static const UINT8 val_dc_luminance[] =
583 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
585 static const UINT8 bits_dc_chrominance[17] =
586 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
587 static const UINT8 val_dc_chrominance[] =
588 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
590 static const UINT8 bits_ac_luminance[17] =
591 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
592 static const UINT8 val_ac_luminance[] =
593 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
594 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
595 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
596 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
597 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
598 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
599 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
600 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
601 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
602 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
603 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
604 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
605 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
606 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
607 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
608 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
609 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
610 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
611 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
612 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
616 static const UINT8 bits_ac_chrominance[17] =
617 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
618 static const UINT8 val_ac_chrominance[] =
619 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
620 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
621 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
622 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
623 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
624 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
625 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
626 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
627 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
628 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
629 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
630 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
631 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
632 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
633 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
634 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
635 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
636 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
637 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
638 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
642 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
643 bits_dc_luminance, val_dc_luminance);
644 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
645 bits_ac_luminance, val_ac_luminance);
646 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
647 bits_dc_chrominance, val_dc_chrominance);
648 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
649 bits_ac_chrominance, val_ac_chrominance);
655 guarantee_huff_tables (j_decompress_ptr dinfo)
657 if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
658 (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
659 (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
660 (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
661 GST_DEBUG ("Generating standard Huffman tables for this frame.");
662 std_huff_tables (dinfo);
667 gst_jpeg_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
669 GstJpegDec *jpeg = GST_JPEG_DEC (dec);
670 GstVideoInfo *info = &state->info;
672 /* FIXME : previously jpegdec would handled input as packetized
673 * if the framerate was present. Here we consider it packetized if
674 * the fps is != 1/1 */
675 if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1)
676 gst_video_decoder_set_packetized (dec, TRUE);
678 gst_video_decoder_set_packetized (dec, FALSE);
680 if (jpeg->input_state)
681 gst_video_codec_state_unref (jpeg->input_state);
682 jpeg->input_state = gst_video_codec_state_ref (state);
690 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
694 for (i = 0; i < len; ++i) {
695 /* equivalent to: dest[i] = src[i << 1] */
704 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
708 for (i = 0; i < 16; i++) {
709 g_free (dec->idr_y[i]);
710 g_free (dec->idr_u[i]);
711 g_free (dec->idr_v[i]);
712 dec->idr_y[i] = NULL;
713 dec->idr_u[i] = NULL;
714 dec->idr_v[i] = NULL;
717 dec->idr_width_allocated = 0;
720 static inline gboolean
721 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
725 if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
728 /* FIXME: maybe just alloc one or three blocks altogether? */
729 for (i = 0; i < 16; i++) {
730 dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
731 dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
732 dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
734 if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
735 GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
740 dec->idr_width_allocated = maxrowbytes;
741 GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
746 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, GstVideoFrame * frame)
749 guchar **scanarray[1] = { rows };
754 gint pstride, rstride;
756 GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
758 width = GST_VIDEO_FRAME_WIDTH (frame);
759 height = GST_VIDEO_FRAME_HEIGHT (frame);
761 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
764 base[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
765 pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
766 rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
768 memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
772 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
773 if (G_LIKELY (lines > 0)) {
774 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
778 for (k = 0; k < width; k++) {
779 base[0][p] = rows[j][k];
785 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
791 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, GstVideoFrame * frame)
793 guchar *r_rows[16], *g_rows[16], *b_rows[16];
794 guchar **scanarray[3] = { r_rows, g_rows, b_rows };
798 guint pstride, rstride;
801 GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
803 width = GST_VIDEO_FRAME_WIDTH (frame);
804 height = GST_VIDEO_FRAME_HEIGHT (frame);
806 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
809 for (i = 0; i < 3; i++)
810 base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
812 pstride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
813 rstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
815 memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
816 memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
817 memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
821 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
822 if (G_LIKELY (lines > 0)) {
823 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
827 for (k = 0; k < width; k++) {
828 base[0][p] = r_rows[j][k];
829 base[1][p] = g_rows[j][k];
830 base[2][p] = b_rows[j][k];
838 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
844 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame, gint r_v,
847 guchar *y_rows[16], *u_rows[16], *v_rows[16];
848 guchar **scanarray[3] = { y_rows, u_rows, v_rows };
851 guchar *base[3], *last[3];
855 GST_DEBUG_OBJECT (dec,
856 "unadvantageous width or r_h, taking slow route involving memcpy");
858 width = GST_VIDEO_FRAME_WIDTH (frame);
859 height = GST_VIDEO_FRAME_HEIGHT (frame);
861 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
864 for (i = 0; i < 3; i++) {
865 base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
866 stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
867 /* make sure we don't make jpeglib write beyond our buffer,
868 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
869 last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
870 (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
873 memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
874 memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
875 memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
877 /* fill chroma components for grayscale */
879 GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
880 for (i = 0; i < 16; i++) {
881 memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
882 memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
886 for (i = 0; i < height; i += r_v * DCTSIZE) {
887 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
888 if (G_LIKELY (lines > 0)) {
889 for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
890 if (G_LIKELY (base[0] <= last[0])) {
891 memcpy (base[0], y_rows[j], stride[0]);
892 base[0] += stride[0];
895 if (G_LIKELY (base[0] <= last[0])) {
896 memcpy (base[0], y_rows[j + 1], stride[0]);
897 base[0] += stride[0];
900 if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
902 memcpy (base[1], u_rows[k], stride[1]);
903 memcpy (base[2], v_rows[k], stride[2]);
904 } else if (r_h == 1) {
905 hresamplecpy1 (base[1], u_rows[k], stride[1]);
906 hresamplecpy1 (base[2], v_rows[k], stride[2]);
908 /* FIXME: implement (at least we avoid crashing by doing nothing) */
912 if (r_v == 2 || (k & 1) != 0) {
913 base[1] += stride[1];
914 base[2] += stride[2];
918 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
924 gst_jpeg_dec_decode_direct (GstJpegDec * dec, GstVideoFrame * frame)
926 guchar **line[3]; /* the jpeg line buffer */
927 guchar *y[4 * DCTSIZE] = { NULL, }; /* alloc enough for the lines */
928 guchar *u[4 * DCTSIZE] = { NULL, }; /* r_v will be <4 */
929 guchar *v[4 * DCTSIZE] = { NULL, };
931 gint lines, v_samp[3];
932 guchar *base[3], *last[3];
940 v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
941 v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
942 v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
944 if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
945 goto format_not_supported;
947 height = GST_VIDEO_FRAME_HEIGHT (frame);
949 for (i = 0; i < 3; i++) {
950 base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
951 stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
952 /* make sure we don't make jpeglib write beyond our buffer,
953 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
954 last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
955 (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
958 /* let jpeglib decode directly into our final buffer */
959 GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
961 for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
962 for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
964 line[0][j] = base[0] + (i + j) * stride[0];
965 if (G_UNLIKELY (line[0][j] > last[0]))
966 line[0][j] = last[0];
968 if (v_samp[1] == v_samp[0]) {
969 line[1][j] = base[1] + ((i + j) / 2) * stride[1];
970 } else if (j < (v_samp[1] * DCTSIZE)) {
971 line[1][j] = base[1] + ((i / 2) + j) * stride[1];
973 if (G_UNLIKELY (line[1][j] > last[1]))
974 line[1][j] = last[1];
976 if (v_samp[2] == v_samp[0]) {
977 line[2][j] = base[2] + ((i + j) / 2) * stride[2];
978 } else if (j < (v_samp[2] * DCTSIZE)) {
979 line[2][j] = base[2] + ((i / 2) + j) * stride[2];
981 if (G_UNLIKELY (line[2][j] > last[2]))
982 line[2][j] = last[2];
985 lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
986 if (G_UNLIKELY (!lines)) {
987 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
992 format_not_supported:
994 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
995 "Unsupported subsampling schema: v_samp factors: %u %u %u",
996 v_samp[0], v_samp[1], v_samp[2]);
997 return GST_FLOW_ERROR;
1002 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1004 GstVideoCodecState *outstate;
1006 GstVideoFormat format;
1010 format = GST_VIDEO_FORMAT_RGB;
1013 format = GST_VIDEO_FORMAT_GRAY8;
1016 format = GST_VIDEO_FORMAT_I420;
1020 /* Compare to currently configured output state */
1021 outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
1023 info = &outstate->info;
1025 if (width == GST_VIDEO_INFO_WIDTH (info) &&
1026 height == GST_VIDEO_INFO_HEIGHT (info) &&
1027 format == GST_VIDEO_INFO_FORMAT (info)) {
1028 gst_video_codec_state_unref (outstate);
1031 gst_video_codec_state_unref (outstate);
1035 gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format,
1036 width, height, dec->input_state);
1043 outstate->info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
1044 outstate->info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
1045 outstate->info.colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
1046 outstate->info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
1050 gst_video_codec_state_unref (outstate);
1052 GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1053 GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1056 static GstFlowReturn
1057 gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
1059 GstFlowReturn ret = GST_FLOW_OK;
1060 GstJpegDec *dec = (GstJpegDec *) bdec;
1061 GstVideoFrame vframe;
1065 gboolean need_unmap = TRUE;
1066 GstVideoCodecState *state = NULL;
1068 dec->current_frame = frame;
1069 gst_buffer_map (frame->input_buffer, &dec->current_frame_map, GST_MAP_READ);
1070 gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1072 if (setjmp (dec->jerr.setjmp_buffer)) {
1073 code = dec->jerr.pub.msg_code;
1075 if (code == JERR_INPUT_EOF) {
1076 GST_DEBUG ("jpeg input EOF error, we probably need more data");
1077 goto need_more_data;
1083 hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1084 if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1085 GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1088 GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1089 GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1091 if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1092 goto components_not_supported;
1094 r_h = dec->cinfo.comp_info[0].h_samp_factor;
1095 r_v = dec->cinfo.comp_info[0].v_samp_factor;
1097 GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1099 if (dec->cinfo.num_components > 3)
1100 goto components_not_supported;
1102 /* verify color space expectation to avoid going *boom* or bogus output */
1103 if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1104 dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1105 dec->cinfo.jpeg_color_space != JCS_RGB)
1106 goto unsupported_colorspace;
1108 #ifndef GST_DISABLE_GST_DEBUG
1112 for (i = 0; i < dec->cinfo.num_components; ++i) {
1113 GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1114 i, dec->cinfo.comp_info[i].h_samp_factor,
1115 dec->cinfo.comp_info[i].v_samp_factor,
1116 dec->cinfo.comp_info[i].component_id);
1121 /* prepare for raw output */
1122 dec->cinfo.do_fancy_upsampling = FALSE;
1123 dec->cinfo.do_block_smoothing = FALSE;
1124 dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1125 dec->cinfo.dct_method = dec->idct_method;
1126 dec->cinfo.raw_data_out = TRUE;
1128 GST_LOG_OBJECT (dec, "starting decompress");
1129 guarantee_huff_tables (&dec->cinfo);
1130 if (!jpeg_start_decompress (&dec->cinfo)) {
1131 GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1134 /* sanity checks to get safe and reasonable output */
1135 switch (dec->cinfo.jpeg_color_space) {
1137 if (dec->cinfo.num_components != 1)
1138 goto invalid_yuvrgbgrayscale;
1141 if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1142 dec->cinfo.max_h_samp_factor > 1)
1143 goto invalid_yuvrgbgrayscale;
1146 if (dec->cinfo.num_components != 3 ||
1147 r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1148 r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1149 r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1150 r_h < dec->cinfo.comp_info[1].h_samp_factor)
1151 goto invalid_yuvrgbgrayscale;
1154 g_assert_not_reached ();
1158 width = dec->cinfo.output_width;
1159 height = dec->cinfo.output_height;
1161 if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1162 height < MIN_HEIGHT || height > MAX_HEIGHT))
1165 gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1167 state = gst_video_decoder_get_output_state (bdec);
1168 ret = gst_video_decoder_alloc_output_frame (bdec, frame);
1169 if (G_UNLIKELY (ret != GST_FLOW_OK))
1172 if (!gst_video_frame_map (&vframe, &state->info, frame->output_buffer,
1176 GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1178 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1179 gst_jpeg_dec_decode_rgb (dec, &vframe);
1180 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1181 gst_jpeg_dec_decode_grayscale (dec, &vframe);
1183 GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1184 dec->cinfo.rec_outbuf_height);
1186 /* For some widths jpeglib requires more horizontal padding than I420
1187 * provides. In those cases we need to decode into separate buffers and then
1188 * copy over the data into our final picture buffer, otherwise jpeglib might
1189 * write over the end of a line into the beginning of the next line,
1190 * resulting in blocky artifacts on the left side of the picture. */
1191 if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1192 || dec->cinfo.comp_info[0].h_samp_factor != 2
1193 || dec->cinfo.comp_info[1].h_samp_factor != 1
1194 || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1195 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1196 "indirect decoding using extra buffer copy");
1197 gst_jpeg_dec_decode_indirect (dec, &vframe, r_v, r_h,
1198 dec->cinfo.num_components);
1200 ret = gst_jpeg_dec_decode_direct (dec, &vframe);
1202 if (G_UNLIKELY (ret != GST_FLOW_OK))
1203 goto decode_direct_failed;
1207 gst_video_frame_unmap (&vframe);
1209 GST_LOG_OBJECT (dec, "decompressing finished");
1210 jpeg_finish_decompress (&dec->cinfo);
1212 /* reset error count on successful decode */
1213 dec->error_count = 0;
1215 gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1216 ret = gst_video_decoder_finish_frame (bdec, frame);
1223 if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1224 jpeg_abort_decompress (&dec->cinfo);
1225 ret = gst_jpeg_dec_post_error_or_warning (dec);
1229 gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1232 gst_video_codec_state_unref (state);
1239 GST_LOG_OBJECT (dec, "we need more data");
1246 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1247 "Picture is too small or too big (%ux%u)", width, height);
1248 ret = GST_FLOW_ERROR;
1253 gchar err_msg[JMSG_LENGTH_MAX];
1255 dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1257 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1258 "Decode error #%u: %s", code, err_msg);
1260 gst_buffer_unmap (frame->input_buffer, &dec->current_frame_map);
1261 gst_video_decoder_drop_frame (bdec, frame);
1264 ret = GST_FLOW_ERROR;
1267 decode_direct_failed:
1269 /* already posted an error message */
1270 jpeg_abort_decompress (&dec->cinfo);
1275 const gchar *reason;
1277 reason = gst_flow_get_name (ret);
1279 GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1280 /* Reset for next time */
1281 jpeg_abort_decompress (&dec->cinfo);
1282 if (ret != GST_FLOW_EOS && ret != GST_FLOW_FLUSHING &&
1283 ret != GST_FLOW_NOT_LINKED) {
1284 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1285 "Buffer allocation failed, reason: %s", reason);
1289 components_not_supported:
1291 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1292 "number of components not supported: %d (max 3)",
1293 dec->cinfo.num_components);
1294 ret = GST_FLOW_ERROR;
1297 unsupported_colorspace:
1299 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1300 "Picture has unknown or unsupported colourspace");
1301 ret = GST_FLOW_ERROR;
1304 invalid_yuvrgbgrayscale:
1306 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1307 "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1308 ret = GST_FLOW_ERROR;
1314 gst_jpeg_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
1316 GstBufferPool *pool;
1317 GstStructure *config;
1319 if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
1322 g_assert (gst_query_get_n_allocation_pools (query) > 0);
1323 gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
1324 g_assert (pool != NULL);
1326 config = gst_buffer_pool_get_config (pool);
1327 if (gst_query_has_allocation_meta (query, GST_VIDEO_META_API_TYPE)) {
1328 gst_buffer_pool_config_add_option (config,
1329 GST_BUFFER_POOL_OPTION_VIDEO_META);
1331 gst_buffer_pool_set_config (pool, config);
1332 gst_object_unref (pool);
1338 gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard)
1340 GstJpegDec *dec = (GstJpegDec *) bdec;
1342 jpeg_abort_decompress (&dec->cinfo);
1343 dec->parse_entropy_len = 0;
1344 dec->parse_resync = FALSE;
1345 dec->saw_header = FALSE;
1351 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1352 const GValue * value, GParamSpec * pspec)
1356 dec = GST_JPEG_DEC (object);
1359 case PROP_IDCT_METHOD:
1360 dec->idct_method = g_value_get_enum (value);
1362 case PROP_MAX_ERRORS:
1363 g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1373 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1378 dec = GST_JPEG_DEC (object);
1381 case PROP_IDCT_METHOD:
1382 g_value_set_enum (value, dec->idct_method);
1384 case PROP_MAX_ERRORS:
1385 g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1389 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1395 gst_jpeg_dec_start (GstVideoDecoder * bdec)
1397 GstJpegDec *dec = (GstJpegDec *) bdec;
1399 dec->error_count = 0;
1400 dec->parse_entropy_len = 0;
1401 dec->parse_resync = FALSE;
1407 gst_jpeg_dec_stop (GstVideoDecoder * bdec)
1409 GstJpegDec *dec = (GstJpegDec *) bdec;
1411 gst_jpeg_dec_free_buffers (dec);