diff options
author | Edward Hervey <bilboed@bilboed.com> | 2009-03-08 11:31:35 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2009-04-21 18:28:54 +0200 |
commit | 57e66c5a221f274e40400497be731815d29dca99 (patch) | |
tree | 3bdd0e36dd06270b5472d4f736110c864a22600c | |
parent | ea76b437236821e636b59cc6cfe48ff07a769419 (diff) |
Make sure we provide ffmpeg with 128bit-aligned data.
Add a new function new_aligned_buffer() which creates a GstBuffer of
the requested size/caps, with the memory being allocated/freed by ffmpeg's
av_malloc/av_free which guarantees properly aligned memory.
Added a can_allocate_aligned internal property which we use to figure out
whether downstream can provide us with 128bit aligned buffers.
-rw-r--r-- | ext/ffmpeg/gstffmpegcodecmap.h | 3 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegdec.c | 33 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegutils.c | 19 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegutils.h | 3 |
4 files changed, 48 insertions, 10 deletions
diff --git a/ext/ffmpeg/gstffmpegcodecmap.h b/ext/ffmpeg/gstffmpegcodecmap.h index a34338c..6c60223 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.h +++ b/ext/ffmpeg/gstffmpegcodecmap.h @@ -115,4 +115,7 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name, +GstBuffer * +new_aligned_buffer (gint size, GstCaps * caps); + #endif /* __GST_FFMPEG_CODECMAP_H__ */ diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index 70f9d08..1db6e4b 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -110,6 +110,9 @@ struct _GstFFMpegDec /* reverse playback queue */ GList *queued; + + /* Can downstream allocate 16bytes aligned data. */ + gboolean can_allocate_aligned; }; typedef struct _GstFFMpegDecClass GstFFMpegDecClass; @@ -366,6 +369,9 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec) ffmpegdec->format.video.fps_n = -1; ffmpegdec->format.video.old_fps_n = -1; gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME); + + /* We initially assume downstream can allocate 16 bytes aligned buffers */ + ffmpegdec->can_allocate_aligned = TRUE; } static void @@ -792,7 +798,7 @@ alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf, fsize = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt, width, height); - if (!ffmpegdec->context->palctrl) { + if (!ffmpegdec->context->palctrl && ffmpegdec->can_allocate_aligned) { GST_LOG_OBJECT (ffmpegdec, "calling pad_alloc"); /* no pallete, we can use the buffer size to alloc */ ret = gst_pad_alloc_buffer_and_set_caps (ffmpegdec->srcpad, @@ -800,14 +806,23 @@ alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf, GST_PAD_CAPS (ffmpegdec->srcpad), outbuf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto alloc_failed; + + /* If buffer isn't 128-bit aligned, create a memaligned one ourselves */ + if (((uintptr_t) GST_BUFFER_DATA (*outbuf)) % 16) { + GST_DEBUG_OBJECT (ffmpegdec, + "Downstream can't allocate aligned buffers."); + ffmpegdec->can_allocate_aligned = FALSE; + gst_buffer_unref (*outbuf); + *outbuf = new_aligned_buffer (fsize, GST_PAD_CAPS (ffmpegdec->srcpad)); + } } else { - GST_LOG_OBJECT (ffmpegdec, "not calling pad_alloc, we have a pallete"); + GST_LOG_OBJECT (ffmpegdec, + "not calling pad_alloc, we have a pallete or downstream can't give 16 byte aligned buffers."); /* for paletted data we can't use pad_alloc_buffer(), because * fsize contains the size of the palette, so the overall size * is bigger than ffmpegcolorspace's unit size, which will * prompt GstBaseTransform to complain endlessly ... */ - *outbuf = gst_buffer_new_and_alloc (fsize); - gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad)); + *outbuf = new_aligned_buffer (fsize, GST_PAD_CAPS (ffmpegdec->srcpad)); ret = GST_FLOW_OK; } return ret; @@ -1815,12 +1830,9 @@ gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec, in_offset, GST_TIME_ARGS (in_timestamp), GST_TIME_ARGS (in_duration), GST_TIME_ARGS (ffmpegdec->next_ts)); - /* outgoing buffer. We use av_malloc() to have properly aligned memory. */ - *outbuf = gst_buffer_new (); - GST_BUFFER_DATA (*outbuf) = GST_BUFFER_MALLOCDATA (*outbuf) = - av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE); - GST_BUFFER_SIZE (*outbuf) = AVCODEC_MAX_AUDIO_FRAME_SIZE; - GST_BUFFER_FREE_FUNC (*outbuf) = av_free; + *outbuf = + new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE, + GST_PAD_CAPS (ffmpegdec->srcpad)); len = avcodec_decode_audio2 (ffmpegdec->context, (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, data, size); @@ -2469,6 +2481,7 @@ gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition) g_free (ffmpegdec->padded); ffmpegdec->padded = NULL; ffmpegdec->padded_size = 0; + ffmpegdec->can_allocate_aligned = TRUE; break; default: break; diff --git a/ext/ffmpeg/gstffmpegutils.c b/ext/ffmpeg/gstffmpegutils.c index 988cc1c..0747d5a 100644 --- a/ext/ffmpeg/gstffmpegutils.c +++ b/ext/ffmpeg/gstffmpegutils.c @@ -396,3 +396,22 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture, return 0; } + +/* Create a GstBuffer of the requested size and caps. + * The memory will be allocated by ffmpeg, making sure it's properly aligned + * for any processing. */ + +GstBuffer * +new_aligned_buffer (gint size, GstCaps * caps) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = av_malloc (size); + GST_BUFFER_SIZE (buf) = size; + GST_BUFFER_FREE_FUNC (buf) = av_free; + if (caps) + gst_buffer_set_caps (buf, caps); + + return buf; +} diff --git a/ext/ffmpeg/gstffmpegutils.h b/ext/ffmpeg/gstffmpegutils.h index 96efd24..184034b 100644 --- a/ext/ffmpeg/gstffmpegutils.h +++ b/ext/ffmpeg/gstffmpegutils.h @@ -87,4 +87,7 @@ gst_ffmpeg_get_codecid_longname (enum CodecID codec_id); gint av_smp_format_depth(enum SampleFormat smp_fmt); +GstBuffer * +new_aligned_buffer (gint size, GstCaps * caps); + #endif /* __GST_FFMPEG_UTILS_H__ */ |