/** * gst_vaapi_surface_proxy_new_from_pool: * @pool: a #GstVaapiSurfacePool * * Allocates a new surface from the supplied surface @pool and creates * the wrapped surface proxy object from it. When the last reference * to the proxy object is released, then the underlying VA surface is * pushed back to its parent pool. * * Returns: The same newly allocated @proxy object, or %NULL on error */ GstVaapiSurfaceProxy * gst_vaapi_surface_proxy_new_from_pool (GstVaapiSurfacePool * pool) { GstVaapiSurfaceProxy *proxy; g_return_val_if_fail (pool != NULL, NULL); proxy = (GstVaapiSurfaceProxy *) gst_vaapi_mini_object_new (gst_vaapi_surface_proxy_class ()); if (!proxy) return NULL; proxy->parent = NULL; proxy->destroy_func = NULL; proxy->pool = gst_vaapi_video_pool_ref (GST_VAAPI_VIDEO_POOL (pool)); proxy->surface = gst_vaapi_video_pool_get_object (proxy->pool); if (!proxy->surface) goto error; gst_vaapi_object_ref (proxy->surface); gst_vaapi_surface_proxy_init_properties (proxy); return proxy; /* ERRORS */ error: { gst_vaapi_surface_proxy_unref (proxy); return NULL; } }
/** * gst_vaapi_coded_buffer_proxy_new_from_pool: * @pool: a #GstVaapiCodedBufferPool * * Allocates a new coded buffer from the supplied @pool and creates * the wrapped coded buffer proxy object from it. When the last * reference to the proxy object is released, then the underlying VA * coded buffer is pushed back to its parent pool. * * Returns: The same newly allocated @proxy object, or %NULL on error */ GstVaapiCodedBufferProxy * gst_vaapi_coded_buffer_proxy_new_from_pool (GstVaapiCodedBufferPool * pool) { GstVaapiCodedBufferProxy *proxy; g_return_val_if_fail (pool != NULL, NULL); g_return_val_if_fail (GST_VAAPI_VIDEO_POOL (pool)->object_type == GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER, NULL); proxy = (GstVaapiCodedBufferProxy *) gst_vaapi_mini_object_new (gst_vaapi_coded_buffer_proxy_class ()); if (!proxy) return NULL; proxy->destroy_func = NULL; proxy->user_data_destroy = NULL; proxy->pool = gst_vaapi_video_pool_ref (pool); proxy->buffer = gst_vaapi_video_pool_get_object (proxy->pool); if (!proxy->buffer) goto error; gst_vaapi_object_ref (proxy->buffer); return proxy; /* ERRORS */ error: { gst_vaapi_coded_buffer_proxy_unref (proxy); return NULL; } }
static gboolean ensure_image (GstVaapiVideoMemory * mem) { if (!mem->image && mem->use_direct_rendering) { mem->image = gst_vaapi_surface_derive_image (mem->surface); if (!mem->image) { GST_WARNING ("failed to derive image, fallbacking to copy"); mem->use_direct_rendering = FALSE; } else if (gst_vaapi_surface_get_format (mem->surface) != GST_VIDEO_INFO_FORMAT (mem->image_info)) { gst_vaapi_object_replace (&mem->image, NULL); mem->use_direct_rendering = FALSE; } } if (!mem->image) { GstVaapiVideoAllocator *const allocator = GST_VAAPI_VIDEO_ALLOCATOR_CAST (GST_MEMORY_CAST (mem)->allocator); mem->image = gst_vaapi_video_pool_get_object (allocator->image_pool); if (!mem->image) return FALSE; } gst_vaapi_video_meta_set_image (mem->meta, mem->image); return TRUE; }
static gboolean set_image_from_pool (GstVaapiVideoMeta * meta, GstVaapiVideoPool * pool) { GstVaapiImage *image; image = gst_vaapi_video_pool_get_object (pool); if (!image) return FALSE; set_image (meta, image); meta->image_pool = gst_vaapi_video_pool_ref (pool); return TRUE; }
int main (int argc, char *argv[]) { GstVaapiDisplay *display; GstVaapiSurface *surface; GstVaapiID surface_id; GstVaapiSurface *surfaces[MAX_SURFACES]; GstVaapiVideoPool *pool; gint i; static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420; static const guint width = 320; static const guint height = 240; if (!video_output_init (&argc, argv, NULL)) g_error ("failed to initialize video output subsystem"); display = video_output_create_display (NULL); if (!display) g_error ("could not create Gst/VA display"); surface = gst_vaapi_surface_new (display, chroma_type, width, height); if (!surface) g_error ("could not create Gst/VA surface"); surface_id = gst_vaapi_surface_get_id (surface); g_print ("created surface %" GST_VAAPI_ID_FORMAT "\n", GST_VAAPI_ID_ARGS (surface_id)); gst_vaapi_object_unref (surface); pool = gst_vaapi_surface_pool_new (display, GST_VIDEO_FORMAT_ENCODED, width, height); if (!pool) g_error ("could not create Gst/VA surface pool"); for (i = 0; i < MAX_SURFACES; i++) { surface = gst_vaapi_video_pool_get_object (pool); if (!surface) g_error ("could not allocate Gst/VA surface from pool"); g_print ("created surface %" GST_VAAPI_ID_FORMAT " from pool\n", GST_VAAPI_ID_ARGS (gst_vaapi_surface_get_id (surface))); surfaces[i] = surface; } /* Check the pool doesn't return the last free'd surface */ surface = gst_vaapi_object_ref (surfaces[1]); for (i = 0; i < 2; i++) gst_vaapi_video_pool_put_object (pool, surfaces[i]); for (i = 0; i < 2; i++) { surfaces[i] = gst_vaapi_video_pool_get_object (pool); if (!surfaces[i]) g_error ("could not re-allocate Gst/VA surface%d from pool", i); g_print ("created surface %" GST_VAAPI_ID_FORMAT " from pool (realloc)\n", GST_VAAPI_ID_ARGS (gst_vaapi_surface_get_id (surfaces[i]))); } if (surface == surfaces[0]) g_error ("Gst/VA pool doesn't queue free surfaces"); for (i = MAX_SURFACES - 1; i >= 0; i--) { if (!surfaces[i]) continue; gst_vaapi_video_pool_put_object (pool, surfaces[i]); surfaces[i] = NULL; } /* Unref in random order to check objects are correctly refcounted */ gst_vaapi_display_unref (display); gst_vaapi_video_pool_unref (pool); gst_vaapi_object_unref (surface); video_output_exit (); return 0; }
static GstVaapiSurface * vpp_convert (GstVaapiWindow * window, GstVaapiSurface * surface, const GstVaapiRectangle * src_rect, const GstVaapiRectangle * dst_rect, guint flags) { GstVaapiWindowWaylandPrivate *const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window); GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (window); GstVaapiSurface *vpp_surface = NULL; GstVaapiFilterStatus status; /* Ensure VA surface pool is created */ /* XXX: optimize the surface format to use. e.g. YUY2 */ if (!priv->surface_pool) { priv->surface_pool = gst_vaapi_surface_pool_new (display, priv->surface_format, window->width, window->height); if (!priv->surface_pool) return NULL; gst_vaapi_filter_replace (&priv->filter, NULL); } /* Ensure VPP pipeline is built */ if (!priv->filter) { priv->filter = gst_vaapi_filter_new (display); if (!priv->filter) goto error_create_filter; if (!gst_vaapi_filter_set_format (priv->filter, priv->surface_format)) goto error_unsupported_format; } if (!gst_vaapi_filter_set_cropping_rectangle (priv->filter, src_rect)) return NULL; if (!gst_vaapi_filter_set_target_rectangle (priv->filter, dst_rect)) return NULL; /* Post-process the decoded source surface */ vpp_surface = gst_vaapi_video_pool_get_object (priv->surface_pool); if (!vpp_surface) return NULL; status = gst_vaapi_filter_process (priv->filter, surface, vpp_surface, flags); if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) goto error_process_filter; return vpp_surface; /* ERRORS */ error_create_filter: { GST_WARNING ("failed to create VPP filter. Disabling"); priv->use_vpp = FALSE; return NULL; } error_unsupported_format: { GST_ERROR ("unsupported render target format %s", gst_vaapi_video_format_to_string (priv->surface_format)); priv->use_vpp = FALSE; return NULL; } error_process_filter: { GST_ERROR ("failed to process surface %" GST_VAAPI_ID_FORMAT " (error %d)", GST_VAAPI_ID_ARGS (GST_VAAPI_OBJECT_ID (surface)), status); gst_vaapi_video_pool_put_object (priv->surface_pool, vpp_surface); return NULL; } }