static void setup (void) { display = gst_gl_display_new (); context = gst_gl_context_new (display); gst_gl_context_create (context, 0, NULL); }
static void setup (void) { GError *error = NULL; display = gst_gl_display_new (); context = gst_gl_context_new (display); gst_gl_context_create (context, NULL, &error); fail_if (error != NULL, "Error creating context: %s\n", error ? error->message : "Unknown Error"); }
static gboolean _ensure_gl_setup(WebKitVideoSink* gl_sink) { GError* error = NULL; if (!gst_gl_ensure_display(gl_sink, &gl_sink->priv->display)) return FALSE; if (!gl_sink->priv->context) { gl_sink->priv->context = gst_gl_context_new(gl_sink->priv->display); if (!gst_gl_context_create(gl_sink->priv->context, gl_sink->priv->other_context, &error)) { GST_ELEMENT_ERROR(gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); gst_object_unref(gl_sink->priv->context); gl_sink->priv->context = NULL; return FALSE; } } return TRUE; }
/** * gst_gl_display_create_context: * @display: a #GstGLDisplay * @other_context: other #GstGLContext to share resources with. * @p_context: resulting #GstGLContext * @error: resulting #GError * * It requires the display's object lock to be held. * * Returns: whether a new context could be created. * * Since: 1.6 */ gboolean gst_gl_display_create_context (GstGLDisplay * display, GstGLContext * other_context, GstGLContext ** p_context, GError ** error) { GstGLContext *context = NULL; gboolean ret = FALSE; g_return_val_if_fail (display != NULL, FALSE); g_return_val_if_fail (p_context != NULL, FALSE); g_return_val_if_fail (error != NULL, FALSE); g_return_val_if_fail (*error == NULL, FALSE); g_signal_emit (display, gst_gl_display_signals[CREATE_CONTEXT], 0, other_context, &context); if (context) { *p_context = context; return TRUE; } context = gst_gl_context_new (display); if (!context) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, "Failed to create GL context"); return FALSE; } GST_DEBUG_OBJECT (display, "creating context %" GST_PTR_FORMAT " from other context %" GST_PTR_FORMAT, context, other_context); ret = gst_gl_context_create (context, other_context, error); if (ret) *p_context = context; return ret; }
static gboolean _ensure_gl_setup (GstGLImageSink * gl_sink) { GError *error = NULL; if (!gst_gl_ensure_display (gl_sink, &gl_sink->display)) return FALSE; if (!gl_sink->context) { gl_sink->context = gst_gl_context_new (gl_sink->display); if (!gst_gl_context_create (gl_sink->context, gl_sink->other_context, &error)) goto context_error; } if (!gl_sink->upload) { gl_sink->upload = gst_gl_upload_new (gl_sink->context); if (!gst_gl_upload_init_format (gl_sink->upload, gl_sink->info, gl_sink->info)) goto upload_error; } return TRUE; upload_error: { GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("Failed to init upload"), (NULL)); return FALSE; } context_error: { GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
static GstContext *gub_provide_graphic_context_egl(GUBGraphicContextEGL *gcontext, const gchar *type) { GstContext *context = NULL; gub_log("Providing context. gub_context=%p, type=%s", gcontext, type); if (!gcontext) return NULL; if (type != NULL) { if (g_strcmp0(type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) { context = gst_context_new(GST_GL_DISPLAY_CONTEXT_TYPE, TRUE); gst_context_set_gl_display(context, gcontext->display); } else if (g_strcmp0(type, "gst.gl.app_context") == 0) { GstStructure *s; context = gst_context_new("gst.gl.app_context", TRUE); s = gst_context_writable_structure(context); gst_structure_set(s, "context", GST_GL_TYPE_CONTEXT, gcontext->gl, NULL); } else if (g_strcmp0(type, "gst.gl.local_context") == 0) { GstGLContext *local_context = gst_gl_context_new(gcontext->display); GError *error = NULL; gst_gl_context_create(local_context, gcontext->gl, &error); if (error) { gub_log("Cannot create local context: %s", error->message); g_error_free(error); } else { GstStructure *s; context = gst_context_new("gst.gl.local_context", TRUE); s = gst_context_writable_structure(context); gst_structure_set(s, "context", GST_GL_TYPE_CONTEXT, local_context, NULL); } } } return context; }
static GstStateChangeReturn gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) { GstGLImageSink *glimage_sink; GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GST_DEBUG ("change state"); glimage_sink = GST_GLIMAGE_SINK (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: g_atomic_int_set (&glimage_sink->to_quit, 0); if (!glimage_sink->display) { GstGLWindow *window; GError *error = NULL; if (!gst_gl_ensure_display (glimage_sink, &glimage_sink->display)) return GST_STATE_CHANGE_FAILURE; glimage_sink->context = gst_gl_context_new (glimage_sink->display); window = gst_gl_context_get_window (glimage_sink->context); if (!glimage_sink->window_id && !glimage_sink->new_window_id) gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (glimage_sink)); if (glimage_sink->window_id != glimage_sink->new_window_id) { glimage_sink->window_id = glimage_sink->new_window_id; gst_gl_window_set_window_handle (window, glimage_sink->window_id); } if (!gst_gl_context_create (glimage_sink->context, glimage_sink->other_context, &error)) { GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); if (glimage_sink->display) { gst_object_unref (glimage_sink->display); glimage_sink->display = NULL; } gst_object_unref (glimage_sink->context); gst_object_unref (window); return GST_STATE_CHANGE_FAILURE; } /* setup callbacks */ gst_gl_window_set_resize_callback (window, GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize), gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref); gst_gl_window_set_draw_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_draw), gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref); gst_gl_window_set_close_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_close), gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref); gst_object_unref (window); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: { /* mark the redisplay_texture as unavailable (=0) * to avoid drawing */ GST_GLIMAGE_SINK_LOCK (glimage_sink); glimage_sink->redisplay_texture = 0; GST_GLIMAGE_SINK_UNLOCK (glimage_sink); if (glimage_sink->upload) { gst_object_unref (glimage_sink->upload); glimage_sink->upload = NULL; } glimage_sink->window_id = 0; //but do not reset glimage_sink->new_window_id if (glimage_sink->pool) { gst_buffer_pool_set_active (glimage_sink->pool, FALSE); gst_object_unref (glimage_sink->pool); glimage_sink->pool = NULL; } GST_VIDEO_SINK_WIDTH (glimage_sink) = 1; GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1; if (glimage_sink->context) { GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context); gst_gl_window_send_message (window, GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink); gst_gl_window_set_resize_callback (window, NULL, NULL, NULL); gst_gl_window_set_draw_callback (window, NULL, NULL, NULL); gst_gl_window_set_close_callback (window, NULL, NULL, NULL); gst_object_unref (window); gst_object_unref (glimage_sink->context); glimage_sink->context = NULL; gst_object_unref (glimage_sink->display); glimage_sink->display = NULL; } break; } case GST_STATE_CHANGE_READY_TO_NULL: break; default: break; } return ret; }
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_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_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 _ensure_gl_setup (GstGLImageSink * gl_sink) { GError *error = NULL; if (!gst_gl_ensure_display (gl_sink, &gl_sink->display)) return FALSE; if (!gl_sink->context) { GstGLWindow *window; gl_sink->context = gst_gl_context_new (gl_sink->display); if (!gl_sink->context) goto context_creation_error; window = gst_gl_context_get_window (gl_sink->context); if (!gl_sink->window_id && !gl_sink->new_window_id) gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (gl_sink)); if (gl_sink->window_id != gl_sink->new_window_id) { gl_sink->window_id = gl_sink->new_window_id; gst_gl_window_set_window_handle (window, gl_sink->window_id); } if (!gst_gl_context_create (gl_sink->context, gl_sink->other_context, &error)) { gst_object_unref (window); goto context_error; } /* setup callbacks */ gst_gl_window_set_resize_callback (window, GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize), gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); gst_gl_window_set_draw_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_draw), gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); gst_gl_window_set_close_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_close), gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); gl_sink->key_sig_id = g_signal_connect (window, "key-event", G_CALLBACK (gst_glimage_sink_key_event_cb), gl_sink); gl_sink->mouse_sig_id = g_signal_connect (window, "mouse-event", G_CALLBACK (gst_glimage_sink_mouse_event_cb), gl_sink); gst_object_unref (window); } return TRUE; context_creation_error: { GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("Failed to create GL context"), (NULL)); return FALSE; } context_error: { GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); gst_object_unref (gl_sink->context); gl_sink->context = NULL; return FALSE; } }