summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2009-03-08 11:31:35 +0100
committerEdward Hervey <bilboed@bilboed.com>2009-04-21 18:28:54 +0200
commit57e66c5a221f274e40400497be731815d29dca99 (patch)
tree3bdd0e36dd06270b5472d4f736110c864a22600c
parentea76b437236821e636b59cc6cfe48ff07a769419 (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.h3
-rw-r--r--ext/ffmpeg/gstffmpegdec.c33
-rw-r--r--ext/ffmpeg/gstffmpegutils.c19
-rw-r--r--ext/ffmpeg/gstffmpegutils.h3
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__ */