From 35c937f2a45e23762bbfb43ce3378d4d05f48d25 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Fri, 13 Mar 2015 17:00:03 +0000 Subject: [PATCH] mpeg2dec: Add stride support This allow using external pools that have different strides from the default. These strides need to respect certain rules, which we check and if these are not met, we fallback to generic pool. https://bugzilla.gnome.org/show_bug.cgi?id=735379 --- ext/mpeg2dec/gstmpeg2dec.c | 87 ++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/ext/mpeg2dec/gstmpeg2dec.c b/ext/mpeg2dec/gstmpeg2dec.c index 7390875923..3f77b5a0a7 100644 --- a/ext/mpeg2dec/gstmpeg2dec.c +++ b/ext/mpeg2dec/gstmpeg2dec.c @@ -254,6 +254,25 @@ gst_mpeg2dec_finish (GstVideoDecoder * decoder) return GST_FLOW_OK; } +static GstBufferPool * +gst_mpeg2dec_create_generic_pool (GstAllocator * allocator, + GstAllocationParams * params, GstCaps * caps, guint size, guint min, + guint max, GstStructure ** out_config) +{ + GstBufferPool *pool; + GstStructure *config; + + pool = gst_video_buffer_pool_new (); + config = gst_buffer_pool_get_config (pool); + + gst_buffer_pool_config_set_allocator (config, allocator, params); + gst_buffer_pool_config_set_params (config, caps, size, min, max); + gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); + + *out_config = config; + return pool; +} + static gboolean gst_mpeg2dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) { @@ -334,14 +353,9 @@ gst_mpeg2dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) config = NULL; } - if (!pool) { - pool = gst_video_buffer_pool_new (); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); - gst_buffer_pool_config_set_params (config, caps, size, min, max); - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_META); - } + if (!pool) + pool = gst_mpeg2dec_create_generic_pool (allocator, ¶ms, caps, size, + min, max, &config); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); @@ -351,7 +365,7 @@ gst_mpeg2dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) if (allocator) gst_object_unref (allocator); - /* If we are copying out, we'll need to setup and active the other pool */ + /* If we are copying out, we'll need to setup and activate the other pool */ if (dec->downstream_pool) { if (!gst_buffer_pool_set_config (dec->downstream_pool, down_config)) { down_config = gst_buffer_pool_get_config (dec->downstream_pool); @@ -366,7 +380,7 @@ gst_mpeg2dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) } if (!gst_buffer_pool_set_active (dec->downstream_pool, TRUE)) - goto pool_activation_failed; + goto activate_failed; } /* Now configure the pool, if the pool had made some changes, it will @@ -399,8 +413,48 @@ gst_mpeg2dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; + } - /* FIXME Activate the pool, and check that strides are uniform */ + /* For external pools, we need to check strides */ + if (!GST_IS_VIDEO_BUFFER_POOL (pool) && has_videometa) { + GstBuffer *buffer; + const GstVideoFormatInfo *finfo; + GstVideoMeta *vmeta; + gint uv_stride; + + if (!gst_buffer_pool_set_active (pool, TRUE)) + goto activate_failed; + + if (gst_buffer_pool_acquire_buffer (pool, &buffer, NULL) != GST_FLOW_OK) { + gst_buffer_pool_set_active (pool, FALSE); + goto acquire_failed; + } + + vmeta = gst_buffer_get_video_meta (buffer); + finfo = gst_video_format_get_info (vmeta->format); + + /* Check that strides are compatible. In this case, we can scale the + * stride directly since all the pixel strides for the formats we support + * is 1 */ + uv_stride = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, 1, vmeta->stride[0]); + if (uv_stride != vmeta->stride[1] || uv_stride != vmeta->stride[2]) { + gst_buffer_pool_set_active (pool, FALSE); + gst_object_unref (pool); + + pool = gst_mpeg2dec_create_generic_pool (allocator, ¶ms, caps, size, + min, max, &config); + + if (dec->need_alignment) { + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); + gst_buffer_pool_config_set_video_alignment (config, &dec->valign); + } + + /* Generic pool don't fail on _set_config() */ + gst_buffer_pool_set_config (pool, config); + } + + gst_buffer_unref (buffer); } gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); @@ -415,10 +469,16 @@ config_failed: ("Configuration is most likely invalid, please report this issue.")); return FALSE; -pool_activation_failed: +activate_failed: gst_object_unref (pool); GST_ELEMENT_ERROR (dec, RESOURCE, SETTINGS, - ("Failed to activate downstream buffer pool"), (NULL)); + ("Failed to activate buffer pool"), (NULL)); + return FALSE; + +acquire_failed: + gst_object_unref (pool); + GST_ELEMENT_ERROR (dec, RESOURCE, SETTINGS, + ("Failed to acquire a buffer"), (NULL)); return FALSE; } @@ -900,6 +960,7 @@ handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info, /* Note: We use a non-null 'id' value to make the distinction * between the dummy buffers (which have an id of NULL) and the * ones we did */ + mpeg2_stride (mpeg2dec->decoder, vframe.info.stride[0]); mpeg2_set_buf (mpeg2dec->decoder, buf, GINT_TO_POINTER (frame->system_frame_number + 1)); gst_mpeg2dec_save_buffer (mpeg2dec, frame->system_frame_number, &vframe);