gl/mixer: support GstGLDisplay changes

This commit is contained in:
Matthew Waters 2020-02-04 13:58:06 +11:00 committed by GStreamer Merge Bot
parent 0e038a5612
commit 55e80b550e
4 changed files with 298 additions and 103 deletions

View file

@ -41,11 +41,19 @@ static void gst_gl_base_mixer_set_context (GstElement * element,
static GstStateChangeReturn gst_gl_base_mixer_change_state (GstElement *
element, GstStateChange transition);
static void gst_gl_base_mixer_gl_start (GstGLContext * context, gpointer data);
static void gst_gl_base_mixer_gl_stop (GstGLContext * context, gpointer data);
struct _GstGLBaseMixerPrivate
{
gboolean negotiated;
GstGLContext *other_context;
gboolean gl_started;
gboolean gl_result;
GRecMutex context_lock;
};
#define gst_gl_base_mixer_parent_class parent_class
@ -95,21 +103,37 @@ gst_gl_base_mixer_pad_set_property (GObject * object, guint prop_id,
static gboolean
_find_local_gl_context (GstGLBaseMixer * mix)
{
if (gst_gl_query_local_gl_context (GST_ELEMENT (mix), GST_PAD_SRC,
&mix->context))
return TRUE;
if (gst_gl_query_local_gl_context (GST_ELEMENT (mix), GST_PAD_SINK,
&mix->context))
return TRUE;
GstGLContext *context = mix->context;
if (gst_gl_query_local_gl_context (GST_ELEMENT (mix), GST_PAD_SRC, &context)) {
if (context->display == mix->display) {
mix->context = context;
return TRUE;
}
if (context != mix->context)
gst_clear_object (&context);
}
if (gst_gl_query_local_gl_context (GST_ELEMENT (mix), GST_PAD_SINK, &context)) {
if (context->display == mix->display) {
mix->context = context;
return TRUE;
}
if (context != mix->context)
gst_clear_object (&context);
}
return FALSE;
}
static gboolean
_get_gl_context (GstGLBaseMixer * mix)
_get_gl_context_unlocked (GstGLBaseMixer * mix)
{
GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
gboolean new_context = FALSE;
GError *error = NULL;
if (!mix->context)
new_context = TRUE;
if (!gst_gl_ensure_element_data (mix, &mix->display,
&mix->priv->other_context))
return FALSE;
@ -139,10 +163,20 @@ _get_gl_context (GstGLBaseMixer * mix)
}
GST_OBJECT_UNLOCK (mix->display);
{
GstGLAPI current_gl_api = gst_gl_context_get_gl_api (mix->context);
if ((current_gl_api & mix_class->supported_gl_api) == 0)
goto unsupported_gl_api;
if (new_context || !mix->priv->gl_started) {
if (mix->priv->gl_started)
gst_gl_context_thread_add (mix->context, gst_gl_base_mixer_gl_stop, mix);
{
if ((gst_gl_context_get_gl_api (mix->
context) & mix_class->supported_gl_api) == 0)
goto unsupported_gl_api;
}
gst_gl_context_thread_add (mix->context, gst_gl_base_mixer_gl_start, mix);
if (!mix->priv->gl_started)
goto error;
}
return TRUE;
@ -168,6 +202,22 @@ context_error:
g_clear_error (&error);
return FALSE;
}
error:
{
GST_ELEMENT_ERROR (mix, LIBRARY, INIT,
("Subclass failed to initialize."), (NULL));
return FALSE;
}
}
static gboolean
_get_gl_context (GstGLBaseMixer * mix)
{
gboolean ret;
g_rec_mutex_lock (&mix->priv->context_lock);
ret = _get_gl_context_unlocked (mix);
g_rec_mutex_unlock (&mix->priv->context_lock);
return ret;
}
static gboolean
@ -193,9 +243,13 @@ gst_gl_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONTEXT:
{
if (gst_gl_handle_context_query ((GstElement *) mix, query,
mix->display, mix->context, mix->priv->other_context))
return TRUE;
gboolean ret;
g_rec_mutex_lock (&mix->priv->context_lock);
ret = gst_gl_handle_context_query ((GstElement *) mix, query,
mix->display, mix->context, mix->priv->other_context);
g_rec_mutex_unlock (&mix->priv->context_lock);
if (ret)
return ret;
break;
}
default:
@ -232,6 +286,7 @@ gst_gl_base_mixer_src_activate_mode (GstAggregator * aggregator,
static gboolean gst_gl_base_mixer_stop (GstAggregator * agg);
static gboolean gst_gl_base_mixer_start (GstAggregator * agg);
static void gst_gl_base_mixer_finalize (GObject * object);
static void gst_gl_base_mixer_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_gl_base_mixer_get_property (GObject * object, guint prop_id,
@ -240,6 +295,9 @@ static void gst_gl_base_mixer_get_property (GObject * object, guint prop_id,
static gboolean gst_gl_base_mixer_decide_allocation (GstAggregator * agg,
GstQuery * query);
static gboolean gst_gl_base_mixer_default_gl_start (GstGLBaseMixer * src);
static void gst_gl_base_mixer_default_gl_stop (GstGLBaseMixer * src);
static void
gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
{
@ -252,6 +310,7 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
gobject_class = (GObjectClass *) klass;
element_class = GST_ELEMENT_CLASS (klass);
gobject_class->finalize = gst_gl_base_mixer_finalize;
gobject_class->get_property = gst_gl_base_mixer_get_property;
gobject_class->set_property = gst_gl_base_mixer_set_property;
@ -267,6 +326,9 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
agg_class->decide_allocation = gst_gl_base_mixer_decide_allocation;
agg_class->propose_allocation = gst_gl_base_mixer_propose_allocation;
klass->gl_start = gst_gl_base_mixer_default_gl_start;
klass->gl_stop = gst_gl_base_mixer_default_gl_stop;
g_object_class_install_property (gobject_class, PROP_CONTEXT,
g_param_spec_object ("context",
"OpenGL context",
@ -283,6 +345,58 @@ static void
gst_gl_base_mixer_init (GstGLBaseMixer * mix)
{
mix->priv = gst_gl_base_mixer_get_instance_private (mix);
g_rec_mutex_init (&mix->priv->context_lock);
}
static void
gst_gl_base_mixer_finalize (GObject * object)
{
GstGLBaseMixer *mix = GST_GL_BASE_MIXER (object);
g_rec_mutex_clear (&mix->priv->context_lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
gst_gl_base_mixer_default_gl_start (GstGLBaseMixer * src)
{
return TRUE;
}
static void
gst_gl_base_mixer_gl_start (GstGLContext * context, gpointer data)
{
GstGLBaseMixer *src = GST_GL_BASE_MIXER (data);
GstGLBaseMixerClass *src_class = GST_GL_BASE_MIXER_GET_CLASS (src);
GST_INFO_OBJECT (src, "starting");
gst_gl_insert_debug_marker (src->context,
"starting element %s", GST_OBJECT_NAME (src));
src->priv->gl_started = src_class->gl_start (src);
}
static void
gst_gl_base_mixer_default_gl_stop (GstGLBaseMixer * src)
{
}
static void
gst_gl_base_mixer_gl_stop (GstGLContext * context, gpointer data)
{
GstGLBaseMixer *src = GST_GL_BASE_MIXER (data);
GstGLBaseMixerClass *src_class = GST_GL_BASE_MIXER_GET_CLASS (src);
GST_INFO_OBJECT (src, "stopping");
gst_gl_insert_debug_marker (src->context,
"stopping element %s", GST_OBJECT_NAME (src));
if (src->priv->gl_started)
src_class->gl_stop (src);
src->priv->gl_started = FALSE;
}
static void
@ -290,12 +404,26 @@ gst_gl_base_mixer_set_context (GstElement * element, GstContext * context)
{
GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element);
GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
GstGLDisplay *old_display, *new_display;
g_rec_mutex_lock (&mix->priv->context_lock);
old_display = mix->display ? gst_object_ref (mix->display) : NULL;
gst_gl_handle_set_context (element, context, &mix->display,
&mix->priv->other_context);
if (mix->display)
gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
new_display = mix->display ? gst_object_ref (mix->display) : NULL;
if (old_display && new_display) {
if (old_display != new_display) {
gst_clear_object (&mix->context);
_get_gl_context_unlocked (mix);
gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (mix));
}
}
gst_clear_object (&old_display);
gst_clear_object (&new_display);
g_rec_mutex_unlock (&mix->priv->context_lock);
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
@ -307,11 +435,15 @@ gst_gl_base_mixer_activate (GstGLBaseMixer * mix, gboolean active)
gboolean result = TRUE;
if (active) {
g_rec_mutex_lock (&mix->priv->context_lock);
if (!gst_gl_ensure_element_data (mix, &mix->display,
&mix->priv->other_context))
&mix->priv->other_context)) {
g_rec_mutex_lock (&mix->priv->context_lock);
return FALSE;
}
gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
g_rec_mutex_unlock (&mix->priv->context_lock);
}
return result;
@ -346,9 +478,13 @@ gst_gl_base_mixer_src_query (GstAggregator * agg, GstQuery * query)
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONTEXT:
{
if (gst_gl_handle_context_query ((GstElement *) mix, query,
mix->display, mix->context, mix->priv->other_context))
return TRUE;
gboolean ret;
g_rec_mutex_lock (&mix->priv->context_lock);
ret = gst_gl_handle_context_query ((GstElement *) mix, query,
mix->display, mix->context, mix->priv->other_context);
g_rec_mutex_unlock (&mix->priv->context_lock);
if (ret)
return ret;
break;
}
default:
@ -407,10 +543,11 @@ gst_gl_base_mixer_stop (GstAggregator * agg)
{
GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg);
if (mix->context) {
gst_object_unref (mix->context);
mix->context = NULL;
}
g_rec_mutex_lock (&mix->priv->context_lock);
if (mix->priv->gl_started)
gst_gl_context_thread_add (mix->context, gst_gl_base_mixer_gl_stop, mix);
gst_clear_object (&mix->context);
g_rec_mutex_unlock (&mix->priv->context_lock);
return TRUE;
}
@ -449,10 +586,9 @@ gst_gl_base_mixer_change_state (GstElement * element, GstStateChange transition)
mix->priv->other_context = NULL;
}
if (mix->display) {
gst_object_unref (mix->display);
mix->display = NULL;
}
g_rec_mutex_lock (&mix->priv->context_lock);
gst_clear_object (&mix->display);
g_rec_mutex_unlock (&mix->priv->context_lock);
break;
default:
break;
@ -460,3 +596,24 @@ gst_gl_base_mixer_change_state (GstElement * element, GstStateChange transition)
return ret;
}
/**
* gst_gl_base_mixer_get_gl_context:
* @mix: a #GstGLBaseMixer
*
* Returns: (transfer full) (nullable): the #GstGLContext found by @mix
*
* Since: 1.18
*/
GstGLContext *
gst_gl_base_mixer_get_gl_context (GstGLBaseMixer * mix)
{
GstGLContext *ret;
g_return_val_if_fail (GST_IS_GL_BASE_MIXER (mix), NULL);
g_rec_mutex_lock (&mix->priv->context_lock);
ret = mix->context ? gst_object_ref (mix->context) : NULL;
g_rec_mutex_unlock (&mix->priv->context_lock);
return ret;
}

View file

@ -89,10 +89,15 @@ struct _GstGLBaseMixerClass
GstVideoAggregatorClass parent_class;
GstGLAPI supported_gl_api;
gboolean (*gl_start) (GstGLBaseMixer * mix);
void (*gl_stop) (GstGLBaseMixer * mix);
gpointer _padding[GST_PADDING];
};
GType gst_gl_base_mixer_get_type(void);
GstGLContext * gst_gl_base_mixer_get_gl_context (GstGLBaseMixer * mix);
G_END_DECLS
#endif /* __GST_GL_BASE_MIXER_H__ */

View file

@ -392,6 +392,9 @@ static void gst_gl_mixer_get_property (GObject * object, guint prop_id,
static gboolean gst_gl_mixer_decide_allocation (GstAggregator * agg,
GstQuery * query);
static gboolean gst_gl_mixer_gl_start (GstGLBaseMixer * mix);
static void gst_gl_mixer_gl_stop (GstGLBaseMixer * mix);
static void gst_gl_mixer_finalize (GObject * object);
static void
@ -402,6 +405,7 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass)
GstVideoAggregatorClass *videoaggregator_class =
(GstVideoAggregatorClass *) klass;
GstAggregatorClass *agg_class = (GstAggregatorClass *) klass;
GstGLBaseMixerClass *base_class = (GstGLBaseMixerClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glmixer", 0, "OpenGL mixer");
@ -426,6 +430,8 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass)
videoaggregator_class->aggregate_frames = gst_gl_mixer_aggregate_frames;
videoaggregator_class->find_best_format = _find_best_format;
base_class->gl_start = gst_gl_mixer_gl_start;
base_class->gl_stop = gst_gl_mixer_gl_stop;
/* Register the pad class */
g_type_class_ref (GST_TYPE_GL_MIXER_PAD);
@ -527,12 +533,62 @@ _mixer_create_fbo (GstGLContext * context, GstGLMixer * mix)
out_height);
}
static gboolean
gst_gl_mixer_gl_start (GstGLBaseMixer * base_mix)
{
GstGLMixer *mix = GST_GL_MIXER (base_mix);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
g_mutex_lock (&mix->priv->gl_resource_lock);
mix->priv->gl_resource_ready = FALSE;
if (mix->fbo)
gst_object_unref (mix->fbo);
gst_gl_context_thread_add (base_mix->context,
(GstGLContextThreadFunc) _mixer_create_fbo, mix);
if (!mix->fbo) {
g_cond_signal (&mix->priv->gl_resource_cond);
g_mutex_unlock (&mix->priv->gl_resource_lock);
goto context_error;
}
if (mixer_class->set_caps)
mixer_class->set_caps (mix, mix->out_caps);
mix->priv->gl_resource_ready = TRUE;
g_cond_signal (&mix->priv->gl_resource_cond);
g_mutex_unlock (&mix->priv->gl_resource_lock);
return GST_GL_BASE_MIXER_CLASS (parent_class)->gl_start (base_mix);
context_error:
{
GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("Context error"), (NULL));
return FALSE;
}
}
static void
gst_gl_mixer_gl_stop (GstGLBaseMixer * base_mix)
{
GstGLMixer *mix = GST_GL_MIXER (base_mix);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
if (mixer_class->reset)
mixer_class->reset (mix);
if (mix->fbo) {
gst_object_unref (mix->fbo);
mix->fbo = NULL;
}
GST_GL_BASE_MIXER_CLASS (parent_class)->gl_stop (base_mix);
}
static gboolean
gst_gl_mixer_decide_allocation (GstAggregator * agg, GstQuery * query)
{
GstGLBaseMixer *base_mix = GST_GL_BASE_MIXER (agg);
GstGLMixer *mix = GST_GL_MIXER (base_mix);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
GstGLContext *context;
GstBufferPool *pool = NULL;
GstStructure *config;
@ -544,30 +600,14 @@ gst_gl_mixer_decide_allocation (GstAggregator * agg, GstQuery * query)
query))
return FALSE;
context = base_mix->context;
g_mutex_lock (&mix->priv->gl_resource_lock);
mix->priv->gl_resource_ready = FALSE;
if (mix->fbo)
gst_object_unref (mix->fbo);
gst_gl_context_thread_add (context,
(GstGLContextThreadFunc) _mixer_create_fbo, mix);
if (!mix->fbo) {
g_cond_signal (&mix->priv->gl_resource_cond);
g_mutex_unlock (&mix->priv->gl_resource_lock);
goto context_error;
context = gst_gl_base_mixer_get_gl_context (base_mix);
if (!context) {
GST_WARNING_OBJECT (agg, "No OpenGL context");
return FALSE;
}
gst_query_parse_allocation (query, &caps, NULL);
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 (gst_query_get_n_allocation_pools (query) > 0) {
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
@ -598,13 +638,9 @@ gst_gl_mixer_decide_allocation (GstAggregator * agg, GstQuery * query)
gst_object_unref (pool);
return TRUE;
gst_clear_object (&context);
context_error:
{
GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("Context error"), (NULL));
return FALSE;
}
return TRUE;
}
gboolean
@ -615,7 +651,6 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
GstVideoFrame out_frame;
GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
GstGLMixerPrivate *priv = mix->priv;
GST_TRACE ("Processing buffers");
@ -626,12 +661,12 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
out_tex = (GstGLMemory *) out_frame.map[0].memory;
g_mutex_lock (&priv->gl_resource_lock);
if (!priv->gl_resource_ready)
g_cond_wait (&priv->gl_resource_cond, &priv->gl_resource_lock);
g_mutex_lock (&mix->priv->gl_resource_lock);
if (!mix->priv->gl_resource_ready)
g_cond_wait (&mix->priv->gl_resource_cond, &mix->priv->gl_resource_lock);
if (!priv->gl_resource_ready) {
g_mutex_unlock (&priv->gl_resource_lock);
if (!mix->priv->gl_resource_ready) {
g_mutex_unlock (&mix->priv->gl_resource_lock);
GST_ERROR_OBJECT (mix,
"fbo used to render can't be created, do not run process_textures");
res = FALSE;
@ -640,7 +675,7 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
mix_class->process_textures (mix, out_tex);
g_mutex_unlock (&priv->gl_resource_lock);
g_mutex_unlock (&mix->priv->gl_resource_lock);
out:
gst_video_frame_unmap (&out_frame);
@ -659,12 +694,18 @@ gst_gl_mixer_process_buffers (GstGLMixer * mix, GstBuffer * outbuf)
static GstFlowReturn
gst_gl_mixer_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
{
GstGLBaseMixer *base_mix = GST_GL_BASE_MIXER (vagg);
gboolean res = FALSE;
GstGLMixer *mix = GST_GL_MIXER (vagg);
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (vagg);
GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
GstGLContext *context = gst_gl_base_mixer_get_gl_context (base_mix);
GstGLSyncMeta *sync_meta;
if (!context) {
GST_DEBUG_OBJECT (vagg, "No OpenGL context, try again later");
return GST_AGGREGATOR_FLOW_NEED_DATA;
}
if (mix_class->process_buffers)
res = gst_gl_mixer_process_buffers (mix, outbuf);
else if (mix_class->process_textures)
@ -674,6 +715,8 @@ gst_gl_mixer_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
if (sync_meta)
gst_gl_sync_meta_set_sync_point (sync_meta, context);
gst_clear_object (&context);
return res ? GST_FLOW_OK : GST_FLOW_ERROR;
}
@ -709,15 +752,6 @@ static gboolean
gst_gl_mixer_stop (GstAggregator * agg)
{
GstGLMixer *mix = GST_GL_MIXER (agg);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
if (mixer_class->reset)
mixer_class->reset (mix);
if (mix->fbo) {
gst_object_unref (mix->fbo);
mix->fbo = NULL;
}
gst_gl_mixer_reset (mix);

View file

@ -472,7 +472,8 @@ static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps);
static GstCaps *_fixate_caps (GstAggregator * agg, GstCaps * caps);
static gboolean gst_gl_video_mixer_propose_allocation (GstAggregator *
agg, GstAggregatorPad * agg_pad, GstQuery * decide_query, GstQuery * query);
static void gst_gl_video_mixer_reset (GstGLMixer * mixer);
static gboolean gst_gl_video_mixer_gl_start (GstGLBaseMixer * base_mix);
static void gst_gl_video_mixer_gl_stop (GstGLBaseMixer * base_mix);
static gboolean gst_gl_video_mixer_set_caps (GstGLMixer * mixer,
GstCaps * outcaps);
@ -918,10 +919,11 @@ gst_gl_video_mixer_class_init (GstGLVideoMixerClass * klass)
DEFAULT_BACKGROUND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
GST_GL_MIXER_CLASS (klass)->set_caps = gst_gl_video_mixer_set_caps;
GST_GL_MIXER_CLASS (klass)->reset = gst_gl_video_mixer_reset;
GST_GL_MIXER_CLASS (klass)->process_textures =
gst_gl_video_mixer_process_textures;
GST_GL_BASE_MIXER_CLASS (klass)->gl_stop = gst_gl_video_mixer_gl_stop;
GST_GL_BASE_MIXER_CLASS (klass)->gl_start = gst_gl_video_mixer_gl_start;
vagg_class->update_caps = _update_caps;
@ -1057,7 +1059,6 @@ _update_caps (GstVideoAggregator * vagg, GstCaps * caps)
GST_OBJECT_UNLOCK (vagg);
return NULL;
}
}
GST_OBJECT_UNLOCK (vagg);
@ -1180,34 +1181,11 @@ _reset_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
gst_element_foreach_sink_pad (GST_ELEMENT (video_mixer), _reset_pad_gl, NULL);
}
static void
gst_gl_video_mixer_reset (GstGLMixer * mixer)
{
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer);
GstGLContext *context = GST_GL_BASE_MIXER (mixer)->context;
GST_DEBUG_OBJECT (mixer, "context:%p", context);
if (video_mixer->shader)
gst_object_unref (video_mixer->shader);
video_mixer->shader = NULL;
if (video_mixer->checker)
gst_object_unref (video_mixer->checker);
video_mixer->checker = NULL;
if (GST_GL_BASE_MIXER (mixer)->context)
gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _reset_gl,
mixer);
}
static gboolean
gst_gl_video_mixer_set_caps (GstGLMixer * mixer, GstCaps * outcaps)
{
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer);
g_clear_object (&video_mixer->shader);
/* need reconfigure output geometry */
video_mixer->output_geo_change = TRUE;
@ -1215,23 +1193,44 @@ gst_gl_video_mixer_set_caps (GstGLMixer * mixer, GstCaps * outcaps)
}
static void
_video_mixer_process_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
gst_gl_video_mixer_gl_stop (GstGLBaseMixer * base_mix)
{
GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (base_mix);
gst_clear_object (&video_mixer->shader);
gst_clear_object (&video_mixer->checker);
_reset_gl (base_mix->context, video_mixer);
GST_GL_BASE_MIXER_CLASS (parent_class)->gl_stop (base_mix);
}
static gboolean
gst_gl_video_mixer_gl_start (GstGLBaseMixer * base_mix)
{
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (base_mix);
if (!video_mixer->shader) {
gchar *frag_str = g_strdup_printf ("%s%s",
gst_gl_shader_string_get_highest_precision (GST_GL_BASE_MIXER
(mixer)->context, GST_GLSL_VERSION_NONE,
gst_gl_shader_string_get_highest_precision (base_mix->context,
GST_GLSL_VERSION_NONE,
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY),
video_mixer_f_src);
gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
gst_gl_context_gen_shader (base_mix->context,
gst_gl_shader_string_vertex_mat4_vertex_transform,
frag_str, &video_mixer->shader);
g_free (frag_str);
}
return GST_GL_BASE_MIXER_CLASS (parent_class)->gl_start (base_mix);
}
static void
_video_mixer_process_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
{
GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
gst_gl_framebuffer_draw_to_texture (mixer->fbo, video_mixer->out_tex,
gst_gl_video_mixer_callback, video_mixer);
}