mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
rawparse: Properly align raw audio/video output buffers
That is, aligned to the basic type for audio and 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
This commit is contained in:
parent
33f4b9cc8e
commit
0c79a06dd1
4 changed files with 97 additions and 2 deletions
|
@ -161,6 +161,8 @@ static gboolean gst_raw_audio_parse_is_unit_format_supported (GstRawBaseParse *
|
|||
static void gst_raw_audio_parse_get_units_per_second (GstRawBaseParse *
|
||||
raw_base_parse, GstFormat format, GstRawBaseParseConfig config,
|
||||
gsize * units_per_sec_n, gsize * units_per_sec_d);
|
||||
static gint gst_raw_audio_parse_get_alignment (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config);
|
||||
|
||||
static gboolean gst_raw_audio_parse_is_using_sink_caps (GstRawAudioParse *
|
||||
raw_audio_parse);
|
||||
|
@ -228,6 +230,8 @@ gst_raw_audio_parse_class_init (GstRawAudioParseClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_is_unit_format_supported);
|
||||
rawbaseparse_class->get_units_per_second =
|
||||
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_units_per_second);
|
||||
rawbaseparse_class->get_alignment =
|
||||
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_alignment);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FORMAT,
|
||||
|
@ -669,6 +673,38 @@ gst_raw_audio_parse_is_config_ready (GstRawBaseParse * raw_base_parse,
|
|||
return gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config)->ready;
|
||||
}
|
||||
|
||||
static guint
|
||||
round_up_pow2 (guint n)
|
||||
{
|
||||
n = n - 1;
|
||||
n = n | (n >> 1);
|
||||
n = n | (n >> 2);
|
||||
n = n | (n >> 4);
|
||||
n = n | (n >> 8);
|
||||
n = n | (n >> 16);
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_raw_audio_parse_get_alignment (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config)
|
||||
{
|
||||
GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
|
||||
GstRawAudioParseConfig *config_ptr =
|
||||
gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config);
|
||||
gint width;
|
||||
|
||||
if (config_ptr->format != GST_RAW_AUDIO_PARSE_FORMAT_PCM)
|
||||
return 1;
|
||||
|
||||
width =
|
||||
GST_AUDIO_FORMAT_INFO_WIDTH (gst_audio_format_get_info
|
||||
(config_ptr->pcm_format)) / 8;
|
||||
width = GST_ROUND_UP_8 (width);
|
||||
width = round_up_pow2 (width);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_audio_parse_process (GstRawBaseParse * raw_base_parse,
|
||||
|
|
|
@ -430,6 +430,43 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_raw_base_parse_align_buffer (GstRawBaseParse * raw_base_parse,
|
||||
gsize alignment, GstBuffer * buffer)
|
||||
{
|
||||
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 (raw_base_parse,
|
||||
"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_raw_base_parse_handle_frame (GstBaseParse * parse,
|
||||
|
@ -442,6 +479,7 @@ gst_raw_base_parse_handle_frame (GstBaseParse * parse,
|
|||
guint64 buffer_duration;
|
||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
GstEvent *new_caps_event = NULL;
|
||||
gint alignment;
|
||||
GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
|
||||
GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (parse);
|
||||
|
||||
|
@ -567,6 +605,15 @@ gst_raw_base_parse_handle_frame (GstBaseParse * parse,
|
|||
frame->out_buffer = NULL;
|
||||
}
|
||||
|
||||
if (klass->get_alignment
|
||||
&& (alignment =
|
||||
klass->get_alignment (raw_base_parse,
|
||||
GST_RAW_BASE_PARSE_CONFIG_CURRENT)) != 1) {
|
||||
frame->out_buffer =
|
||||
gst_raw_base_parse_align_buffer (raw_base_parse, alignment,
|
||||
gst_buffer_ref (frame->buffer));
|
||||
}
|
||||
|
||||
/* Set the duration of the output buffer, or if none exists, of
|
||||
* the input buffer. Do this after the process() call, since in
|
||||
* case out_buffer is set, the subclass has created a new buffer.
|
||||
|
|
|
@ -193,6 +193,9 @@ struct _GstRawBaseParseClass
|
|||
|
||||
gint (*get_overhead_size) (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config);
|
||||
|
||||
gint (*get_alignment) (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -182,11 +182,12 @@ static GstRawVideoParseConfig
|
|||
* gst_raw_video_parse_get_config_ptr (GstRawVideoParse * raw_video_parse,
|
||||
GstRawBaseParseConfig config);
|
||||
|
||||
static gint gst_raw_video_parse_get_alignment (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config);
|
||||
|
||||
static void gst_raw_video_parse_init_config (GstRawVideoParseConfig * config);
|
||||
static void gst_raw_video_parse_update_info (GstRawVideoParseConfig * config);
|
||||
|
||||
|
||||
|
||||
static void
|
||||
gst_raw_video_parse_class_init (GstRawVideoParseClass * klass)
|
||||
{
|
||||
|
@ -236,6 +237,8 @@ gst_raw_video_parse_class_init (GstRawVideoParseClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_raw_video_parse_get_units_per_second);
|
||||
rawbaseparse_class->get_overhead_size =
|
||||
GST_DEBUG_FUNCPTR (gst_raw_video_parse_get_overhead_size);
|
||||
rawbaseparse_class->get_alignment =
|
||||
GST_DEBUG_FUNCPTR (gst_raw_video_parse_get_alignment);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WIDTH,
|
||||
|
@ -929,6 +932,12 @@ gst_raw_video_parse_is_config_ready (GstRawBaseParse * raw_base_parse,
|
|||
return gst_raw_video_parse_get_config_ptr (raw_video_parse, config)->ready;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_raw_video_parse_get_alignment (GstRawBaseParse * raw_base_parse,
|
||||
GstRawBaseParseConfig config)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_video_parse_process (GstRawBaseParse * raw_base_parse,
|
||||
|
|
Loading…
Reference in a new issue