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 ! jpegddec ! 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 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
78 GST_STATIC_PAD_TEMPLATE ("sink",
81 GST_STATIC_CAPS ("image/jpeg, "
82 "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
83 " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
84 G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (fraction) [ 0/1, MAX ]")
87 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
88 #define GST_CAT_DEFAULT jpeg_dec_debug
89 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
91 /* These macros are adapted from videotestsrc.c
92 * and/or gst-plugins/gst/games/gstvideoimage.c */
93 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
94 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
95 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
97 #define I420_Y_OFFSET(w,h) (0)
98 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
99 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
101 #define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
103 static GstElementClass *parent_class; /* NULL */
105 static void gst_jpeg_dec_base_init (gpointer g_class);
106 static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
107 static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
109 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
110 const GValue * value, GParamSpec * pspec);
111 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
112 GValue * value, GParamSpec * pspec);
114 static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
115 static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
116 static gboolean gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event);
117 static gboolean gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event);
118 static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
119 GstStateChange transition);
120 static void gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
121 GstClockTimeDiff diff, GstClockTime ts);
122 static void gst_jpeg_dec_reset_qos (GstJpegDec * dec);
123 static void gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
124 GstClockTime * time);
127 gst_jpeg_dec_get_type (void)
129 static GType type = 0;
132 static const GTypeInfo jpeg_dec_info = {
133 sizeof (GstJpegDecClass),
134 (GBaseInitFunc) gst_jpeg_dec_base_init,
136 (GClassInitFunc) gst_jpeg_dec_class_init,
141 (GInstanceInitFunc) gst_jpeg_dec_init,
144 type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
151 gst_jpeg_dec_finalize (GObject * object)
153 GstJpegDec *dec = GST_JPEG_DEC (object);
155 jpeg_destroy_decompress (&dec->cinfo);
157 g_object_unref (dec->adapter);
159 G_OBJECT_CLASS (parent_class)->finalize (object);
163 gst_jpeg_dec_base_init (gpointer g_class)
165 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
167 gst_element_class_add_pad_template (element_class,
168 gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
169 gst_element_class_add_pad_template (element_class,
170 gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
171 gst_element_class_set_details_simple (element_class, "JPEG image decoder",
172 "Codec/Decoder/Image",
173 "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
177 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
179 GstElementClass *gstelement_class;
180 GObjectClass *gobject_class;
182 gstelement_class = (GstElementClass *) klass;
183 gobject_class = (GObjectClass *) klass;
185 parent_class = g_type_class_peek_parent (klass);
187 gobject_class->finalize = gst_jpeg_dec_finalize;
188 gobject_class->set_property = gst_jpeg_dec_set_property;
189 gobject_class->get_property = gst_jpeg_dec_get_property;
191 g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
192 g_param_spec_enum ("idct-method", "IDCT Method",
193 "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
194 JPEG_DEFAULT_IDCT_METHOD,
195 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198 * GstJpegDec:max-errors
200 * Error out after receiving N consecutive decoding errors
201 * (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
205 g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
206 g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
207 "Error out after receiving N consecutive decoding errors "
208 "(-1 = never fail, 0 = automatic, 1 = fail on first error)",
209 -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
210 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
212 gstelement_class->change_state =
213 GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
215 GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
216 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
220 gst_jpeg_dec_clear_error (GstJpegDec * dec)
222 g_free (dec->error_msg);
223 dec->error_msg = NULL;
225 dec->error_func = NULL;
229 gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
230 const gchar * debug_msg_format, va_list args)
232 #ifndef GST_DISABLE_GST_DEBUG
233 gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
234 line, (GObject *) dec, debug_msg_format, args);
237 g_free (dec->error_msg);
238 if (debug_msg_format)
239 dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
241 dec->error_msg = NULL;
243 dec->error_line = line;
244 dec->error_func = func;
248 gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
249 const gchar * debug_msg_format, ...)
253 va_start (va, debug_msg_format);
254 gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
259 gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
265 max_errors = g_atomic_int_get (&dec->max_errors);
267 if (max_errors < 0) {
269 } else if (max_errors == 0) {
270 /* FIXME: do something more clever in "automatic mode" */
271 if (dec->packetized) {
272 ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
274 ret = GST_FLOW_ERROR;
277 ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
280 GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
281 max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
283 gst_element_message_full (GST_ELEMENT (dec),
284 (ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
285 GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
286 g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
287 __FILE__, dec->error_func, dec->error_line);
289 dec->error_msg = NULL;
290 gst_jpeg_dec_clear_error (dec);
295 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
300 dec = CINFO_GET_JPEGDEC (cinfo);
301 g_return_val_if_fail (dec != NULL, FALSE);
303 av = gst_adapter_available_fast (dec->adapter);
304 GST_DEBUG_OBJECT (dec, "fill_input_buffer: fast av=%u, remaining=%u", av,
308 GST_DEBUG_OBJECT (dec, "Out of data");
312 if (dec->rem_img_len < av)
313 av = dec->rem_img_len;
314 dec->rem_img_len -= av;
316 g_free (dec->cur_buf);
317 dec->cur_buf = gst_adapter_take (dec->adapter, av);
319 cinfo->src->next_input_byte = dec->cur_buf;
320 cinfo->src->bytes_in_buffer = av;
326 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
328 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
333 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
335 GstJpegDec *dec = CINFO_GET_JPEGDEC (cinfo);
337 GST_DEBUG_OBJECT (dec, "skip %ld bytes", num_bytes);
339 if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
340 cinfo->src->next_input_byte += (size_t) num_bytes;
341 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
342 } else if (num_bytes > 0) {
345 num_bytes -= cinfo->src->bytes_in_buffer;
346 cinfo->src->next_input_byte += (size_t) cinfo->src->bytes_in_buffer;
347 cinfo->src->bytes_in_buffer = 0;
349 available = gst_adapter_available (dec->adapter);
350 if (available < num_bytes || available < dec->rem_img_len) {
351 GST_WARNING_OBJECT (dec, "Less bytes to skip than available in the "
352 "adapter or the remaining image length %ld < %d or %u",
353 num_bytes, available, dec->rem_img_len);
355 num_bytes = MIN (MIN (num_bytes, available), dec->rem_img_len);
356 gst_adapter_flush (dec->adapter, num_bytes);
357 dec->rem_img_len -= num_bytes;
362 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
364 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
369 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
371 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
376 gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
378 return; /* do nothing */
382 gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
384 /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
389 gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
391 struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
393 (*cinfo->err->output_message) (cinfo);
394 longjmp (err_mgr->setjmp_buffer, 1);
398 gst_jpeg_dec_init (GstJpegDec * dec)
400 GST_DEBUG ("initializing");
402 /* create the sink and src pads */
404 gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
406 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
407 gst_pad_set_setcaps_function (dec->sinkpad,
408 GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
409 gst_pad_set_chain_function (dec->sinkpad,
410 GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
411 gst_pad_set_event_function (dec->sinkpad,
412 GST_DEBUG_FUNCPTR (gst_jpeg_dec_sink_event));
415 gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
416 gst_pad_set_event_function (dec->srcpad,
417 GST_DEBUG_FUNCPTR (gst_jpeg_dec_src_event));
418 gst_pad_use_fixed_caps (dec->srcpad);
419 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
422 memset (&dec->cinfo, 0, sizeof (dec->cinfo));
423 memset (&dec->jerr, 0, sizeof (dec->jerr));
424 dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
425 dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
426 dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
427 dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
429 jpeg_create_decompress (&dec->cinfo);
431 dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
432 dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
433 dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
434 dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
435 dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
436 dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
439 /* init properties */
440 dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
441 dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
443 dec->adapter = gst_adapter_new ();
447 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
452 av = gst_adapter_available (dec->adapter);
453 /* we expect at least 4 bytes, first of which start marker */
454 offset = gst_adapter_masked_scan_uint32 (dec->adapter, 0xffffff00, 0xffd8ff00,
456 if (G_UNLIKELY (offset < 0)) {
457 GST_DEBUG_OBJECT (dec, "No JPEG header in current buffer");
460 gst_adapter_flush (dec->adapter, av - 4);
465 GST_LOG_OBJECT (dec, "Skipping %u bytes.", offset);
466 gst_adapter_flush (dec->adapter, offset);
468 GST_DEBUG_OBJECT (dec, "Found JPEG header");
473 static inline gboolean
474 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
476 if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
481 /* returns image length in bytes if parsed successfully,
482 * otherwise 0 if more data needed,
483 * if < 0 the absolute value needs to be flushed */
485 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
489 GstAdapter *adapter = dec->adapter;
490 gint offset, noffset;
492 size = gst_adapter_available (adapter);
494 /* we expect at least 4 bytes, first of which start marker */
495 if (gst_adapter_masked_scan_uint32 (adapter, 0xffff0000, 0xffd80000, 0, 4))
498 GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
500 GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d",
501 dec->parse_offset, dec->parse_resync, dec->parse_entropy_len);
503 /* offset is 2 less than actual offset;
504 * - adapter needs at least 4 bytes for scanning,
505 * - start and end marker ensure at least that much
507 /* resume from state offset */
508 offset = dec->parse_offset;
515 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
516 offset, size - offset, &value);
517 /* lost sync if 0xff marker not where expected */
518 if ((resync = (noffset != offset))) {
519 GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
521 /* may have marker, but could have been resyncng */
522 resync = resync || dec->parse_resync;
523 /* Skip over extra 0xff */
524 while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
527 gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00, 0x0000ff00,
528 noffset, size - noffset, &value);
530 /* enough bytes left for marker? (we need 0xNN after the 0xff) */
532 GST_DEBUG ("at end of input and no EOI marker found, need more data");
536 /* now lock on the marker we found */
538 value = value & 0xff;
540 GST_DEBUG ("0x%08x: EOI marker", offset + 2);
541 /* clear parse state */
542 dec->parse_resync = FALSE;
543 dec->parse_offset = 0;
545 } else if (value == 0xd8) {
546 /* Skip this frame if we found another SOI marker */
547 GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
548 dec->parse_resync = FALSE;
549 dec->parse_offset = 0;
550 return -(offset + 2);
554 if (value >= 0xd0 && value <= 0xd7)
557 /* peek tag and subsequent length */
558 if (offset + 2 + 4 > size)
561 gst_adapter_masked_scan_uint32_peek (adapter, 0x0, 0x0, offset + 2, 4,
563 frame_len = frame_len & 0xffff;
565 GST_DEBUG ("0x%08x: tag %02x, frame_len=%u", offset + 2, value, frame_len);
566 /* the frame length includes the 2 bytes for the length; here we want at
567 * least 2 more bytes at the end for an end marker */
568 if (offset + 2 + 2 + frame_len + 2 > size) {
572 if (gst_jpeg_dec_parse_tag_has_entropy_segment (value)) {
573 guint eseglen = dec->parse_entropy_len;
575 GST_DEBUG ("0x%08x: finding entropy segment length", offset + 2);
576 noffset = offset + 2 + frame_len + dec->parse_entropy_len;
578 noffset = gst_adapter_masked_scan_uint32_peek (adapter, 0x0000ff00,
579 0x0000ff00, noffset, size - noffset, &value);
582 dec->parse_entropy_len = size - offset - 4 - frame_len - 2;
585 if ((value & 0xff) != 0x00) {
586 eseglen = noffset - offset - frame_len - 2;
591 dec->parse_entropy_len = 0;
592 frame_len += eseglen;
593 GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
597 /* check if we will still be in sync if we interpret
598 * this as a sync point and skip this frame */
599 noffset = offset + frame_len + 2;
600 noffset = gst_adapter_masked_scan_uint32 (adapter, 0x0000ff00, 0x0000ff00,
603 /* ignore and continue resyncing until we hit the end
604 * of our data or find a sync point that looks okay */
608 GST_DEBUG ("found sync at 0x%x", offset + 2);
611 offset += frame_len + 2;
617 dec->parse_offset = offset;
618 dec->parse_resync = resync;
623 /* shamelessly ripped from jpegutils.c in mjpegtools */
625 add_huff_table (j_decompress_ptr dinfo,
626 JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
627 /* Define a Huffman table */
631 if (*htblptr == NULL)
632 *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
636 /* Copy the number-of-symbols-of-each-code-length counts */
637 memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
639 /* Validate the counts. We do this here mainly so we can copy the right
640 * number of symbols from the val[] array, without risking marching off
641 * the end of memory. jchuff.c will do a more thorough test later.
644 for (len = 1; len <= 16; len++)
645 nsymbols += bits[len];
646 if (nsymbols < 1 || nsymbols > 256)
647 g_error ("jpegutils.c: add_huff_table failed badly. ");
649 memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
655 std_huff_tables (j_decompress_ptr dinfo)
656 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
657 /* IMPORTANT: these are only valid for 8-bit data precision! */
659 static const UINT8 bits_dc_luminance[17] =
660 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
661 static const UINT8 val_dc_luminance[] =
662 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
664 static const UINT8 bits_dc_chrominance[17] =
665 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
666 static const UINT8 val_dc_chrominance[] =
667 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
669 static const UINT8 bits_ac_luminance[17] =
670 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
671 static const UINT8 val_ac_luminance[] =
672 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
673 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
674 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
675 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
676 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
677 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
678 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
679 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
680 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
681 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
682 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
683 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
684 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
685 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
686 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
687 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
688 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
689 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
690 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
691 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
695 static const UINT8 bits_ac_chrominance[17] =
696 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
697 static const UINT8 val_ac_chrominance[] =
698 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
699 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
700 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
701 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
702 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
703 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
704 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
705 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
706 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
707 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
708 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
709 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
710 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
711 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
712 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
713 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
714 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
715 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
716 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
717 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
721 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
722 bits_dc_luminance, val_dc_luminance);
723 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
724 bits_ac_luminance, val_ac_luminance);
725 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
726 bits_dc_chrominance, val_dc_chrominance);
727 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
728 bits_ac_chrominance, val_ac_chrominance);
734 guarantee_huff_tables (j_decompress_ptr dinfo)
736 if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
737 (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
738 (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
739 (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
740 GST_DEBUG ("Generating standard Huffman tables for this frame.");
741 std_huff_tables (dinfo);
746 gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
750 const GValue *framerate;
752 dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
753 s = gst_caps_get_structure (caps, 0);
755 if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
756 dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
757 dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
758 dec->packetized = TRUE;
759 GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
760 dec->framerate_numerator, dec->framerate_denominator);
763 /* do not extract width/height here. we do that in the chain
764 * function on a per-frame basis (including the line[] array
767 /* But we can take the framerate values and set them on the src pad */
774 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
778 for (i = 0; i < len; ++i) {
779 /* equivalent to: dest[i] = src[i << 1] */
788 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
792 for (i = 0; i < 16; i++) {
793 g_free (dec->idr_y[i]);
794 g_free (dec->idr_u[i]);
795 g_free (dec->idr_v[i]);
796 dec->idr_y[i] = NULL;
797 dec->idr_u[i] = NULL;
798 dec->idr_v[i] = NULL;
801 dec->idr_width_allocated = 0;
804 static inline gboolean
805 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
809 if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
812 /* FIXME: maybe just alloc one or three blocks altogether? */
813 for (i = 0; i < 16; i++) {
814 dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
815 dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
816 dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
818 if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
819 GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
824 dec->idr_width_allocated = maxrowbytes;
825 GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
830 gst_jpeg_dec_decode_grayscale (GstJpegDec * dec, guchar * base[1],
831 guint width, guint height, guint pstride, guint rstride)
834 guchar **scanarray[1] = { rows };
838 GST_DEBUG_OBJECT (dec, "indirect decoding of grayscale");
840 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
843 memcpy (rows, dec->idr_y, 16 * sizeof (gpointer));
847 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
848 if (G_LIKELY (lines > 0)) {
849 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
853 for (k = 0; k < width; k++) {
854 base[0][p] = rows[j][k];
860 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
866 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, guchar * base[3],
867 guint width, guint height, guint pstride, guint rstride)
869 guchar *r_rows[16], *g_rows[16], *b_rows[16];
870 guchar **scanarray[3] = { r_rows, g_rows, b_rows };
874 GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
876 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
879 memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
880 memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
881 memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
885 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
886 if (G_LIKELY (lines > 0)) {
887 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
891 for (k = 0; k < width; k++) {
892 base[0][p] = r_rows[j][k];
893 base[1][p] = g_rows[j][k];
894 base[2][p] = b_rows[j][k];
902 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
908 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
909 guchar * last[3], guint width, guint height, gint r_v, gint r_h, gint comp)
911 guchar *y_rows[16], *u_rows[16], *v_rows[16];
912 guchar **scanarray[3] = { y_rows, u_rows, v_rows };
916 GST_DEBUG_OBJECT (dec,
917 "unadvantageous width or r_h, taking slow route involving memcpy");
919 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
922 memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
923 memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
924 memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
926 /* fill chroma components for grayscale */
928 GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
929 for (i = 0; i < 16; i++) {
930 memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
931 memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
935 for (i = 0; i < height; i += r_v * DCTSIZE) {
936 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
937 if (G_LIKELY (lines > 0)) {
938 for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
939 if (G_LIKELY (base[0] <= last[0])) {
940 memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
941 base[0] += I420_Y_ROWSTRIDE (width);
944 if (G_LIKELY (base[0] <= last[0])) {
945 memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
946 base[0] += I420_Y_ROWSTRIDE (width);
949 if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
951 memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
952 memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
953 } else if (r_h == 1) {
954 hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
955 hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
957 /* FIXME: implement (at least we avoid crashing by doing nothing) */
961 if (r_v == 2 || (k & 1) != 0) {
962 base[1] += I420_U_ROWSTRIDE (width);
963 base[2] += I420_V_ROWSTRIDE (width);
967 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
972 #ifndef GST_DISABLE_GST_DEBUG
974 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
978 for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
979 GST_LOG ("[%02d] %5d %5d %5d", j,
980 (line[0][j] >= base[0]) ?
981 (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
982 (line[1][j] >= base[1]) ?
983 (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
984 (line[2][j] >= base[2]) ?
985 (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
991 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
992 guchar * last[3], guint width, guint height)
994 guchar **line[3]; /* the jpeg line buffer */
995 guchar *y[4 * DCTSIZE] = { NULL, }; /* alloc enough for the lines */
996 guchar *u[4 * DCTSIZE] = { NULL, }; /* r_v will be <4 */
997 guchar *v[4 * DCTSIZE] = { NULL, };
999 gint lines, v_samp[3];
1005 v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
1006 v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
1007 v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
1009 if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
1010 goto format_not_supported;
1012 /* let jpeglib decode directly into our final buffer */
1013 GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
1015 for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
1016 for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
1018 line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
1019 if (G_UNLIKELY (line[0][j] > last[0]))
1020 line[0][j] = last[0];
1022 if (v_samp[1] == v_samp[0]) {
1023 line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
1024 } else if (j < (v_samp[1] * DCTSIZE)) {
1025 line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
1027 if (G_UNLIKELY (line[1][j] > last[1]))
1028 line[1][j] = last[1];
1030 if (v_samp[2] == v_samp[0]) {
1031 line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
1032 } else if (j < (v_samp[2] * DCTSIZE)) {
1033 line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
1035 if (G_UNLIKELY (line[2][j] > last[2]))
1036 line[2][j] = last[2];
1039 /* dump_lines (base, line, v_samp[0], width); */
1041 lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
1042 if (G_UNLIKELY (!lines)) {
1043 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
1048 format_not_supported:
1050 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1051 "Unsupported subsampling schema: v_samp factors: %u %u %u",
1052 v_samp[0], v_samp[1], v_samp[2]);
1053 return GST_FLOW_ERROR;
1058 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
1059 GstClockTimeDiff diff, GstClockTime ts)
1061 GST_OBJECT_LOCK (dec);
1062 dec->proportion = proportion;
1063 if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
1064 if (G_UNLIKELY (diff > dec->qos_duration))
1065 dec->earliest_time = ts + 2 * diff + dec->qos_duration;
1067 dec->earliest_time = ts + diff;
1069 dec->earliest_time = GST_CLOCK_TIME_NONE;
1071 GST_OBJECT_UNLOCK (dec);
1075 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
1077 gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
1081 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
1082 GstClockTime * time)
1084 GST_OBJECT_LOCK (dec);
1085 *proportion = dec->proportion;
1086 *time = dec->earliest_time;
1087 GST_OBJECT_UNLOCK (dec);
1090 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
1091 * frame should be decoded, FALSE if the frame can be dropped entirely */
1093 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
1095 GstClockTime qostime, earliest_time;
1098 /* no timestamp, can't do QoS => decode frame */
1099 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1100 GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
1104 /* get latest QoS observation values */
1105 gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
1107 /* skip qos if we have no observation (yet) => decode frame */
1108 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1109 GST_LOG_OBJECT (dec, "no observation yet, decode frame");
1113 /* qos is done on running time */
1114 qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
1117 /* see how our next timestamp relates to the latest qos timestamp */
1118 GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
1119 GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1121 if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1122 GST_DEBUG_OBJECT (dec, "we are late, drop frame");
1126 GST_LOG_OBJECT (dec, "decode frame");
1131 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
1134 GstVideoFormat format;
1136 if (G_UNLIKELY (width == dec->caps_width && height == dec->caps_height &&
1137 dec->framerate_numerator == dec->caps_framerate_numerator &&
1138 dec->framerate_denominator == dec->caps_framerate_denominator &&
1139 clrspc == dec->clrspc))
1142 /* framerate == 0/1 is a still frame */
1143 if (dec->framerate_denominator == 0) {
1144 dec->framerate_numerator = 0;
1145 dec->framerate_denominator = 1;
1148 /* calculate or assume an average frame duration for QoS purposes */
1149 GST_OBJECT_LOCK (dec);
1150 if (dec->framerate_numerator != 0) {
1151 dec->qos_duration = gst_util_uint64_scale (GST_SECOND,
1152 dec->framerate_denominator, dec->framerate_numerator);
1154 /* if not set just use 25fps */
1155 dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1157 GST_OBJECT_UNLOCK (dec);
1159 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1161 GstCaps *allowed_caps;
1163 GST_DEBUG_OBJECT (dec, "selecting RGB format");
1164 /* retrieve allowed caps, and find the first one that reasonably maps
1165 * to the parameters of the colourspace */
1166 caps = gst_pad_get_allowed_caps (dec->srcpad);
1168 GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1169 /* need to copy because get_allowed_caps returns a ref,
1170 * and get_pad_template_caps doesn't */
1171 caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
1173 /* avoid lists of fourcc, etc */
1174 allowed_caps = gst_caps_normalize (caps);
1175 gst_caps_unref (caps);
1177 GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1179 for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1181 gst_caps_unref (caps);
1182 caps = gst_caps_copy_nth (allowed_caps, i);
1183 /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1184 gst_pad_fixate_caps (dec->srcpad, caps);
1185 GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1186 if (!gst_video_format_parse_caps (caps, &format, NULL, NULL))
1188 /* we'll settle for the first (preferred) downstream rgb format */
1189 if (gst_video_format_is_rgb (format))
1191 /* default fall-back */
1192 format = GST_VIDEO_FORMAT_RGB;
1195 gst_caps_unref (caps);
1196 gst_caps_unref (allowed_caps);
1197 caps = gst_video_format_new_caps (format, width, height,
1198 dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1199 dec->outsize = gst_video_format_get_size (format, width, height);
1200 /* some format info */
1202 gst_video_format_get_component_offset (format, 0, width, height);
1204 gst_video_format_get_component_offset (format, 1, width, height);
1206 gst_video_format_get_component_offset (format, 2, width, height);
1207 /* equal for all components */
1208 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1209 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1210 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1211 /* TODO is anything else then 8bit supported in jpeg? */
1212 format = GST_VIDEO_FORMAT_GRAY8;
1213 caps = gst_video_format_new_caps (format, width, height,
1214 dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1215 dec->outsize = gst_video_format_get_size (format, width, height);
1217 gst_video_format_get_component_offset (format, 0, width, height);
1218 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1219 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1221 /* go for plain and simple I420 */
1222 /* TODO other YUV cases ? */
1223 caps = gst_caps_new_simple ("video/x-raw-yuv",
1224 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
1225 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
1226 "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
1227 dec->framerate_denominator, NULL);
1228 dec->outsize = I420_SIZE (width, height);
1231 GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1232 GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1233 GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1235 gst_pad_set_caps (dec->srcpad, caps);
1236 gst_caps_unref (caps);
1238 dec->caps_width = width;
1239 dec->caps_height = height;
1240 dec->caps_framerate_numerator = dec->framerate_numerator;
1241 dec->caps_framerate_denominator = dec->framerate_denominator;
1244 static GstFlowReturn
1245 gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
1247 GstFlowReturn ret = GST_FLOW_OK;
1249 GstBuffer *outbuf = NULL;
1250 #ifndef GST_DISABLE_GST_DEBUG
1254 guchar *base[3], *last[3];
1260 GstClockTime timestamp, duration;
1262 dec = GST_JPEG_DEC (GST_PAD_PARENT (pad));
1264 timestamp = GST_BUFFER_TIMESTAMP (buf);
1265 duration = GST_BUFFER_DURATION (buf);
1267 if (GST_CLOCK_TIME_IS_VALID (timestamp))
1268 dec->next_ts = timestamp;
1270 if (GST_BUFFER_IS_DISCONT (buf)) {
1271 GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1272 dec->discont = TRUE;
1273 if (!dec->packetized && gst_adapter_available (dec->adapter)) {
1274 GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1275 gst_adapter_clear (dec->adapter);
1279 gst_adapter_push (dec->adapter, buf);
1282 /* If we are non-packetized and know the total incoming size in bytes,
1283 * just wait until we have enough before doing any processing. */
1285 if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1286 (dec->segment.stop != -1) &&
1287 (gst_adapter_available (dec->adapter) < dec->segment.stop)) {
1288 /* We assume that non-packetized input in bytes is *one* single jpeg image */
1289 GST_DEBUG ("Non-packetized mode. Got %d bytes, need %" G_GINT64_FORMAT,
1290 gst_adapter_available (dec->adapter), dec->segment.stop);
1291 goto need_more_data;
1295 if (!gst_jpeg_dec_ensure_header (dec))
1296 goto need_more_data;
1298 /* If we know that each input buffer contains data
1299 * for a whole jpeg image (e.g. MJPEG streams), just
1300 * do some sanity checking instead of parsing all of
1302 if (dec->packetized) {
1303 img_len = gst_adapter_available (dec->adapter);
1305 /* Parse jpeg image to handle jpeg input that
1306 * is not aligned to buffer boundaries */
1307 img_len = gst_jpeg_dec_parse_image_data (dec);
1310 goto need_more_data;
1311 } else if (img_len < 0) {
1312 gst_adapter_flush (dec->adapter, -img_len);
1317 dec->rem_img_len = img_len;
1319 GST_LOG_OBJECT (dec, "image size = %u", img_len);
1321 /* QoS: if we're too late anyway, skip decoding */
1322 if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1325 #ifndef GST_DISABLE_GST_DEBUG
1326 data = (guint8 *) gst_adapter_peek (dec->adapter, 4);
1327 GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1331 gst_jpeg_dec_fill_input_buffer (&dec->cinfo);
1333 if (setjmp (dec->jerr.setjmp_buffer)) {
1334 code = dec->jerr.pub.msg_code;
1336 if (code == JERR_INPUT_EOF) {
1337 GST_DEBUG ("jpeg input EOF error, we probably need more data");
1338 goto need_more_data;
1344 hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1345 if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1346 GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1349 r_h = dec->cinfo.comp_info[0].h_samp_factor;
1350 r_v = dec->cinfo.comp_info[0].v_samp_factor;
1352 GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1353 GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1354 GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1356 if (dec->cinfo.num_components > 3)
1357 goto components_not_supported;
1359 /* verify color space expectation to avoid going *boom* or bogus output */
1360 if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1361 dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1362 dec->cinfo.jpeg_color_space != JCS_RGB)
1363 goto unsupported_colorspace;
1365 #ifndef GST_DISABLE_GST_DEBUG
1369 for (i = 0; i < dec->cinfo.num_components; ++i) {
1370 GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1371 i, dec->cinfo.comp_info[i].h_samp_factor,
1372 dec->cinfo.comp_info[i].v_samp_factor,
1373 dec->cinfo.comp_info[i].component_id);
1378 /* prepare for raw output */
1379 dec->cinfo.do_fancy_upsampling = FALSE;
1380 dec->cinfo.do_block_smoothing = FALSE;
1381 dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1382 dec->cinfo.dct_method = dec->idct_method;
1383 dec->cinfo.raw_data_out = TRUE;
1385 GST_LOG_OBJECT (dec, "starting decompress");
1386 guarantee_huff_tables (&dec->cinfo);
1387 if (!jpeg_start_decompress (&dec->cinfo)) {
1388 GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1391 /* sanity checks to get safe and reasonable output */
1392 switch (dec->cinfo.jpeg_color_space) {
1394 if (dec->cinfo.num_components != 1)
1395 goto invalid_yuvrgbgrayscale;
1398 if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1399 dec->cinfo.max_h_samp_factor > 1)
1400 goto invalid_yuvrgbgrayscale;
1403 if (dec->cinfo.num_components != 3 ||
1404 r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1405 r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1406 r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1407 r_h < dec->cinfo.comp_info[1].h_samp_factor)
1408 goto invalid_yuvrgbgrayscale;
1411 g_assert_not_reached ();
1415 width = dec->cinfo.output_width;
1416 height = dec->cinfo.output_height;
1418 if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1419 height < MIN_HEIGHT || height > MAX_HEIGHT))
1422 gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1424 ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
1425 dec->outsize, GST_PAD_CAPS (dec->srcpad), &outbuf);
1426 if (G_UNLIKELY (ret != GST_FLOW_OK))
1429 outdata = GST_BUFFER_DATA (outbuf);
1430 outsize = GST_BUFFER_SIZE (outbuf);
1432 GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
1433 width, height, outsize, dec->outsize);
1435 GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1437 if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1438 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1439 /* use duration from incoming buffer for outgoing buffer */
1440 dec->next_ts += duration;
1441 } else if (dec->framerate_numerator != 0) {
1442 duration = gst_util_uint64_scale (GST_SECOND,
1443 dec->framerate_denominator, dec->framerate_numerator);
1444 dec->next_ts += duration;
1446 duration = GST_CLOCK_TIME_NONE;
1447 dec->next_ts = GST_CLOCK_TIME_NONE;
1450 duration = GST_CLOCK_TIME_NONE;
1451 dec->next_ts = GST_CLOCK_TIME_NONE;
1453 GST_BUFFER_DURATION (outbuf) = duration;
1455 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1456 base[0] = outdata + dec->offset[0];
1457 base[1] = outdata + dec->offset[1];
1458 base[2] = outdata + dec->offset[2];
1459 gst_jpeg_dec_decode_rgb (dec, base, width, height, dec->inc, dec->stride);
1460 } else if (dec->cinfo.jpeg_color_space == JCS_GRAYSCALE) {
1461 base[0] = outdata + dec->offset[0];
1462 gst_jpeg_dec_decode_grayscale (dec, base, width, height, dec->inc,
1465 /* mind the swap, jpeglib outputs blue chroma first
1466 * ensonic: I see no swap?
1468 base[0] = outdata + I420_Y_OFFSET (width, height);
1469 base[1] = outdata + I420_U_OFFSET (width, height);
1470 base[2] = outdata + I420_V_OFFSET (width, height);
1472 /* make sure we don't make jpeglib write beyond our buffer,
1473 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1474 last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1476 base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1479 base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1482 GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1483 dec->cinfo.rec_outbuf_height);
1485 /* For some widths jpeglib requires more horizontal padding than I420
1486 * provides. In those cases we need to decode into separate buffers and then
1487 * copy over the data into our final picture buffer, otherwise jpeglib might
1488 * write over the end of a line into the beginning of the next line,
1489 * resulting in blocky artifacts on the left side of the picture. */
1490 if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1491 || dec->cinfo.comp_info[0].h_samp_factor != 2
1492 || dec->cinfo.comp_info[1].h_samp_factor != 1
1493 || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1494 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1495 "indirect decoding using extra buffer copy");
1496 gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h,
1497 dec->cinfo.num_components);
1499 ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1501 if (G_UNLIKELY (ret != GST_FLOW_OK))
1502 goto decode_direct_failed;
1506 GST_LOG_OBJECT (dec, "decompressing finished");
1507 jpeg_finish_decompress (&dec->cinfo);
1510 if (dec->segment.format == GST_FORMAT_TIME) {
1511 gint64 start, stop, clip_start, clip_stop;
1513 GST_LOG_OBJECT (dec, "Attempting clipping");
1515 start = GST_BUFFER_TIMESTAMP (outbuf);
1516 if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1519 stop = start + GST_BUFFER_DURATION (outbuf);
1521 if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1522 start, stop, &clip_start, &clip_stop)) {
1523 GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1524 GST_TIME_ARGS (clip_start));
1525 GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1526 if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1527 GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1528 GST_TIME_ARGS (clip_stop - clip_start));
1529 GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1535 /* reset error count on successful decode */
1536 dec->error_count = 0;
1540 GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1541 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1542 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1544 ret = gst_pad_push (dec->srcpad, outbuf);
1548 gst_adapter_flush (dec->adapter, dec->rem_img_len);
1552 if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
1553 jpeg_abort_decompress (&dec->cinfo);
1554 ret = gst_jpeg_dec_post_error_or_warning (dec);
1562 GST_LOG_OBJECT (dec, "we need more data");
1564 gst_buffer_unref (outbuf);
1573 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1574 "Picture is too small or too big (%ux%u)", width, height);
1575 ret = GST_FLOW_ERROR;
1580 gchar err_msg[JMSG_LENGTH_MAX];
1582 dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1584 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1585 "Decode error #%u: %s", code, err_msg);
1588 gst_buffer_unref (outbuf);
1591 ret = GST_FLOW_ERROR;
1594 decode_direct_failed:
1596 /* already posted an error message */
1597 jpeg_abort_decompress (&dec->cinfo);
1598 gst_buffer_replace (&outbuf, NULL);
1603 const gchar *reason;
1605 reason = gst_flow_get_name (ret);
1607 GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1608 /* Reset for next time */
1609 jpeg_abort_decompress (&dec->cinfo);
1610 if (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_WRONG_STATE &&
1611 ret != GST_FLOW_NOT_LINKED) {
1612 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1613 "Buffer allocation failed, reason: %s", reason);
1619 GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1620 gst_buffer_unref (outbuf);
1624 components_not_supported:
1626 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1627 "more components than supported: %d > 3", dec->cinfo.num_components);
1628 ret = GST_FLOW_ERROR;
1631 unsupported_colorspace:
1633 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1634 "Picture has unknown or unsupported colourspace");
1635 ret = GST_FLOW_ERROR;
1638 invalid_yuvrgbgrayscale:
1640 gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
1641 "Picture is corrupt or unhandled YUV/RGB/grayscale layout");
1642 ret = GST_FLOW_ERROR;
1648 gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
1653 dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
1655 switch (GST_EVENT_TYPE (event)) {
1656 case GST_EVENT_QOS:{
1657 GstClockTimeDiff diff;
1658 GstClockTime timestamp;
1661 gst_event_parse_qos (event, &proportion, &diff, ×tamp);
1662 gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1669 res = gst_pad_push_event (dec->sinkpad, event);
1671 gst_object_unref (dec);
1676 gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event)
1678 gboolean ret = TRUE;
1679 GstJpegDec *dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
1681 GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1683 switch (GST_EVENT_TYPE (event)) {
1684 case GST_EVENT_FLUSH_STOP:
1685 GST_DEBUG_OBJECT (dec, "Aborting decompress");
1686 jpeg_abort_decompress (&dec->cinfo);
1687 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1688 gst_adapter_clear (dec->adapter);
1689 g_free (dec->cur_buf);
1690 dec->cur_buf = NULL;
1691 dec->parse_offset = 0;
1692 dec->parse_entropy_len = 0;
1693 dec->parse_resync = FALSE;
1694 gst_jpeg_dec_reset_qos (dec);
1696 case GST_EVENT_NEWSEGMENT:{
1698 gdouble rate, applied_rate;
1700 gint64 start, stop, position;
1702 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1703 &format, &start, &stop, &position);
1705 GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
1706 " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
1707 GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
1708 GST_TIME_ARGS (position));
1710 gst_segment_set_newsegment_full (&dec->segment, update, rate,
1711 applied_rate, format, start, stop, position);
1719 ret = gst_pad_push_event (dec->srcpad, event);
1725 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1726 const GValue * value, GParamSpec * pspec)
1730 dec = GST_JPEG_DEC (object);
1733 case PROP_IDCT_METHOD:
1734 dec->idct_method = g_value_get_enum (value);
1736 case PROP_MAX_ERRORS:
1737 g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
1741 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1747 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1752 dec = GST_JPEG_DEC (object);
1755 case PROP_IDCT_METHOD:
1756 g_value_set_enum (value, dec->idct_method);
1758 case PROP_MAX_ERRORS:
1759 g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
1763 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1768 static GstStateChangeReturn
1769 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1771 GstStateChangeReturn ret;
1774 dec = GST_JPEG_DEC (element);
1776 switch (transition) {
1777 case GST_STATE_CHANGE_READY_TO_PAUSED:
1778 dec->error_count = 0;
1779 dec->good_count = 0;
1780 dec->framerate_numerator = 0;
1781 dec->framerate_denominator = 1;
1782 dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
1783 dec->caps_width = -1;
1784 dec->caps_height = -1;
1786 dec->packetized = FALSE;
1788 dec->discont = TRUE;
1789 dec->parse_offset = 0;
1790 dec->parse_entropy_len = 0;
1791 dec->parse_resync = FALSE;
1792 dec->cur_buf = NULL;
1793 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1794 gst_jpeg_dec_reset_qos (dec);
1799 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1800 if (ret != GST_STATE_CHANGE_SUCCESS)
1803 switch (transition) {
1804 case GST_STATE_CHANGE_PAUSED_TO_READY:
1805 gst_adapter_clear (dec->adapter);
1806 g_free (dec->cur_buf);
1807 dec->cur_buf = NULL;
1808 gst_jpeg_dec_free_buffers (dec);