void gst_gl_window_activate_gl_context (GstGLWindow * window, gboolean activate) { GstGLWindowPrivate *priv = window->priv; if (activate) gst_gl_window_send_message (window, GST_GL_WINDOW_CB (callback_activate_gl_context), priv); else gst_gl_window_send_message (window, GST_GL_WINDOW_CB (callback_inactivate_gl_context), priv); }
static gboolean gst_glimage_sink_redisplay (GstGLImageSink * gl_sink) { GstGLWindow *window; gboolean alive; window = gst_gl_context_get_window (gl_sink->context); if (window && gst_gl_window_is_running (window)) { #if GST_GL_HAVE_GLES2 if (USING_GLES2 (gl_sink->context)) { if (!gl_sink->redisplay_shader) { gst_gl_window_send_message (window, GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), gl_sink); } } #endif /* Drawing is asynchrone: gst_gl_window_draw is not blocking * It means that it does not wait for stuff being executed in other threads */ gst_gl_window_draw (window, GST_VIDEO_SINK_WIDTH (gl_sink), GST_VIDEO_SINK_HEIGHT (gl_sink)); } alive = gst_gl_window_is_running (window); gst_object_unref (window); return alive; }
/** * gst_gl_context_thread_add: * @context: a #GstGLContext * @func: a #GstGLContextThreadFunc * @data: (closure): user data to call @func with * * Execute @func in the OpenGL thread of @context with @data * * MT-safe * * Since: 1.4 */ void gst_gl_context_thread_add (GstGLContext * context, GstGLContextThreadFunc func, gpointer data) { GstGLWindow *window; RunGenericData rdata; g_return_if_fail (GST_IS_GL_CONTEXT (context)); g_return_if_fail (func != NULL); if (GST_IS_GL_WRAPPED_CONTEXT (context)) { g_return_if_fail (context->priv->active_thread == g_thread_self ()); func (context, data); return; } rdata.context = context; rdata.data = data; rdata.func = func; window = gst_gl_context_get_window (context); gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gst_gl_context_thread_run_generic), &rdata); gst_object_unref (window); }
static gboolean gst_glimage_sink_redisplay (GstGLImageSink * gl_sink) { GstGLWindow *window; gboolean alive; window = gst_gl_context_get_window (gl_sink->context); if (!window) return FALSE; if (gst_gl_window_is_running (window)) { #if GST_GL_HAVE_GLES2 if (USING_GLES2 (gl_sink->context)) { if (G_UNLIKELY (!gl_sink->redisplay_shader)) { gst_gl_window_send_message (window, GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), gl_sink); /* if the shader is still null it means it failed to be useable */ if (G_UNLIKELY (!gl_sink->redisplay_shader)) { gst_object_unref (window); return FALSE; } } } #endif /* Drawing is asynchronous: gst_gl_window_draw is not blocking * It means that it does not wait for stuff to be executed in other threads */ gst_gl_window_draw (window, GST_VIDEO_SINK_WIDTH (gl_sink), GST_VIDEO_SINK_HEIGHT (gl_sink)); } alive = gst_gl_window_is_running (window); gst_object_unref (window); return alive; }
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 GstStateChangeReturn gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) { GstGLImageSink *glimage_sink; GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GST_DEBUG ("changing state: %s => %s", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); 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) { if (!gst_gl_ensure_display (glimage_sink, &glimage_sink->display)) return GST_STATE_CHANGE_FAILURE; } 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; if (glimage_sink->stored_buffer) { gst_buffer_unref (glimage_sink->stored_buffer); glimage_sink->stored_buffer = NULL; } 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; } if (glimage_sink->display) { 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 _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; } }