From 0ade1a58227a383985a431250589aca1b377e676 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 18 Oct 2011 11:58:57 +0200 Subject: [PATCH 01/16] pulsesink: only disable trickmodes for !pcm Only disable trickmodes when we are not dealing with raw PCM samples. --- ext/pulse/pulsesink.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c index 33dd6763ea..fdcb5c5efa 100644 --- a/ext/pulse/pulsesink.c +++ b/ext/pulse/pulsesink.c @@ -145,6 +145,7 @@ struct _GstPulseRingBuffer #else pa_sample_spec sample_spec; #endif + gboolean is_pcm; void *m_data; size_t m_towrite; @@ -234,6 +235,7 @@ gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf) #else pa_sample_spec_init (&pbuf->sample_spec); #endif + pbuf->is_pcm = FALSE; pbuf->m_data = NULL; pbuf->m_towrite = 0; @@ -267,6 +269,7 @@ gst_pulsering_destroy_stream (GstPulseRingBuffer * pbuf) pa_format_info_free (pbuf->format); pbuf->format = NULL; pbuf->channels = 0; + pbuf->is_pcm = FALSE; } #endif @@ -421,7 +424,7 @@ gst_pulsering_context_subscribe_cb (pa_context * c, continue; #ifdef HAVE_PULSE_1_0 - if (psink->device && pa_format_info_is_pcm (pbuf->format) && + if (psink->device && pbuf->is_pcm && !g_str_equal (psink->device, pa_stream_get_device_name (pbuf->stream))) { /* Underlying sink changed. And this is not a passthrough stream. Let's @@ -821,9 +824,11 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) #ifdef HAVE_PULSE_1_0 if (!gst_pulse_fill_format_info (spec, &pbuf->format, &pbuf->channels)) goto invalid_spec; + pbuf->is_pcm = pa_format_info_is_pcm (pbuf->format); #else if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec)) goto invalid_spec; + pbuf->is_pcm = TRUE; #endif pa_threaded_mainloop_lock (mainloop); @@ -842,8 +847,7 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) /* initialize the channel map */ #ifdef HAVE_PULSE_1_0 - if (pa_format_info_is_pcm (pbuf->format) && - gst_pulse_gst_to_channel_map (&channel_map, spec)) + if (pbuf->is_pcm && gst_pulse_gst_to_channel_map (&channel_map, spec)) pa_format_info_set_channel_map (pbuf->format, &channel_map); #else gst_pulse_gst_to_channel_map (&channel_map, spec); @@ -905,7 +909,7 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) GST_LOG_OBJECT (psink, "have volume of %f", psink->volume); pv = &v; #ifdef HAVE_PULSE_1_0 - if (pa_format_info_is_pcm (pbuf->format)) + if (pbuf->is_pcm) gst_pulse_cvolume_from_linear (pv, pbuf->channels, psink->volume); else { GST_DEBUG_OBJECT (psink, "passthrough stream, not setting volume"); @@ -1168,8 +1172,8 @@ gst_pulseringbuffer_start (GstRingBuffer * buf) /* EOS needs running clock */ if (GST_BASE_SINK_CAST (psink)->eos || - g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata.ABI. - eos_rendering)) + g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata. + ABI.eos_rendering)) gst_pulsering_set_corked (pbuf, FALSE, FALSE); pa_threaded_mainloop_unlock (mainloop); @@ -1536,7 +1540,7 @@ gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample, #ifdef HAVE_PULSE_1_0 /* No trick modes for passthrough streams */ - if (G_UNLIKELY (inr != outr || reverse)) { + if (G_UNLIKELY (!pbuf->is_pcm && (inr != outr || reverse))) { GST_WARNING_OBJECT (psink, "Passthrough stream can't run in trick mode"); goto unlock_and_fail; } @@ -2281,7 +2285,7 @@ gst_pulsesink_set_volume (GstPulseSink * psink, gdouble volume) goto no_index; #ifdef HAVE_PULSE_1_0 - if (pa_format_info_is_pcm (pbuf->format)) + if (pbuf->is_pcm) gst_pulse_cvolume_from_linear (&v, pbuf->channels, volume); else /* FIXME: this will eventually be superceded by checks to see if the volume From 6de67bb0143ea2e9ae0abe907acdb38e5c239bef Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 18 Oct 2011 12:05:01 +0200 Subject: [PATCH 02/16] pulsesink: only use is_pcm for 1.0 of pulseaudio --- ext/pulse/pulsesink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c index fdcb5c5efa..ca769787c5 100644 --- a/ext/pulse/pulsesink.c +++ b/ext/pulse/pulsesink.c @@ -142,10 +142,10 @@ struct _GstPulseRingBuffer #ifdef HAVE_PULSE_1_0 pa_format_info *format; guint channels; + gboolean is_pcm; #else pa_sample_spec sample_spec; #endif - gboolean is_pcm; void *m_data; size_t m_towrite; @@ -232,10 +232,10 @@ gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf) #ifdef HAVE_PULSE_1_0 pbuf->format = NULL; pbuf->channels = 0; + pbuf->is_pcm = FALSE; #else pa_sample_spec_init (&pbuf->sample_spec); #endif - pbuf->is_pcm = FALSE; pbuf->m_data = NULL; pbuf->m_towrite = 0; @@ -828,7 +828,6 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) #else if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec)) goto invalid_spec; - pbuf->is_pcm = TRUE; #endif pa_threaded_mainloop_lock (mainloop); From e9ad06e20225d98f75959708b851e855a4ef271d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 18 Oct 2011 12:25:14 +0100 Subject: [PATCH 03/16] wavpackenc: don't unref buffer with gst_object_unref() --- ext/wavpack/gstwavpackenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/wavpack/gstwavpackenc.c b/ext/wavpack/gstwavpackenc.c index aa085fc0b8..91af97c1e3 100644 --- a/ext/wavpack/gstwavpackenc.c +++ b/ext/wavpack/gstwavpackenc.c @@ -858,7 +858,7 @@ gst_wavpack_enc_sink_event (GstPad * pad, GstEvent * event) /* Drop all remaining data, this is no complete block otherwise * it would've been pushed already */ if (enc->pending_buffer) { - gst_object_unref (enc->pending_buffer); + gst_buffer_unref (enc->pending_buffer); enc->pending_buffer = NULL; enc->pending_offset = 0; } From a7790efd04c463fe20a1d829d140cf3b40af8548 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Tue, 18 Oct 2011 18:31:17 +0530 Subject: [PATCH 04/16] pulse: Get caps correctly on pad block Instead of always going upstream, we should first see if already got caps from a setcaps() call. https://bugzilla.gnome.org/show_bug.cgi?id=661262 --- ext/pulse/pulseaudiosink.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/pulse/pulseaudiosink.c b/ext/pulse/pulseaudiosink.c index b7e1a07254..bfd54836cf 100644 --- a/ext/pulse/pulseaudiosink.c +++ b/ext/pulse/pulseaudiosink.c @@ -653,7 +653,14 @@ proxypad_blocked_cb (GstPad * pad, gboolean blocked, gpointer data) if (!pbin->format_lost) { sinkpad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink), "sink"); - caps = gst_pad_get_caps_reffed (pad); + + if (GST_PAD_CAPS (pbin->sinkpad)) { + /* See if we already got caps on our sinkpad */ + caps = gst_caps_ref (GST_PAD_CAPS (pbin->sinkpad)); + } else { + /* We haven't, so get caps from upstream */ + caps = gst_pad_get_caps_reffed (pad); + } if (gst_pad_accept_caps (sinkpad, caps)) { if (pbin->dbin2) { From 4b5f8ff8d1692709691ef24373b77ce785e1a8a4 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 19 Oct 2011 13:09:51 +0200 Subject: [PATCH 05/16] ebml: Fix push-based behaviour The 'peek' method was completely wrong (!?) --- gst/matroska/matroska-read-common.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index 672dcc3fc6..276fa85d4a 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -1547,11 +1547,15 @@ gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common, return ret; } -static const guint8 * +static GstFlowReturn gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint - peek) + peek, const guint8 ** data) { - return gst_adapter_peek (common->adapter, peek); + *data = gst_adapter_peek (common->adapter, peek); + if (*data == NULL) + return GST_FLOW_ERROR; + + return GST_FLOW_OK; } /* From 5baca05ec38e507352a178b5faf4eed1d85e1479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Fri, 21 Oct 2011 10:01:43 +0200 Subject: [PATCH 06/16] ebml: small correction to previous commit Signal a short read with UNEXPECTED, exactly like the peek_bytes function. --- gst/matroska/matroska-read-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index 276fa85d4a..5fd178fe38 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -1553,7 +1553,7 @@ gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint { *data = gst_adapter_peek (common->adapter, peek); if (*data == NULL) - return GST_FLOW_ERROR; + return GST_FLOW_UNEXPECTED; return GST_FLOW_OK; } From 9eb55c3d8feff7ef496cd66551b4275d23eb40eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Sun, 16 Oct 2011 19:41:28 +0200 Subject: [PATCH 07/16] pngenc: make setcaps more robust, use gstvideo functions A setcaps function needs to actually verify the caps carefully. In this case, it was possible to e.g. link a video decoder with YUV+RGB template caps to pngenc. That would cause a crash when the decoder pushes a YUV buffer. Same thing when pushing a valid buffer that exceeds the resolution limits. Also, missing framerate caps field would cause a glib critical warning due to invalid GValue. This fails hard now. --- ext/libpng/Makefile.am | 3 +- ext/libpng/gstpngenc.c | 69 ++++++++++++++++++++++++++---------------- ext/libpng/gstpngenc.h | 2 +- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/ext/libpng/Makefile.am b/ext/libpng/Makefile.am index 5d1f63af75..bce5b1abcc 100644 --- a/ext/libpng/Makefile.am +++ b/ext/libpng/Makefile.am @@ -2,7 +2,8 @@ plugin_LTLIBRARIES = libgstpng.la libgstpng_la_SOURCES = gstpng.c gstpngenc.c gstpngdec.c libgstpng_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(LIBPNG_CFLAGS) -libgstpng_la_LIBADD = $(GST_LIBS) $(LIBPNG_LIBS) +libgstpng_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-@GST_MAJORMINOR@ \ + $(GST_LIBS) $(LIBPNG_LIBS) libgstpng_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstpng_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c index a7bfaef4f7..21ab56471c 100644 --- a/ext/libpng/gstpngenc.c +++ b/ext/libpng/gstpngenc.c @@ -146,35 +146,60 @@ static gboolean gst_pngenc_setcaps (GstPad * pad, GstCaps * caps) { GstPngEnc *pngenc; - const GValue *fps; - GstStructure *structure; + GstVideoFormat format; + int fps_n, fps_d; GstCaps *pcaps; - gboolean ret = TRUE; + gboolean ret; pngenc = GST_PNGENC (gst_pad_get_parent (pad)); - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "width", &pngenc->width); - gst_structure_get_int (structure, "height", &pngenc->height); - fps = gst_structure_get_value (structure, "framerate"); - gst_structure_get_int (structure, "bpp", &pngenc->bpp); + ret = gst_video_format_parse_caps (caps, &format, + &pngenc->width, &pngenc->height); + if (G_LIKELY (ret)) + ret = gst_video_parse_caps_framerate (caps, &fps_n, &fps_d); - if (pngenc->bpp == 32) - pngenc->stride = pngenc->width * 4; - else if (pngenc->bpp == 8) - pngenc->stride = GST_ROUND_UP_4 (pngenc->width); - else - pngenc->stride = GST_ROUND_UP_4 (pngenc->width * 3); + if (G_UNLIKELY (!ret)) + goto done; + + switch (format) { + case GST_VIDEO_FORMAT_RGBA: + pngenc->png_color_type = PNG_COLOR_TYPE_RGBA; + break; + case GST_VIDEO_FORMAT_RGB: + pngenc->png_color_type = PNG_COLOR_TYPE_RGB; + break; + case GST_VIDEO_FORMAT_GRAY8: + pngenc->png_color_type = PNG_COLOR_TYPE_GRAY; + break; + default: + ret = FALSE; + goto done; + } + + if (G_UNLIKELY (pngenc->width < 16 || pngenc->width > 4096 || + pngenc->height < 16 || pngenc->height > 4096)) { + ret = FALSE; + goto done; + } + + pngenc->stride = gst_video_format_get_row_stride (format, 0, pngenc->width); pcaps = gst_caps_new_simple ("image/png", "width", G_TYPE_INT, pngenc->width, - "height", G_TYPE_INT, pngenc->height, NULL); - structure = gst_caps_get_structure (pcaps, 0); - gst_structure_set_value (structure, "framerate", fps); + "height", G_TYPE_INT, pngenc->height, + "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); ret = gst_pad_set_caps (pngenc->srcpad, pcaps); gst_caps_unref (pcaps); + + /* Fall-through. */ +done: + if (G_UNLIKELY (!ret)) { + pngenc->width = 0; + pngenc->height = 0; + } + gst_object_unref (pngenc); return ret; @@ -238,7 +263,6 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) { GstPngEnc *pngenc; gint row_index; - gint color_type; png_byte *row_pointers[MAX_HEIGHT]; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *encoded_buf = NULL; @@ -282,19 +306,12 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE); png_set_compression_level (pngenc->png_struct_ptr, pngenc->compression_level); - if (pngenc->bpp == 32) - color_type = PNG_COLOR_TYPE_RGBA; - else if (pngenc->bpp == 8) - color_type = PNG_COLOR_TYPE_GRAY; - else - color_type = PNG_COLOR_TYPE_RGB; - png_set_IHDR (pngenc->png_struct_ptr, pngenc->png_info_ptr, pngenc->width, pngenc->height, 8, - color_type, + pngenc->png_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); diff --git a/ext/libpng/gstpngenc.h b/ext/libpng/gstpngenc.h index 848d15e83e..792a7c90b6 100644 --- a/ext/libpng/gstpngenc.h +++ b/ext/libpng/gstpngenc.h @@ -49,9 +49,9 @@ struct _GstPngEnc png_structp png_struct_ptr; png_infop png_info_ptr; + gint png_color_type; gint width; gint height; - gint bpp; gint stride; guint compression_level; From 7e390c4635b8368ba7dc15c5c00e52491317f867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Sun, 16 Oct 2011 19:44:27 +0200 Subject: [PATCH 08/16] pngenc: validate input buffer size Just for safety; of course such mismatch represents a bug in another element. --- ext/libpng/gstpngenc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c index 21ab56471c..e59da9be08 100644 --- a/ext/libpng/gstpngenc.c +++ b/ext/libpng/gstpngenc.c @@ -271,6 +271,14 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) GST_DEBUG_OBJECT (pngenc, "BEGINNING"); + if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < pngenc->height * pngenc->stride)) { + gst_buffer_unref (buf); + GST_ELEMENT_ERROR (pngenc, STREAM, FORMAT, (NULL), + ("Provided input buffer is too small, caps problem?")); + ret = GST_FLOW_ERROR; + goto done; + } + /* initialize png struct stuff */ pngenc->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, user_error_fn, user_warning_fn); From 65f935480360a55f8d1ec5211812c1e921d86666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Sun, 16 Oct 2011 20:05:28 +0200 Subject: [PATCH 09/16] pngenc: ensure setcaps was called before chain function This is needed to properly error out for e.g. "fakesrc ! pngenc ! fakesink". --- ext/libpng/gstpngenc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c index e59da9be08..7bad0377bd 100644 --- a/ext/libpng/gstpngenc.c +++ b/ext/libpng/gstpngenc.c @@ -271,6 +271,11 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) GST_DEBUG_OBJECT (pngenc, "BEGINNING"); + if (G_UNLIKELY (pngenc->width <= 0 || pngenc->height <= 0)) { + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < pngenc->height * pngenc->stride)) { gst_buffer_unref (buf); GST_ELEMENT_ERROR (pngenc, STREAM, FORMAT, (NULL), From db1f10adc81aeb0508f5ebee2281bac9d20b3080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Sun, 16 Oct 2011 20:25:41 +0200 Subject: [PATCH 10/16] pngenc: don't unconditionally allocate 4096 pointers on the stack Instead allocate as many as needed (on the stack still). --- ext/libpng/gstpngenc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c index 7bad0377bd..8ccb804ce6 100644 --- a/ext/libpng/gstpngenc.c +++ b/ext/libpng/gstpngenc.c @@ -30,8 +30,6 @@ #include #include -#define MAX_HEIGHT 4096 - GST_DEBUG_CATEGORY_STATIC (pngenc_debug); #define GST_CAT_DEFAULT pngenc_debug @@ -263,7 +261,7 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) { GstPngEnc *pngenc; gint row_index; - png_byte *row_pointers[MAX_HEIGHT]; + png_byte **row_pointers; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *encoded_buf = NULL; @@ -331,6 +329,8 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) png_set_write_fn (pngenc->png_struct_ptr, pngenc, (png_rw_ptr) user_write_data, user_flush_data); + row_pointers = g_newa (png_byte *, pngenc->height); + for (row_index = 0; row_index < pngenc->height; row_index++) { row_pointers[row_index] = GST_BUFFER_DATA (buf) + (row_index * pngenc->stride); From 41116224c88162e2fa8d6c9e7631a7e31a68f138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Sun, 16 Oct 2011 20:30:25 +0200 Subject: [PATCH 11/16] pngenc: increase arbitrary resolution limits Apparently libpng can technically do up to 2^31-1 rows and columns. However it imposes an (arbitrary) default limit of 1 million (that could theoretically be lifted by using some additional API). Moved array allocation to the heap now. --- ext/libpng/gstpngenc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c index 8ccb804ce6..578d568db6 100644 --- a/ext/libpng/gstpngenc.c +++ b/ext/libpng/gstpngenc.c @@ -57,8 +57,8 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("image/png, " - "width = (int) [ 16, 4096 ], " - "height = (int) [ 16, 4096 ], " "framerate = " GST_VIDEO_FPS_RANGE) + "width = (int) [ 16, 1000000 ], " + "height = (int) [ 16, 1000000 ], " "framerate = " GST_VIDEO_FPS_RANGE) ); static GstStaticPadTemplate pngenc_sink_template = @@ -174,8 +174,8 @@ gst_pngenc_setcaps (GstPad * pad, GstCaps * caps) goto done; } - if (G_UNLIKELY (pngenc->width < 16 || pngenc->width > 4096 || - pngenc->height < 16 || pngenc->height > 4096)) { + if (G_UNLIKELY (pngenc->width < 16 || pngenc->width > 1000000 || + pngenc->height < 16 || pngenc->height > 1000000)) { ret = FALSE; goto done; } @@ -329,7 +329,7 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) png_set_write_fn (pngenc->png_struct_ptr, pngenc, (png_rw_ptr) user_write_data, user_flush_data); - row_pointers = g_newa (png_byte *, pngenc->height); + row_pointers = g_new (png_byte *, pngenc->height); for (row_index = 0; row_index < pngenc->height; row_index++) { row_pointers[row_index] = GST_BUFFER_DATA (buf) + @@ -345,6 +345,8 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf) png_write_image (pngenc->png_struct_ptr, row_pointers); png_write_end (pngenc->png_struct_ptr, NULL); + g_free (row_pointers); + encoded_buf = gst_buffer_create_sub (pngenc->buffer_out, 0, pngenc->written); png_destroy_info_struct (pngenc->png_struct_ptr, &pngenc->png_info_ptr); From dcd493279d691b0e34cb2288b394f82edc71929d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Fri, 21 Oct 2011 22:32:38 +0200 Subject: [PATCH 12/16] deinterlace: remove avoidable call to gst_object_set_name --- gst/deinterlace/gstdeinterlace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index 4e1b488698..8e505a8eb8 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -392,10 +392,9 @@ gst_deinterlace_set_method (GstDeinterlace * self, GstDeinterlaceMethods method) g_assert (method_type != G_TYPE_INVALID); } - self->method = g_object_new (method_type, NULL); + self->method = g_object_new (method_type, "name", "method", NULL); self->method_id = method; - gst_object_set_name (GST_OBJECT (self->method), "method"); gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self)); gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method)); From 6082f27d483357d7392b952ebf201a9e6db6706d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Fri, 21 Oct 2011 22:33:34 +0200 Subject: [PATCH 13/16] equalizer: remove avoidable call to gst_object_set_name --- gst/equalizer/gstiirequalizer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/equalizer/gstiirequalizer.c b/gst/equalizer/gstiirequalizer.c index 0b767489ea..80345821ee 100644 --- a/gst/equalizer/gstiirequalizer.c +++ b/gst/equalizer/gstiirequalizer.c @@ -658,10 +658,10 @@ gst_iir_equalizer_compute_frequencies (GstIirEqualizer * equ, guint new_count) /* add new bands */ equ->bands = g_realloc (equ->bands, sizeof (GstObject *) * new_count); for (i = old_count; i < new_count; i++) { - equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, NULL); /* otherwise they get names like 'iirequalizerband5' */ sprintf (name, "band%u", i); - gst_object_set_name (GST_OBJECT (equ->bands[i]), name); + equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, + "name", name, NULL); GST_DEBUG ("adding band[%d]=%p", i, equ->bands[i]); gst_object_set_parent (GST_OBJECT (equ->bands[i]), GST_OBJECT (equ)); From 6fc85e6c9d883184992ab12abd4a28645aad6f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Tue, 11 Oct 2011 22:10:27 +0200 Subject: [PATCH 14/16] matroskamux: fix possible crash with malformed dirac codec_data Since size is unsigned, we need to safeguard against wrapping below zero. --- gst/matroska/matroska-mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index b0ff579ae0..5204b39a6e 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -2594,7 +2594,7 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux, next_parse_offset = GST_READ_UINT32_BE (data + 5); - if (G_UNLIKELY (next_parse_offset == 0)) + if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size)) break; data += next_parse_offset; From 003a14e15a57558f12e87ee95e8ddc616cc0520a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Tue, 11 Oct 2011 21:45:46 +0200 Subject: [PATCH 15/16] matroska: remove stale floatcast include GDOUBLE_TO_BE was moved to core a long time ago. --- gst/matroska/ebml-write.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst/matroska/ebml-write.c b/gst/matroska/ebml-write.c index b66098709d..7afaddbb5b 100644 --- a/gst/matroska/ebml-write.c +++ b/gst/matroska/ebml-write.c @@ -25,7 +25,6 @@ #endif #include -#include #include "ebml-write.h" #include "ebml-ids.h" From 1b213d905ac2b9a1e015be6daf0dfeb92294154c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Stadler?= Date: Mon, 10 Oct 2011 15:36:14 +0200 Subject: [PATCH 16/16] matroska: refactor ebml-write to be more 0.11 friendly Switching to a more 0.11-friendly pattern, where getting the buffer's data pointer and setting the size many times is less natural. This is of course in preparation to the upcoming port of the plugin. --- gst/matroska/ebml-write.c | 187 +++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 72 deletions(-) diff --git a/gst/matroska/ebml-write.c b/gst/matroska/ebml-write.c index 7afaddbb5b..9bc88eafd3 100644 --- a/gst/matroska/ebml-write.c +++ b/gst/matroska/ebml-write.c @@ -279,7 +279,7 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe, * Returns: A new #GstBuffer. */ static GstBuffer * -gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size) +gst_ebml_write_element_new (GstEbmlWrite * ebml, guint8 ** data_out, guint size) { /* Create new buffer of size + ID + length */ GstBuffer *buf; @@ -288,24 +288,25 @@ gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size) size += 12; buf = gst_buffer_new_and_alloc (size); - GST_BUFFER_SIZE (buf) = 0; GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp; + *data_out = GST_BUFFER_DATA (buf); + return buf; } /** * gst_ebml_write_element_id: - * @buf: Buffer to which id should be written. + * @data_inout: Pointer to data pointer * @id: Element ID that should be written. * * Write element ID into a buffer. */ static void -gst_ebml_write_element_id (GstBuffer * buf, guint32 id) +gst_ebml_write_element_id (guint8 ** data_inout, guint32 id) { - guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf); + guint8 *data = *data_inout; guint bytes = 4, mask = 0x10; /* get ID length */ @@ -322,7 +323,7 @@ gst_ebml_write_element_id (GstBuffer * buf, guint32 id) } /* write out, BE */ - GST_BUFFER_SIZE (buf) += bytes; + *data_inout += bytes; while (bytes--) { data[bytes] = id & 0xff; id >>= 8; @@ -332,15 +333,15 @@ gst_ebml_write_element_id (GstBuffer * buf, guint32 id) /** * gst_ebml_write_element_size: - * @buf: #GstBuffer to which size should be written. + * @data_inout: Pointer to data pointer * @size: Element length. - * + * * Write element length into a buffer. */ static void -gst_ebml_write_element_size (GstBuffer * buf, guint64 size) +gst_ebml_write_element_size (guint8 ** data_inout, guint64 size) { - guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf); + guint8 *data = *data_inout; guint bytes = 1, mask = 0x80; if (size != GST_EBML_SIZE_UNKNOWN) { @@ -364,7 +365,7 @@ gst_ebml_write_element_size (GstBuffer * buf, guint64 size) } /* write out, BE, with length size marker */ - GST_BUFFER_SIZE (buf) += bytes; + *data_inout += bytes; while (bytes-- > 0) { data[bytes] = size & 0xff; size >>= 8; @@ -376,19 +377,18 @@ gst_ebml_write_element_size (GstBuffer * buf, guint64 size) /** * gst_ebml_write_element_data: - * @buf: #GstBuffer to which data should be written. + * @data_inout: Pointer to data pointer * @write: Data that should be written. * @length: Length of the data. * * Write element data into a buffer. */ static void -gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length) +gst_ebml_write_element_data (guint8 ** data_inout, guint8 * write, + guint64 length) { - guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf); - - memcpy (data, write, length); - GST_BUFFER_SIZE (buf) += length; + memcpy (*data_inout, write, length); + *data_inout += length; } @@ -396,23 +396,34 @@ gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length) * gst_ebml_write_element_push: * @ebml: #GstEbmlWrite * @buf: #GstBuffer to be written. + * @buf_data: Start of data to push from @buf (or NULL for whole buffer). + * @buf_data_end: Data pointer positioned after the last byte in @buf_data (or + * NULL for whole buffer). * * Write out buffer by moving it to the next element. */ static void -gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf) +gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf, + guint8 * buf_data, guint8 * buf_data_end) { - guint data_size = GST_BUFFER_SIZE (buf); + guint data_size; + + if (!buf_data) + buf_data = GST_BUFFER_DATA (buf); + + if (buf_data_end) + data_size = buf_data_end - buf_data; + else + data_size = GST_BUFFER_SIZE (buf); ebml->pos += data_size; /* if there's no cache, then don't push it! */ if (ebml->writing_streamheader) { - gst_byte_writer_put_data (ebml->streamheader, GST_BUFFER_DATA (buf), - data_size); + gst_byte_writer_put_data (ebml->streamheader, buf_data, data_size); } if (ebml->cache) { - gst_byte_writer_put_data (ebml->cache, GST_BUFFER_DATA (buf), data_size); + gst_byte_writer_put_data (ebml->cache, buf_data, data_size); gst_buffer_unref (buf); return; } @@ -420,7 +431,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf) if (ebml->last_write_result == GST_FLOW_OK) { buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, ebml->caps); - GST_BUFFER_OFFSET (buf) = ebml->pos - GST_BUFFER_SIZE (buf); + GST_BUFFER_OFFSET (buf) = ebml->pos - data_size; GST_BUFFER_OFFSET_END (buf) = ebml->pos; if (ebml->writing_streamheader) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); @@ -507,19 +518,19 @@ gst_ebml_write_get_uint_size (guint64 num) /** * gst_ebml_write_set_uint: - * @buf: #GstBuffer to which ithe number should be written. + * @data_inout: Pointer to data pointer * @num: Number to be written. * @size: Encoded number length. * * Write an uint into a buffer. */ static void -gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size) +gst_ebml_write_set_uint (guint8 ** data_inout, guint64 num, guint size) { - guint8 *data; + guint8 *data = *data_inout; + + *data_inout += size; - data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf); - GST_BUFFER_SIZE (buf) += size; while (size-- > 0) { data[size] = num & 0xff; num >>= 8; @@ -538,14 +549,18 @@ gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size) void gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num) { - GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num)); + GstBuffer *buf; + guint8 *data_start, *data_end; guint size = gst_ebml_write_get_uint_size (num); + buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num)); + data_end = data_start; + /* write */ - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, size); - gst_ebml_write_set_uint (buf, num, size); - gst_ebml_write_element_push (ebml, buf); + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, size); + gst_ebml_write_set_uint (&data_end, num, size); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } @@ -560,8 +575,8 @@ gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num) void gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num) { - GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num)); - + GstBuffer *buf; + guint8 *data_start, *data_end; /* if the signed number is on the edge of a extra-byte, * then we'll fall over when detecting it. Example: if I * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1 @@ -569,6 +584,9 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num) guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1); guint size = gst_ebml_write_get_uint_size (unum); + buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num)); + data_end = data_start; + /* make unsigned */ if (num >= 0) { unum = num; @@ -579,10 +597,10 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num) } /* write */ - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, size); - gst_ebml_write_set_uint (buf, unum, size); - gst_ebml_write_element_push (ebml, buf); + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, size); + gst_ebml_write_set_uint (&data_end, unum, size); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } @@ -597,13 +615,17 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num) void gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num) { - GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num)); + GstBuffer *buf; + guint8 *data_start, *data_end; - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, 8); + buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num)); + data_end = data_start; + + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, 8); num = GDOUBLE_TO_BE (num); - gst_ebml_write_element_data (buf, (guint8 *) & num, 8); - gst_ebml_write_element_push (ebml, buf); + gst_ebml_write_element_data (&data_end, (guint8 *) & num, 8); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } @@ -619,12 +641,16 @@ void gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str) { gint len = strlen (str) + 1; /* add trailing '\0' */ - GstBuffer *buf = gst_ebml_write_element_new (ebml, len); + GstBuffer *buf; + guint8 *data_start, *data_end; - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, len); - gst_ebml_write_element_data (buf, (guint8 *) str, len); - gst_ebml_write_element_push (ebml, buf); + buf = gst_ebml_write_element_new (ebml, &data_start, len); + data_end = data_start; + + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, len); + gst_ebml_write_element_data (&data_end, (guint8 *) str, len); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } @@ -673,14 +699,17 @@ gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date) guint64 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id) { - guint64 pos = ebml->pos, t; - GstBuffer *buf = gst_ebml_write_element_new (ebml, 0); + guint64 pos = ebml->pos; + GstBuffer *buf; + guint8 *data_start, *data_end; - t = GST_BUFFER_SIZE (buf); - gst_ebml_write_element_id (buf, id); - pos += GST_BUFFER_SIZE (buf) - t; - gst_ebml_write_element_size (buf, GST_EBML_SIZE_UNKNOWN); - gst_ebml_write_element_push (ebml, buf); + buf = gst_ebml_write_element_new (ebml, &data_start, 0); + data_end = data_start; + + gst_ebml_write_element_id (&data_end, id); + pos += data_end - data_start; + gst_ebml_write_element_size (&data_end, GST_EBML_SIZE_UNKNOWN); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); return pos; } @@ -702,10 +731,12 @@ gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos, GstBuffer *buf; gst_ebml_write_seek (ebml, startpos); + buf = gst_buffer_new_and_alloc (8); GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size)); - gst_ebml_write_element_push (ebml, buf); + + gst_ebml_write_element_push (ebml, buf, NULL, NULL); gst_ebml_write_seek (ebml, pos); } @@ -728,12 +759,16 @@ void gst_ebml_write_binary (GstEbmlWrite * ebml, guint32 id, guint8 * binary, guint64 length) { - GstBuffer *buf = gst_ebml_write_element_new (ebml, length); + GstBuffer *buf; + guint8 *data_start, *data_end; - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, length); - gst_ebml_write_element_data (buf, binary, length); - gst_ebml_write_element_push (ebml, buf); + buf = gst_ebml_write_element_new (ebml, &data_start, length); + data_end = data_start; + + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, length); + gst_ebml_write_element_data (&data_end, binary, length); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } @@ -753,25 +788,29 @@ gst_ebml_write_binary (GstEbmlWrite * ebml, void gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length) { - GstBuffer *buf = gst_ebml_write_element_new (ebml, 0); + GstBuffer *buf; + guint8 *data_start, *data_end; - gst_ebml_write_element_id (buf, id); - gst_ebml_write_element_size (buf, length); - gst_ebml_write_element_push (ebml, buf); + buf = gst_ebml_write_element_new (ebml, &data_start, 0); + data_end = data_start; + + gst_ebml_write_element_id (&data_end, id); + gst_ebml_write_element_size (&data_end, length); + gst_ebml_write_element_push (ebml, buf, data_start, data_end); } /** * gst_ebml_write_buffer: * @ebml: #GstEbmlWrite - * @data: #GstBuffer cointaining the data. + * @buf: #GstBuffer cointaining the data. * * Write binary element (see gst_ebml_write_buffer_header). */ void -gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data) +gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * buf) { - gst_ebml_write_element_push (ebml, data); + gst_ebml_write_element_push (ebml, buf, NULL, NULL); } @@ -795,11 +834,15 @@ gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num) { guint64 oldpos = ebml->pos; GstBuffer *buf = gst_buffer_new_and_alloc (8); + guint8 *data_start, *data_end; + + data_start = GST_BUFFER_DATA (buf); + data_end = data_start; gst_ebml_write_seek (ebml, pos); - GST_BUFFER_SIZE (buf) = 0; - gst_ebml_write_set_uint (buf, num, 8); - gst_ebml_write_element_push (ebml, buf); + gst_ebml_write_set_uint (&data_end, num, 8); + + gst_ebml_write_element_push (ebml, buf, data_start, data_end); gst_ebml_write_seek (ebml, oldpos); }