/** * gst_vaapi_plugin_base_propose_allocation: * @plugin: a #GstVaapiPluginBase * @query: the allocation query to configure * * Proposes allocation parameters to the upstream elements. * * Returns: %TRUE if successful, %FALSE otherwise. */ gboolean gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin, GstQuery * query) { GstCaps *caps = NULL; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) goto error_no_caps; if (need_pool) { if (!ensure_sinkpad_buffer_pool (plugin, caps)) return FALSE; gst_query_add_allocation_pool (query, plugin->sinkpad_buffer_pool, plugin->sinkpad_buffer_size, BUFFER_POOL_SINK_MIN_BUFFERS, 0); gst_query_add_allocation_param (query, plugin->sinkpad_allocator, NULL); } gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); return TRUE; /* ERRORS */ error_no_caps: { GST_INFO_OBJECT (plugin, "no caps specified"); return FALSE; } }
static gboolean gst_v4l2sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstV4l2Object *obj = v4l2sink->v4l2object; GstBufferPool *pool; guint size = 0; GstCaps *caps; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if ((pool = obj->pool)) gst_object_ref (pool); if (pool != NULL) { GstCaps *pcaps; GstStructure *config; /* we had a pool, check caps */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); GST_DEBUG_OBJECT (v4l2sink, "we had a pool with caps %" GST_PTR_FORMAT, pcaps); if (!gst_caps_is_equal (caps, pcaps)) { gst_structure_free (config); gst_object_unref (pool); goto different_caps; } gst_structure_free (config); } /* we need at least 2 buffers to operate */ gst_query_add_allocation_pool (query, pool, size, 2, 0); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); if (pool) gst_object_unref (pool); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (v4l2sink, "no caps specified"); return FALSE; } different_caps: { /* different caps, we can't use this pool */ GST_DEBUG_OBJECT (v4l2sink, "pool has different caps"); return FALSE; } }
static gboolean gst_kms_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstKMSSink *self; GstCaps *caps; gboolean need_pool; GstVideoInfo vinfo; GstBufferPool *pool; gsize size; self = GST_KMS_SINK (bsink); gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) goto no_caps; if (!gst_video_info_from_caps (&vinfo, caps)) goto invalid_caps; size = GST_VIDEO_INFO_SIZE (&vinfo); pool = NULL; if (need_pool) { pool = gst_kms_sink_create_pool (self, caps, size, 0); if (!pool) goto no_pool; } if (pool) { /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } no_pool: { /* Already warned in create_pool */ return FALSE; } }
static gboolean gst_analyzer_sink_propose_allocation (GstBaseSink * base_sink, GstQuery * query) { GstStructure *param; const gchar *mime_type = NULL; GstAnalyzerSink *analyzersink = GST_ANALYZER_SINK (base_sink); CodecInfo *info = analyzersink->codec_info; if (!info) { mime_type = get_mime_type (analyzersink); if (!mime_type) { GST_ERROR_OBJECT (analyzersink, "Failed to identify the mime type"); return FALSE; } info = gst_codec_info_new_from_mime_type (mime_type); if (!info) { GST_ERROR_OBJECT (analyzersink, "Failed to create the CodecInfo"); return FALSE; } g_free ((gchar *) mime_type); analyzersink->codec_info = info; } param = gst_structure_new (info->query_param_name, "need-slice-header", G_TYPE_BOOLEAN, TRUE, NULL); gst_query_add_allocation_meta (query, info->get_codec_meta_api_type (), param); gst_structure_free (param); return TRUE; }
static gboolean gst_imx_blitter_video_sink_propose_allocation(GstBaseSink *sink, GstQuery *query) { GstCaps *caps; GstVideoInfo info; GstBufferPool *pool; guint size; gst_query_parse_allocation(query, &caps, NULL); if (caps == NULL) { GST_DEBUG_OBJECT(sink, "no caps specified"); return FALSE; } if (!gst_video_info_from_caps(&info, caps)) return FALSE; size = GST_VIDEO_INFO_SIZE(&info); if (gst_query_get_n_allocation_pools(query) == 0) { GstStructure *structure; GstAllocationParams params; GstAllocator *allocator = NULL; memset(¶ms, 0, sizeof(params)); params.flags = 0; params.align = 15; params.prefix = 0; params.padding = 0; if (gst_query_get_n_allocation_params(query) > 0) gst_query_parse_nth_allocation_param(query, 0, &allocator, ¶ms); else gst_query_add_allocation_param(query, allocator, ¶ms); pool = gst_video_buffer_pool_new(); structure = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_set_params(structure, caps, size, 0, 0); gst_buffer_pool_config_set_allocator(structure, allocator, ¶ms); if (allocator) gst_object_unref(allocator); if (!gst_buffer_pool_set_config(pool, structure)) { GST_ERROR_OBJECT(sink, "failed to set config"); gst_object_unref(pool); return FALSE; } gst_query_add_allocation_pool(query, pool, size, 0, 0); gst_object_unref(pool); gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL); } return TRUE; }
static gboolean gst_x265_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) { gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder, query); }
static gboolean webkitVideoSinkProposeAllocation(GstBaseSink* baseSink, GstQuery* query) { GstCaps* caps; gst_query_parse_allocation(query, &caps, 0); if (!caps) return FALSE; WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink); if (!gst_video_info_from_caps(&sink->priv->info, caps)) return FALSE; gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, 0); gst_query_add_allocation_meta(query, GST_VIDEO_CROP_META_API_TYPE, 0); #if GST_CHECK_VERSION(1, 1, 0) gst_query_add_allocation_meta(query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, 0); #endif return TRUE; }
static gboolean gst_vlc_video_sink_propose_allocation( GstBaseSink* p_bsink, GstQuery* p_query ) { GstVlcVideoSink *p_vsink = GST_VLC_VIDEO_SINK( p_bsink ); GstCaps *p_caps; gboolean b_need_pool; GstBufferPool* p_pool = NULL; gsize i_size; gst_query_parse_allocation (p_query, &p_caps, &b_need_pool); if( p_caps == NULL ) goto no_caps; if( b_need_pool ) { GstVideoInfo info; if( !gst_video_info_from_caps( &info, p_caps )) goto invalid_caps; p_pool = (GstBufferPool*) gst_vlc_video_sink_create_pool( p_vsink, p_caps, info.size, 2 ); if( p_pool == NULL ) goto no_pool; i_size = GST_VIDEO_INFO_SIZE( &GST_VLC_VIDEO_POOL_CAST( p_pool )->info); } if( p_pool ) { /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool( p_query, p_pool, i_size, 2, 0); gst_object_unref (p_pool); } /* we support various metadata */ gst_query_add_allocation_meta( p_query, GST_VIDEO_META_API_TYPE, NULL ); return TRUE; /* ERRORS */ no_pool: { msg_Err( p_vsink->p_dec, "failed to create the pool" ); return FALSE; } no_caps: { msg_Err( p_vsink->p_dec, "no caps in allocation query" ); return FALSE; } invalid_caps: { msg_Err( p_vsink->p_dec, "invalid caps in allocation query" ); return FALSE; } }
/** * gst_vaapi_plugin_base_propose_allocation: * @plugin: a #GstVaapiPluginBase * @query: the allocation query to configure * * Proposes allocation parameters to the upstream elements. * * Returns: %TRUE if successful, %FALSE otherwise. */ gboolean gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin, GstQuery * query) { GstCaps *caps = NULL; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (need_pool) { if (!caps) goto error_no_caps; if (!ensure_sinkpad_buffer_pool (plugin, caps)) return FALSE; gst_query_add_allocation_pool (query, plugin->sinkpad_buffer_pool, plugin->sinkpad_buffer_size, 0, 0); if (has_dmabuf_capable_peer (plugin, plugin->sinkpad)) { GstStructure *const config = gst_buffer_pool_get_config (plugin->sinkpad_buffer_pool); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_DMABUF_MEMORY); if (!gst_buffer_pool_set_config (plugin->sinkpad_buffer_pool, config)) goto error_pool_config; } } gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); return TRUE; /* ERRORS */ error_no_caps: { GST_INFO_OBJECT (plugin, "no caps specified"); return FALSE; } error_pool_config: { GST_ERROR_OBJECT (plugin, "failed to reset buffer pool config"); return FALSE; } }
static gboolean gst_decklink_video_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstCaps *caps; GstVideoInfo info; GstBufferPool *pool; guint size; gst_query_parse_allocation (query, &caps, NULL); if (caps == NULL) return FALSE; if (!gst_video_info_from_caps (&info, caps)) return FALSE; size = GST_VIDEO_INFO_SIZE (&info); if (gst_query_get_n_allocation_pools (query) == 0) { GstStructure *structure; GstAllocator *allocator = NULL; GstAllocationParams params = { (GstMemoryFlags) 0, 15, 0, 0 }; if (gst_query_get_n_allocation_params (query) > 0) gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); else gst_query_add_allocation_param (query, allocator, ¶ms); pool = gst_video_buffer_pool_new (); structure = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (structure, caps, size, 0, 0); gst_buffer_pool_config_set_allocator (structure, allocator, ¶ms); if (allocator) gst_object_unref (allocator); if (!gst_buffer_pool_set_config (pool, structure)) goto config_failed; gst_query_add_allocation_pool (query, pool, size, 0, 0); gst_object_unref (pool); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); } return TRUE; // ERRORS config_failed: { GST_ERROR_OBJECT (bsink, "failed to set config"); gst_object_unref (pool); return FALSE; } }
static GstPadProbeReturn query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { APP_STATE_T *state = (APP_STATE_T *) user_data; GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info); GstStructure *external_gl_context_desc = NULL; gchar *platform = NULL; gchar *gl_apis = NULL; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ALLOCATION: { platform = gst_gl_platform_to_string (GST_GL_PLATFORM_EGL); gl_apis = gst_gl_api_to_string (GST_GL_API_GLES2); external_gl_context_desc = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.context.handle", G_TYPE_POINTER, state->context, "gst.gl.context.type", G_TYPE_STRING, platform, "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, external_gl_context_desc); gst_structure_free (external_gl_context_desc); g_free (gl_apis); g_free (platform); GST_DEBUG ("done alocation"); return GST_PAD_PROBE_OK; break; } case GST_QUERY_CONTEXT: { return gst_gl_handle_context_query (state->pipeline, query, (GstGLDisplay **) & state->gst_display); break; } case GST_QUERY_DRAIN: { flush_internal (state); break; } default: break; } return GST_PAD_PROBE_OK; }
static gboolean gst_aasink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstCaps *caps; GstVideoInfo info; guint size; gst_query_parse_allocation (query, &caps, NULL); if (caps == NULL) goto no_caps; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; size = GST_VIDEO_INFO_SIZE (&info); /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, NULL, size, 2, 0); /* we support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } }
static gboolean gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (bsink); GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; GstStructure *gl_context; gchar *platform, *gl_apis; gpointer handle; if (!_ensure_gl_setup (glimage_sink)) return FALSE; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if ((pool = glimage_sink->pool)) gst_object_ref (pool); if (pool != NULL) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (glimage_sink, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (glimage_sink, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (glimage_sink, "create new pool"); pool = gst_gl_buffer_pool_new (glimage_sink->context); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); gst_object_unref (pool); gl_apis = gst_gl_api_to_string (gst_gl_context_get_gl_api (glimage_sink->context)); platform = gst_gl_platform_to_string (gst_gl_context_get_gl_platform (glimage_sink->context)); handle = (gpointer) gst_gl_context_get_gl_context (glimage_sink->context); gl_context = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, glimage_sink->context, "gst.gl.context.handle", G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform, "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context); g_free (gl_apis); g_free (platform); gst_structure_free (gl_context); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (bsink, "failed setting config"); return FALSE; } }
static GstPadProbeReturn query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { APP_STATE_T *state = (APP_STATE_T *) user_data; GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ALLOCATION:{ GstBufferPool *pool; GstStructure *config; GstCaps *caps; GstVideoInfo info; gboolean need_pool; guint size; GstAllocator *allocator; GstAllocationParams params; gst_allocation_params_init (¶ms); gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) { GST_ERROR ("allocation query without caps"); return GST_PAD_PROBE_OK; } if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR ("allocation query with invalid caps"); return GST_PAD_PROBE_OK; } g_mutex_lock (state->queue_lock); pool = state->pool ? gst_object_ref (state->pool) : NULL; g_mutex_unlock (state->queue_lock); if (pool) { GstCaps *pcaps; /* we had a pool, check caps */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); GST_DEBUG ("check existing pool caps %" GST_PTR_FORMAT " with new caps %" GST_PTR_FORMAT, pcaps, caps); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG ("pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } GST_DEBUG ("pool %p", pool); if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR ("allocation query has invalid caps %" GST_PTR_FORMAT, caps); return GST_PAD_PROBE_OK; } GST_DEBUG ("create new pool"); state->pool = pool = gst_egl_image_buffer_pool_new (state, state->display); GST_DEBUG ("done create new pool %p", pool); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); /* we need at least 2 buffer because we hold on to the last one */ gst_buffer_pool_config_set_params (config, caps, size, 2, 0); gst_buffer_pool_config_set_allocator (config, NULL, ¶ms); if (!gst_buffer_pool_set_config (pool, config)) { gst_object_unref (pool); GST_ERROR ("failed to set pool configuration"); return GST_PAD_PROBE_OK; } } if (pool) { /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } /* First the default allocator */ if (!gst_egl_image_memory_is_mappable ()) { allocator = gst_allocator_find (NULL); gst_query_add_allocation_param (query, allocator, ¶ms); gst_object_unref (allocator); } allocator = gst_egl_image_allocator_obtain (); GST_WARNING ("Allocator obtained %p", allocator); if (!gst_egl_image_memory_is_mappable ()) params.flags |= GST_MEMORY_FLAG_NOT_MAPPABLE; gst_query_add_allocation_param (query, allocator, ¶ms); gst_object_unref (allocator); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL); GST_DEBUG ("done alocation"); return GST_PAD_PROBE_OK; } break; default: break; } return GST_PAD_PROBE_OK; }
static gboolean gst_gl_mixer_propose_allocation (GstGLMixer * mix, GstQuery * decide_query, GstQuery * query) { GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size = 0; gboolean need_pool; GError *error = NULL; GstStructure *gl_context; gchar *platform, *gl_apis; gpointer handle; GstAllocator *allocator = NULL; GstAllocationParams params; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if ((pool = mix->priv->pool)) gst_object_ref (pool); if (pool != NULL) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (mix, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (mix, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (!gst_gl_ensure_display (mix, &mix->display)) return FALSE; if (!mix->context) { mix->context = gst_gl_context_new (mix->display); if (!gst_gl_context_create (mix->context, NULL, &error)) goto context_error; } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (mix, "create new pool"); pool = gst_gl_buffer_pool_new (mix->context); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } if (pool) { gst_query_add_allocation_pool (query, pool, size, 1, 0); gst_object_unref (pool); } /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); gl_apis = gst_gl_api_to_string (gst_gl_context_get_gl_api (mix->context)); platform = gst_gl_platform_to_string (gst_gl_context_get_gl_platform (mix->context)); handle = (gpointer) gst_gl_context_get_gl_context (mix->context); gl_context = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, mix->context, "gst.gl.context.handle", G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform, "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context); g_free (gl_apis); g_free (platform); gst_structure_free (gl_context); gst_allocation_params_init (¶ms); allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR); gst_query_add_allocation_param (query, allocator, ¶ms); gst_object_unref (allocator); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (mix, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (mix, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (mix, "failed setting config"); return FALSE; } context_error: { GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
static gboolean gst_pvrvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstPVRVideoSink *pvrvideosink = (GstPVRVideoSink *) bsink; GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; g_mutex_lock (pvrvideosink->flow_lock); if ((pool = pvrvideosink->pool)) gst_object_ref (pool); g_mutex_unlock (pvrvideosink->flow_lock); if (pool != NULL) { const GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (pvrvideosink, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get (config, &pcaps, &size, NULL, NULL, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (pvrvideosink, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } } if (pool == NULL && need_pool) { GstVideoInfo info; GST_DEBUG_OBJECT (pvrvideosink, "create new pool"); pool = gst_pvr_buffer_pool_new (GST_ELEMENT_CAST (pvrvideosink)); if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set (config, caps, size, 0, 0, 0, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } /* we need at least 3 buffers */ gst_query_set_allocation_params (query, size, 3, 0, 0, 0, pool); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API); gst_object_unref (pool); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (bsink, "failed setting config"); return FALSE; } }
/* Answer the allocation query downstream. */ static gboolean gst_video_filter_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query) { GstVideoFilter *filter = GST_VIDEO_FILTER_CAST (trans); GstVideoInfo info; GstBufferPool *pool; GstCaps *caps; guint size; if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans, decide_query, query)) return FALSE; /* passthrough, we're done */ if (decide_query == NULL) return TRUE; gst_query_parse_allocation (query, &caps, NULL); if (caps == NULL) return FALSE; if (!gst_video_info_from_caps (&info, caps)) return FALSE; size = GST_VIDEO_INFO_SIZE (&info); if (gst_query_get_n_allocation_pools (query) == 0) { GstStructure *structure; GstAllocator *allocator = NULL; GstAllocationParams params = { 0, 15, 0, 0, }; if (gst_query_get_n_allocation_params (query) > 0) gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); else gst_query_add_allocation_param (query, allocator, ¶ms); pool = gst_video_buffer_pool_new (); structure = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (structure, caps, size, 0, 0); gst_buffer_pool_config_set_allocator (structure, allocator, ¶ms); if (allocator) gst_object_unref (allocator); if (!gst_buffer_pool_set_config (pool, structure)) goto config_failed; gst_query_add_allocation_pool (query, pool, size, 0, 0); gst_object_unref (pool); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); } return TRUE; /* ERRORS */ config_failed: { GST_ERROR_OBJECT (filter, "failed to set config"); gst_object_unref (pool); return FALSE; } }
static gboolean gst_msdkvpp_decide_allocation (GstBaseTransform * trans, GstQuery * query) { GstMsdkVPP *thiz = GST_MSDKVPP (trans); GstVideoInfo info; GstBufferPool *pool = NULL; GstStructure *config = NULL; GstCaps *caps; guint size = 0, min_buffers = 0, max_buffers = 0; GstAllocator *allocator = NULL; GstAllocationParams params; gboolean update_pool = FALSE; gst_query_parse_allocation (query, &caps, NULL); if (!caps) { GST_ERROR_OBJECT (thiz, "Failed to parse the decide_allocation caps"); return FALSE; } if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (thiz, "Failed to get video info"); return FALSE; } /* if downstream allocation query supports dmabuf-capsfeatures, * we do allocate dmabuf backed memory */ if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) { GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory"); thiz->use_srcpad_dmabuf = TRUE; } if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) thiz->add_video_meta = TRUE; else thiz->add_video_meta = FALSE; /* Check whether the query has pool */ if (gst_query_get_n_allocation_pools (query) > 0) update_pool = TRUE; /* increase the min_buffers with number of concurrent vpp operations */ min_buffers += thiz->async_depth; /* invalidate the cached pool if there is an allocation_query */ if (thiz->srcpad_buffer_pool) gst_object_unref (thiz->srcpad_buffer_pool); /* Always create a pool for vpp out buffers. Each of the msdk element * has to create it's own mfxsurfacepool which is an msdk contraint. * For eg: Each Msdk component (vpp, dec and enc) will invoke the external * Frame allocator for video-memory usage.So sharing the pool between * gst-msdk elements might not be a good idea, rather each element * can check the buffer type (whether it is from msdk-buffer pool) * to make sure there is no copy. Since we share the context between * msdk elements, using buffers from one sdk's framealloator in another * sdk-components is perfectly fine */ pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, caps, min_buffers); thiz->srcpad_buffer_pool = pool; /* get the configured pool properties inorder to set in query */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers); if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) gst_query_add_allocation_param (query, allocator, ¶ms); gst_structure_free (config); if (update_pool) gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers, max_buffers); else gst_query_add_allocation_pool (query, pool, size, min_buffers, max_buffers); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); /* Fixme if downstream doesn't have videometa support, msdkvpp should * copy the output buffers */ return TRUE; }
static gboolean gst_d3dvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink); GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) { GST_DEBUG_OBJECT (sink, "no caps specified"); return FALSE; } gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); #ifdef DISABLE_BUFFER_POOL return TRUE; #endif GST_OBJECT_LOCK (sink); pool = sink->pool ? gst_object_ref (sink->pool) : NULL; GST_OBJECT_UNLOCK (sink); if (pool) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (sink, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (sink, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (sink, "allocation query has invalid caps %" GST_PTR_FORMAT, caps); return FALSE; } GST_DEBUG_OBJECT (sink, "create new pool"); pool = gst_d3dsurface_buffer_pool_new (sink); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); /* we need at least 2 buffer because we hold on to the last one */ gst_buffer_pool_config_set_params (config, caps, size, 2, 0); if (!gst_buffer_pool_set_config (pool, config)) { gst_object_unref (pool); GST_ERROR_OBJECT (sink, "failed to set pool configuration"); return FALSE; } } if (pool) { /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } return TRUE; }
static gboolean gst_gl_filter_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query) { GstGLFilter *filter = GST_GL_FILTER (trans); GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; GError *error = NULL; GstStructure *gl_context; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if ((pool = filter->pool)) gst_object_ref (pool); if (pool != NULL) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (filter, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (filter, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (!gst_gl_ensure_display (filter, &filter->display)) return FALSE; if (!filter->context) { filter->context = gst_gl_context_new (filter->display); if (!gst_gl_context_create (filter->context, filter->other_context, &error)) goto context_error; } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (filter, "create new pool"); pool = gst_gl_buffer_pool_new (filter->context); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 1, 0); gst_object_unref (pool); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); gl_context = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, filter->context, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context); gst_structure_free (gl_context); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (trans, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (trans, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (trans, "failed setting config"); return FALSE; } context_error: { GST_ELEMENT_ERROR (trans, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
static gboolean gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; GstStructure *allocation_meta = NULL; gint display_width, display_height; if (!gtk_sink->display || !gtk_sink->context) return FALSE; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if (need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (gtk_sink, "create new pool"); pool = gst_gl_buffer_pool_new (gtk_sink->context); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } GST_OBJECT_LOCK (gtk_sink); display_width = gtk_sink->display_width; display_height = gtk_sink->display_height; GST_OBJECT_UNLOCK (gtk_sink); if (display_width != 0 && display_height != 0) { GST_DEBUG_OBJECT (gtk_sink, "sending alloc query with size %dx%d", display_width, display_height); allocation_meta = gst_structure_new ("GstVideoOverlayCompositionMeta", "width", G_TYPE_UINT, display_width, "height", G_TYPE_UINT, display_height, NULL); } gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta); if (allocation_meta) gst_structure_free (allocation_meta); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); if (gtk_sink->context->gl_vtable->FenceSync) gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (bsink, "failed setting config"); return FALSE; } }
static gboolean gst_msdkvpp_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query) { GstMsdkVPP *thiz = GST_MSDKVPP (trans); GstVideoInfo info; GstBufferPool *pool = NULL; GstAllocator *allocator = NULL; GstCaps *caps; GstStructure *config; gboolean need_pool; GstAllocationParams params; guint size; guint min_buffers = thiz->async_depth + 1; gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) { GST_ERROR_OBJECT (thiz, "Failed to parse the allocation caps"); return FALSE; } if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (thiz, "Failed to get video info"); return FALSE; } /* if upstream allocation query supports dmabuf-capsfeatures, * we do allocate dmabuf backed memory */ if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) { GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory"); thiz->use_sinkpad_dmabuf = TRUE; } if (need_pool) { /* alwys provide a new pool for upstream to help re-negotiation * more info here: https://bugzilla.gnome.org/show_bug.cgi?id=748344 */ pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps, min_buffers); } /* Update the internal pool if any allocation attribute changed */ if (!gst_video_info_is_equal (&thiz->sinkpad_buffer_pool_info, &info)) { gst_object_unref (thiz->sinkpad_buffer_pool); thiz->sinkpad_buffer_pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps, min_buffers); } /* get the size and allocator params from configured pool and set it in query */ if (!need_pool) pool = gst_object_ref (thiz->sinkpad_buffer_pool); config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); gst_buffer_pool_config_get_params (config, NULL, &size, NULL, NULL); if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) gst_query_add_allocation_param (query, allocator, ¶ms); gst_structure_free (config); /* if upstream does't have a pool requirement, set only * size, min_buffers and max_buffers in query */ gst_query_add_allocation_pool (query, need_pool ? pool : NULL, size, min_buffers, 0); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_object_unref (pool); return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans, decide_query, query); }
static gboolean webkitVideoSinkProposeAllocation(GstBaseSink* baseSink, GstQuery* query) { WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink); GstCaps* caps = NULL; gboolean need_pool; gst_query_parse_allocation(query, &caps, &need_pool); if (!caps) return FALSE; if (!gst_video_info_from_caps(&sink->priv->info, caps)) return FALSE; #if USE(OPENGL_ES_2) && GST_CHECK_VERSION(1, 3, 0) // Code adapted from gst-plugins-bad's glimagesink. GstBufferPool* pool; GstStructure* config; guint size; GstAllocator* allocator = 0; GstAllocationParams params; if (!_ensure_gl_setup(sink)) return FALSE; if ((pool = sink->priv->pool)) gst_object_ref(pool); if (pool) { GstCaps* pcaps; // We had a pool, check its caps. GST_DEBUG_OBJECT (sink, "check existing pool caps"); config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_get_params(config, &pcaps, &size, 0, 0); if (!gst_caps_is_equal(caps, pcaps)) { GST_DEBUG_OBJECT(sink, "pool has different caps"); // Different caps, we can't use this pool. gst_object_unref(pool); pool = 0; } gst_structure_free(config); } if (need_pool && !pool) { GstVideoInfo info; if (!gst_video_info_from_caps(&info, caps)) { GST_DEBUG_OBJECT(sink, "invalid caps specified"); return FALSE; } GST_DEBUG_OBJECT(sink, "create new pool"); pool = gst_gl_buffer_pool_new(sink->priv->context); // The normal size of a frame. size = info.size; config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_set_params(config, caps, size, 0, 0); if (!gst_buffer_pool_set_config(pool, config)) { GST_DEBUG_OBJECT(sink, "failed setting config"); return FALSE; } } // [WiP] Let's require 8 buffers for now. The player holds to the last 3 // ones and the sink holds only the last one so in theory 5 should // be enough. if (pool) { gst_query_add_allocation_pool(query, pool, size, 8, 0); gst_object_unref(pool); } gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, 0); gst_allocation_params_init(¶ms); allocator = gst_allocator_find(GST_EGL_IMAGE_MEMORY_TYPE); gst_query_add_allocation_param(query, allocator, ¶ms); gst_object_unref(allocator); #else gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, 0); gst_query_add_allocation_meta(query, GST_VIDEO_CROP_META_API_TYPE, 0); gst_query_add_allocation_meta(query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, 0); #endif return TRUE; }