From fae3777c1581e408419035afc2e03e6392a5793a Mon Sep 17 00:00:00 2001 From: gb Date: Tue, 16 Mar 2010 17:57:57 +0000 Subject: [PATCH] Alias sink & src pad buffers whenever possible. --- sys/vaapiconvert/gstvaapiconvert.c | 137 ++++++++++++++++++++++++++++++++----- sys/vaapiconvert/gstvaapiconvert.h | 1 + 2 files changed, 120 insertions(+), 18 deletions(-) diff --git a/sys/vaapiconvert/gstvaapiconvert.c b/sys/vaapiconvert/gstvaapiconvert.c index afd5578..c93dee9 100644 --- a/sys/vaapiconvert/gstvaapiconvert.c +++ b/sys/vaapiconvert/gstvaapiconvert.c @@ -193,6 +193,7 @@ gst_vaapiconvert_init(GstVaapiConvert *convert, GstVaapiConvertClass *klass) convert->surfaces = NULL; convert->surface_width = 0; convert->surface_height = 0; + convert->use_inout_buffers = 0; /* Override buffer allocator on sink pad */ sinkpad = gst_element_get_static_pad(GST_ELEMENT(convert), "sink"); @@ -245,14 +246,34 @@ gst_vaapiconvert_transform( GstVaapiSurface *surface; GstVaapiImage *image; - image = gst_vaapi_video_pool_get_object(convert->images); - if (!image) - return GST_FLOW_UNEXPECTED; - surface = gst_vaapi_video_buffer_get_surface(vbuffer); if (!surface) return GST_FLOW_UNEXPECTED; + if (convert->use_inout_buffers) { + if (!GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) { + GST_DEBUG("GstVaapiVideoBuffer was expected"); + return GST_FLOW_UNEXPECTED; + } + if (inbuf != outbuf) { + GST_DEBUG("same GstVaapiVideoBuffer was expected on both pads"); + return GST_FLOW_UNEXPECTED; + } + + image = gst_vaapi_video_buffer_get_image(vbuffer); + if (!image) + return GST_FLOW_UNEXPECTED; + if (!gst_vaapi_image_unmap(image)) + return GST_FLOW_UNEXPECTED; + + gst_vaapi_surface_put_image(surface, image); + return GST_FLOW_OK; + } + + image = gst_vaapi_video_pool_get_object(convert->images); + if (!image) + return GST_FLOW_UNEXPECTED; + gst_vaapi_image_update_from_buffer(image, inbuf); gst_vaapi_surface_put_image(surface, image); gst_vaapi_video_pool_put_object(convert->images, image); @@ -314,17 +335,13 @@ gst_vaapiconvert_transform_caps( } static gboolean -gst_vaapiconvert_set_caps( - GstBaseTransform *trans, - GstCaps *incaps, - GstCaps *outcaps -) +gst_vaapiconvert_ensure_image_pool(GstVaapiConvert *convert, GstCaps *caps) { - GstVaapiConvert * const convert = GST_VAAPICONVERT(trans); - GstStructure *structure; + GstStructure * const structure = gst_caps_get_structure(caps, 0); + GstVideoFormat vformat; + GstVaapiImage *image; gint width, height; - structure = gst_caps_get_structure(incaps, 0); gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); @@ -333,12 +350,31 @@ gst_vaapiconvert_set_caps( convert->image_height = height; if (convert->images) g_object_unref(convert->images); - convert->images = gst_vaapi_image_pool_new(convert->display, incaps); + convert->images = gst_vaapi_image_pool_new(convert->display, caps); if (!convert->images) return FALSE; + + /* Check if we can alias sink & output buffers (same data_size) */ + if (gst_video_format_parse_caps(caps, &vformat, NULL, NULL)) { + image = gst_vaapi_video_pool_get_object(convert->images); + if (image) { + convert->use_inout_buffers = + (gst_vaapi_image_is_linear(image) && + (gst_vaapi_image_get_data_size(image) == + gst_video_format_get_size(vformat, width, height))); + gst_vaapi_video_pool_put_object(convert->images, image); + } + } } + return TRUE; +} + +static gboolean +gst_vaapiconvert_ensure_surface_pool(GstVaapiConvert *convert, GstCaps *caps) +{ + GstStructure * const structure = gst_caps_get_structure(caps, 0); + gint width, height; - structure = gst_caps_get_structure(outcaps, 0); gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); @@ -347,7 +383,7 @@ gst_vaapiconvert_set_caps( convert->surface_height = height; if (convert->surfaces) g_object_unref(convert->surfaces); - convert->surfaces = gst_vaapi_surface_pool_new(convert->display, outcaps); + convert->surfaces = gst_vaapi_surface_pool_new(convert->display, caps); if (!convert->surfaces) return FALSE; } @@ -355,6 +391,24 @@ gst_vaapiconvert_set_caps( } static gboolean +gst_vaapiconvert_set_caps( + GstBaseTransform *trans, + GstCaps *incaps, + GstCaps *outcaps +) +{ + GstVaapiConvert * const convert = GST_VAAPICONVERT(trans); + + if (!gst_vaapiconvert_ensure_image_pool(convert, incaps)) + return FALSE; + + if (!gst_vaapiconvert_ensure_surface_pool(convert, outcaps)) + return FALSE; + + return TRUE; +} + +static gboolean gst_vaapiconvert_get_unit_size( GstBaseTransform *trans, GstCaps *caps, @@ -383,6 +437,44 @@ gst_vaapiconvert_buffer_alloc( GstBuffer **pbuf ) { + GstVaapiConvert * const convert = GST_VAAPICONVERT(trans); + GstBuffer *buffer = NULL; + GstVaapiImage *image; + + /* Check if we can use the inout-buffers optimization */ + if (!gst_vaapiconvert_ensure_surface_pool(convert, caps)) + goto error; + if (!gst_vaapiconvert_ensure_image_pool(convert, caps)) + goto error; + if (!convert->use_inout_buffers) + return GST_FLOW_OK; + + buffer = gst_vaapi_video_buffer_new_from_pool(convert->surfaces); + if (!buffer) + goto error; + + GstVaapiVideoBuffer * const vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer); + if (!gst_vaapi_video_buffer_set_image_from_pool(vbuffer, convert->images)) + goto error; + + image = gst_vaapi_video_buffer_get_image(vbuffer); + g_assert(image); + + if (!gst_vaapi_image_map(image)) + goto error; + + GST_BUFFER_DATA(buffer) = gst_vaapi_image_get_plane(image, 0); + GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(image); + + gst_buffer_set_caps(buffer, caps); + *pbuf = buffer; + return GST_FLOW_OK; + +error: + /* We can't use the inout-buffers optimization. Disable it. */ + if (buffer) + gst_buffer_unref(buffer); + convert->use_inout_buffers = FALSE; return GST_FLOW_OK; } @@ -419,9 +511,18 @@ gst_vaapiconvert_prepare_output_buffer( GstVaapiConvert * const convert = GST_VAAPICONVERT(trans); GstBuffer *buffer; - buffer = gst_vaapi_video_buffer_new_from_pool(convert->surfaces); - if (!buffer) - return GST_FLOW_UNEXPECTED; + if (convert->use_inout_buffers) { + if (!GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) { + GST_DEBUG("GstVaapiVideoBuffer was expected"); + return GST_FLOW_UNEXPECTED; + } + buffer = gst_buffer_ref(inbuf); + } + else { + buffer = gst_vaapi_video_buffer_new_from_pool(convert->surfaces); + if (!buffer) + return GST_FLOW_UNEXPECTED; + } gst_buffer_set_caps(buffer, caps); *poutbuf = buffer; diff --git a/sys/vaapiconvert/gstvaapiconvert.h b/sys/vaapiconvert/gstvaapiconvert.h index 98487f6..aee556d 100644 --- a/sys/vaapiconvert/gstvaapiconvert.h +++ b/sys/vaapiconvert/gstvaapiconvert.h @@ -71,6 +71,7 @@ struct _GstVaapiConvert { GstVaapiVideoPool *surfaces; guint surface_width; guint surface_height; + unsigned int use_inout_buffers : 1; }; struct _GstVaapiConvertClass { -- 2.7.4