static gboolean
stereosplit_propose_allocation (GstGLStereoSplit * self, GstQuery * query)
{

  if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
    return FALSE;

  _init_upload (self);

  gst_gl_upload_propose_allocation (self->upload, NULL, query);

  return TRUE;
}
Beispiel #2
0
static gboolean
gst_gl_mixer_activate (GstGLMixer * mix, gboolean active)
{
    GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
    gboolean result = TRUE;

    if (active) {
        if (!gst_gl_ensure_element_data (mix, &mix->display, &mix->other_context))
            return FALSE;

        gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
    }

    return result;
}
static gboolean
gst_gl_test_src_start (GstBaseSrc * basesrc)
{
  GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc);

  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);

  src->running_time = 0;
  src->n_frames = 0;
  src->negotiated = FALSE;

  return TRUE;
}
static GstStateChangeReturn
gst_gl_base_mixer_change_state (GstElement * element, GstStateChange transition)
{
    GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element);
    GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

    GST_DEBUG_OBJECT (mix, "changing state: %s => %s",
                      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
                      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));

    switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
        if (!gst_gl_ensure_element_data (element, &mix->display,
                                         &mix->priv->other_context))
            return GST_STATE_CHANGE_FAILURE;

        gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
        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_READY_TO_NULL:
        if (mix->priv->other_context) {
            gst_object_unref (mix->priv->other_context);
            mix->priv->other_context = NULL;
        }

        if (mix->display) {
            gst_object_unref (mix->display);
            mix->display = NULL;
        }
        break;
    default:
        break;
    }

    return ret;
}
static GstStateChangeReturn
gst_gl_test_src_change_state (GstElement * element, GstStateChange transition)
{
  GstGLTestSrc *src = GST_GL_TEST_SRC (element);
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  GST_DEBUG_OBJECT (src, "changing state: %s => %s",
      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!gst_gl_ensure_element_data (element, &src->display,
              &src->other_context))
        return GST_STATE_CHANGE_FAILURE;

      gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS);
      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_READY_TO_NULL:
      if (src->other_context) {
        gst_object_unref (src->other_context);
        src->other_context = NULL;
      }

      if (src->display) {
        gst_object_unref (src->display);
        src->display = NULL;
      }
      break;
    default:
      break;
  }

  return ret;
}
static GstStateChangeReturn
stereosplit_change_state (GstElement * element, GstStateChange transition)
{
  GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element);
  GstStateChangeReturn result;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!gst_gl_ensure_element_data (element, &stereosplit->display,
              &stereosplit->other_context))
        return GST_STATE_CHANGE_FAILURE;

      gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
      break;
    default:
      break;
  }

  result =
      GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->change_state
      (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_NULL:
      if (stereosplit->other_context) {
        gst_object_unref (stereosplit->other_context);
        stereosplit->other_context = NULL;
      }

      if (stereosplit->display) {
        gst_object_unref (stereosplit->display);
        stereosplit->display = NULL;
      }
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      stereosplit_reset (stereosplit);
      break;
    default:
      break;
  }

  return result;
}
static void
gst_vaapi_find_gl_context (GstElement * element)
{
#if USE_GST_GL_HELPERS
  GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element);

  /* if the element is vaapisink or any vaapi encoder it doesn't need
   * to know a GstGLContext in order to create an appropriate
   * GstVaapiDisplay. Let's them to choose their own
   * GstVaapiDisplay */
  if (GST_IS_VIDEO_SINK (element) || GST_IS_VIDEO_ENCODER (element))
    return;

  if (!gst_gl_ensure_element_data (plugin,
          (GstGLDisplay **) & plugin->gl_display,
          (GstGLContext **) & plugin->gl_other_context))
    goto no_valid_gl_display;

  gst_vaapi_find_gl_local_context (element, &plugin->gl_context);

  if (plugin->gl_context) {
    gst_vaapi_plugin_base_set_srcpad_can_dmabuf (plugin, plugin->gl_context);
  } else {
    GstObject *gl_context;

    gl_context = gst_vaapi_plugin_base_create_gl_context (plugin);
    if (gl_context) {
      gst_vaapi_plugin_base_set_gl_context (plugin, gl_context);
      gst_object_unref (gl_context);
    }
  }

  /* ERRORS */
no_valid_gl_display:
  {
    GST_INFO_OBJECT (plugin, "No valid GL display found");
    gst_object_replace (&plugin->gl_display, NULL);
    gst_object_replace (&plugin->gl_other_context, NULL);
    return;
  }
#endif
}
static gboolean
ensure_context (GstGLStereoSplit * self)
{
  GError *error = NULL;

  if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
    return FALSE;

  gst_gl_display_filter_gl_api (self->display, SUPPORTED_GL_APIS);

  _find_local_gl_context (self);

  if (!self->context) {
    GST_OBJECT_LOCK (self->display);
    do {
      if (self->context)
        gst_object_unref (self->context);
      /* just get a GL context.  we don't care */
      self->context =
          gst_gl_display_get_gl_context_for_thread (self->display, NULL);
      if (!self->context) {
        if (!gst_gl_display_create_context (self->display, self->other_context,
                &self->context, &error)) {
          GST_OBJECT_UNLOCK (self->display);
          goto context_error;
        }
      }
    } while (!gst_gl_display_add_context (self->display, self->context));
    GST_OBJECT_UNLOCK (self->display);
  }

  return TRUE;

context_error:
  {
    GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("%s", error->message),
        (NULL));
    g_clear_error (&error);
    return FALSE;
  }
}
/**
 * gst_vaapi_plugin_base_create_gl_context:
 * @plugin: a #GstVaapiPluginBase
 *
 * It queries downstream and upstream for a #GstGLDisplay and a other
 * #GstGLContext. If not found, a new #GstGLDisplay and #GstGLContext
 * are created, if it is possible.
 *
 * Returns: (transfer full) a new created #GstGLContext or %NULL
 **/
GstObject *
gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin)
{
#if USE_GST_GL_HELPERS
  GstGLContext *gl_other_context, *gl_context = NULL;
  GstGLDisplay *gl_display;

  gst_gl_ensure_element_data (plugin, (GstGLDisplay **) & plugin->gl_display,
      (GstGLContext **) & plugin->gl_other_context);

  gl_display = (GstGLDisplay *) plugin->gl_display;
  if (!gl_display ||
      gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY) {
    gst_object_replace (&plugin->gl_display, NULL);
    gst_object_replace (&plugin->gl_other_context, NULL);
    return NULL;
  }
  gl_other_context = (GstGLContext *) plugin->gl_other_context;

  GST_INFO_OBJECT (plugin, "creating a new GstGL context");

  GST_OBJECT_LOCK (gl_display);
  do {
    if (gl_context)
      gst_object_unref (gl_context);
    gl_context = gst_gl_display_get_gl_context_for_thread (gl_display, NULL);
    if (!gl_context) {
      if (!gst_gl_display_create_context (gl_display, gl_other_context,
              &gl_context, NULL))
        break;
    }
  } while (!gst_gl_display_add_context (gl_display, gl_context));
  GST_OBJECT_UNLOCK (gl_display);

  return GST_OBJECT_CAST (gl_context);
#else
  return NULL;
#endif
}
Beispiel #10
0
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);
    gboolean same_downstream_gl_context = FALSE;

    if (!gst_gl_ensure_element_data (mix, &mix->display, &mix->other_context))
        return FALSE;

    gst_gl_display_filter_gl_api (mix->display, mixer_class->supported_gl_api);

    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);
                same_downstream_gl_context = TRUE;
            } 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;
                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->other_context) {
        if (!other_context) {
            other_context = mix->other_context;
        } else {
            GST_ELEMENT_WARNING (mix, LIBRARY, SETTINGS,
                                 ("%s", "Cannot share with more than one GL context"),
                                 ("%s", "Cannot share with more than one GL context"));
        }
    }

    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);

    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);

        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 || (!same_downstream_gl_context
                  && gst_query_find_allocation_meta (query, GST_GL_SYNC_META_API_TYPE,
                          NULL)
                  && !gst_buffer_pool_has_option (pool,
                          GST_BUFFER_POOL_OPTION_GL_SYNC_META))) {
        /* can't use this pool */
        if (pool)
            gst_object_unref (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);
    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_object_unref (pool);

    return TRUE;

context_error:
    {
        GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message),
                           (NULL));
        return FALSE;
    }
}
Beispiel #11
0
static gboolean
gst_gl_mixer_propose_allocation (GstGLMixer * mix,
                                 GstQuery * decide_query, GstQuery * query)
{
    GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
    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_element_data (mix, &mix->display, &mix->other_context))
        return FALSE;

    gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);

    if (!mix->context) {
        mix->context = gst_gl_context_new (mix->display);
        if (!gst_gl_context_create (mix->context, mix->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 (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);
    if (mix->context->gl_vtable->FenceSync)
        gst_query_add_allocation_meta (query, GST_GL_SYNC_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 (&params);

    allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
    gst_query_add_allocation_param (query, allocator, &params);
    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_base_mixer_decide_allocation (GstGLBaseMixer * mix, GstQuery * query)
{
    GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
    GError *error = NULL;
    gboolean ret = TRUE;

    if (!gst_gl_ensure_element_data (mix, &mix->display,
                                     &mix->priv->other_context))
        return FALSE;

    gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);

    _find_local_gl_context (mix);

    if (!mix->context) {
        GST_OBJECT_LOCK (mix->display);
        do {
            if (mix->context) {
                gst_object_unref (mix->context);
                mix->context = NULL;
            }
            /* just get a GL context.  we don't care */
            mix->context =
                gst_gl_display_get_gl_context_for_thread (mix->display, NULL);
            if (!mix->context) {
                if (!gst_gl_display_create_context (mix->display,
                                                    mix->priv->other_context, &mix->context, &error)) {
                    GST_OBJECT_UNLOCK (mix->display);
                    goto context_error;
                }
            }
        } while (!gst_gl_display_add_context (mix->display, mix->context));
        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 (mix_class->decide_allocation)
        ret = mix_class->decide_allocation (mix, query);

    return ret;

unsupported_gl_api:
    {
        GstGLAPI gl_api = gst_gl_context_get_gl_api (mix->context);
        gchar *gl_api_str = gst_gl_api_to_string (gl_api);
        gchar *supported_gl_api_str =
            gst_gl_api_to_string (mix_class->supported_gl_api);
        GST_ELEMENT_ERROR (mix, 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 (mix, RESOURCE, NOT_FOUND, ("%s", error->message),
                           (NULL));
        g_clear_error (&error);
        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;
  }
}
void
gst_gl_context_helper_ensure_context (GstGLContextHelper * ctxh)
{
  GError *error = NULL;
  GstGLContext *context;

  g_return_if_fail (ctxh != NULL);

  if (!ctxh->display)
    gst_gl_ensure_element_data (ctxh->element, &ctxh->display,
        &ctxh->other_context);

  if (!ctxh->display)
    goto display_error;

  context = _find_local_gl_context (ctxh);
  if (context) {
    GST_INFO_OBJECT (ctxh->element, "found local context %p, old context %p",
        context, ctxh->context);
    if (ctxh->context)
      gst_object_unref (ctxh->context);
    ctxh->context = context;
  }

  if (!ctxh->context) {
    GST_OBJECT_LOCK (ctxh->display);
    do {
      if (ctxh->context)
        gst_object_unref (ctxh->context);
      ctxh->context =
          gst_gl_display_get_gl_context_for_thread (ctxh->display, NULL);
      if (!ctxh->context) {
        if (!gst_gl_display_create_context (ctxh->display,
                ctxh->other_context, &ctxh->context, &error)) {
          GST_OBJECT_UNLOCK (ctxh->display);
          goto context_error;
        }
      }
    } while (!gst_gl_display_add_context (ctxh->display, ctxh->context));
    GST_OBJECT_UNLOCK (ctxh->display);
  }

  return;

context_error:
  {
    GST_ELEMENT_ERROR (ctxh->element, RESOURCE, NOT_FOUND, ("%s",
            error->message), (NULL));
    g_clear_error (&error);

    return;
  }

display_error:
  {
    GST_ELEMENT_ERROR (ctxh->element, RESOURCE, NOT_FOUND,
        ("Failed to obtain display"), (NULL));

    return;
  }
}