2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * SECTION:element-jpegdec
24 * Decodes jpeg images.
27 * <title>Example launch line</title>
29 * gst-launch -v v4l2src ! jpegdec ! ffmpegcolorspace ! xvimagesink
30 * ]| The above pipeline reads a motion JPEG stream from a v4l2 camera
31 * and renders it to the screen.
40 #include "gstjpegdec.h"
42 #include <gst/video/video.h>
43 #include "gst/gst-i18n-plugin.h"
47 #define MAX_WIDTH 65535
49 #define MAX_HEIGHT 65535
51 #define CINFO_GET_JPEGDEC(cinfo_ptr) \
52 (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
54 #define JPEG_DEFAULT_IDCT_METHOD JDCT_FASTEST
55 #define JPEG_DEFAULT_MAX_ERRORS 0
65 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
66 GST_STATIC_PAD_TEMPLATE ("src",
69 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") "; "
70 GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; "
71 GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; "
72 GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR "; "
77 /* FIXME: sof-marker is for IJG libjpeg 8, should be different for 6.2 */
78 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
79 GST_STATIC_PAD_TEMPLATE ("sink",
82 GST_STATIC_CAPS ("image/jpeg, "
83 "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
84 " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
85 G_STRINGIFY (MAX_HEIGHT) " ], framerate = (fraction) [ 0/1, MAX ], "
86 "sof-marker = (int) { 0, 1, 2, 5, 6, 7, 9, 10, 13, 14 }")
89 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
90 #define GST_CAT_DEFAULT jpeg_dec_debug
91 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
93 /* These macros are adapted from videotestsrc.c
94 * and/or gst-plugins/gst/games/gstvideoimage.c */
95 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
96 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
97 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
99 #define I420_Y_OFFSET(w,h) (0)
100 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
101 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
103 #define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
105 static GstElementClass *parent_class; /* NULL */
107 static void gst_jpeg_dec_base_init (gpointer g_class);
108 static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
109 static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
111 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
112 const GValue * value, GParamSpec * pspec);
113 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
114 GValue * value, GParamSpec * pspec);
116 static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
117 static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
118 static GstCaps *gst_jpeg_dec_getcaps (GstPad * pad);
119 static gboolean gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event);
120 static gboolean gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event);
121 static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
122 GstStateChange transition);
123 static void gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
124 GstClockTimeDiff diff, GstClockTime ts);
125 static void gst_jpeg_dec_reset_qos (GstJpegDec * dec);
126 static void gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
127 GstClockTime * time);
130 gst_jpeg_dec_get_type (void)
132 static GType type = 0;
135 static const GTypeInfo jpeg_dec_info = {
136 sizeof (GstJpegDecClass),
137 (GBaseInitFunc) gst_jpeg_dec_base_init,
139 (GClassInitFunc) gst_jpeg_dec_class_init,
144 (GInstanceInitFunc) gst_jpeg_dec_init,
147 type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
154 gst_jpeg_dec_finalize (GObject * object)
156 GstJpegDec *dec = GST_JPEG_DEC (object);
158 jpeg_destroy_decompress (&dec->cinfo);
160 g_object_unref (dec->adapter);
162 G_OBJECT_CLASS (parent_class)->finalize (object);
166 gst_jpeg_dec_base_init (gpointer g_class)
168 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
170 gst_element_class_add_static_pad_template (element_class,
171 &gst_jpeg_dec_src_pad_template);
172 gst_element_class_add_static_pad_template (element_class,
173 &gst_jpeg_dec_sink_pad_template);
174 gst_element_class_set_details_simple (element_class, "JPEG image decoder",
175 "Codec/Decoder/Image",
176 "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
180 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
182 GstElementClass *gstelement_class;
183 GObjectClass *gobject_class;
185 gstelement_class = (GstElementClass *) klass;
186 gobject_class = (GObjectClass *) klass;
188 parent_class = g_type_class_peek_parent (klass);
190 gobject_class->finalize = gst_jpeg_dec_finalize;
191 gobject_class->set_property = gst_jpeg_dec_set_property;
192 gobject_class->get_property = gst_jpeg_dec_get_property;
194 g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
195 g_param_spec_enum ("idct-method", "IDCT Method",
196 "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
197 JPEG_DEFAULT_IDCT_METHOD,
198 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
201 * GstJpegDec:max-errors
203 * Error out after receiving N consecutive decoding errors
204 * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
208 g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
209 g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
210 "Error out after receiving N consecutive decoding errors "
211 "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
212 -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
213 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
215 gstelement_class->change_state =
216 GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
218 GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
219 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
223 gst_jpeg_dec_clear_error (GstJpegDec * dec)
225 g_free (dec->error_msg);
226 dec->error_msg = NULL;
228 dec->error_func = NULL;
232 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
233 const gchar * debug_msg_format, va_list args)
235 #ifndef GST_DISABLE_GST_DEBUG
236 gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
237 line, (GObject *) dec, debug_msg_format, args);
240 g_free (dec->error_msg);
241 if (debug_msg_format)
242 dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
244 dec->error_msg = NULL;
246 dec->error_line = line;
247 dec->error_func = func;
251 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
252 const gchar * debug_msg_format, ...)
256 va_start (va, debug_msg_format);
257 gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
262 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
268 max_errors = g_atomic_int_get (&dec->max_errors);
270 if (max_errors < 0) {
272 } else if (max_errors == 0) {
273 /* FIXME: do something more clever in "automatic mode" */
274 if (dec->packetized) {
275 ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
277 ret = GST_FLOW_ERROR;
280 ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
283 GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
284 max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
286 gst_element_message_full (GST_ELEMENT (dec),
287 (ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
288 GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
289 g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
290 __FILE__, dec->error_func, dec->error_line);
292 dec->error_msg = NULL;
293 gst_jpeg_dec_clear_error (dec);
298 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
303 dec = CINFO_GET_JPEGDEC (cinfo);
304 g_return_val_if_fail (dec != NULL, FALSE);
306 av = gst_adapter_available_fast (dec->adapter);
307 GST_DEBUG_OBJECT (dec, "fill_input_buffer: fast av=%u, remaining=%u", av,
311 GST_DEBUG_OBJECT (dec, "Out of data");
315 if (dec->rem_img_len < av)
316 av = dec->rem_img_len;
317 dec->rem_img_len -= av;
319 g_free (dec->cur_buf);
320 dec->cur_buf = gst_adapter_take (dec->adapter, av);
322 cinfo->src->next_input_byte = dec->cur_buf;
323 cinfo->src->bytes_in_buffer = av;
329 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
331 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
336 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
338 GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
340 GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
342 if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
343 cinfo->src->next_input_byte += (size_t) num_bytes;
344 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
345 } else if (num_bytes > 0) {
348 num_bytes -= cinfo->src->bytes_in_buffer;
349 cinfo->src->next_input_byte += (size_t) cinfo->src->bytes_in_buffer;
350 cinfo->src->bytes_in_buffer = 0;
352 available = gst_adapter_available (dec->adapter);
353 if (available < num_bytes || available < dec->rem_img_len) {
354 GST_WARNING_OBJECT (dec, "Less bytes to skip than available in the "
355 "adapter or the remaining image length %ld < %d or %u",
356 num_bytes, available, dec->rem_img_len);
358 num_bytes = MIN (MIN (num_bytes, available), dec->rem_img_len);
359 gst_adapter_flush (dec->adapter, num_bytes);
360 dec->rem_img_len -= num_bytes;
365 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
367 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
372 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
374 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
379 gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
381 return; /* do nothing */
385 gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
387 /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
392 gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
394 struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
396 (*cinfo->err->output_message) (cinfo);
397 longjmp (err_mgr->setjmp_buffer, 1);
401 gst_jpeg_dec_init (GstJpegDec * dec)
403 GST_DEBUG ("initializing");
405 /* create the sink and src pads */
407 gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
409 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
410 gst_pad_set_setcaps_function (dec->sinkpad,
411 GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
412 gst_pad_set_getcaps_function (dec->sinkpad,
413 GST_DEBUG_FUNCPTR (gst_jpeg_dec_getcaps));
414 gst_pad_set_chain_function (dec->sinkpad,
415 GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
416 gst_pad_set_event_function (dec->sinkpad,
417 GST_DEBUG_FUNCPTR (gst_jpeg_dec_sink_event));
420 gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
421 gst_pad_set_event_function (dec->srcpad,
422 GST_DEBUG_FUNCPTR (gst_jpeg_dec_src_event));
423 gst_pad_use_fixed_caps (dec->srcpad);
424 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
427 memset (&dec->cinfo, 0, sizeof (dec->cinfo));
428 memset (&dec->jerr, 0, sizeof (dec->jerr));
429 dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
430 dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
431 dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
432 dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
434 jpeg_create_decompress (&dec->cinfo);
436 dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
437 dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
438 dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
439 dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
440 dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
441 dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
444 /* init properties */
445 dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
446 dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
448 dec->adapter = gst_adapter_new ();
452 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
457 av = gst_adapter_available (dec->adapter);
458 /* we expect at least 4 bytes, first of which start marker */
459 offset = gst_adapter_masked_scan_uint32 (dec->adapter, 0xffffff00, 0xffd8ff00,
461 if (G_UNLIKELY (offset < 0)) {
462 GST_DEBUG_OBJECT (dec, "No JPEG header in current buffer");
465 gst_adapter_flush (dec->adapter, av - 4);
470 GST_LOG_OBJECT (dec, "Skipping %u bytes.", offset);
471 gst_adapter_flush (dec->adapter, offset);
473 GST_DEBUG_OBJECT (dec, "Found JPEG header");
478 static inline gboolean
479 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
481 if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
486 /* returns image length in bytes if parsed successfully,
487 * otherwise 0 if more data needed,
488 * if < 0 the absolute value needs to be flushed */
490 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
494 GstAdapter *adapter = dec->adapter;
495 gint offset, noffset;
497 size = gst_adapter_available (adapter);
499 /* we expect at least 4 bytes, first of which start marker */
500 if (gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0, 4))
503 GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
505 GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d",
506 dec->parse_offset, dec->parse_resync, dec->parse_entropy_len);
508 /* offset is 2 less than actual offset;
509 * - adapter needs at least 4 bytes for scanning,
510 * - start and end marker ensure at least that much
512 /* resume from state offset */
513 offset = dec->parse_offset;
520 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
521 offset, size - offset, &value);
522 /* lost sync if 0xff marker not where expected */
523 if ((resync = (noffset != offset))) {
524 GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
526 /* may have marker, but could have been resyncng */
527 resync = resync || dec->parse_resync;
528 /* Skip over extra 0xff */
529 while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
532 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
533 noffset, size - noffset, &value);
535 /* enough bytes left for marker? (we need 0xNN after the 0xff) */
537 GST_DEBUG ("at end of input and no EOI marker found, need more data");
541 /* now lock on the marker we found */
543 value = value & 0xff;
545 GST_DEBUG ("0x%08x: EOI marker", offset + 2);
546 /* clear parse state */
547 dec->parse_resync = FALSE;
548 dec->parse_offset = 0;
550 } else if (value == 0xd8) {
551 /* Skip this frame if we found another SOI marker */
552 GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
553 dec->parse_resync = FALSE;
554 dec->parse_offset = 0;
555 return -(offset + 2);
559 if (value >= 0xd0 && value <= 0xd7)
562 /* peek tag and subsequent length */
563 if (offset + 2 + 4 > size)
566 gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
568 frame_len = frame_len & 0xffff;
570 GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
571 /* the frame length includes the 2 bytes for the length; here we want at
572 * least 2 more bytes at the end for an end marker */
573 if (offset + 2 + 2 + frame_len + 2 > size) {
577 if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
578 guint eseglen = dec->parse_entropy_len;
580 GST_DEBUG ("0x%08x: finding entropy segment length", offset + 2);
581 noffset = offset + 2 + frame_len + dec->parse_entropy_len;
583 noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
584 0x0000ff00, noffset, size - noffset, &value);
587 dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
590 if ((value & 0xff) != 0x00) {
591 eseglen = noffset - offset - frame_len - 2;
596 dec->parse_entropy_len = 0;
597 frame_len += eseglen;
598 GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
602 /* check if we will still be in sync if we interpret
603 * this as a sync point and skip this frame */
604 noffset = offset + frame_len + 2;
605 noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
608 /* ignore and continue resyncing until we hit the end
609 * of our data or find a sync point that looks okay */
613 GST_DEBUG ("found sync at 0x%x", offset + 2);
616 offset += frame_len + 2;
622 dec->parse_offset = offset;
623 dec->parse_resync = resync;
628 /* shamelessly ripped from jpegutils.c in mjpegtools */
630 add_huff_table (j_decompress_ptr dinfo,
631 JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
632 /* Define a Huffman table */
636 if (*htblptr == NULL)
637 *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
641 /* Copy the number-of-symbols-of-each-code-length counts */
642 memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
644 /* Validate the counts. We do this here mainly so we can copy the right
645 * number of symbols from the val[] array, without risking marching off
646 * the end of memory. jchuff.c will do a more thorough test later.
649 for (len = 1; len <= 16; len++)
650 nsymbols += bits[len];
651 if (nsymbols < 1 || nsymbols > 256)
652 g_error ("jpegutils.c: add_huff_table failed badly. ");
654 memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
660 std_huff_tables (j_decompress_ptr dinfo)
661 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
662 /* IMPORTANT: these are only valid for 8-bit data precision! */
664 static const UINT8 bits_dc_luminance[17] =
665 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
666 static const UINT8 val_dc_luminance[] =
667 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
669 static const UINT8 bits_dc_chrominance[17] =
670 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
671 static const UINT8 val_dc_chrominance[] =
672 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
674 static const UINT8 bits_ac_luminance[17] =
675 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
676 static const UINT8 val_ac_luminance[] =
677 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
678 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
679 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
680 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
681 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
682 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
683 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
684 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
685 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
686 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
687 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
688 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
689 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
690 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
691 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
692 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
693 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
694 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
695 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
696 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
700 static const UINT8 bits_ac_chrominance[17] =
701 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
702 static const UINT8 val_ac_chrominance[] =
703 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
704 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
705 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
706 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
707 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
708 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
709 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
710 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
711 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
712 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
713 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
714 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
715 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
716 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
717 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
718 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
719 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
720 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
721 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
722 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
726 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
727 bits_dc_luminance, val_dc_luminance);
728 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
729 bits_ac_luminance, val_ac_luminance);
730 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
731 bits_dc_chrominance, val_dc_chrominance);
732 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
733 bits_ac_chrominance, val_ac_chrominance);
739 guarantee_huff_tables (j_decompress_ptr dinfo)
741 if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
742 (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
743 (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
744 (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
745 GST_DEBUG ("Generating standard Huffman tables for this frame.");
746 std_huff_tables (dinfo);
751 gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
755 const GValue *framerate;
757 dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
758 s = gst_caps_get_structure (caps, 0);
760 if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
761 dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
762 dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
763 dec->packetized = TRUE;
764 GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
765 dec->framerate_numerator, dec->framerate_denominator);
768 /* do not extract width/height here. we do that in the chain
769 * function on a per-frame basis (including the line[] array
772 /* But we can take the framerate values and set them on the src pad */
778 gst_jpeg_dec_getcaps (GstPad * pad)
784 dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
786 if (GST_PAD_CAPS (pad))
787 return gst_caps_ref (GST_PAD_CAPS (pad));
789 peer = gst_pad_get_peer (dec->srcpad);
793 const GstCaps *templ_caps;
797 peer_caps = gst_pad_get_caps (peer);
799 /* Translate peercaps to image/jpeg */
800 peer_caps = gst_caps_make_writable (peer_caps);
801 n = gst_caps_get_size (peer_caps);
802 for (i = 0; i < n; i++) {
803 s = gst_caps_get_structure (peer_caps, i);
805 gst_structure_set_name (s, "image/jpeg");
808 templ_caps = gst_pad_get_pad_template_caps (pad);
809 caps = gst_caps_intersect_full (peer_caps, templ_caps,
810 GST_CAPS_INTERSECT_FIRST);
812 gst_object_unref (peer);
814 caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
823 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
827 for (i = 0; i < len; ++i) {
828 /* equivalent to: dest[i] = src[i << 1] */
837 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
841 for (i = 0; i < 16; i++) {
842 g_free (dec->idr_y[i]);
843 g_free (dec->idr_u[i]);
844 g_free (dec->idr_v[i]);
845 dec->idr_y[i] = NULL;
846 dec->idr_u[i] = NULL;
847 dec->idr_v[i] = NULL;
850 dec->idr_width_allocated = 0;
853 static inline gboolean
854 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
858 if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
861 /* FIXME: maybe just alloc one or three blocks altogether? */
862 for (i = 0; i < 16; i++) {
863 dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
864 dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
865 dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
867 if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
868 GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
873 dec->idr_width_allocated = maxrowbytes;
874 GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
879 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, guchar * base[1],
880 guint width, guint height, guint pstride, guint rstride)
883 guchar **scanarray[1] = { rows };
887 GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
889 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
892 memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
896 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
897 if (G_LIKELY (lines > 0)) {
898 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
902 for (k = 0; k < width; k++) {
903 base[0][p] = rows[j][k];
909 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
915 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, guchar * base[3],
916 guint width, guint height, guint pstride, guint rstride)
918 guchar *r_rows[16], *g_rows[16], *b_rows[16];
919 guchar **scanarray[3] = { r_rows, g_rows, b_rows };
923 GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
925 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
928 memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
929 memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
930 memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
934 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
935 if (G_LIKELY (lines > 0)) {
936 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
940 for (k = 0; k < width; k++) {
941 base[0][p] = r_rows[j][k];
942 base[1][p] = g_rows[j][k];
943 base[2][p] = b_rows[j][k];
951 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
957 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
958 guchar * last[3], guint width, guint height, gint r_v, gint r_h, gint comp)
960 guchar *y_rows[16], *u_rows[16], *v_rows[16];
961 guchar **scanarray[3] = { y_rows, u_rows, v_rows };
965 GST_DEBUG_OBJECT (dec,
966 "unadvantageous width or r_h, taking slow route involving memcpy");
968 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
971 memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
972 memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
973 memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
975 /* fill chroma components for grayscale */
977 GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
978 for (i = 0; i < 16; i++) {
979 memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
980 memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
984 for (i = 0; i < height; i += r_v * DCTSIZE) {
985 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
986 if (G_LIKELY (lines > 0)) {
987 for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
988 if (G_LIKELY (base[0] <= last[0])) {
989 memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
990 base[0] += I420_Y_ROWSTRIDE (width);
993 if (G_LIKELY (base[0] <= last[0])) {
994 memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
995 base[0] += I420_Y_ROWSTRIDE (width);
998 if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
1000 memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
1001 memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
1002 } else if (r_h == 1) {
1003 hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
1004 hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
1006 /* FIXME: implement (at least we avoid crashing by doing nothing) */
1010 if (r_v == 2 || (k & 1) != 0) {
1011 base[1] += I420_U_ROWSTRIDE (width);
1012 base[2] += I420_V_ROWSTRIDE (width);
1016 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1021 #ifndef GST_DISABLE_GST_DEBUG
1023 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
1027 for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
1028 GST_LOG ("[%02d] %5d %5d %5d", j,
1029 (line[0][j] >= base[0]) ?
1030 (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
1031 (line[1][j] >= base[1]) ?
1032 (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
1033 (line[2][j] >= base[2]) ?
1034 (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
1039 static GstFlowReturn
1040 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
1041 guchar * last[3], guint width, guint height)
1043 guchar **line[3]; /* the jpeg line buffer */
1044 guchar *y[4 * DCTSIZE] = { NULL, }; /* alloc enough for the lines */
1045 guchar *u[4 * DCTSIZE] = { NULL, }; /* r_v will be <4 */
1046 guchar *v[4 * DCTSIZE] = { NULL, };
1048 gint lines, v_samp[3];
1054 v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1055 v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1056 v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1058 if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1059 goto format_not_supported;
1061 /* let jpeglib decode directly into our final buffer */
1062 GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1064 for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1065 for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1067 line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
1068 if (G_UNLIKELY (line[0][j] > last[0]))
1069 line[0][j] = last[0];
1071 if (v_samp[1] == v_samp[0]) {
1072 line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
1073 } else if (j < (v_samp[1] * DCTSIZE)) {
1074 line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
1076 if (G_UNLIKELY (line[1][j] > last[1]))
1077 line[1][j] = last[1];
1079 if (v_samp[2] == v_samp[0]) {
1080 line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
1081 } else if (j < (v_samp[2] * DCTSIZE)) {
1082 line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
1084 if (G_UNLIKELY (line[2][j] > last[2]))
1085 line[2][j] = last[2];
1088 /* dump_lines (base, line, v_samp[0], width); */
1090 lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1091 if (G_UNLIKELY (!lines)) {
1092 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1097 format_not_supported:
1099 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1100 "Unsupported subsampling schema: v_samp factors: %u %u %u",
1101 v_samp[0], v_samp[1], v_samp[2]);
1102 return GST_FLOW_ERROR;
1107 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
1108 GstClockTimeDiff diff, GstClockTime ts)
1110 GST_OBJECT_LOCK (dec);
1111 dec->proportion = proportion;
1112 if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
1113 if (G_UNLIKELY (diff > 0))
1114 dec->earliest_time = ts + 2 * diff + dec->qos_duration;
1116 dec->earliest_time = ts + diff;
1118 dec->earliest_time = GST_CLOCK_TIME_NONE;
1120 GST_OBJECT_UNLOCK (dec);
1124 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
1126 gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
1130 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
1131 GstClockTime * time)
1133 GST_OBJECT_LOCK (dec);
1134 *proportion = dec->proportion;
1135 *time = dec->earliest_time;
1136 GST_OBJECT_UNLOCK (dec);
1139 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
1140 * frame should be decoded, FALSE if the frame can be dropped entirely */
1142 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
1144 GstClockTime qostime, earliest_time;
1147 /* no timestamp, can't do QoS => decode frame */
1148 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1149 GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
1153 /* get latest QoS observation values */
1154 gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
1156 /* skip qos if we have no observation (yet) => decode frame */
1157 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1158 GST_LOG_OBJECT (dec, "no observation yet, decode frame");
1162 /* qos is done on running time */
1163 qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
1166 /* see how our next timestamp relates to the latest qos timestamp */
1167 GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
1168 GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1170 if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1171 GST_DEBUG_OBJECT (dec, "we are late, drop frame");
1175 GST_LOG_OBJECT (dec, "decode frame");
1180 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1183 GstVideoFormat format;
1185 if (G_UNLIKELY (width == dec->caps_width && height == dec->caps_height &&
1186 dec->framerate_numerator == dec->caps_framerate_numerator &&
1187 dec->framerate_denominator == dec->caps_framerate_denominator &&
1188 clrspc == dec->clrspc))
1191 /* framerate == 0/1 is a still frame */
1192 if (dec->framerate_denominator == 0) {
1193 dec->framerate_numerator = 0;
1194 dec->framerate_denominator = 1;
1197 /* calculate or assume an average frame duration for QoS purposes */
1198 GST_OBJECT_LOCK (dec);
1199 if (dec->framerate_numerator != 0) {
1200 dec->qos_duration = gst_util_uint64_scale (GST_SECOND,
1201 dec->framerate_denominator, dec->framerate_numerator);
1203 /* if not set just use 25fps */
1204 dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1206 GST_OBJECT_UNLOCK (dec);
1208 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1210 GstCaps *allowed_caps;
1212 GST_DEBUG_OBJECT (dec, "selecting RGB format");
1213 /* retrieve allowed caps, and find the first one that reasonably maps
1214 * to the parameters of the colourspace */
1215 caps = gst_pad_get_allowed_caps (dec->srcpad);
1217 GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1218 /* need to copy because get_allowed_caps returns a ref,
1219 * and get_pad_template_caps doesn't */
1220 caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
1222 /* avoid lists of fourcc, etc */
1223 allowed_caps = gst_caps_normalize (caps);
1224 gst_caps_unref (caps);
1226 GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1228 for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1230 gst_caps_unref (caps);
1231 caps = gst_caps_copy_nth (allowed_caps, i);
1232 /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1233 gst_pad_fixate_caps (dec->srcpad, caps);
1234 GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1235 if (!gst_video_format_parse_caps (caps, &format, NULL, NULL))
1237 /* we'll settle for the first (preferred) downstream rgb format */
1238 if (gst_video_format_is_rgb (format))
1240 /* default fall-back */
1241 format = GST_VIDEO_FORMAT_RGB;
1244 gst_caps_unref (caps);
1245 gst_caps_unref (allowed_caps);
1246 caps = gst_video_format_new_caps (format, width, height,
1247 dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1248 dec->outsize = gst_video_format_get_size (format, width, height);
1249 /* some format info */
1251 gst_video_format_get_component_offset (format, 0, width, height);
1253 gst_video_format_get_component_offset (format, 1, width, height);
1255 gst_video_format_get_component_offset (format, 2, width, height);
1256 /* equal for all components */
1257 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1258 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1259 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1260 /* TODO is anything else then 8bit supported in jpeg? */
1261 format = GST_VIDEO_FORMAT_GRAY8;
1262 caps = gst_video_format_new_caps (format, width, height,
1263 dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1264 dec->outsize = gst_video_format_get_size (format, width, height);
1266 gst_video_format_get_component_offset (format, 0, width, height);
1267 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1268 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1270 /* go for plain and simple I420 */
1271 /* TODO other YUV cases ? */
1272 caps = gst_caps_new_simple ("video/x-raw-yuv",
1273 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
1274 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
1275 "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
1276 dec->framerate_denominator, NULL);
1277 dec->outsize = I420_SIZE (width, height);
1280 GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1281 GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1282 GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1284 gst_pad_set_caps (dec->srcpad, caps);
1285 gst_caps_unref (caps);
1287 dec->caps_width = width;
1288 dec->caps_height = height;
1289 dec->caps_framerate_numerator = dec->framerate_numerator;
1290 dec->caps_framerate_denominator = dec->framerate_denominator;
1293 static GstFlowReturn
1294 gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
1296 GstFlowReturn ret = GST_FLOW_OK;
1298 GstBuffer *outbuf = NULL;
1299 #ifndef GST_DISABLE_GST_DEBUG
1303 guchar *base[3], *last[3];
1309 GstClockTime timestamp, duration;
1311 dec = GST_JPEG_DEC (GST_PAD_PARENT (pad));
1313 timestamp = GST_BUFFER_TIMESTAMP (buf);
1314 duration = GST_BUFFER_DURATION (buf);
1316 if (GST_CLOCK_TIME_IS_VALID (timestamp))
1317 dec->next_ts = timestamp;
1319 if (GST_BUFFER_IS_DISCONT (buf)) {
1320 GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1321 dec->discont = TRUE;
1322 if (!dec->packetized && gst_adapter_available (dec->adapter)) {
1323 GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1324 gst_adapter_clear (dec->adapter);
1328 gst_adapter_push (dec->adapter, buf);
1331 /* If we are non-packetized and know the total incoming size in bytes,
1332 * just wait until we have enough before doing any processing. */
1334 if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1335 (dec->segment.stop != -1) &&
1336 (gst_adapter_available (dec->adapter) < dec->segment.stop)) {
1337 /* We assume that non-packetized input in bytes is *one* single jpeg image */
1338 GST_DEBUG ("Non-packetized mode. Got %d bytes, need %" G_GINT64_FORMAT,
1339 gst_adapter_available (dec->adapter), dec->segment.stop);
1340 goto need_more_data;
1344 if (!gst_jpeg_dec_ensure_header (dec))
1345 goto need_more_data;
1347 /* If we know that each input buffer contains data
1348 * for a whole jpeg image (e.g. MJPEG streams), just
1349 * do some sanity checking instead of parsing all of
1351 if (dec->packetized) {
1352 img_len = gst_adapter_available (dec->adapter);
1354 /* Parse jpeg image to handle jpeg input that
1355 * is not aligned to buffer boundaries */
1356 img_len = gst_jpeg_dec_parse_image_data (dec);
1359 goto need_more_data;
1360 } else if (img_len < 0) {
1361 gst_adapter_flush (dec->adapter, -img_len);
1366 dec->rem_img_len = img_len;
1368 GST_LOG_OBJECT (dec, "image size = %u", img_len);
1370 /* QoS: if we're too late anyway, skip decoding */
1371 if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1374 #ifndef GST_DISABLE_GST_DEBUG
1375 data = (guint8 *) gst_adapter_peek (dec->adapter, 4);
1376 GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1380 gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1382 if (setjmp (dec->jerr.setjmp_buffer)) {
1383 code = dec->jerr.pub.msg_code;
1385 if (code == JERR_INPUT_EOF) {
1386 GST_DEBUG ("jpeg input EOF error, we probably need more data");
1387 goto need_more_data;
1393 hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1394 if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1395 GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1398 GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1399 GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1401 if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
1402 goto components_not_supported;
1404 r_h = dec->cinfo.comp_info[0].h_samp_factor;
1405 r_v = dec->cinfo.comp_info[0].v_samp_factor;
1407 GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1409 if (dec->cinfo.num_components > 3)
1410 goto components_not_supported;
1412 /* verify color space expectation to avoid going *boom* or bogus output */
1413 if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1414 dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1415 dec->cinfo.jpeg_color_space != JCS_RGB)
1416 goto unsupported_colorspace;
1418 #ifndef GST_DISABLE_GST_DEBUG
1422 for (i = 0; i < dec->cinfo.num_components; ++i) {
1423 GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1424 i, dec->cinfo.comp_info[i].h_samp_factor,
1425 dec->cinfo.comp_info[i].v_samp_factor,
1426 dec->cinfo.comp_info[i].component_id);
1431 /* prepare for raw output */
1432 dec->cinfo.do_fancy_upsampling = FALSE;
1433 dec->cinfo.do_block_smoothing = FALSE;
1434 dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1435 dec->cinfo.dct_method = dec->idct_method;
1436 dec->cinfo.raw_data_out = TRUE;
1438 GST_LOG_OBJECT (dec, "starting decompress");
1439 guarantee_huff_tables (&dec->cinfo);
1440 if (!jpeg_start_decompress (&dec->cinfo)) {
1441 GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1444 /* sanity checks to get safe and reasonable output */
1445 switch (dec->cinfo.jpeg_color_space) {
1447 if (dec->cinfo.num_components != 1)
1448 goto invalid_yuvrgbgrayscale;
1451 if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1452 dec->cinfo.max_h_samp_factor > 1)
1453 goto invalid_yuvrgbgrayscale;
1456 if (dec->cinfo.num_components != 3 ||
1457 r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1458 r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1459 r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1460 r_h < dec->cinfo.comp_info[1].h_samp_factor)
1461 goto invalid_yuvrgbgrayscale;
1464 g_assert_not_reached ();
1468 width = dec->cinfo.output_width;
1469 height = dec->cinfo.output_height;
1471 if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1472 height < MIN_HEIGHT || height > MAX_HEIGHT))
1475 gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1477 ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
1478 dec->outsize, GST_PAD_CAPS (dec->srcpad), &outbuf);
1479 if (G_UNLIKELY (ret != GST_FLOW_OK))
1482 outdata = GST_BUFFER_DATA (outbuf);
1483 outsize = GST_BUFFER_SIZE (outbuf);
1485 GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
1486 width, height, outsize, dec->outsize);
1488 GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1490 if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1491 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1492 /* use duration from incoming buffer for outgoing buffer */
1493 dec->next_ts += duration;
1494 } else if (dec->framerate_numerator != 0) {
1495 duration = gst_util_uint64_scale (GST_SECOND,
1496 dec->framerate_denominator, dec->framerate_numerator);
1497 dec->next_ts += duration;
1499 duration = GST_CLOCK_TIME_NONE;
1500 dec->next_ts = GST_CLOCK_TIME_NONE;
1503 duration = GST_CLOCK_TIME_NONE;
1504 dec->next_ts = GST_CLOCK_TIME_NONE;
1506 GST_BUFFER_DURATION (outbuf) = duration;
1508 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1509 base[0] = outdata + dec->offset[0];
1510 base[1] = outdata + dec->offset[1];
1511 base[2] = outdata + dec->offset[2];
1512 gst_jpeg_dec_decode_rgb (dec, base, width, height, dec->inc, dec->stride);
1513 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1514 base[0] = outdata + dec->offset[0];
1515 gst_jpeg_dec_decode_grayscale (dec, base, width, height, dec->inc,
1518 /* mind the swap, jpeglib outputs blue chroma first
1519 * ensonic: I see no swap?
1521 base[0] = outdata + I420_Y_OFFSET (width, height);
1522 base[1] = outdata + I420_U_OFFSET (width, height);
1523 base[2] = outdata + I420_V_OFFSET (width, height);
1525 /* make sure we don't make jpeglib write beyond our buffer,
1526 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1527 last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1529 base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1532 base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1535 GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1536 dec->cinfo.rec_outbuf_height);
1538 /* For some widths jpeglib requires more horizontal padding than I420
1539 * provides. In those cases we need to decode into separate buffers and then
1540 * copy over the data into our final picture buffer, otherwise jpeglib might
1541 * write over the end of a line into the beginning of the next line,
1542 * resulting in blocky artifacts on the left side of the picture. */
1543 if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1544 || dec->cinfo.comp_info[0].h_samp_factor != 2
1545 || dec->cinfo.comp_info[1].h_samp_factor != 1
1546 || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1547 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1548 "indirect decoding using extra buffer copy");
1549 gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h,
1550 dec->cinfo.num_components);
1552 ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1554 if (G_UNLIKELY (ret != GST_FLOW_OK))
1555 goto decode_direct_failed;
1559 GST_LOG_OBJECT (dec, "decompressing finished");
1560 jpeg_finish_decompress (&dec->cinfo);
1563 if (dec->segment.format == GST_FORMAT_TIME) {
1564 gint64 start, stop, clip_start, clip_stop;
1566 GST_LOG_OBJECT (dec, "Attempting clipping");
1568 start = GST_BUFFER_TIMESTAMP (outbuf);
1569 if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1572 stop = start + GST_BUFFER_DURATION (outbuf);
1574 if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1575 start, stop, &clip_start, &clip_stop)) {
1576 GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1577 GST_TIME_ARGS (clip_start));
1578 GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1579 if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1580 GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1581 GST_TIME_ARGS (clip_stop - clip_start));
1582 GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1588 /* reset error count on successful decode */
1589 dec->error_count = 0;
1593 GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1594 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1595 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1597 ret = gst_pad_push (dec->srcpad, outbuf);
1601 gst_adapter_flush (dec->adapter, dec->rem_img_len);
1605 if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1606 jpeg_abort_decompress (&dec->cinfo);
1607 ret = gst_jpeg_dec_post_error_or_warning (dec);
1615 GST_LOG_OBJECT (dec, "we need more data");
1617 gst_buffer_unref (outbuf);
1626 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1627 "Picture is too small or too big (%ux%u)", width, height);
1628 ret = GST_FLOW_ERROR;
1633 gchar err_msg[JMSG_LENGTH_MAX];
1635 dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1637 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1638 "Decode error #%u: %s", code, err_msg);
1641 gst_buffer_unref (outbuf);
1644 ret = GST_FLOW_ERROR;
1647 decode_direct_failed:
1649 /* already posted an error message */
1650 jpeg_abort_decompress (&dec->cinfo);
1651 gst_buffer_replace (&outbuf, NULL);
1656 const gchar *reason;
1658 reason = gst_flow_get_name (ret);
1660 GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1661 /* Reset for next time */
1662 jpeg_abort_decompress (&dec->cinfo);
1663 if (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_WRONG_STATE &&
1664 ret != GST_FLOW_NOT_LINKED) {
1665 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1666 "Buffer allocation failed, reason: %s", reason);
1672 GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1673 gst_buffer_unref (outbuf);
1677 components_not_supported:
1679 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1680 "number of components not supported: %d (max 3)",
1681 dec->cinfo.num_components);
1682 ret = GST_FLOW_ERROR;
1685 unsupported_colorspace:
1687 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1688 "Picture has unknown or unsupported colourspace");
1689 ret = GST_FLOW_ERROR;
1692 invalid_yuvrgbgrayscale:
1694 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1695 "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1696 ret = GST_FLOW_ERROR;
1702 gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
1707 dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
1708 if (G_UNLIKELY (dec == NULL)) {
1709 gst_event_unref (event);
1713 switch (GST_EVENT_TYPE (event)) {
1714 case GST_EVENT_QOS:{
1715 GstClockTimeDiff diff;
1716 GstClockTime timestamp;
1719 gst_event_parse_qos (event, &proportion, &diff, ×tamp);
1720 gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1727 res = gst_pad_push_event (dec->sinkpad, event);
1729 gst_object_unref (dec);
1734 gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event)
1736 gboolean ret = TRUE;
1737 GstJpegDec *dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
1739 GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1741 switch (GST_EVENT_TYPE (event)) {
1742 case GST_EVENT_FLUSH_STOP:
1743 GST_DEBUG_OBJECT (dec, "Aborting decompress");
1744 jpeg_abort_decompress (&dec->cinfo);
1745 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1746 gst_adapter_clear (dec->adapter);
1747 g_free (dec->cur_buf);
1748 dec->cur_buf = NULL;
1749 dec->parse_offset = 0;
1750 dec->parse_entropy_len = 0;
1751 dec->parse_resync = FALSE;
1752 gst_jpeg_dec_reset_qos (dec);
1754 case GST_EVENT_NEWSEGMENT:{
1756 gdouble rate, applied_rate;
1758 gint64 start, stop, position;
1760 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1761 &format, &start, &stop, &position);
1763 GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
1764 " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
1765 GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
1766 GST_TIME_ARGS (position));
1768 gst_segment_set_newsegment_full (&dec->segment, update, rate,
1769 applied_rate, format, start, stop, position);
1777 ret = gst_pad_push_event (dec->srcpad, event);
1783 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1784 const GValue * value, GParamSpec * pspec)
1788 dec = GST_JPEG_DEC (object);
1791 case PROP_IDCT_METHOD:
1792 dec->idct_method = g_value_get_enum (value);
1794 case PROP_MAX_ERRORS:
1795 g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1799 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1805 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1810 dec = GST_JPEG_DEC (object);
1813 case PROP_IDCT_METHOD:
1814 g_value_set_enum (value, dec->idct_method);
1816 case PROP_MAX_ERRORS:
1817 g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1821 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1826 static GstStateChangeReturn
1827 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1829 GstStateChangeReturn ret;
1832 dec = GST_JPEG_DEC (element);
1834 switch (transition) {
1835 case GST_STATE_CHANGE_READY_TO_PAUSED:
1836 dec->error_count = 0;
1837 dec->good_count = 0;
1838 dec->framerate_numerator = 0;
1839 dec->framerate_denominator = 1;
1840 dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
1841 dec->caps_width = -1;
1842 dec->caps_height = -1;
1844 dec->packetized = FALSE;
1846 dec->discont = TRUE;
1847 dec->parse_offset = 0;
1848 dec->parse_entropy_len = 0;
1849 dec->parse_resync = FALSE;
1850 dec->cur_buf = NULL;
1851 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1852 gst_jpeg_dec_reset_qos (dec);
1857 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1858 if (ret != GST_STATE_CHANGE_SUCCESS)
1861 switch (transition) {
1862 case GST_STATE_CHANGE_PAUSED_TO_READY:
1863 gst_adapter_clear (dec->adapter);
1864 g_free (dec->cur_buf);
1865 dec->cur_buf = NULL;
1866 gst_jpeg_dec_free_buffers (dec);