/** * ensure_sinkpad_buffer_pool: * @plugin: a #GstVaapiPluginBase * @caps: the initial #GstCaps for the resulting buffer pool * * Makes sure the sink pad video buffer pool is created with the * appropriate @caps. * * Returns: %TRUE if successful, %FALSE otherwise. */ static gboolean ensure_sinkpad_buffer_pool (GstVaapiPluginBase * plugin, GstCaps * caps) { GstBufferPool *pool; GstCaps *pool_caps; GstStructure *config; GstVideoInfo vi; gboolean need_pool; if (!gst_vaapi_plugin_base_ensure_display (plugin)) return FALSE; if (plugin->sinkpad_buffer_pool) { config = gst_buffer_pool_get_config (plugin->sinkpad_buffer_pool); gst_buffer_pool_config_get_params (config, &pool_caps, NULL, NULL, NULL); need_pool = !gst_caps_is_equal (caps, pool_caps); gst_structure_free (config); if (!need_pool) return TRUE; g_clear_object (&plugin->sinkpad_buffer_pool); plugin->sinkpad_buffer_size = 0; } pool = gst_vaapi_video_buffer_pool_new (plugin->display); if (!pool) goto error_create_pool; gst_video_info_init (&vi); gst_video_info_from_caps (&vi, caps); if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) { GST_DEBUG ("assume video buffer pool format is NV12"); gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_NV12, GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi)); } plugin->sinkpad_buffer_size = vi.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, plugin->sinkpad_buffer_size, 0, 0); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); if (!gst_buffer_pool_set_config (pool, config)) goto error_pool_config; plugin->sinkpad_buffer_pool = pool; return TRUE; /* ERRORS */ error_create_pool: { GST_ERROR ("failed to create buffer pool"); return FALSE; } error_pool_config: { GST_ERROR ("failed to reset buffer pool config"); gst_object_unref (pool); return FALSE; } }
/** * gst_vaapi_plugin_base_decide_allocation: * @plugin: a #GstVaapiPluginBase * @query: the allocation query to parse * @feature: the desired #GstVaapiCapsFeature, or zero to find the * preferred one * * Decides allocation parameters for the downstream elements. * * Returns: %TRUE if successful, %FALSE otherwise. */ gboolean gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin, GstQuery * query, guint feature) { GstCaps *caps = NULL; GstBufferPool *pool; GstStructure *config; GstVideoInfo vi; guint size, min, max; gboolean update_pool = FALSE; gboolean has_video_meta = FALSE; gboolean has_video_alignment = FALSE; #if (USE_GLX || USE_EGL) gboolean has_texture_upload_meta = FALSE; guint idx; #endif g_return_val_if_fail (plugin->display != NULL, FALSE); gst_query_parse_allocation (query, &caps, NULL); /* We don't need any GL context beyond this point if not requested so explicitly through GstVideoGLTextureUploadMeta */ gst_object_replace (&plugin->gl_context, NULL); if (!caps) goto error_no_caps; if (!feature) feature = gst_vaapi_find_preferred_caps_feature (plugin->srcpad, GST_VIDEO_FORMAT_ENCODED, NULL); has_video_meta = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); #if (USE_GLX || USE_EGL) has_texture_upload_meta = gst_query_find_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx) && (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META); #if USE_GST_GL_HELPERS if (has_texture_upload_meta) { const GstStructure *params; GstObject *gl_context; gst_query_parse_nth_allocation_meta (query, idx, ¶ms); if (params) { if (gst_structure_get (params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, &gl_context, NULL) && gl_context) { gst_vaapi_plugin_base_set_gl_context (plugin, gl_context); gst_object_unref (gl_context); } } } #endif #endif /* Make sure the display we pass down to the buffer pool is actually the expected one, especially when the downstream element requires a GLX or EGL display */ if (!gst_vaapi_plugin_base_ensure_display (plugin)) goto error_ensure_display; gst_video_info_init (&vi); gst_video_info_from_caps (&vi, caps); if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_I420, GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi)); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; size = MAX (size, vi.size); if (pool) { /* Check whether downstream element proposed a bufferpool but did not provide a correct propose_allocation() implementation */ has_video_alignment = gst_buffer_pool_has_option (pool, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); } } else { pool = NULL; size = vi.size; min = max = 0; } /* GstVaapiVideoMeta is mandatory, and this implies VA surface memory */ if (!pool || !gst_buffer_pool_has_option (pool, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) { GST_INFO_OBJECT (plugin, "%s. Making a new pool", pool == NULL ? "No pool" : "Pool hasn't GstVaapiVideoMeta"); if (pool) gst_object_unref (pool); pool = gst_vaapi_video_buffer_pool_new (plugin->display); if (!pool) goto error_create_pool; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } /* Check whether GstVideoMeta, or GstVideoAlignment, is needed (raw video) */ if (has_video_meta) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_META)) goto config_failed; } else if (has_video_alignment) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) goto config_failed; } /* GstVideoGLTextureUploadMeta (OpenGL) */ #if (USE_GLX || USE_EGL) if (has_texture_upload_meta) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META)) goto config_failed; } #endif if (update_pool) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); g_clear_object (&plugin->srcpad_buffer_pool); plugin->srcpad_buffer_pool = pool; return TRUE; /* ERRORS */ error_no_caps: { GST_ERROR_OBJECT (plugin, "no caps specified"); return FALSE; } error_ensure_display: { GST_ERROR_OBJECT (plugin, "failed to ensure display of type %d", plugin->display_type_req); return FALSE; } error_create_pool: { GST_ERROR_OBJECT (plugin, "failed to create buffer pool"); return FALSE; } config_failed: { if (pool) gst_object_unref (pool); GST_ELEMENT_ERROR (plugin, RESOURCE, SETTINGS, ("Failed to configure the buffer pool"), ("Configuration is most likely invalid, please report this issue.")); return FALSE; } }
/** * gst_vaapi_plugin_base_create_pool: * @plugin: a #GstVaapiPluginBase * @caps: the initial #GstCaps for the resulting buffer pool * @size: the size of each buffer, not including prefix and padding * @options: a set of #GstVaapiVideoBufferPoolOption encoded as bit-wise * @allocator: (allow-none): the #GstAllocator to use or %NULL * * Create an instance of #GstVaapiVideoBufferPool * * Returns: (transfer full): a new allocated #GstBufferPool **/ static GstBufferPool * gst_vaapi_plugin_base_create_pool (GstVaapiPluginBase * plugin, GstCaps * caps, gsize size, guint min_buffers, guint max_buffers, guint options, GstAllocator * allocator) { GstBufferPool *pool; GstStructure *config; if (!(pool = gst_vaapi_video_buffer_pool_new (plugin->display))) goto error_create_pool; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META); if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META) { gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT) { gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); } #if (USE_GLX || USE_EGL) if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_GL_TEXTURE_UPLOAD) { gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); } #endif if (allocator) gst_buffer_pool_config_set_allocator (config, allocator, NULL); if (!gst_buffer_pool_set_config (pool, config)) { config = gst_buffer_pool_get_config (pool); if (!gst_buffer_pool_config_validate_params (config, caps, size, min_buffers, max_buffers)) { gst_structure_free (config); goto error_pool_config; } if (!gst_buffer_pool_set_config (pool, config)) goto error_pool_config; } return pool; /* ERRORS */ error_create_pool: { GST_ERROR_OBJECT (plugin, "failed to create buffer pool"); return NULL; } error_pool_config: { gst_object_unref (pool); GST_ELEMENT_ERROR (plugin, RESOURCE, SETTINGS, ("Failed to configure the buffer pool"), ("Configuration is most likely invalid, please report this issue.")); return NULL; } }