static gboolean gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstGLImageSink *glimage_sink; gint width; gint height; gboolean ok; gint par_n, par_d; gint display_par_n, display_par_d; guint display_ratio_num, display_ratio_den; GstVideoInfo vinfo; GstStructure *structure; GstBufferPool *newpool, *oldpool; GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); glimage_sink = GST_GLIMAGE_SINK (bsink); ok = gst_video_info_from_caps (&vinfo, caps); if (!ok) return FALSE; width = GST_VIDEO_INFO_WIDTH (&vinfo); height = GST_VIDEO_INFO_HEIGHT (&vinfo); if (glimage_sink->tex_id) gst_gl_context_del_texture (glimage_sink->context, &glimage_sink->tex_id); //FIXME: this texture seems to be never deleted when going to STATE_NULL gst_gl_context_gen_texture (glimage_sink->context, &glimage_sink->tex_id, GST_VIDEO_INFO_FORMAT (&vinfo), width, height); par_n = GST_VIDEO_INFO_PAR_N (&vinfo); par_d = GST_VIDEO_INFO_PAR_D (&vinfo); if (!par_n) par_n = 1; /* get display's PAR */ if (glimage_sink->par_n != 0 && glimage_sink->par_d != 0) { display_par_n = glimage_sink->par_n; display_par_d = glimage_sink->par_d; } else { display_par_n = 1; display_par_d = 1; } ok = gst_video_calculate_display_ratio (&display_ratio_num, &display_ratio_den, width, height, par_n, par_d, display_par_n, display_par_d); if (!ok) return FALSE; GST_TRACE ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, display_par_d); if (height % display_ratio_den == 0) { GST_DEBUG ("keeping video height"); GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint) gst_util_uint64_scale_int (height, display_ratio_num, display_ratio_den); GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; } else if (width % display_ratio_num == 0) { GST_DEBUG ("keeping video width"); GST_VIDEO_SINK_WIDTH (glimage_sink) = width; GST_VIDEO_SINK_HEIGHT (glimage_sink) = (guint) gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); } else { GST_DEBUG ("approximating while keeping video height"); GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint) gst_util_uint64_scale_int (height, display_ratio_num, display_ratio_den); GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; } GST_DEBUG ("scaling to %dx%d", GST_VIDEO_SINK_WIDTH (glimage_sink), GST_VIDEO_SINK_HEIGHT (glimage_sink)); glimage_sink->info = vinfo; newpool = gst_gl_buffer_pool_new (glimage_sink->context); structure = gst_buffer_pool_get_config (newpool); gst_buffer_pool_config_set_params (structure, caps, vinfo.size, 2, 0); gst_buffer_pool_set_config (newpool, structure); oldpool = glimage_sink->pool; /* we don't activate the pool yet, this will be done by downstream after it * has configured the pool. If downstream does not want our pool we will * activate it when we render into it */ glimage_sink->pool = newpool; /* unref the old sink */ if (oldpool) { /* we don't deactivate, some elements might still be using it, it will * be deactivated when the last ref is gone */ gst_object_unref (oldpool); } return TRUE; }
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 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_gl_mixer_decide_allocation (GstGLMixer * mix, GstQuery * query) { GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint min, max, size; gboolean update_pool; GError *error = NULL; guint idx; guint out_width, out_height; GstGLContext *other_context = NULL; GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix); gst_query_parse_allocation (query, &caps, NULL); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; } else { GstVideoInfo vinfo; gst_video_info_init (&vinfo); gst_video_info_from_caps (&vinfo, caps); size = vinfo.size; min = max = 0; update_pool = FALSE; } if (!gst_gl_ensure_display (mix, &mix->display)) return FALSE; if (gst_query_find_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx)) { GstGLContext *context; const GstStructure *upload_meta_params; gpointer handle; gchar *type; gchar *apis; gst_query_parse_nth_allocation_meta (query, idx, &upload_meta_params); if (upload_meta_params) { if (gst_structure_get (upload_meta_params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, &context, NULL) && context) { GstGLContext *old = mix->context; mix->context = context; if (old) gst_object_unref (old); } else if (gst_structure_get (upload_meta_params, "gst.gl.context.handle", G_TYPE_POINTER, &handle, "gst.gl.context.type", G_TYPE_STRING, &type, "gst.gl.context.apis", G_TYPE_STRING, &apis, NULL) && handle) { GstGLPlatform platform = GST_GL_PLATFORM_NONE; GstGLAPI gl_apis; GST_DEBUG ("got GL context handle 0x%p with type %s and apis %s", handle, type, apis); platform = gst_gl_platform_from_string (type); gl_apis = gst_gl_api_from_string (apis); if (gl_apis && platform) other_context = gst_gl_context_new_wrapped (mix->display, (guintptr) handle, platform, gl_apis); } } } if (!mix->context) { mix->context = gst_gl_context_new (mix->display); if (!gst_gl_context_create (mix->context, other_context, &error)) goto context_error; } out_width = GST_VIDEO_INFO_WIDTH (&vagg->info); out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info); g_mutex_lock (&mix->priv->gl_resource_lock); mix->priv->gl_resource_ready = FALSE; if (mix->fbo) { gst_gl_context_del_fbo (mix->context, mix->fbo, mix->depthbuffer); mix->fbo = 0; mix->depthbuffer = 0; } if (!gst_gl_context_gen_fbo (mix->context, out_width, out_height, &mix->fbo, &mix->depthbuffer)) { g_cond_signal (&mix->priv->gl_resource_cond); g_mutex_unlock (&mix->priv->gl_resource_lock); goto context_error; } if (mix->out_tex_id) gst_gl_context_del_texture (mix->context, &mix->out_tex_id); gst_gl_context_gen_texture (mix->context, &mix->out_tex_id, GST_VIDEO_FORMAT_RGBA, out_width, out_height); if (mixer_class->set_caps) mixer_class->set_caps (mix, caps); mix->priv->gl_resource_ready = TRUE; g_cond_signal (&mix->priv->gl_resource_cond); g_mutex_unlock (&mix->priv->gl_resource_lock); if (!pool) pool = gst_gl_buffer_pool_new (mix->context); 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_VIDEO_META); gst_buffer_pool_set_config (pool, config); 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); gst_object_unref (pool); return TRUE; context_error: { GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
static gboolean gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query) { GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint min, max, size; gboolean update_pool; GError *error = NULL; if (!gst_gl_ensure_element_data (src, &src->display, &src->other_context)) return FALSE; gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS); _find_local_gl_context (src); if (!src->context) { GST_OBJECT_LOCK (src->display); do { if (src->context) { gst_object_unref (src->context); src->context = NULL; } /* just get a GL context. we don't care */ src->context = gst_gl_display_get_gl_context_for_thread (src->display, NULL); if (!src->context) { if (!gst_gl_display_create_context (src->display, src->other_context, &src->context, &error)) { GST_OBJECT_UNLOCK (src->display); goto context_error; } } } while (!gst_gl_display_add_context (src->display, src->context)); GST_OBJECT_UNLOCK (src->display); } if ((gst_gl_context_get_gl_api (src->context) & SUPPORTED_GL_APIS) == 0) goto unsupported_gl_api; gst_gl_context_thread_add (src->context, (GstGLContextThreadFunc) _src_generate_fbo_gl, src); if (!src->fbo) goto context_error; gst_query_parse_allocation (query, &caps, NULL); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; } else { GstVideoInfo vinfo; gst_video_info_init (&vinfo); gst_video_info_from_caps (&vinfo, caps); size = vinfo.size; min = max = 0; update_pool = FALSE; } if (!pool || !GST_IS_GL_BUFFER_POOL (pool)) { /* can't use this pool */ if (pool) gst_object_unref (pool); pool = gst_gl_buffer_pool_new (src->context); } 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_VIDEO_META); if (gst_query_find_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL)) gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); gst_buffer_pool_set_config (pool, config); 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); gst_gl_test_src_init_shader (src); gst_object_unref (pool); return TRUE; unsupported_gl_api: { GstGLAPI gl_api = gst_gl_context_get_gl_api (src->context); gchar *gl_api_str = gst_gl_api_to_string (gl_api); gchar *supported_gl_api_str = gst_gl_api_to_string (SUPPORTED_GL_APIS); GST_ELEMENT_ERROR (src, RESOURCE, BUSY, ("GL API's not compatible context: %s supported: %s", gl_api_str, supported_gl_api_str), (NULL)); g_free (supported_gl_api_str); g_free (gl_api_str); return FALSE; } context_error: { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); g_clear_error (&error); if (src->context) gst_object_unref (src->context); src->context = 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_gl_filter_decide_allocation (GstBaseTransform * trans, GstQuery * query) { GstGLFilter *filter = GST_GL_FILTER (trans); GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint min, max, size; gboolean update_pool; guint idx; GError *error = NULL; guint in_width, in_height, out_width, out_height; gst_query_parse_allocation (query, &caps, NULL); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; } else { GstVideoInfo vinfo; gst_video_info_init (&vinfo); gst_video_info_from_caps (&vinfo, caps); size = vinfo.size; min = max = 0; update_pool = FALSE; } if (!gst_gl_ensure_display (filter, &filter->display)) return FALSE; if (gst_query_find_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx)) { GstGLContext *context; const GstStructure *upload_meta_params; gst_query_parse_nth_allocation_meta (query, idx, &upload_meta_params); if (gst_structure_get (upload_meta_params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, &context, NULL) && context) { GstGLContext *old = filter->context; filter->context = context; if (old) gst_object_unref (old); } } 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; } in_width = GST_VIDEO_INFO_WIDTH (&filter->in_info); in_height = GST_VIDEO_INFO_HEIGHT (&filter->in_info); out_width = GST_VIDEO_INFO_WIDTH (&filter->out_info); out_height = GST_VIDEO_INFO_HEIGHT (&filter->out_info); if (!filter->upload) { filter->upload = gst_gl_upload_new (filter->context); gst_gl_upload_init_format (filter->upload, filter->in_info, filter->out_info); } //blocking call, generate a FBO if (!gst_gl_context_gen_fbo (filter->context, out_width, out_height, &filter->fbo, &filter->depthbuffer)) goto context_error; gst_gl_context_gen_texture (filter->context, &filter->in_tex_id, GST_VIDEO_FORMAT_RGBA, in_width, in_height); gst_gl_context_gen_texture (filter->context, &filter->out_tex_id, GST_VIDEO_FORMAT_RGBA, out_width, out_height); if (filter_class->display_init_cb != NULL) { gst_gl_context_thread_add (filter->context, gst_gl_filter_start_gl, filter); } if (filter_class->onInitFBO) { if (!filter_class->onInitFBO (filter)) goto error; } if (!pool) pool = gst_gl_buffer_pool_new (filter->context); 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_VIDEO_META); gst_buffer_pool_set_config (pool, config); 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); gst_object_unref (pool); return TRUE; context_error: { GST_ELEMENT_ERROR (trans, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } error: { GST_ELEMENT_ERROR (trans, LIBRARY, INIT, ("Subclass failed to initialize."), (NULL)); return FALSE; } }
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 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; }