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
63 static GstStaticPadTemplate gst_jpeg_dec_src_pad_template =
64 GST_STATIC_PAD_TEMPLATE ("src",
67 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") "; "
68 GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; "
69 GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; "
70 GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR)
74 static GstStaticPadTemplate gst_jpeg_dec_sink_pad_template =
75 GST_STATIC_PAD_TEMPLATE ("sink",
78 GST_STATIC_CAPS ("image/jpeg, "
79 "width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
80 " ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
81 G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (fraction) [ 0/1, MAX ]")
84 GST_DEBUG_CATEGORY_STATIC (jpeg_dec_debug);
85 #define GST_CAT_DEFAULT jpeg_dec_debug
86 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
88 /* These macros are adapted from videotestsrc.c
89 * and/or gst-plugins/gst/games/gstvideoimage.c */
90 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
91 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
92 #define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
94 #define I420_Y_OFFSET(w,h) (0)
95 #define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
96 #define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
98 #define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
100 static GstElementClass *parent_class; /* NULL */
102 static void gst_jpeg_dec_base_init (gpointer g_class);
103 static void gst_jpeg_dec_class_init (GstJpegDecClass * klass);
104 static void gst_jpeg_dec_init (GstJpegDec * jpegdec);
106 static void gst_jpeg_dec_set_property (GObject * object, guint prop_id,
107 const GValue * value, GParamSpec * pspec);
108 static void gst_jpeg_dec_get_property (GObject * object, guint prop_id,
109 GValue * value, GParamSpec * pspec);
111 static GstFlowReturn gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buffer);
112 static gboolean gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps);
113 static gboolean gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event);
114 static gboolean gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event);
115 static GstStateChangeReturn gst_jpeg_dec_change_state (GstElement * element,
116 GstStateChange transition);
117 static void gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
118 GstClockTimeDiff diff, GstClockTime ts);
119 static void gst_jpeg_dec_reset_qos (GstJpegDec * dec);
120 static void gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
121 GstClockTime * time);
124 gst_jpeg_dec_get_type (void)
126 static GType type = 0;
129 static const GTypeInfo jpeg_dec_info = {
130 sizeof (GstJpegDecClass),
131 (GBaseInitFunc) gst_jpeg_dec_base_init,
133 (GClassInitFunc) gst_jpeg_dec_class_init,
138 (GInstanceInitFunc) gst_jpeg_dec_init,
141 type = g_type_register_static (GST_TYPE_ELEMENT, "GstJpegDec",
148 gst_jpeg_dec_finalize (GObject * object)
150 GstJpegDec *dec = GST_JPEG_DEC (object);
152 jpeg_destroy_decompress (&dec->cinfo);
155 gst_buffer_unref (dec->tempbuf);
157 G_OBJECT_CLASS (parent_class)->finalize (object);
161 gst_jpeg_dec_base_init (gpointer g_class)
163 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
165 gst_element_class_add_pad_template (element_class,
166 gst_static_pad_template_get (&gst_jpeg_dec_src_pad_template));
167 gst_element_class_add_pad_template (element_class,
168 gst_static_pad_template_get (&gst_jpeg_dec_sink_pad_template));
169 gst_element_class_set_details_simple (element_class, "JPEG image decoder",
170 "Codec/Decoder/Image",
171 "Decode images from JPEG format", "Wim Taymans <wim@fluendo.com>");
175 gst_jpeg_dec_class_init (GstJpegDecClass * klass)
177 GstElementClass *gstelement_class;
178 GObjectClass *gobject_class;
180 gstelement_class = (GstElementClass *) klass;
181 gobject_class = (GObjectClass *) klass;
183 parent_class = g_type_class_peek_parent (klass);
185 gobject_class->finalize = gst_jpeg_dec_finalize;
186 gobject_class->set_property = gst_jpeg_dec_set_property;
187 gobject_class->get_property = gst_jpeg_dec_get_property;
189 g_object_class_install_property (gobject_class, PROP_IDCT_METHOD,
190 g_param_spec_enum ("idct-method", "IDCT Method",
191 "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
192 JPEG_DEFAULT_IDCT_METHOD, G_PARAM_READWRITE));
194 gstelement_class->change_state =
195 GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
197 GST_DEBUG_CATEGORY_INIT (jpeg_dec_debug, "jpegdec", 0, "JPEG decoder");
198 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
202 gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
205 struct GstJpegDecSourceMgr *src_mgr;
208 src_mgr = (struct GstJpegDecSourceMgr*) &cinfo->src;
209 dec = GST_JPEG_DEC (src_mgr->dec);
211 GST_DEBUG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "fill_input_buffer");
213 g_return_val_if_fail (dec != NULL, TRUE);
215 src_mgr->pub.next_input_byte = GST_BUFFER_DATA (dec->tempbuf);
216 src_mgr->pub.bytes_in_buffer = GST_BUFFER_SIZE (dec->tempbuf);
222 gst_jpeg_dec_init_source (j_decompress_ptr cinfo)
224 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "init_source");
229 gst_jpeg_dec_skip_input_data (j_decompress_ptr cinfo, glong num_bytes)
231 GST_DEBUG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "skip %ld bytes", num_bytes);
233 if (num_bytes > 0 && cinfo->src->bytes_in_buffer >= num_bytes) {
234 cinfo->src->next_input_byte += (size_t) num_bytes;
235 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
240 gst_jpeg_dec_resync_to_restart (j_decompress_ptr cinfo, gint desired)
242 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "resync_to_start");
247 gst_jpeg_dec_term_source (j_decompress_ptr cinfo)
249 GST_LOG_OBJECT (CINFO_GET_JPEGDEC (cinfo), "term_source");
254 gst_jpeg_dec_my_output_message (j_common_ptr cinfo)
256 return; /* do nothing */
260 gst_jpeg_dec_my_emit_message (j_common_ptr cinfo, int msg_level)
262 /* GST_LOG_OBJECT (CINFO_GET_JPEGDEC (&cinfo), "msg_level=%d", msg_level); */
267 gst_jpeg_dec_my_error_exit (j_common_ptr cinfo)
269 struct GstJpegDecErrorMgr *err_mgr = (struct GstJpegDecErrorMgr *) cinfo->err;
271 (*cinfo->err->output_message) (cinfo);
272 longjmp (err_mgr->setjmp_buffer, 1);
276 gst_jpeg_dec_init (GstJpegDec * dec)
278 GST_DEBUG ("initializing");
280 /* create the sink and src pads */
282 gst_pad_new_from_static_template (&gst_jpeg_dec_sink_pad_template,
284 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
285 gst_pad_set_setcaps_function (dec->sinkpad,
286 GST_DEBUG_FUNCPTR (gst_jpeg_dec_setcaps));
287 gst_pad_set_chain_function (dec->sinkpad,
288 GST_DEBUG_FUNCPTR (gst_jpeg_dec_chain));
289 gst_pad_set_event_function (dec->sinkpad,
290 GST_DEBUG_FUNCPTR (gst_jpeg_dec_sink_event));
293 gst_pad_new_from_static_template (&gst_jpeg_dec_src_pad_template, "src");
294 gst_pad_set_event_function (dec->srcpad,
295 GST_DEBUG_FUNCPTR (gst_jpeg_dec_src_event));
296 gst_pad_use_fixed_caps (dec->srcpad);
297 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
300 memset (&dec->cinfo, 0, sizeof (dec->cinfo));
301 memset (&dec->jerr, 0, sizeof (dec->jerr));
302 dec->cinfo.err = jpeg_std_error (&dec->jerr.pub);
303 dec->jerr.pub.output_message = gst_jpeg_dec_my_output_message;
304 dec->jerr.pub.emit_message = gst_jpeg_dec_my_emit_message;
305 dec->jerr.pub.error_exit = gst_jpeg_dec_my_error_exit;
307 jpeg_create_decompress (&dec->cinfo);
309 dec->cinfo.src = (struct jpeg_source_mgr *) &dec->jsrc;
310 dec->cinfo.src->init_source = gst_jpeg_dec_init_source;
311 dec->cinfo.src->fill_input_buffer = gst_jpeg_dec_fill_input_buffer;
312 dec->cinfo.src->skip_input_data = gst_jpeg_dec_skip_input_data;
313 dec->cinfo.src->resync_to_restart = gst_jpeg_dec_resync_to_restart;
314 dec->cinfo.src->term_source = gst_jpeg_dec_term_source;
317 /* init properties */
318 dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
321 static inline gboolean
322 is_jpeg_start_marker (const guint8 * data)
324 return (data[0] == 0xff && data[1] == 0xd8);
328 gst_jpeg_dec_find_jpeg_header (GstJpegDec * dec)
333 data = GST_BUFFER_DATA (dec->tempbuf);
334 size = GST_BUFFER_SIZE (dec->tempbuf);
336 g_return_val_if_fail (size >= 2, FALSE);
338 while (!is_jpeg_start_marker (data) || data[2] != 0xff) {
339 const guint8 *marker;
343 marker = memchr (data + 1, 0xff, size - 1 - 2);
344 if (marker == NULL) {
345 off = size - 1; /* keep last byte */
350 tmp = gst_buffer_create_sub (dec->tempbuf, off, size - off);
351 gst_buffer_unref (dec->tempbuf);
354 data = GST_BUFFER_DATA (dec->tempbuf);
355 size = GST_BUFFER_SIZE (dec->tempbuf);
358 return FALSE; /* wait for more data */
361 return TRUE; /* got header */
365 gst_jpeg_dec_ensure_header (GstJpegDec * dec)
367 g_return_val_if_fail (dec->tempbuf != NULL, FALSE);
371 /* we need at least a start marker (0xff 0xd8)
372 * and an end marker (0xff 0xd9) */
373 if (GST_BUFFER_SIZE (dec->tempbuf) <= 4) {
374 GST_DEBUG ("Not enough data");
375 return FALSE; /* we need more data */
378 if (!is_jpeg_start_marker (GST_BUFFER_DATA (dec->tempbuf))) {
379 GST_DEBUG ("Not a JPEG header, resyncing to header...");
380 if (!gst_jpeg_dec_find_jpeg_header (dec)) {
381 GST_DEBUG ("No JPEG header in current buffer");
382 return FALSE; /* we need more data */
384 GST_DEBUG ("Found JPEG header");
385 goto check_header; /* buffer might have changed */
393 gst_jpeg_dec_have_end_marker (GstJpegDec * dec)
395 guint8 *data = GST_BUFFER_DATA (dec->tempbuf);
396 guint size = GST_BUFFER_SIZE (dec->tempbuf);
398 return (size > 2 && data && is_jpeg_end_marker (data + size - 2));
402 static inline gboolean
403 gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
405 if (tag == 0xda || (tag >= 0xd0 && tag <= 0xd7))
410 /* returns image length in bytes if parsed
411 * successfully, otherwise 0 */
413 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
415 guint8 *start, *data, *end;
418 size = GST_BUFFER_SIZE (dec->tempbuf);
419 start = GST_BUFFER_DATA (dec->tempbuf);
423 g_return_val_if_fail (is_jpeg_start_marker (data), 0);
425 GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
427 /* skip start marker */
434 /* do we need to resync? */
435 resync = (*data != 0xff);
437 GST_DEBUG ("Lost sync at 0x%08" G_GINT64_MODIFIER "x, resyncing",
438 (gint64) (data - start));
439 /* at the very least we expect 0xff 0xNN, thus end-1 */
440 while (*data != 0xff && data < end - 1)
442 if (G_UNLIKELY (*data != 0xff)) {
443 GST_DEBUG ("at end of input and no next marker found, need more data");
447 /* Skip over extra 0xff */
448 while (*data == 0xff && data < end)
450 /* enough bytes left for marker? (we need 0xNN after the 0xff) */
452 GST_DEBUG ("at end of input and no EOI marker found, need more data");
457 GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: EOI marker",
458 (gint64) (data - start));
459 return (data - start + 1);
462 if (*data >= 0xd0 && *data <= 0xd7)
464 else if (data >= end - 2)
467 frame_len = GST_READ_UINT16_BE (data + 1);
468 GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: tag %02x, frame_len=%u",
469 (gint64) (data - start - 1), *data, frame_len);
470 /* the frame length includes the 2 bytes for the length; here we want at
471 * least 2 more bytes at the end for an end marker, thus end-2 */
472 if (data + 1 + frame_len >= end - 2) {
474 GST_DEBUG ("not a valid sync (not enough data).");
475 /* Since *data != 0xff, the next iteration will go into resync again. */
478 /* theoretically we could have lost sync and not really need more
479 * data, but that's just tough luck and a broken image then */
480 GST_DEBUG ("at end of input and no EOI marker found, need more data");
484 if (gst_jpeg_dec_parse_tag_has_entropy_segment (*data)) {
485 guint8 *d2 = data + 1 + frame_len;
488 GST_DEBUG ("0x%08" G_GINT64_MODIFIER "x: finding entropy segment length",
489 (gint64) (data - start - 1));
491 if (d2 + eseglen >= end - 1)
492 return 0; /* need more data */
493 if (d2[eseglen] == 0xff && d2[eseglen + 1] != 0x00)
497 frame_len += eseglen;
498 GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
502 /* check if we will still be in sync if we interpret
503 * this as a sync point and skip this frame */
504 if (data[2 + frame_len] != 0xff) {
505 /* ignore and continue resyncing until we hit the end
506 * of our data or find a sync point that looks okay */
509 GST_DEBUG ("found sync at %p", data - size);
512 data += 1 + frame_len;
516 /* shamelessly ripped from jpegutils.c in mjpegtools */
518 add_huff_table (j_decompress_ptr dinfo,
519 JHUFF_TBL ** htblptr, const UINT8 * bits, const UINT8 * val)
520 /* Define a Huffman table */
524 if (*htblptr == NULL)
525 *htblptr = jpeg_alloc_huff_table ((j_common_ptr) dinfo);
529 /* Copy the number-of-symbols-of-each-code-length counts */
530 memcpy ((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
532 /* Validate the counts. We do this here mainly so we can copy the right
533 * number of symbols from the val[] array, without risking marching off
534 * the end of memory. jchuff.c will do a more thorough test later.
537 for (len = 1; len <= 16; len++)
538 nsymbols += bits[len];
539 if (nsymbols < 1 || nsymbols > 256)
540 g_error ("jpegutils.c: add_huff_table failed badly. ");
542 memcpy ((*htblptr)->huffval, val, nsymbols * sizeof (UINT8));
548 std_huff_tables (j_decompress_ptr dinfo)
549 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
550 /* IMPORTANT: these are only valid for 8-bit data precision! */
552 static const UINT8 bits_dc_luminance[17] =
553 { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
554 static const UINT8 val_dc_luminance[] =
555 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
557 static const UINT8 bits_dc_chrominance[17] =
558 { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
559 static const UINT8 val_dc_chrominance[] =
560 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
562 static const UINT8 bits_ac_luminance[17] =
563 { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
564 static const UINT8 val_ac_luminance[] =
565 { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
566 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
567 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
568 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
569 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
570 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
571 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
572 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
573 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
574 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
575 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
576 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
577 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
578 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
579 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
580 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
581 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
582 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
583 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
584 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
588 static const UINT8 bits_ac_chrominance[17] =
589 { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
590 static const UINT8 val_ac_chrominance[] =
591 { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
592 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
593 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
594 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
595 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
596 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
597 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
598 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
599 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
600 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
601 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
602 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
603 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
604 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
605 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
606 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
607 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
608 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
609 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
610 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
614 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[0],
615 bits_dc_luminance, val_dc_luminance);
616 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[0],
617 bits_ac_luminance, val_ac_luminance);
618 add_huff_table (dinfo, &dinfo->dc_huff_tbl_ptrs[1],
619 bits_dc_chrominance, val_dc_chrominance);
620 add_huff_table (dinfo, &dinfo->ac_huff_tbl_ptrs[1],
621 bits_ac_chrominance, val_ac_chrominance);
627 guarantee_huff_tables (j_decompress_ptr dinfo)
629 if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
630 (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
631 (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
632 (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
633 GST_DEBUG ("Generating standard Huffman tables for this frame.");
634 std_huff_tables (dinfo);
639 gst_jpeg_dec_setcaps (GstPad * pad, GstCaps * caps)
643 const GValue *framerate;
645 dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
646 s = gst_caps_get_structure (caps, 0);
648 if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
649 dec->framerate_numerator = gst_value_get_fraction_numerator (framerate);
650 dec->framerate_denominator = gst_value_get_fraction_denominator (framerate);
651 dec->packetized = TRUE;
652 GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
653 dec->framerate_numerator, dec->framerate_denominator);
656 /* do not extract width/height here. we do that in the chain
657 * function on a per-frame basis (including the line[] array
660 /* But we can take the framerate values and set them on the src pad */
667 hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
671 for (i = 0; i < len; ++i) {
672 /* equivalent to: dest[i] = src[i << 1] */
681 gst_jpeg_dec_free_buffers (GstJpegDec * dec)
685 for (i = 0; i < 16; i++) {
686 g_free (dec->idr_y[i]);
687 g_free (dec->idr_u[i]);
688 g_free (dec->idr_v[i]);
689 dec->idr_y[i] = NULL;
690 dec->idr_u[i] = NULL;
691 dec->idr_v[i] = NULL;
694 dec->idr_width_allocated = 0;
697 static inline gboolean
698 gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
702 if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
705 /* FIXME: maybe just alloc one or three blocks altogether? */
706 for (i = 0; i < 16; i++) {
707 dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
708 dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
709 dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
711 if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
712 GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
717 dec->idr_width_allocated = maxrowbytes;
718 GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
723 gst_jpeg_dec_decode_rgb (GstJpegDec * dec, guchar * base[3],
724 guint width, guint height, guint pstride, guint rstride)
726 guchar *r_rows[16], *g_rows[16], *b_rows[16];
727 guchar **scanarray[3] = { r_rows, g_rows, b_rows };
731 GST_DEBUG_OBJECT (dec, "indirect decoding of RGB");
733 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
736 memcpy (r_rows, dec->idr_y, 16 * sizeof (gpointer));
737 memcpy (g_rows, dec->idr_u, 16 * sizeof (gpointer));
738 memcpy (b_rows, dec->idr_v, 16 * sizeof (gpointer));
742 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, DCTSIZE);
743 if (G_LIKELY (lines > 0)) {
744 for (j = 0; (j < DCTSIZE) && (i < height); j++, i++) {
748 for (k = 0; k < width; k++) {
749 base[0][p] = r_rows[j][k];
750 base[1][p] = g_rows[j][k];
751 base[2][p] = b_rows[j][k];
759 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
765 gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
766 guchar * last[3], guint width, guint height, gint r_v, gint r_h, gint comp)
768 guchar *y_rows[16], *u_rows[16], *v_rows[16];
769 guchar **scanarray[3] = { y_rows, u_rows, v_rows };
773 GST_DEBUG_OBJECT (dec,
774 "unadvantageous width or r_h, taking slow route involving memcpy");
776 if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
779 memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
780 memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
781 memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
783 /* fill chroma components for grayscale */
785 GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
786 for (i = 0; i < 16; i++) {
787 memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
788 memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
792 for (i = 0; i < height; i += r_v * DCTSIZE) {
793 lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
794 if (G_LIKELY (lines > 0)) {
795 for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
796 memcpy (base[0], y_rows[j], I420_Y_ROWSTRIDE (width));
797 if (G_LIKELY (base[0] < last[0]))
798 base[0] += I420_Y_ROWSTRIDE (width);
800 memcpy (base[0], y_rows[j + 1], I420_Y_ROWSTRIDE (width));
801 if (G_LIKELY (base[0] < last[0]))
802 base[0] += I420_Y_ROWSTRIDE (width);
805 memcpy (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
806 memcpy (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
807 } else if (r_h == 1) {
808 hresamplecpy1 (base[1], u_rows[k], I420_U_ROWSTRIDE (width));
809 hresamplecpy1 (base[2], v_rows[k], I420_V_ROWSTRIDE (width));
811 /* FIXME: implement (at least we avoid crashing by doing nothing) */
814 if (r_v == 2 || (k & 1) != 0) {
815 if (G_LIKELY (base[1] < last[1] && base[2] < last[2])) {
816 base[1] += I420_U_ROWSTRIDE (width);
817 base[2] += I420_V_ROWSTRIDE (width);
822 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
827 #ifndef GST_DISABLE_GST_DEBUG
829 dump_lines (guchar * base[3], guchar ** line[3], int v_samp0, int width)
833 for (j = 0; j < (v_samp0 * DCTSIZE); ++j) {
834 GST_LOG ("[%02d] %5d %5d %5d", j,
835 (line[0][j] >= base[0]) ?
836 (int) (line[0][j] - base[0]) / I420_Y_ROWSTRIDE (width) : -1,
837 (line[1][j] >= base[1]) ?
838 (int) (line[1][j] - base[1]) / I420_U_ROWSTRIDE (width) : -1,
839 (line[2][j] >= base[2]) ?
840 (int) (line[2][j] - base[2]) / I420_V_ROWSTRIDE (width) : -1);
846 gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
847 guchar * last[3], guint width, guint height)
849 guchar **line[3]; /* the jpeg line buffer */
850 guchar *y[4 * DCTSIZE] = { NULL, }; /* alloc enough for the lines */
851 guchar *u[4 * DCTSIZE] = { NULL, }; /* r_v will be <4 */
852 guchar *v[4 * DCTSIZE] = { NULL, };
854 gint lines, v_samp[3];
860 v_samp[0] = dec->cinfo.comp_info[0].v_samp_factor;
861 v_samp[1] = dec->cinfo.comp_info[1].v_samp_factor;
862 v_samp[2] = dec->cinfo.comp_info[2].v_samp_factor;
864 if (G_UNLIKELY (v_samp[0] > 2 || v_samp[1] > 2 || v_samp[2] > 2))
865 goto format_not_supported;
867 /* let jpeglib decode directly into our final buffer */
868 GST_DEBUG_OBJECT (dec, "decoding directly into output buffer");
870 for (i = 0; i < height; i += v_samp[0] * DCTSIZE) {
871 for (j = 0; j < (v_samp[0] * DCTSIZE); ++j) {
873 line[0][j] = base[0] + (i + j) * I420_Y_ROWSTRIDE (width);
874 if (G_UNLIKELY (line[0][j] > last[0]))
875 line[0][j] = last[0];
877 if (v_samp[1] == v_samp[0]) {
878 line[1][j] = base[1] + ((i + j) / 2) * I420_U_ROWSTRIDE (width);
879 } else if (j < (v_samp[1] * DCTSIZE)) {
880 line[1][j] = base[1] + ((i / 2) + j) * I420_U_ROWSTRIDE (width);
882 if (G_UNLIKELY (line[1][j] > last[1]))
883 line[1][j] = last[1];
885 if (v_samp[2] == v_samp[0]) {
886 line[2][j] = base[2] + ((i + j) / 2) * I420_V_ROWSTRIDE (width);
887 } else if (j < (v_samp[2] * DCTSIZE)) {
888 line[2][j] = base[2] + ((i / 2) + j) * I420_V_ROWSTRIDE (width);
890 if (G_UNLIKELY (line[2][j] > last[2]))
891 line[2][j] = last[2];
894 /* dump_lines (base, line, v_samp[0], width); */
896 lines = jpeg_read_raw_data (&dec->cinfo, line, v_samp[0] * DCTSIZE);
897 if (G_UNLIKELY (!lines)) {
898 GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
903 format_not_supported:
905 GST_ELEMENT_ERROR (dec, STREAM, DECODE,
906 (_("Failed to decode JPEG image")),
907 ("Unsupported subsampling schema: v_samp factors: %u %u %u",
908 v_samp[0], v_samp[1], v_samp[2]));
909 return GST_FLOW_ERROR;
914 gst_jpeg_dec_update_qos (GstJpegDec * dec, gdouble proportion,
915 GstClockTimeDiff diff, GstClockTime ts)
917 GST_OBJECT_LOCK (dec);
918 dec->proportion = proportion;
919 if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
920 if (G_UNLIKELY (diff > 0))
921 dec->earliest_time = ts + 2 * diff + dec->qos_duration;
923 dec->earliest_time = ts + diff;
925 dec->earliest_time = GST_CLOCK_TIME_NONE;
927 GST_OBJECT_UNLOCK (dec);
931 gst_jpeg_dec_reset_qos (GstJpegDec * dec)
933 gst_jpeg_dec_update_qos (dec, 0.5, 0, GST_CLOCK_TIME_NONE);
937 gst_jpeg_dec_read_qos (GstJpegDec * dec, gdouble * proportion,
940 GST_OBJECT_LOCK (dec);
941 *proportion = dec->proportion;
942 *time = dec->earliest_time;
943 GST_OBJECT_UNLOCK (dec);
946 /* Perform qos calculations before decoding the next frame. Returns TRUE if the
947 * frame should be decoded, FALSE if the frame can be dropped entirely */
949 gst_jpeg_dec_do_qos (GstJpegDec * dec, GstClockTime timestamp)
951 GstClockTime qostime, earliest_time;
954 /* no timestamp, can't do QoS => decode frame */
955 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
956 GST_LOG_OBJECT (dec, "invalid timestamp, can't do QoS, decode frame");
960 /* get latest QoS observation values */
961 gst_jpeg_dec_read_qos (dec, &proportion, &earliest_time);
963 /* skip qos if we have no observation (yet) => decode frame */
964 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
965 GST_LOG_OBJECT (dec, "no observation yet, decode frame");
969 /* qos is done on running time */
970 qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
973 /* see how our next timestamp relates to the latest qos timestamp */
974 GST_LOG_OBJECT (dec, "qostime %" GST_TIME_FORMAT ", earliest %"
975 GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
977 if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
978 GST_DEBUG_OBJECT (dec, "we are late, drop frame");
982 GST_LOG_OBJECT (dec, "decode frame");
987 gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc)
990 GstVideoFormat format;
992 if (G_UNLIKELY (width == dec->caps_width && height == dec->caps_height &&
993 dec->framerate_numerator == dec->caps_framerate_numerator &&
994 dec->framerate_denominator == dec->caps_framerate_denominator &&
995 clrspc == dec->clrspc))
998 /* framerate == 0/1 is a still frame */
999 if (dec->framerate_denominator == 0) {
1000 dec->framerate_numerator = 0;
1001 dec->framerate_denominator = 1;
1004 /* calculate or assume an average frame duration for QoS purposes */
1005 GST_OBJECT_LOCK (dec);
1006 if (dec->framerate_numerator != 0) {
1007 dec->qos_duration = gst_util_uint64_scale (GST_SECOND,
1008 dec->framerate_denominator, dec->framerate_numerator);
1010 /* if not set just use 25fps */
1011 dec->qos_duration = gst_util_uint64_scale (GST_SECOND, 1, 25);
1013 GST_OBJECT_UNLOCK (dec);
1015 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1017 GstCaps *allowed_caps;
1019 GST_DEBUG_OBJECT (dec, "selecting RGB format");
1020 /* retrieve allowed caps, and find the first one that reasonably maps
1021 * to the parameters of the colourspace */
1022 caps = gst_pad_get_allowed_caps (dec->srcpad);
1024 GST_DEBUG_OBJECT (dec, "... but no peer, using template caps");
1025 /* need to copy because get_allowed_caps returns a ref,
1026 * and get_pad_template_caps doesn't */
1027 caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad));
1029 /* avoid lists of fourcc, etc */
1030 allowed_caps = gst_caps_normalize (caps);
1031 gst_caps_unref (caps);
1033 GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps);
1035 for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1037 gst_caps_unref (caps);
1038 caps = gst_caps_copy_nth (allowed_caps, i);
1039 /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */
1040 gst_pad_fixate_caps (dec->srcpad, caps);
1041 GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps);
1042 if (!gst_video_format_parse_caps (caps, &format, NULL, NULL))
1044 /* we'll settle for the first (preferred) downstream rgb format */
1045 if (gst_video_format_is_rgb (format))
1047 /* default fall-back */
1048 format = GST_VIDEO_FORMAT_RGB;
1051 gst_caps_unref (caps);
1052 gst_caps_unref (allowed_caps);
1053 caps = gst_video_format_new_caps (format, width, height,
1054 dec->framerate_numerator, dec->framerate_denominator, 1, 1);
1055 dec->outsize = gst_video_format_get_size (format, width, height);
1056 /* some format info */
1058 gst_video_format_get_component_offset (format, 0, width, height);
1060 gst_video_format_get_component_offset (format, 1, width, height);
1062 gst_video_format_get_component_offset (format, 2, width, height);
1063 /* equal for all components */
1064 dec->stride = gst_video_format_get_row_stride (format, 0, width);
1065 dec->inc = gst_video_format_get_pixel_stride (format, 0);
1067 /* go for plain and simple I420 */
1068 /* TODO other YUV cases ? */
1069 caps = gst_caps_new_simple ("video/x-raw-yuv",
1070 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
1071 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
1072 "framerate", GST_TYPE_FRACTION, dec->framerate_numerator,
1073 dec->framerate_denominator, NULL);
1074 dec->outsize = I420_SIZE (width, height);
1077 GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
1078 GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
1079 GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor);
1081 gst_pad_set_caps (dec->srcpad, caps);
1082 gst_caps_unref (caps);
1084 dec->caps_width = width;
1085 dec->caps_height = height;
1086 dec->caps_framerate_numerator = dec->framerate_numerator;
1087 dec->caps_framerate_denominator = dec->framerate_denominator;
1090 static GstFlowReturn
1091 gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
1093 GstFlowReturn ret = GST_FLOW_OK;
1095 GstBuffer *outbuf = NULL;
1096 guchar *data, *outdata;
1097 guchar *base[3], *last[3];
1098 guint img_len, outsize;
1102 GstClockTime timestamp, duration;
1104 dec = GST_JPEG_DEC (GST_PAD_PARENT (pad));
1106 timestamp = GST_BUFFER_TIMESTAMP (buf);
1107 duration = GST_BUFFER_DURATION (buf);
1109 if (GST_CLOCK_TIME_IS_VALID (timestamp))
1110 dec->next_ts = timestamp;
1112 if (GST_BUFFER_IS_DISCONT (buf)) {
1113 GST_DEBUG_OBJECT (dec, "buffer has DISCONT flag set");
1114 dec->discont = TRUE;
1115 if (!dec->packetized && dec->tempbuf != NULL) {
1116 GST_WARNING_OBJECT (dec, "DISCONT buffer in non-packetized mode, bad");
1117 gst_buffer_replace (&dec->tempbuf, NULL);
1122 dec->tempbuf = gst_buffer_join (dec->tempbuf, buf);
1128 /* If we are non-packetized and know the total incoming size in bytes,
1129 * just wait until we have enough before doing any processing. */
1131 if (!dec->packetized && (dec->segment.format == GST_FORMAT_BYTES) &&
1132 (dec->segment.stop != -1) &&
1133 (GST_BUFFER_SIZE (dec->tempbuf) < dec->segment.stop)) {
1134 /* We assume that non-packetized input in bytes is *one* single jpeg image */
1135 GST_DEBUG ("Non-packetized mode. Got %d bytes, need %" G_GINT64_FORMAT,
1136 GST_BUFFER_SIZE (dec->tempbuf), dec->segment.stop);
1137 goto need_more_data;
1140 if (!gst_jpeg_dec_ensure_header (dec))
1141 goto need_more_data;
1143 /* If we know that each input buffer contains data
1144 * for a whole jpeg image (e.g. MJPEG streams), just
1145 * do some sanity checking instead of parsing all of
1147 if (dec->packetized) {
1148 img_len = GST_BUFFER_SIZE (dec->tempbuf);
1150 /* Parse jpeg image to handle jpeg input that
1151 * is not aligned to buffer boundaries */
1152 img_len = gst_jpeg_dec_parse_image_data (dec);
1155 goto need_more_data;
1158 /* QoS: if we're too late anyway, skip decoding */
1159 if (dec->packetized && !gst_jpeg_dec_do_qos (dec, timestamp))
1162 data = (guchar *) GST_BUFFER_DATA (dec->tempbuf);
1163 GST_LOG_OBJECT (dec, "image size = %u", img_len);
1165 dec->jsrc.pub.next_input_byte = data;
1166 dec->jsrc.pub.bytes_in_buffer = img_len;
1168 if (setjmp (dec->jerr.setjmp_buffer)) {
1169 code = dec->jerr.pub.msg_code;
1171 if (code == JERR_INPUT_EOF) {
1172 GST_DEBUG ("jpeg input EOF error, we probably need more data");
1173 goto need_more_data;
1178 GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
1182 hdr_ok = jpeg_read_header (&dec->cinfo, TRUE);
1183 if (G_UNLIKELY (hdr_ok != JPEG_HEADER_OK)) {
1184 GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
1187 r_h = dec->cinfo.comp_info[0].h_samp_factor;
1188 r_v = dec->cinfo.comp_info[0].v_samp_factor;
1190 GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
1191 GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
1192 GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
1194 if (dec->cinfo.num_components > 3)
1195 goto components_not_supported;
1197 /* verify color space expectation to avoid going *boom* or bogus output */
1198 if (dec->cinfo.jpeg_color_space != JCS_YCbCr &&
1199 dec->cinfo.jpeg_color_space != JCS_GRAYSCALE &&
1200 dec->cinfo.jpeg_color_space != JCS_RGB)
1201 goto unsupported_colorspace;
1203 #ifndef GST_DISABLE_GST_DEBUG
1207 for (i = 0; i < dec->cinfo.num_components; ++i) {
1208 GST_LOG_OBJECT (dec, "[%d] h_samp_factor=%d, v_samp_factor=%d, cid=%d",
1209 i, dec->cinfo.comp_info[i].h_samp_factor,
1210 dec->cinfo.comp_info[i].v_samp_factor,
1211 dec->cinfo.comp_info[i].component_id);
1216 /* prepare for raw output */
1217 dec->cinfo.do_fancy_upsampling = FALSE;
1218 dec->cinfo.do_block_smoothing = FALSE;
1219 dec->cinfo.out_color_space = dec->cinfo.jpeg_color_space;
1220 dec->cinfo.dct_method = dec->idct_method;
1221 dec->cinfo.raw_data_out = TRUE;
1223 GST_LOG_OBJECT (dec, "starting decompress");
1224 guarantee_huff_tables (&dec->cinfo);
1225 if (!jpeg_start_decompress (&dec->cinfo)) {
1226 GST_WARNING_OBJECT (dec, "failed to start decompression cycle");
1229 /* sanity checks to get safe and reasonable output */
1230 switch (dec->cinfo.jpeg_color_space) {
1234 if (dec->cinfo.num_components != 3 || dec->cinfo.max_v_samp_factor > 1 ||
1235 dec->cinfo.max_h_samp_factor > 1)
1236 goto invalid_yuvrgb;
1239 if (dec->cinfo.num_components != 3 ||
1240 r_v > 2 || r_v < dec->cinfo.comp_info[0].v_samp_factor ||
1241 r_v < dec->cinfo.comp_info[1].v_samp_factor ||
1242 r_h < dec->cinfo.comp_info[0].h_samp_factor ||
1243 r_h < dec->cinfo.comp_info[1].h_samp_factor)
1244 goto invalid_yuvrgb;
1247 g_assert_not_reached ();
1251 width = dec->cinfo.output_width;
1252 height = dec->cinfo.output_height;
1254 if (G_UNLIKELY (width < MIN_WIDTH || width > MAX_WIDTH ||
1255 height < MIN_HEIGHT || height > MAX_HEIGHT))
1258 gst_jpeg_dec_negotiate (dec, width, height, dec->cinfo.jpeg_color_space);
1260 ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
1261 dec->outsize, GST_PAD_CAPS (dec->srcpad), &outbuf);
1262 if (G_UNLIKELY (ret != GST_FLOW_OK))
1265 outdata = GST_BUFFER_DATA (outbuf);
1266 outsize = GST_BUFFER_SIZE (outbuf);
1268 GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
1269 width, height, outsize, dec->outsize);
1271 GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
1273 if (dec->packetized && GST_CLOCK_TIME_IS_VALID (dec->next_ts)) {
1274 if (GST_CLOCK_TIME_IS_VALID (duration)) {
1275 /* use duration from incoming buffer for outgoing buffer */
1276 dec->next_ts += duration;
1277 } else if (dec->framerate_numerator != 0) {
1278 duration = gst_util_uint64_scale (GST_SECOND,
1279 dec->framerate_denominator, dec->framerate_numerator);
1280 dec->next_ts += duration;
1282 duration = GST_CLOCK_TIME_NONE;
1283 dec->next_ts = GST_CLOCK_TIME_NONE;
1286 duration = GST_CLOCK_TIME_NONE;
1287 dec->next_ts = GST_CLOCK_TIME_NONE;
1289 GST_BUFFER_DURATION (outbuf) = duration;
1291 if (dec->cinfo.jpeg_color_space == JCS_RGB) {
1292 base[0] = outdata + dec->offset[0];
1293 base[1] = outdata + dec->offset[1];
1294 base[2] = outdata + dec->offset[2];
1295 gst_jpeg_dec_decode_rgb (dec, base, width, height, dec->inc, dec->stride);
1297 /* mind the swap, jpeglib outputs blue chroma first
1298 * ensonic: I see no swap?
1300 base[0] = outdata + I420_Y_OFFSET (width, height);
1301 base[1] = outdata + I420_U_OFFSET (width, height);
1302 base[2] = outdata + I420_V_OFFSET (width, height);
1304 /* make sure we don't make jpeglib write beyond our buffer,
1305 * which might happen if (height % (r_v*DCTSIZE)) != 0 */
1306 last[0] = base[0] + (I420_Y_ROWSTRIDE (width) * (height - 1));
1308 base[1] + (I420_U_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1311 base[2] + (I420_V_ROWSTRIDE (width) * ((GST_ROUND_UP_2 (height) / 2) -
1314 GST_LOG_OBJECT (dec, "decompressing (reqired scanline buffer height = %u)",
1315 dec->cinfo.rec_outbuf_height);
1317 /* For some widths jpeglib requires more horizontal padding than I420
1318 * provides. In those cases we need to decode into separate buffers and then
1319 * copy over the data into our final picture buffer, otherwise jpeglib might
1320 * write over the end of a line into the beginning of the next line,
1321 * resulting in blocky artifacts on the left side of the picture. */
1322 if (G_UNLIKELY (width % (dec->cinfo.max_h_samp_factor * DCTSIZE) != 0
1323 || dec->cinfo.comp_info[0].h_samp_factor != 2
1324 || dec->cinfo.comp_info[1].h_samp_factor != 1
1325 || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
1326 GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, dec,
1327 "indirect decoding using extra buffer copy");
1328 gst_jpeg_dec_decode_indirect (dec, base, last, width, height, r_v, r_h,
1329 dec->cinfo.num_components);
1331 ret = gst_jpeg_dec_decode_direct (dec, base, last, width, height);
1333 if (G_UNLIKELY (ret != GST_FLOW_OK))
1334 goto decode_direct_failed;
1338 GST_LOG_OBJECT (dec, "decompressing finished");
1339 jpeg_finish_decompress (&dec->cinfo);
1342 if (dec->segment.format == GST_FORMAT_TIME) {
1343 gint64 start, stop, clip_start, clip_stop;
1345 GST_LOG_OBJECT (dec, "Attempting clipping");
1347 start = GST_BUFFER_TIMESTAMP (outbuf);
1348 if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
1351 stop = start + GST_BUFFER_DURATION (outbuf);
1353 if (gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
1354 start, stop, &clip_start, &clip_stop)) {
1355 GST_LOG_OBJECT (dec, "Clipping start to %" GST_TIME_FORMAT,
1356 GST_TIME_ARGS (clip_start));
1357 GST_BUFFER_TIMESTAMP (outbuf) = clip_start;
1358 if (GST_BUFFER_DURATION (outbuf) != GST_CLOCK_TIME_NONE) {
1359 GST_LOG_OBJECT (dec, "Clipping duration to %" GST_TIME_FORMAT,
1360 GST_TIME_ARGS (clip_stop - clip_start));
1361 GST_BUFFER_DURATION (outbuf) = clip_stop - clip_start;
1367 GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
1368 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1369 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1371 ret = gst_pad_push (dec->srcpad, outbuf);
1375 if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) {
1376 gst_buffer_unref (dec->tempbuf);
1377 dec->tempbuf = NULL;
1379 GstBuffer *buf = gst_buffer_create_sub (dec->tempbuf, img_len,
1380 GST_BUFFER_SIZE (dec->tempbuf) - img_len);
1382 gst_buffer_unref (dec->tempbuf);
1393 GST_LOG_OBJECT (dec, "we need more data");
1395 gst_buffer_unref (outbuf);
1404 GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1405 ("Picture is too small or too big (%ux%u)", width, height),
1406 ("Picture is too small or too big (%ux%u)", width, height));
1407 ret = GST_FLOW_ERROR;
1412 gchar err_msg[JMSG_LENGTH_MAX];
1414 dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
1416 GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1417 (_("Failed to decode JPEG image")), ("Error #%u: %s", code, err_msg));
1419 gst_buffer_unref (outbuf);
1422 ret = GST_FLOW_ERROR;
1425 decode_direct_failed:
1427 /* already posted an error message */
1428 jpeg_abort_decompress (&dec->cinfo);
1429 gst_buffer_replace (&outbuf, NULL);
1434 const gchar *reason;
1436 reason = gst_flow_get_name (ret);
1438 GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
1439 /* Reset for next time */
1440 jpeg_abort_decompress (&dec->cinfo);
1441 if (GST_FLOW_IS_FATAL (ret)) {
1442 GST_ELEMENT_ERROR (dec, STREAM, DECODE,
1443 ("Buffer allocation failed, reason: %s", reason),
1444 ("Buffer allocation failed, reason: %s", reason));
1450 GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
1451 gst_buffer_unref (outbuf);
1455 components_not_supported:
1457 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1458 ("more components than supported: %d > 3", dec->cinfo.num_components));
1459 ret = GST_FLOW_ERROR;
1462 unsupported_colorspace:
1464 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1465 ("Picture has unknown or unsupported colourspace"));
1466 ret = GST_FLOW_ERROR;
1471 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1472 ("Picture is corrupt or unhandled YUV/RGB layout"));
1473 ret = GST_FLOW_ERROR;
1479 gst_jpeg_dec_src_event (GstPad * pad, GstEvent * event)
1484 dec = GST_JPEG_DEC (gst_pad_get_parent (pad));
1486 switch (GST_EVENT_TYPE (event)) {
1487 case GST_EVENT_QOS:{
1488 GstClockTimeDiff diff;
1489 GstClockTime timestamp;
1492 gst_event_parse_qos (event, &proportion, &diff, ×tamp);
1493 gst_jpeg_dec_update_qos (dec, proportion, diff, timestamp);
1500 res = gst_pad_push_event (dec->sinkpad, event);
1502 gst_object_unref (dec);
1507 gst_jpeg_dec_sink_event (GstPad * pad, GstEvent * event)
1509 gboolean ret = TRUE;
1510 GstJpegDec *dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
1512 GST_DEBUG_OBJECT (dec, "event : %s", GST_EVENT_TYPE_NAME (event));
1514 switch (GST_EVENT_TYPE (event)) {
1515 case GST_EVENT_FLUSH_STOP:
1516 GST_DEBUG_OBJECT (dec, "Aborting decompress");
1517 jpeg_abort_decompress (&dec->cinfo);
1518 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1519 gst_jpeg_dec_reset_qos (dec);
1521 case GST_EVENT_NEWSEGMENT:{
1523 gdouble rate, applied_rate;
1525 gint64 start, stop, position;
1527 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1528 &format, &start, &stop, &position);
1530 GST_DEBUG_OBJECT (dec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
1531 " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
1532 GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
1533 GST_TIME_ARGS (position));
1535 gst_segment_set_newsegment_full (&dec->segment, update, rate,
1536 applied_rate, format, start, stop, position);
1544 ret = gst_pad_push_event (dec->srcpad, event);
1550 gst_jpeg_dec_set_property (GObject * object, guint prop_id,
1551 const GValue * value, GParamSpec * pspec)
1555 dec = GST_JPEG_DEC (object);
1558 case PROP_IDCT_METHOD:
1559 dec->idct_method = g_value_get_enum (value);
1563 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1569 gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
1574 dec = GST_JPEG_DEC (object);
1577 case PROP_IDCT_METHOD:
1578 g_value_set_enum (value, dec->idct_method);
1582 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1587 static GstStateChangeReturn
1588 gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
1590 GstStateChangeReturn ret;
1593 dec = GST_JPEG_DEC (element);
1595 switch (transition) {
1596 case GST_STATE_CHANGE_READY_TO_PAUSED:
1597 dec->framerate_numerator = 0;
1598 dec->framerate_denominator = 1;
1599 dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
1600 dec->caps_width = -1;
1601 dec->caps_height = -1;
1603 dec->packetized = FALSE;
1605 dec->discont = TRUE;
1606 gst_segment_init (&dec->segment, GST_FORMAT_UNDEFINED);
1607 gst_jpeg_dec_reset_qos (dec);
1612 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1613 if (ret != GST_STATE_CHANGE_SUCCESS)
1616 switch (transition) {
1617 case GST_STATE_CHANGE_PAUSED_TO_READY:
1619 gst_buffer_unref (dec->tempbuf);
1620 dec->tempbuf = NULL;
1622 gst_jpeg_dec_free_buffers (dec);