From b8265e95a7c75f7a932a421419d6eeda67645d8e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 20 Nov 2016 13:14:08 +0200 Subject: [PATCH] avidemux: Ensure that raw video have properly aligned buffers That is, aligned to to 32 bytes for video. Fixes crashes if the raw buffers are passed to SIMD processing functions. https://bugzilla.gnome.org/show_bug.cgi?id=774428 --- gst/avi/gstavidemux.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ gst/avi/gstavidemux.h | 1 + 2 files changed, 45 insertions(+) diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 1fe3176..5daeef0 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -1936,6 +1936,7 @@ gst_avi_demux_check_caps (GstAviDemux * avi, GstAviStream * stream, s = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (s, "video/x-raw")) { stream->is_raw = TRUE; + stream->alignment = 32; if (!gst_structure_has_field (s, "pixel-aspect-ratio")) gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); @@ -5137,6 +5138,44 @@ gst_avi_demux_find_next (GstAviDemux * avi, gfloat rate) return stream_num; } +static GstBuffer * +gst_avi_demux_align_buffer (GstAviDemux * demux, + GstBuffer * buffer, gsize alignment) +{ + GstMapInfo map; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + if (map.size < sizeof (guintptr)) { + gst_buffer_unmap (buffer, &map); + return buffer; + } + + if (((guintptr) map.data) & (alignment - 1)) { + GstBuffer *new_buffer; + GstAllocationParams params = { 0, alignment - 1, 0, 0, }; + + new_buffer = gst_buffer_new_allocate (NULL, + gst_buffer_get_size (buffer), ¶ms); + + /* Copy data "by hand", so ensure alignment is kept: */ + gst_buffer_fill (new_buffer, 0, map.data, map.size); + + gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1); + GST_DEBUG_OBJECT (demux, + "We want output aligned on %" G_GSIZE_FORMAT ", reallocated", + alignment); + + gst_buffer_unmap (buffer, &map); + gst_buffer_unref (buffer); + + return new_buffer; + } + + gst_buffer_unmap (buffer, &map); + return buffer; +} + static GstFlowReturn gst_avi_demux_loop_data (GstAviDemux * avi) { @@ -5256,6 +5295,8 @@ gst_avi_demux_loop_data (GstAviDemux * avi) gst_buffer_get_size (buf), GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration), out_offset, out_offset_end); + if (stream->alignment > 1) + buf = gst_avi_demux_align_buffer (avi, buf, stream->alignment); ret = gst_pad_push (stream->pad, buf); /* mark as processed, we increment the frame and byte counters then @@ -5545,6 +5586,9 @@ gst_avi_demux_stream_data (GstAviDemux * avi) } else { GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); } + + if (stream->alignment > 1) + buf = gst_avi_demux_align_buffer (avi, buf, stream->alignment); res = gst_pad_push (stream->pad, buf); buf = NULL; diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h index 813ec60..22e46a2 100644 --- a/gst/avi/gstavidemux.h +++ b/gst/avi/gstavidemux.h @@ -120,6 +120,7 @@ typedef struct { gint index_id; gboolean is_raw; + gsize alignment; } GstAviStream; typedef enum { -- 2.7.4