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.
This commit is contained in:
Edward Hervey 2009-03-08 11:31:35 +01:00
parent ea76b43723
commit 57e66c5a22
4 changed files with 48 additions and 10 deletions

View file

@ -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__ */

View file

@ -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;

View file

@ -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;
}

View file

@ -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__ */