diff --git a/ext/libav/gstavauddec.c b/ext/libav/gstavauddec.c index 3e3dea417d..baca8fc401 100644 --- a/ext/libav/gstavauddec.c +++ b/ext/libav/gstavauddec.c @@ -43,6 +43,8 @@ static void gst_ffmpegauddec_base_init (GstFFMpegAudDecClass * klass); static void gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass); static void gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec); static void gst_ffmpegauddec_finalize (GObject * object); +static gboolean gst_ffmpegauddec_propose_allocation (GstAudioDecoder * decoder, + GstQuery * query); static gboolean gst_ffmpegauddec_start (GstAudioDecoder * decoder); static gboolean gst_ffmpegauddec_stop (GstAudioDecoder * decoder); @@ -129,6 +131,8 @@ gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass) gstaudiodecoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ffmpegauddec_handle_frame); gstaudiodecoder_class->flush = GST_DEBUG_FUNCPTR (gst_ffmpegauddec_flush); + gstaudiodecoder_class->propose_allocation = + GST_DEBUG_FUNCPTR (gst_ffmpegauddec_propose_allocation); } static void @@ -225,6 +229,9 @@ gst_ffmpegauddec_stop (GstAudioDecoder * decoder) GST_OBJECT_LOCK (ffmpegdec); gst_ffmpegauddec_close (ffmpegdec, FALSE); + g_free (ffmpegdec->padded); + ffmpegdec->padded = NULL; + ffmpegdec->padded_size = 0; GST_OBJECT_UNLOCK (ffmpegdec); gst_audio_info_init (&ffmpegdec->info); gst_caps_replace (&ffmpegdec->last_caps, NULL); @@ -262,6 +269,24 @@ could_not_open: } } +static gboolean +gst_ffmpegauddec_propose_allocation (GstAudioDecoder * decoder, + GstQuery * query) +{ + GstAllocationParams params; + + gst_allocation_params_init (¶ms); + params.flags = GST_MEMORY_FLAG_ZERO_PADDED; + params.align = 15; + params.padding = FF_INPUT_BUFFER_PADDING_SIZE; + /* we would like to have some padding so that we don't have to + * memcpy. We don't suggest an allocator. */ + gst_query_add_allocation_param (query, NULL, ¶ms); + + return GST_AUDIO_DECODER_CLASS (parent_class)->propose_allocation (decoder, + query); +} + static gboolean gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps) { @@ -669,6 +694,7 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf) GstMapInfo map; gint size, bsize, len, have_data; GstFlowReturn ret = GST_FLOW_OK; + gboolean do_padding; ffmpegdec = (GstFFMpegAudDec *) decoder; @@ -705,13 +731,47 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf) bdata = map.data; bsize = map.size; + if (bsize > 0 && (!GST_MEMORY_IS_ZERO_PADDED (map.memory) + || (map.maxsize - map.size) < FF_INPUT_BUFFER_PADDING_SIZE)) { + /* add padding */ + if (ffmpegdec->padded_size < bsize + FF_INPUT_BUFFER_PADDING_SIZE) { + ffmpegdec->padded_size = bsize + FF_INPUT_BUFFER_PADDING_SIZE; + ffmpegdec->padded = g_realloc (ffmpegdec->padded, ffmpegdec->padded_size); + GST_LOG_OBJECT (ffmpegdec, "resized padding buffer to %d", + ffmpegdec->padded_size); + } + GST_CAT_TRACE_OBJECT (GST_CAT_PERFORMANCE, ffmpegdec, + "Copy input to add padding"); + memcpy (ffmpegdec->padded, bdata, bsize); + memset (ffmpegdec->padded + bsize, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + bdata = ffmpegdec->padded; + do_padding = TRUE; + } else { + do_padding = FALSE; + } + do { + guint8 tmp_padding[FF_INPUT_BUFFER_PADDING_SIZE]; + data = bdata; size = bsize; + if (do_padding) { + /* add temporary padding */ + GST_CAT_TRACE_OBJECT (GST_CAT_PERFORMANCE, ffmpegdec, + "Add temporary input padding"); + memcpy (tmp_padding, data + size, FF_INPUT_BUFFER_PADDING_SIZE); + memset (data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + } + /* decode a frame of audio now */ len = gst_ffmpegauddec_frame (ffmpegdec, data, size, &have_data, &ret); + if (do_padding) { + memcpy (data + size, tmp_padding, FF_INPUT_BUFFER_PADDING_SIZE); + } + if (ret != GST_FLOW_OK) { GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s", gst_flow_get_name (ret)); @@ -738,6 +798,8 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf) bsize -= len; bdata += len; + do_padding = TRUE; + GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0). bsize:%d , bdata:%p", bsize, bdata); } while (bsize > 0); diff --git a/ext/libav/gstavauddec.h b/ext/libav/gstavauddec.h index d88873c119..1d16f740ad 100644 --- a/ext/libav/gstavauddec.h +++ b/ext/libav/gstavauddec.h @@ -37,6 +37,9 @@ struct _GstFFMpegAudDec AVFrame *frame; + guint8 *padded; + guint padded_size; + /* prevent reopening the decoder on GST_EVENT_CAPS when caps are same as last time. */ GstCaps *last_caps;