diff --git a/gst/rawparse/gstrawaudioparse.c b/gst/rawparse/gstrawaudioparse.c index 98575ddb73..626604c02a 100644 --- a/gst/rawparse/gstrawaudioparse.c +++ b/gst/rawparse/gstrawaudioparse.c @@ -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, diff --git a/gst/rawparse/gstrawbaseparse.c b/gst/rawparse/gstrawbaseparse.c index c2ccee511c..99d64dad09 100644 --- a/gst/rawparse/gstrawbaseparse.c +++ b/gst/rawparse/gstrawbaseparse.c @@ -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. diff --git a/gst/rawparse/gstrawbaseparse.h b/gst/rawparse/gstrawbaseparse.h index 519b409ed2..4af4408c23 100644 --- a/gst/rawparse/gstrawbaseparse.h +++ b/gst/rawparse/gstrawbaseparse.h @@ -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); }; diff --git a/gst/rawparse/gstrawvideoparse.c b/gst/rawparse/gstrawvideoparse.c index 2fb58c1383..38083699e7 100644 --- a/gst/rawparse/gstrawvideoparse.c +++ b/gst/rawparse/gstrawvideoparse.c @@ -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,