diff --git a/gst/vaapi/gstvaapivideobufferpool.c b/gst/vaapi/gstvaapivideobufferpool.c index a97fa558d1..275ccc4f63 100644 --- a/gst/vaapi/gstvaapivideobufferpool.c +++ b/gst/vaapi/gstvaapivideobufferpool.c @@ -267,6 +267,8 @@ gst_vaapi_video_buffer_pool_alloc_buffer (GstBufferPool * pool, { GstVaapiVideoBufferPoolPrivate *const priv = GST_VAAPI_VIDEO_BUFFER_POOL (pool)->priv; + GstVaapiVideoBufferPoolAcquireParams *const priv_params = + (GstVaapiVideoBufferPoolAcquireParams *) params; GstVaapiVideoMeta *meta; GstMemory *mem; GstBuffer *buffer; @@ -290,6 +292,9 @@ gst_vaapi_video_buffer_pool_alloc_buffer (GstBufferPool * pool, if (!buffer) goto error_create_buffer; + if (priv_params && priv_params->proxy) + gst_vaapi_video_meta_set_surface_proxy (meta, priv_params->proxy); + if (priv->use_dmabuf_memory) mem = gst_vaapi_dmabuf_memory_new (priv->allocator, meta); else diff --git a/gst/vaapi/gstvaapivideomemory.c b/gst/vaapi/gstvaapivideomemory.c index ebb0065fc6..c37985b03e 100644 --- a/gst/vaapi/gstvaapivideomemory.c +++ b/gst/vaapi/gstvaapivideomemory.c @@ -945,6 +945,7 @@ gst_vaapi_dmabuf_memory_new (GstAllocator * base_allocator, gint dmabuf_fd; const GstVideoInfo *surface_info; guint surface_alloc_flags; + gboolean needs_surface; GstVaapiDmaBufAllocator *const allocator = GST_VAAPI_DMABUF_ALLOCATOR_CAST (base_allocator); @@ -960,22 +961,36 @@ gst_vaapi_dmabuf_memory_new (GstAllocator * base_allocator, if (!display) return NULL; - surface = gst_vaapi_surface_new_full (display, surface_info, - surface_alloc_flags); - if (!surface) - goto error_create_surface; + proxy = gst_vaapi_video_meta_get_surface_proxy (meta); + needs_surface = (proxy == NULL); - proxy = gst_vaapi_surface_proxy_new (surface); - if (!proxy) - goto error_create_surface_proxy; + if (needs_surface) { + /* When exporting output VPP surfaces, or when exporting input + * surfaces to be filled/imported by an upstream element, such as + * v4l2src, we have to instantiate a VA surface to store it. */ + surface = gst_vaapi_surface_new_full (display, surface_info, + surface_alloc_flags); + if (!surface) + goto error_create_surface; + proxy = gst_vaapi_surface_proxy_new (surface); + if (!proxy) + goto error_create_surface_proxy; + } else { + /* When exporting existing surfaces that come from decoder's + * context. */ + surface = GST_VAAPI_SURFACE_PROXY_SURFACE (proxy); + } dmabuf_proxy = gst_vaapi_surface_get_dma_buf_handle (surface); - gst_vaapi_object_unref (surface); if (!dmabuf_proxy) goto error_create_dmabuf_proxy; - gst_vaapi_video_meta_set_surface_proxy (meta, proxy); - gst_vaapi_surface_proxy_unref (proxy); + if (needs_surface) { + /* The proxy has incremented the surface ref count. */ + gst_vaapi_object_unref (surface); + gst_vaapi_video_meta_set_surface_proxy (meta, proxy); + gst_vaapi_surface_proxy_unref (proxy); + } /* Need dup because GstDmabufMemory creates the GstFdMemory with flag * GST_FD_MEMORY_FLAG_NONE. So when being freed it calls close on the fd @@ -989,9 +1004,19 @@ gst_vaapi_dmabuf_memory_new (GstAllocator * base_allocator, if (!mem) goto error_create_dmabuf_memory; - gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem), - GST_VAAPI_BUFFER_PROXY_QUARK, dmabuf_proxy, - (GDestroyNotify) gst_vaapi_buffer_proxy_unref); + if (needs_surface) { + /* Just set the GstVaapiBufferProxy (dmabuf_proxy) as qdata and + * forget about it. */ + gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem), + GST_VAAPI_BUFFER_PROXY_QUARK, dmabuf_proxy, + (GDestroyNotify) gst_vaapi_buffer_proxy_unref); + } else { + /* When not allocating the surface from this pool, so when + * exporting from the decoder's VA context, we need to know which + * GstMemory belongs to a provided surface. */ + gst_vaapi_buffer_proxy_set_mem (dmabuf_proxy, mem); + gst_vaapi_surface_set_buffer_proxy (surface, dmabuf_proxy); + } /* When a VA surface is going to be filled by a VAAPI element * (decoder or VPP), it has _not_ be marked as busy in the driver. @@ -1020,7 +1045,10 @@ error_create_surface_proxy: error_create_dmabuf_proxy: { GST_ERROR ("failed to export VA surface to DMABUF"); - gst_vaapi_surface_proxy_unref (proxy); + if (surface) + gst_vaapi_object_unref (surface); + if (proxy) + gst_vaapi_surface_proxy_unref (proxy); return NULL; } error_create_dmabuf_handle: