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/gst-i18n-plugin.h"
49 #define MAX_WIDTH 65535
51 #define MAX_HEIGHT 65535
53 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
54 (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
56 #define JPEG_DEFAULT_IDCT_METHOD JDCT_FASTEST
57 #define JPEG_DEFAULT_MAX_ERRORS 0
67 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
68 GST_STATIC_PAD_TEMPLATE ("src",
71 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") "; "
72 GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; "
73 GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; "
74 GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR "; "
79 /* FIXME: sof-marker is for IJG libjpeg 8, should be different for 6.2 */
80 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
81 GST_STATIC_PAD_TEMPLATE ("sink",
84 GST_STATIC_CAPS ("image/jpeg, "
85 "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
86 " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
87 G_STRINGIFY (MAX_HEIGHT) " ], framerate = (fraction) [ 0/1, MAX ], "
88 "sof-marker = (int) { 0, 1, 2, 5, 6, 7, 9, 10, 13, 14 }")
91 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
92 #define GST_CAT_DEFAULT jpeg_dec_debug
93 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
95 /* These macros are adapted from videotestsrc.c
96 * and/or gst-plugins/gst/games/gstvideoimage.c */
97 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
98 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
99 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
101 #define I420_Y_OFFSET(w,h) (0)
102 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
103 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
105 #define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
107 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
108 const GValue * value, GParamSpec * pspec);
109 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
110 GValue * value, GParamSpec * pspec);
112 static gboolean gst_jpeg_dec_set_format (GstVideoDecoder * dec,
113 GstVideoCodecState * state);
114 static gboolean gst_jpeg_dec_start (GstVideoDecoder * bdec);
115 static gboolean gst_jpeg_dec_stop (GstVideoDecoder * bdec);
116 static gboolean gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard);
117 static GstFlowReturn gst_jpeg_dec_parse (GstVideoDecoder * bdec,
118 GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
119 static GstFlowReturn gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec,
120 GstVideoCodecFrame * frame);
122 GST_BOILERPLATE (GstJpegDec, gst_jpeg_dec, GstVideoDecoder,
123 GST_TYPE_VIDEO_DECODER);
126 gst_jpeg_dec_finalize (GObject * object)
128 GstJpegDec *dec = GST_JPEG_DEC (object);
130 jpeg_destroy_decompress (&dec->cinfo);
132 G_OBJECT_CLASS (parent_class)->finalize (object);
136 gst_jpeg_dec_base_init (gpointer g_class)
138 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
140 gst_element_class_add_static_pad_template (element_class,
141 &gst_jpeg_dec_src_pad_template);
142 gst_element_class_add_static_pad_template (element_class,
143 &gst_jpeg_dec_sink_pad_template);
144 gst_element_class_set_details_simple (element_class, "JPEG image decoder",
145 "Codec/Decoder/Image",
146 "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
150 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
152 GObjectClass *gobject_class;
153 GstVideoDecoderClass *vdec_class;
155 gobject_class = (GObjectClass *) klass;
156 vdec_class = (GstVideoDecoderClass *) klass;
158 parent_class = g_type_class_peek_parent (klass);
160 gobject_class->finalize = gst_jpeg_dec_finalize;
161 gobject_class->set_property = gst_jpeg_dec_set_property;
162 gobject_class->get_property = gst_jpeg_dec_get_property;
164 g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
165 g_param_spec_enum ("idct-method", "IDCT Method",
166 "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
167 JPEG_DEFAULT_IDCT_METHOD,
168 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
171 * GstJpegDec:max-errors
173 * Error out after receiving N consecutive decoding errors
174 * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
178 g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
179 g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
180 "Error out after receiving N consecutive decoding errors "
181 "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
182 -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
183 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185 vdec_class->start = gst_jpeg_dec_start;
186 vdec_class->stop = gst_jpeg_dec_stop;
187 vdec_class->reset = gst_jpeg_dec_reset;
188 vdec_class->parse = gst_jpeg_dec_parse;
189 vdec_class->set_format = gst_jpeg_dec_set_format;
190 vdec_class->handle_frame = gst_jpeg_dec_handle_frame;
192 GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
193 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
197 gst_jpeg_dec_clear_error (GstJpegDec * dec)
199 g_free (dec->error_msg);
200 dec->error_msg = NULL;
202 dec->error_func = NULL;
206 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
207 const gchar * debug_msg_format, va_list args)
209 #ifndef GST_DISABLE_GST_DEBUG
210 gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
211 line, (GObject *) dec, debug_msg_format, args);
214 g_free (dec->error_msg);
215 if (debug_msg_format)
216 dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
218 dec->error_msg = NULL;
220 dec->error_line = line;
221 dec->error_func = func;
225 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
226 const gchar * debug_msg_format, ...)
230 va_start (va, debug_msg_format);
231 gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
236 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
242 max_errors = g_atomic_int_get (&dec->max_errors);
244 if (max_errors < 0) {
246 } else if (max_errors == 0) {
247 /* FIXME: do something more clever in "automatic mode" */
248 if (gst_video_decoder_get_packetized (GST_VIDEO_DECODER (dec))) {
249 ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
251 ret = GST_FLOW_ERROR;
254 ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
257 GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
258 max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
260 gst_element_message_full (GST_ELEMENT (dec),
261 (ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
262 GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
263 g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
264 __FILE__, dec->error_func, dec->error_line);
266 dec->error_msg = NULL;
267 gst_jpeg_dec_clear_error (dec);
272 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
276 dec = CINFO_GET_JPEGDEC (cinfo);
277 g_return_val_if_fail (dec != NULL, FALSE);
278 g_return_val_if_fail (dec->current_frame != NULL, FALSE);
280 cinfo->src->next_input_byte =
281 GST_BUFFER_DATA (dec->current_frame->input_buffer);
282 cinfo->src->bytes_in_buffer =
283 GST_BUFFER_SIZE (dec->current_frame->input_buffer);
289 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
291 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
296 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
298 GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
300 GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
302 if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
303 cinfo->src->next_input_byte += (size_t) num_bytes;
304 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
307 else if (num_bytes > 0) {
310 num_bytes -= cinfo->src->bytes_in_buffer;
311 cinfo->src->next_input_byte += (size_t) cinfo->src->bytes_in_buffer;
312 cinfo->src->bytes_in_buffer = 0;
314 available = gst_adapter_available (dec->adapter);
315 if (available < num_bytes || available < dec->rem_img_len) {
316 GST_WARNING_OBJECT (dec, "Less bytes to skip than available in the "
317 "adapter or the remaining image length %ld < %d or %u",
318 num_bytes, available, dec->rem_img_len);
320 num_bytes = MIN (MIN (num_bytes, available), dec->rem_img_len);
321 gst_adapter_flush (dec->adapter, num_bytes);
322 dec->rem_img_len -= num_bytes;
328 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
330 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
335 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
337 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
342 gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
344 return; /* do nothing */
348 gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
350 /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
355 gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
357 struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
359 (*cinfo->err->output_message) (cinfo);
360 longjmp (err_mgr->setjmp_buffer, 1);
364 gst_jpeg_dec_init (GstJpegDec * dec, GstJpegDecClass * class)
366 GST_DEBUG ("initializing");
369 /* create the sink and src pads */
371 gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
373 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
374 gst_pad_set_setcaps_function (dec->sinkpad,
375 GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
378 gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
379 gst_pad_use_fixed_caps (dec->srcpad);
380 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
384 memset (&dec->cinfo, 0, sizeof (dec->cinfo));
385 memset (&dec->jerr, 0, sizeof (dec->jerr));
386 dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
387 dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
388 dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
389 dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
391 jpeg_create_decompress (&dec->cinfo);
393 dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
394 dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
395 dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
396 dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
397 dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
398 dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
401 /* init properties */
402 dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
403 dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
408 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
413 av = gst_adapter_available (dec->adapter);
414 /* we expect at least 4 bytes, first of which start marker */
415 offset = gst_adapter_masked_scan_uint32 (dec->adapter, 0xffffff00, 0xffd8ff00,
417 if (G_UNLIKELY (offset < 0)) {
418 GST_DEBUG_OBJECT (dec, "No JPEG header in current buffer");
421 gst_adapter_flush (dec->adapter, av - 4);
426 GST_LOG_OBJECT (dec, "Skipping %u bytes.", offset);
427 gst_adapter_flush (dec->adapter, offset);
429 GST_DEBUG_OBJECT (dec, "Found JPEG header");
435 static inline gboolean
436 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
438 if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
444 gst_jpeg_dec_parse (GstVideoDecoder * bdec, GstVideoCodecFrame * frame,
445 GstAdapter * adapter, gboolean at_eos)
450 gint offset = 0, noffset;
451 GstJpegDec *dec = (GstJpegDec *) bdec;
453 /* FIXME : The overhead of using scan_uint32 is massive */
455 size = gst_adapter_available (adapter);
456 GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
459 GST_DEBUG ("Flushing all data out");
461 goto have_full_frame;
467 /* we expect at least 4 bytes, first of which start marker */
469 gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0,
471 GST_DEBUG ("ret:%d", ret);
476 gst_adapter_flush (adapter, ret);
484 GST_DEBUG ("offset:%d, size:%d", offset, size);
487 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
488 offset, size - offset, &value);
490 /* lost sync if 0xff marker not where expected */
491 if ((resync = (noffset != offset))) {
492 GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
494 /* may have marker, but could have been resyncng */
495 resync = resync || dec->parse_resync;
496 /* Skip over extra 0xff */
497 while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
500 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
501 noffset, size - noffset, &value);
503 /* enough bytes left for marker? (we need 0xNN after the 0xff) */
505 GST_DEBUG ("at end of input and no EOI marker found, need more data");
509 /* now lock on the marker we found */
511 value = value & 0xff;
513 GST_DEBUG ("0x%08x: EOI marker", offset + 2);
514 /* clear parse state */
515 dec->parse_resync = FALSE;
516 dec->parse_offset = 0;
518 goto have_full_frame;
521 /* Skip this frame if we found another SOI marker */
522 GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
523 dec->parse_resync = FALSE;
524 dec->parse_offset = 0;
525 /* FIXME : Need to skip data */
527 goto have_full_frame;
531 if (value >= 0xd0 && value <= 0xd7)
534 /* peek tag and subsequent length */
535 if (offset + 2 + 4 > size)
538 gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
540 frame_len = frame_len & 0xffff;
542 GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
543 /* the frame length includes the 2 bytes for the length; here we want at
544 * least 2 more bytes at the end for an end marker */
545 if (offset + 2 + 2 + frame_len + 2 > size) {
549 if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
550 guint eseglen = dec->parse_entropy_len;
552 GST_DEBUG ("0x%08x: finding entropy segment length (eseglen:%d)",
553 offset + 2, eseglen);
554 if (size < offset + 2 + frame_len + eseglen)
556 noffset = offset + 2 + frame_len + dec->parse_entropy_len;
558 GST_DEBUG ("noffset:%d, size:%d, size - noffset:%d",
559 noffset, size, size - noffset);
560 noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
561 0x0000ff00, noffset, size - noffset, &value);
564 dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
567 if ((value & 0xff) != 0x00) {
568 eseglen = noffset - offset - frame_len - 2;
573 dec->parse_entropy_len = 0;
574 frame_len += eseglen;
575 GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
579 /* check if we will still be in sync if we interpret
580 * this as a sync point and skip this frame */
581 noffset = offset + frame_len + 2;
582 noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
585 /* ignore and continue resyncing until we hit the end
586 * of our data or find a sync point that looks okay */
590 GST_DEBUG ("found sync at 0x%x", offset + 2);
593 /* Add current data to output buffer */
594 toadd += frame_len + 2;
595 offset += frame_len + 2;
600 gst_video_decoder_add_to_frame (bdec, toadd);
601 return GST_VIDEO_DECODER_FLOW_NEED_DATA;
605 gst_video_decoder_add_to_frame (bdec, toadd);
606 return gst_video_decoder_have_frame (bdec);
610 /* shamelessly ripped from jpegutils.c in mjpegtools */
612 add_huff_table (j_decompress_ptr dinfo,
613 JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
614 /* Define a Huffman table */
618 if (*htblptr == NULL)
619 *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
623 /* Copy the number-of-symbols-of-each-code-length counts */
624 memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
626 /* Validate the counts. We do this here mainly so we can copy the right
627 * number of symbols from the val[] array, without risking marching off
628 * the end of memory. jchuff.c will do a more thorough test later.
631 for (len = 1; len <= 16; len++)
632 nsymbols += bits[len];
633 if (nsymbols < 1 || nsymbols > 256)
634 g_error ("jpegutils.c: add_huff_table failed badly. ");
636 memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
642 std_huff_tables (j_decompress_ptr dinfo)
643 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
644 /* IMPORTANT: these are only valid for 8-bit data precision! */
646 static const UINT8 bits_dc_luminance[17] =
647 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
648 static const UINT8 val_dc_luminance[] =
649 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
651 static const UINT8 bits_dc_chrominance[17] =
652 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
653 static const UINT8 val_dc_chrominance[] =
654 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
656 static const UINT8 bits_ac_luminance[17] =
657 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
658 static const UINT8 val_ac_luminance[] =
659 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
660 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
661 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
662 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
663 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
664 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
665 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
666 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
667 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
668 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
669 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
670 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
671 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
672 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
673 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
674 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
675 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
676 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
677 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
678 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
682 static const UINT8 bits_ac_chrominance[17] =
683 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
684 static const UINT8 val_ac_chrominance[] =
685 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
686 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
687 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
688 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
689 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
690 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
691 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
692 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
693 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
694 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
695 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
696 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
697 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
698 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
699 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
700 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
701 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
702 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
703 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
704 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
708 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
709 bits_dc_luminance, val_dc_luminance);
710 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
711 bits_ac_luminance, val_ac_luminance);
712 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
713 bits_dc_chrominance, val_dc_chrominance);
714 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
715 bits_ac_chrominance, val_ac_chrominance);
721 guarantee_huff_tables (j_decompress_ptr dinfo)
723 if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
724 (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
725 (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
726 (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
727 GST_DEBUG ("Generating standard Huffman tables for this frame.");
728 std_huff_tables (dinfo);
733 gst_jpeg_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
735 GstJpegDec *jpeg = GST_JPEG_DEC (dec);
736 GstVideoInfo *info = &state->info;
738 /* FIXME : previously jpegdec would handled input as packetized
739 * if the framerate was present. Here we consider it packetized if
740 * the fps is != 1/1 */
741 if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1)
742 gst_video_decoder_set_packetized (dec, TRUE);
744 gst_video_decoder_set_packetized (dec, FALSE);
746 if (jpeg->input_state)
747 gst_video_codec_state_unref (jpeg->input_state);
748 jpeg->input_state = gst_video_codec_state_ref (state);
756 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
760 for (i = 0; i < len; ++i) {
761 /* equivalent to: dest[i] = src[i << 1] */
770 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
774 for (i = 0; i < 16; i++) {
775 g_free (dec->idr_y[i]);
776 g_free (dec->idr_u[i]);
777 g_free (dec->idr_v[i]);
778 dec->idr_y[i] = NULL;
779 dec->idr_u[i] = NULL;
780 dec->idr_v[i] = NULL;
783 dec->idr_width_allocated = 0;
786 static inline gboolean
787 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
791 if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
794 /* FIXME: maybe just alloc one or three blocks altogether? */
795 for (i = 0; i < 16; i++) {
796 dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
797 dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
798 dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
800 if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
801 GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
806 dec->idr_width_allocated = maxrowbytes;
807 GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
812 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, guchar * base[1],
813 guint width, guint height, guint pstride, guint rstride)
816 guchar **scanarray[1] = { rows };
820 GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
822 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
825 memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
829 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
830 if (G_LIKELY (lines > 0)) {
831 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
835 for (k = 0; k < width; k++) {
836 base[0][p] = rows[j][k];
842 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
848 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, guchar * base[3],
849 guint width, guint height, guint pstride, guint rstride)
851 guchar *r_rows[16], *g_rows[16], *b_rows[16];
852 guchar **scanarray[3] = { r_rows, g_rows, b_rows };
856 GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
858 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
861 memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
862 memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
863 memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
867 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
868 if (G_LIKELY (lines > 0)) {
869 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
873 for (k = 0; k < width; k++) {
874 base[0][p] = r_rows[j][k];
875 base[1][p] = g_rows[j][k];
876 base[2][p] = b_rows[j][k];
884 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
890 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
891 guchar * last[3], guint width, guint height, gint r_v, gint r_h, gint comp)
893 guchar *y_rows[16], *u_rows[16], *v_rows[16];
894 guchar **scanarray[3] = { y_rows, u_rows, v_rows };
898 GST_DEBUG_OBJECT (dec,
899 "unadvantageous width or r_h, taking slow route involving memcpy");
901 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
904 memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
905 memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
906 memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
908 /* fill chroma components for grayscale */
910 GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
911 for (i = 0; i < 16; i++) {
912 memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
913 memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
917 for (i = 0; i < height; i += r_v * DCTSIZE) {
918 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
919 if (G_LIKELY (lines > 0)) {
920 for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
921 if (G_LIKELY (base[0] <= last[0])) {
922 memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
923 base[0] += I420_Y_ROWSTRIDE (width);
926 if (G_LIKELY (base[0] <= last[0])) {
927 memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
928 base[0] += I420_Y_ROWSTRIDE (width);
931 if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
933 memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
934 memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
935 } else if (r_h == 1) {
936 hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
937 hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
939 /* FIXME: implement (at least we avoid crashing by doing nothing) */
943 if (r_v == 2 || (k & 1) != 0) {
944 base[1] += I420_U_ROWSTRIDE (width);
945 base[2] += I420_V_ROWSTRIDE (width);
949 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
954 #ifndef GST_DISABLE_GST_DEBUG
956 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
960 for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
961 GST_LOG ("[%02d] %5d %5d %5d", j,
962 (line[0][j] >= base[0]) ?
963 (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
964 (line[1][j] >= base[1]) ?
965 (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
966 (line[2][j] >= base[2]) ?
967 (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
973 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
974 guchar * last[3], guint width, guint height)
976 guchar **line[3]; /* the jpeg line buffer */
977 guchar *y[4 * DCTSIZE] = { NULL, }; /* alloc enough for the lines */
978 guchar *u[4 * DCTSIZE] = { NULL, }; /* r_v will be <4 */
979 guchar *v[4 * DCTSIZE] = { NULL, };
981 gint lines, v_samp[3];
987 v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
988 v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
989 v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
991 if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
992 goto format_not_supported;
994 /* let jpeglib decode directly into our final buffer */
995 GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
997 for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
998 for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1000 line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
1001 if (G_UNLIKELY (line[0][j] > last[0]))
1002 line[0][j] = last[0];
1004 if (v_samp[1] == v_samp[0]) {
1005 line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
1006 } else if (j < (v_samp[1] * DCTSIZE)) {
1007 line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
1009 if (G_UNLIKELY (line[1][j] > last[1]))
1010 line[1][j] = last[1];
1012 if (v_samp[2] == v_samp[0]) {
1013 line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
1014 } else if (j < (v_samp[2] * DCTSIZE)) {
1015 line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
1017 if (G_UNLIKELY (line[2][j] > last[2]))
1018 line[2][j] = last[2];
1021 /* dump_lines (base, line, v_samp[0], width); */
1023 lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1024 if (G_UNLIKELY (!lines)) {
1025 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1030 format_not_supported:
1032 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1033 "Unsupported subsampling schema: v_samp factors: %u %u %u",
1034 v_samp[0], v_samp[1], v_samp[2]);
1035 return GST_FLOW_ERROR;
1040 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1042 GstVideoCodecState *outstate;
1044 GstVideoFormat format;
1048 format = GST_VIDEO_FORMAT_RGB;
1051 format = GST_VIDEO_FORMAT_GRAY8;
1054 format = GST_VIDEO_FORMAT_I420;
1058 /* Compare to currently configured output state */
1059 outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
1061 info = &outstate->info;
1063 if (width == GST_VIDEO_INFO_WIDTH (info) &&
1064 height == GST_VIDEO_INFO_HEIGHT (info) &&
1065 format == GST_VIDEO_INFO_FORMAT (info)) {
1066 gst_video_codec_state_unref (outstate);
1069 gst_video_codec_state_unref (outstate);
1073 gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format,
1074 width, height, dec->input_state);
1076 gst_video_codec_state_unref (outstate);
1078 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1079 /* some format info */
1081 gst_video_format_get_component_offset (format, 0, width, height);
1083 gst_video_format_get_component_offset (format, 1, width, height);
1085 gst_video_format_get_component_offset (format, 2, width, height);
1086 /* equal for all components */
1087 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1088 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1089 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1090 /* TODO is anything else then 8bit supported in jpeg? */
1092 gst_video_format_get_component_offset (format, 0, width, height);
1093 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1094 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1097 GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1098 GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1101 static GstFlowReturn
1102 gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
1104 GstFlowReturn ret = GST_FLOW_OK;
1105 GstJpegDec *dec = (GstJpegDec *) bdec;
1107 guchar *base[3], *last[3];
1114 if (!gst_jpeg_dec_ensure_header (dec))
1115 goto need_more_data;
1117 /* If we know that each input buffer contains data
1118 * for a whole jpeg image (e.g. MJPEG streams), just
1119 * do some sanity checking instead of parsing all of
1121 if (dec->packetized) {
1122 img_len = gst_adapter_available (dec->adapter);
1124 /* Parse jpeg image to handle jpeg input that
1125 * is not aligned to buffer boundaries */
1126 img_len = gst_jpeg_dec_parse_image_data (dec);
1129 goto need_more_data;
1130 } else if (img_len < 0) {
1131 gst_adapter_flush (dec->adapter, -img_len);
1137 dec->current_frame = frame;
1138 gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1140 if (setjmp (dec->jerr.setjmp_buffer)) {
1141 code = dec->jerr.pub.msg_code;
1143 if (code == JERR_INPUT_EOF) {
1144 GST_DEBUG ("jpeg input EOF error, we probably need more data");
1145 goto need_more_data;
1151 hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1152 if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1153 GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1156 GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1157 GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1159 if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1160 goto components_not_supported;
1162 r_h = dec->cinfo.comp_info[0].h_samp_factor;
1163 r_v = dec->cinfo.comp_info[0].v_samp_factor;
1165 GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1167 if (dec->cinfo.num_components > 3)
1168 goto components_not_supported;
1170 /* verify color space expectation to avoid going *boom* or bogus output */
1171 if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1172 dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1173 dec->cinfo.jpeg_color_space != JCS_RGB)
1174 goto unsupported_colorspace;
1176 #ifndef GST_DISABLE_GST_DEBUG
1180 for (i = 0; i < dec->cinfo.num_components; ++i) {
1181 GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1182 i, dec->cinfo.comp_info[i].h_samp_factor,
1183 dec->cinfo.comp_info[i].v_samp_factor,
1184 dec->cinfo.comp_info[i].component_id);
1189 /* prepare for raw output */
1190 dec->cinfo.do_fancy_upsampling = FALSE;
1191 dec->cinfo.do_block_smoothing = FALSE;
1192 dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1193 dec->cinfo.dct_method = dec->idct_method;
1194 dec->cinfo.raw_data_out = TRUE;
1196 GST_LOG_OBJECT (dec, "starting decompress");
1197 guarantee_huff_tables (&dec->cinfo);
1198 if (!jpeg_start_decompress (&dec->cinfo)) {
1199 GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1202 /* sanity checks to get safe and reasonable output */
1203 switch (dec->cinfo.jpeg_color_space) {
1205 if (dec->cinfo.num_components != 1)
1206 goto invalid_yuvrgbgrayscale;
1209 if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1210 dec->cinfo.max_h_samp_factor > 1)
1211 goto invalid_yuvrgbgrayscale;
1214 if (dec->cinfo.num_components != 3 ||
1215 r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1216 r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1217 r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1218 r_h < dec->cinfo.comp_info[1].h_samp_factor)
1219 goto invalid_yuvrgbgrayscale;
1222 g_assert_not_reached ();
1226 width = dec->cinfo.output_width;
1227 height = dec->cinfo.output_height;
1229 if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1230 height < MIN_HEIGHT || height > MAX_HEIGHT))
1233 gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1235 ret = gst_video_decoder_alloc_output_frame (bdec, frame);
1236 if (G_UNLIKELY (ret != GST_FLOW_OK))
1239 outdata = GST_BUFFER_DATA (frame->output_buffer);
1241 GST_LOG_OBJECT (dec, "width %d, height %d", width, height);
1244 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1245 base[0] = outdata + dec->offset[0];
1246 base[1] = outdata + dec->offset[1];
1247 base[2] = outdata + dec->offset[2];
1248 gst_jpeg_dec_decode_rgb (dec, base, width, height, dec->inc, dec->stride);
1249 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1250 base[0] = outdata + dec->offset[0];
1251 gst_jpeg_dec_decode_grayscale (dec, base, width, height, dec->inc,
1254 /* mind the swap, jpeglib outputs blue chroma first
1255 * ensonic: I see no swap?
1257 base[0] = outdata + I420_Y_OFFSET (width, height);
1258 base[1] = outdata + I420_U_OFFSET (width, height);
1259 base[2] = outdata + I420_V_OFFSET (width, height);
1261 /* make sure we don't make jpeglib write beyond our buffer,
1262 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1263 last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1265 base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1268 base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1271 GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1272 dec->cinfo.rec_outbuf_height);
1274 /* For some widths jpeglib requires more horizontal padding than I420
1275 * provides. In those cases we need to decode into separate buffers and then
1276 * copy over the data into our final picture buffer, otherwise jpeglib might
1277 * write over the end of a line into the beginning of the next line,
1278 * resulting in blocky artifacts on the left side of the picture. */
1279 if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1280 || dec->cinfo.comp_info[0].h_samp_factor != 2
1281 || dec->cinfo.comp_info[1].h_samp_factor != 1
1282 || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1283 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1284 "indirect decoding using extra buffer copy");
1285 gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h,
1286 dec->cinfo.num_components);
1288 ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1290 if (G_UNLIKELY (ret != GST_FLOW_OK))
1291 goto decode_direct_failed;
1295 GST_LOG_OBJECT (dec, "decompressing finished");
1296 jpeg_finish_decompress (&dec->cinfo);
1298 /* reset error count on successful decode */
1299 dec->error_count = 0;
1301 ret = gst_video_decoder_finish_frame (bdec, frame);
1307 if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1308 jpeg_abort_decompress (&dec->cinfo);
1309 ret = gst_jpeg_dec_post_error_or_warning (dec);
1317 GST_LOG_OBJECT (dec, "we need more data");
1324 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1325 "Picture is too small or too big (%ux%u)", width, height);
1326 ret = GST_FLOW_ERROR;
1331 gchar err_msg[JMSG_LENGTH_MAX];
1333 dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1335 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1336 "Decode error #%u: %s", code, err_msg);
1338 gst_video_decoder_drop_frame (bdec, frame);
1340 ret = GST_FLOW_ERROR;
1343 decode_direct_failed:
1345 /* already posted an error message */
1346 jpeg_abort_decompress (&dec->cinfo);
1351 const gchar *reason;
1353 reason = gst_flow_get_name (ret);
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_UNEXPECTED && ret != GST_FLOW_WRONG_STATE &&
1359 ret != GST_FLOW_NOT_LINKED) {
1360 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1361 "Buffer allocation failed, reason: %s", reason);
1365 components_not_supported:
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;
1373 unsupported_colorspace:
1375 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1376 "Picture has unknown or unsupported colourspace");
1377 ret = GST_FLOW_ERROR;
1380 invalid_yuvrgbgrayscale:
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;
1390 gst_jpeg_dec_reset (GstVideoDecoder * bdec, gboolean hard)
1392 GstJpegDec *dec = (GstJpegDec *) bdec;
1394 jpeg_abort_decompress (&dec->cinfo);
1395 g_free (dec->cur_buf);
1396 dec->cur_buf = NULL;
1397 dec->parse_offset = 0;
1398 dec->parse_entropy_len = 0;
1399 dec->parse_resync = FALSE;
1405 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1406 const GValue * value, GParamSpec * pspec)
1410 dec = GST_JPEG_DEC (object);
1413 case PROP_IDCT_METHOD:
1414 dec->idct_method = g_value_get_enum (value);
1416 case PROP_MAX_ERRORS:
1417 g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1421 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1427 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1432 dec = GST_JPEG_DEC (object);
1435 case PROP_IDCT_METHOD:
1436 g_value_set_enum (value, dec->idct_method);
1438 case PROP_MAX_ERRORS:
1439 g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1449 gst_jpeg_dec_start (GstVideoDecoder * bdec)
1451 GstJpegDec *dec = (GstJpegDec *) bdec;
1453 dec->error_count = 0;
1454 dec->parse_offset = 0;
1455 dec->parse_entropy_len = 0;
1456 dec->parse_resync = FALSE;
1457 dec->cur_buf = NULL;
1463 gst_jpeg_dec_stop (GstVideoDecoder * bdec)
1465 GstJpegDec *dec = (GstJpegDec *) bdec;
1467 g_free (dec->cur_buf);
1468 dec->cur_buf = NULL;
1469 gst_jpeg_dec_free_buffers (dec);