[0.11] gst-plugins-ugly: mad: helpfully bodge the last buffer to let mad decode the last frame
Sebastian Dröge
slomo at kemper.freedesktop.org
Tue Jan 10 06:17:27 PST 2012
Module: gst-plugins-ugly
Branch: 0.11
Commit: 30e29b6fdbbcd28fc8d70e1146abd54ef0065aa3
URL: http://cgit.freedesktop.org/gstreamer/gst-plugins-ugly/commit/?id=30e29b6fdbbcd28fc8d70e1146abd54ef0065aa3
Author: Vincent Penquerc'h <vincent.penquerch at collabora.co.uk>
Date: Thu Dec 22 15:23:54 2011 +0000
mad: helpfully bodge the last buffer to let mad decode the last frame
If http://www.mars.org/mailman/public/mad-dev/2001-May/000262.html is
to be believed, the last buffer must be followed by a number of 0 bytes
in order for the last frame to be decoded (at least in some cases).
Doing so seems to work here, fixing a missing 1152 samples when using
mp3parse before mad (not using mp3parse would yield the correct amount
of samples, if there's extra non-MP3 data after (eg, tag data)).
---
ext/mad/gstmad.c | 32 ++++++++++++++++++++++++++++++++
ext/mad/gstmad.h | 2 ++
2 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/ext/mad/gstmad.c b/ext/mad/gstmad.c
index e4c3e54..bff7634 100644
--- a/ext/mad/gstmad.c
+++ b/ext/mad/gstmad.c
@@ -82,6 +82,7 @@ static gboolean gst_mad_parse (GstAudioDecoder * dec, GstAdapter * adapter,
gint * offset, gint * length);
static GstFlowReturn gst_mad_handle_frame (GstAudioDecoder * dec,
GstBuffer * buffer);
+static gboolean gst_mad_event (GstAudioDecoder * dec, GstEvent * event);
static void gst_mad_flush (GstAudioDecoder * dec, gboolean hard);
static void gst_mad_set_property (GObject * object, guint prop_id,
@@ -119,6 +120,7 @@ gst_mad_class_init (GstMadClass * klass)
base_class->parse = GST_DEBUG_FUNCPTR (gst_mad_parse);
base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_mad_handle_frame);
base_class->flush = GST_DEBUG_FUNCPTR (gst_mad_flush);
+ base_class->event = GST_DEBUG_FUNCPTR (gst_mad_event);
gobject_class->set_property = gst_mad_set_property;
gobject_class->get_property = gst_mad_get_property;
@@ -168,6 +170,7 @@ gst_mad_start (GstAudioDecoder * dec)
mad_stream_options (&mad->stream, options);
mad->header.mode = -1;
mad->header.emphasis = -1;
+ mad->eos = FALSE;
/* call upon legacy upstream byte support (e.g. seeking) */
gst_audio_decoder_set_byte_time (dec, TRUE);
@@ -282,6 +285,20 @@ gst_mad_parse (GstAudioDecoder * dec, GstAdapter * adapter,
mad = GST_MAD (dec);
+ if (mad->eos) {
+ /* This is one steaming hack right there.
+ * mad will not decode the last frame if it is not followed by
+ * a number of 0 bytes, due to some buffer overflow, which can
+ * not be fixed for reasons I did not inquire into, see
+ * http://www.mars.org/mailman/public/mad-dev/2001-May/000262.html
+ */
+ GstBuffer *guard = gst_buffer_new_and_alloc (MAD_BUFFER_GUARD);
+ memset (GST_BUFFER_DATA (guard), 0, GST_BUFFER_SIZE (guard));
+ GST_DEBUG_OBJECT (mad, "Discreetly stuffing %u zero bytes in the adapter",
+ GST_BUFFER_SIZE (guard));
+ gst_adapter_push (adapter, guard);
+ }
+
/* we basically let mad library do parsing,
* and translate that back to baseclass.
* if a frame is found (and also decoded), subsequent handle_frame
@@ -482,6 +499,21 @@ gst_mad_flush (GstAudioDecoder * dec, gboolean hard)
}
}
+static gboolean
+gst_mad_event (GstAudioDecoder * dec, GstEvent * event)
+{
+ GstMad *mad;
+
+ mad = GST_MAD (dec);
+ if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+ GST_DEBUG_OBJECT (mad, "We got EOS, will pad next time");
+ mad->eos = TRUE;
+ }
+
+ /* Let the base class do its usual thing */
+ return FALSE;
+}
+
static void
gst_mad_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
diff --git a/ext/mad/gstmad.h b/ext/mad/gstmad.h
index 91478ac..a9117ec 100644
--- a/ext/mad/gstmad.h
+++ b/ext/mad/gstmad.h
@@ -63,6 +63,8 @@ struct _GstMad
gint times_pending;
gboolean caps_set; /* used to keep track of whether to change/update caps */
+ gboolean eos;
+
/* properties */
gboolean half;
gboolean ignore_crc;
More information about the gstreamer-commits
mailing list