va: vpp: Add raw buffer copy when needed.
Just like the decoder, the vapostproc also needs to copy the output buffer to raw buffer if downstream elements only supports raw caps and does not support the video meta. The pipeline like: gst-launch-1.0 filesrc location=xxxx ! h264parse ! vah264dec ! \ vapostproc ! capsfilter caps=video/x-raw,width=55,height=128 ! \ filesink location=xxx needs this logic to dump the data correctly. fixes: #1523 Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2026>
This commit is contained in:
parent
438449db69
commit
2e9a096282
@ -105,6 +105,9 @@ struct _GstVaVpp
|
|||||||
GstBufferPool *sinkpad_pool;
|
GstBufferPool *sinkpad_pool;
|
||||||
GstVideoInfo sinkpad_info;
|
GstVideoInfo sinkpad_info;
|
||||||
|
|
||||||
|
GstBufferPool *other_pool;
|
||||||
|
GstVideoInfo srcpad_info;
|
||||||
|
|
||||||
guint op_flags;
|
guint op_flags;
|
||||||
|
|
||||||
/* filters */
|
/* filters */
|
||||||
@ -169,6 +172,11 @@ gst_va_vpp_dispose (GObject * object)
|
|||||||
gst_clear_object (&self->sinkpad_pool);
|
gst_clear_object (&self->sinkpad_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->other_pool) {
|
||||||
|
gst_buffer_pool_set_active (self->other_pool, FALSE);
|
||||||
|
gst_clear_object (&self->other_pool);
|
||||||
|
}
|
||||||
|
|
||||||
gst_clear_caps (&self->incaps);
|
gst_clear_caps (&self->incaps);
|
||||||
gst_clear_caps (&self->outcaps);
|
gst_clear_caps (&self->outcaps);
|
||||||
|
|
||||||
@ -520,6 +528,25 @@ config_failed:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstBufferPool *
|
||||||
|
_create_other_pool (GstAllocator * allocator,
|
||||||
|
GstAllocationParams * params, GstCaps * caps, guint size)
|
||||||
|
{
|
||||||
|
GstBufferPool *pool = NULL;
|
||||||
|
GstStructure *config;
|
||||||
|
|
||||||
|
pool = gst_video_buffer_pool_new ();
|
||||||
|
config = gst_buffer_pool_get_config (pool);
|
||||||
|
|
||||||
|
gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
|
||||||
|
gst_buffer_pool_config_set_allocator (config, allocator, params);
|
||||||
|
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||||
|
gst_clear_object (&pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
/* configure the allocation query that was answered downstream, we can
|
/* configure the allocation query that was answered downstream, we can
|
||||||
* configure some properties on it. Only called when not in
|
* configure some properties on it. Only called when not in
|
||||||
* passthrough mode. */
|
* passthrough mode. */
|
||||||
@ -527,33 +554,44 @@ static gboolean
|
|||||||
gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstVaVpp *self = GST_VA_VPP (trans);
|
GstVaVpp *self = GST_VA_VPP (trans);
|
||||||
GstAllocator *allocator = NULL;
|
GstAllocator *allocator = NULL, *other_allocator = NULL;
|
||||||
GstAllocationParams params;
|
GstAllocationParams params, other_params;
|
||||||
GstBufferPool *pool = NULL;
|
GstBufferPool *pool = NULL, *other_pool = NULL;
|
||||||
GstCaps *outcaps = NULL;
|
GstCaps *outcaps = NULL;
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
guint min, max, size = 0, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE;
|
guint min, max, size = 0, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE;
|
||||||
gboolean update_pool, update_allocator;
|
gboolean update_pool, update_allocator, has_videometa, copy_frames;
|
||||||
|
GstVideoInfo alloc_info;
|
||||||
|
|
||||||
gst_query_parse_allocation (query, &outcaps, NULL);
|
gst_query_parse_allocation (query, &outcaps, NULL);
|
||||||
|
|
||||||
|
gst_allocation_params_init (&other_params);
|
||||||
|
gst_allocation_params_init (¶ms);
|
||||||
|
|
||||||
if (gst_query_get_n_allocation_params (query) > 0) {
|
if (gst_query_get_n_allocation_params (query) > 0) {
|
||||||
gst_query_parse_nth_allocation_param (query, 0, &allocator, NULL);
|
gst_query_parse_nth_allocation_param (query, 0, &allocator, &other_params);
|
||||||
if (allocator && !(GST_IS_VA_DMABUF_ALLOCATOR (allocator)
|
if (allocator && !(GST_IS_VA_DMABUF_ALLOCATOR (allocator)
|
||||||
|| GST_IS_VA_ALLOCATOR (allocator)))
|
|| GST_IS_VA_ALLOCATOR (allocator))) {
|
||||||
gst_clear_object (&allocator);
|
/* save the allocator for the other pool */
|
||||||
|
other_allocator = allocator;
|
||||||
|
allocator = NULL;
|
||||||
|
}
|
||||||
update_allocator = TRUE;
|
update_allocator = TRUE;
|
||||||
} else {
|
} else {
|
||||||
update_allocator = FALSE;
|
update_allocator = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_allocation_params_init (¶ms);
|
|
||||||
|
|
||||||
if (gst_query_get_n_allocation_pools (query) > 0) {
|
if (gst_query_get_n_allocation_pools (query) > 0) {
|
||||||
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
|
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
|
||||||
|
|
||||||
if (pool && !GST_IS_VA_POOL (pool))
|
if (pool) {
|
||||||
gst_clear_object (&pool);
|
if (!GST_IS_VA_POOL (pool)) {
|
||||||
|
GST_DEBUG_OBJECT (self,
|
||||||
|
"may need other pool for copy frames %" GST_PTR_FORMAT, pool);
|
||||||
|
other_pool = pool;
|
||||||
|
pool = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update_pool = TRUE;
|
update_pool = TRUE;
|
||||||
} else {
|
} else {
|
||||||
@ -566,6 +604,9 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||||||
update_pool = FALSE;
|
update_pool = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_videometa = gst_query_find_allocation_meta (query,
|
||||||
|
GST_VIDEO_META_API_TYPE, NULL);
|
||||||
|
|
||||||
if (!allocator) {
|
if (!allocator) {
|
||||||
if (!(allocator = _create_allocator (self, outcaps, usage_hint)))
|
if (!(allocator = _create_allocator (self, outcaps, usage_hint)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -586,17 +627,43 @@ gst_va_vpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
|
|||||||
else
|
else
|
||||||
gst_query_add_allocation_param (query, allocator, ¶ms);
|
gst_query_add_allocation_param (query, allocator, ¶ms);
|
||||||
|
|
||||||
|
alloc_info = self->out_info;
|
||||||
|
if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
|
||||||
|
gst_va_dmabuf_allocator_get_format (allocator, &alloc_info, NULL);
|
||||||
|
} else if (GST_IS_VA_ALLOCATOR (allocator)) {
|
||||||
|
gst_va_allocator_get_format (allocator, &alloc_info, NULL);
|
||||||
|
}
|
||||||
|
self->srcpad_info = alloc_info;
|
||||||
|
|
||||||
if (update_pool)
|
if (update_pool)
|
||||||
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
|
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
|
||||||
else
|
else
|
||||||
gst_query_add_allocation_pool (query, pool, size, min, max);
|
gst_query_add_allocation_pool (query, pool, size, min, max);
|
||||||
|
|
||||||
|
copy_frames = (!has_videometa && gst_va_pool_requires_video_meta (pool)
|
||||||
|
&& gst_caps_is_raw (outcaps));
|
||||||
|
if (copy_frames) {
|
||||||
|
if (other_pool) {
|
||||||
|
gst_object_replace ((GstObject **) & self->other_pool,
|
||||||
|
(GstObject *) other_pool);
|
||||||
|
} else {
|
||||||
|
self->other_pool =
|
||||||
|
_create_other_pool (other_allocator, &other_params, outcaps, size);
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (self, "Use the other pool for copy %" GST_PTR_FORMAT,
|
||||||
|
self->other_pool);
|
||||||
|
} else {
|
||||||
|
gst_clear_object (&self->other_pool);
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self,
|
GST_DEBUG_OBJECT (self,
|
||||||
"decided pool %" GST_PTR_FORMAT " with allocator %" GST_PTR_FORMAT,
|
"decided pool %" GST_PTR_FORMAT " with allocator %" GST_PTR_FORMAT,
|
||||||
pool, allocator);
|
pool, allocator);
|
||||||
|
|
||||||
gst_object_unref (allocator);
|
gst_object_unref (allocator);
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
|
gst_clear_object (&other_allocator);
|
||||||
|
gst_clear_object (&other_pool);
|
||||||
|
|
||||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
|
return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
|
||||||
query);
|
query);
|
||||||
@ -684,6 +751,11 @@ gst_va_vpp_set_caps (GstBaseTransform * trans, GstCaps * incaps,
|
|||||||
gst_clear_object (&self->sinkpad_pool);
|
gst_clear_object (&self->sinkpad_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->other_pool) {
|
||||||
|
gst_buffer_pool_set_active (self->other_pool, FALSE);
|
||||||
|
gst_clear_object (&self->other_pool);
|
||||||
|
}
|
||||||
|
|
||||||
gst_caps_replace (&self->incaps, incaps);
|
gst_caps_replace (&self->incaps, incaps);
|
||||||
gst_caps_replace (&self->outcaps, outcaps);
|
gst_caps_replace (&self->outcaps, outcaps);
|
||||||
|
|
||||||
@ -2105,6 +2177,64 @@ gst_va_vpp_sink_event (GstBaseTransform * trans, GstEvent * event)
|
|||||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
|
return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_va_vpp_generate_output (GstBaseTransform * trans, GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstVaVpp *self = GST_VA_VPP (trans);
|
||||||
|
GstVideoFrame src_frame;
|
||||||
|
GstVideoFrame dest_frame;
|
||||||
|
GstBuffer *buffer = NULL;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
ret = GST_BASE_TRANSFORM_CLASS (parent_class)->generate_output (trans,
|
||||||
|
outbuf);
|
||||||
|
|
||||||
|
if (ret != GST_FLOW_OK || *outbuf == NULL)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!self->other_pool)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* Now need to copy the output buffer */
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
if (!gst_buffer_pool_set_active (self->other_pool, TRUE)) {
|
||||||
|
GST_WARNING_OBJECT (self, "failed to active the other pool %"
|
||||||
|
GST_PTR_FORMAT, self->other_pool);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_buffer_pool_acquire_buffer (self->other_pool, &buffer, NULL);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&src_frame, &self->srcpad_info, *outbuf,
|
||||||
|
GST_MAP_READ))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&dest_frame, &self->out_info, buffer,
|
||||||
|
GST_MAP_WRITE)) {
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_video_frame_copy (&dest_frame, &src_frame)) {
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
gst_video_frame_unmap (&dest_frame);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
gst_video_frame_unmap (&dest_frame);
|
||||||
|
|
||||||
|
gst_buffer_replace (outbuf, buffer);
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
out:
|
||||||
|
gst_clear_buffer (&buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_va_vpp_class_init (gpointer g_class, gpointer class_data)
|
gst_va_vpp_class_init (gpointer g_class, gpointer class_data)
|
||||||
{
|
{
|
||||||
@ -2183,6 +2313,7 @@ gst_va_vpp_class_init (gpointer g_class, gpointer class_data)
|
|||||||
trans_class->filter_meta = GST_DEBUG_FUNCPTR (gst_va_vpp_filter_meta);
|
trans_class->filter_meta = GST_DEBUG_FUNCPTR (gst_va_vpp_filter_meta);
|
||||||
trans_class->src_event = GST_DEBUG_FUNCPTR (gst_va_vpp_src_event);
|
trans_class->src_event = GST_DEBUG_FUNCPTR (gst_va_vpp_src_event);
|
||||||
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_va_vpp_sink_event);
|
trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_va_vpp_sink_event);
|
||||||
|
trans_class->generate_output = GST_DEBUG_FUNCPTR (gst_va_vpp_generate_output);
|
||||||
|
|
||||||
trans_class->transform_ip_on_passthrough = FALSE;
|
trans_class->transform_ip_on_passthrough = FALSE;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user