mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-11 19:06:33 +00:00
gl/mixer: support GstGLDisplay changes
This commit is contained in:
parent
0e038a5612
commit
55e80b550e
4 changed files with 298 additions and 103 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue