Пример #1
0
static gboolean
gst_gl_mixer_src_query (GstAggregator * agg, GstQuery * query)
{
    gboolean res = FALSE;
    GstGLMixer *mix = GST_GL_MIXER (agg);
    GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
        res = gst_gl_handle_context_query ((GstElement *) mix, query,
                                           &mix->display, &mix->other_context);
        if (mix->display)
            gst_gl_display_filter_gl_api (mix->display,
                                          mix_class->supported_gl_api);
        break;
    }
    case GST_QUERY_CAPS:
        res = gst_gl_mixer_query_caps (agg->srcpad, agg, query);
        break;
    default:
        res = GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query);
        break;
    }

    return res;
}
Пример #2
0
static void
gst_gl_mixer_set_context (GstElement * element, GstContext * context)
{
    GstGLMixer *mix = GST_GL_MIXER (element);
    GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);

    gst_gl_handle_set_context (element, context, &mix->display,
                               &mix->other_context);

    if (mix->display)
        gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
}
Пример #3
0
static void
gst_gl_test_src_set_context (GstElement * element, GstContext * context)
{
  GstGLTestSrc *src = GST_GL_TEST_SRC (element);

  gst_gl_handle_set_context (element, context, &src->display,
      &src->other_context);

  if (src->display)
    gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS);

  GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
static gboolean
gst_gl_base_mixer_src_query (GstAggregator * agg, GstQuery * query)
{
    gboolean res = FALSE;
    GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg);
    GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
        const gchar *context_type;
        GstContext *context, *old_context;

        res = gst_gl_handle_context_query ((GstElement *) mix, query,
                                           &mix->display, &mix->priv->other_context);
        if (mix->display)
            gst_gl_display_filter_gl_api (mix->display,
                                          mix_class->supported_gl_api);
        gst_query_parse_context_type (query, &context_type);

        if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
            GstStructure *s;

            gst_query_parse_context (query, &old_context);

            if (old_context)
                context = gst_context_copy (old_context);
            else
                context = gst_context_new ("gst.gl.local_context", FALSE);

            s = gst_context_writable_structure (context);
            gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, mix->context,
                               NULL);
            gst_query_set_context (query, context);
            gst_context_unref (context);

            res = mix->context != NULL;
        }
        GST_LOG_OBJECT (mix, "context query of type %s %i", context_type, res);

        if (res)
            return res;

        break;
    }
    default:
        break;
    }

    return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query);
}
Пример #5
0
static void
stereosplit_set_context (GstElement * element, GstContext * context)
{
  GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element);

  gst_gl_handle_set_context (element, context, &stereosplit->display,
      &stereosplit->other_context);

  if (stereosplit->display)
    gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);

  GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->set_context (element,
      context);
}
Пример #6
0
static gboolean
gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
{
    GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (bsink);
    gboolean res = FALSE;

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
        const gchar *context_type;
        GstContext *context, *old_context;

        res = gst_gl_handle_context_query ((GstElement *) gtk_sink, query,
                                           &gtk_sink->display, &gtk_sink->gtk_context);

        if (gtk_sink->display)
            gst_gl_display_filter_gl_api (gtk_sink->display, GST_GL_API_OPENGL3);

        gst_query_parse_context_type (query, &context_type);

        if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
            GstStructure *s;

            gst_query_parse_context (query, &old_context);

            if (old_context)
                context = gst_context_copy (old_context);
            else
                context = gst_context_new ("gst.gl.local_context", FALSE);

            s = gst_context_writable_structure (context);
            gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, gtk_sink->context,
                               NULL);
            gst_query_set_context (query, context);
            gst_context_unref (context);

            res = gtk_sink->context != NULL;
        }
        GST_LOG_OBJECT (gtk_sink, "context query of type %s %i", context_type,
                        res);
        break;
    }
    default:
        res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
        break;
    }

    return res;
}
Пример #7
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;
}
Пример #8
0
static gboolean
stereosplit_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent);

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
      const gchar *context_type;
      GstContext *context, *old_context;
      gboolean ret;

      ret = gst_gl_handle_context_query ((GstElement *) split, query,
          &split->display, &split->other_context);
      if (split->display)
        gst_gl_display_filter_gl_api (split->display, SUPPORTED_GL_APIS);
      gst_query_parse_context_type (query, &context_type);

      if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
        GstStructure *s;

        gst_query_parse_context (query, &old_context);

        if (old_context)
          context = gst_context_copy (old_context);
        else
          context = gst_context_new ("gst.gl.local_context", FALSE);

        s = gst_context_writable_structure (context);
        gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, split->context,
            NULL);
        gst_query_set_context (query, context);
        gst_context_unref (context);

        ret = split->context != NULL;
      }
      GST_LOG_OBJECT (split, "context query of type %s %i", context_type, ret);

      if (ret)
        return ret;

      return gst_pad_query_default (pad, parent, query);
    }
      /* FIXME: Handle caps query */
    default:
      return gst_pad_query_default (pad, parent, query);
  }
}
Пример #9
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
  }
}
Пример #14
0
static gboolean
gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query)
{
  gboolean res = FALSE;
  GstGLTestSrc *src;

  src = GST_GL_TEST_SRC (bsrc);

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
      const gchar *context_type;
      GstContext *context, *old_context;

      res = gst_gl_handle_context_query ((GstElement *) src, query,
          &src->display, &src->other_context);
      if (src->display)
        gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS);

      gst_query_parse_context_type (query, &context_type);

      if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
        GstStructure *s;

        gst_query_parse_context (query, &old_context);

        if (old_context)
          context = gst_context_copy (old_context);
        else
          context = gst_context_new ("gst.gl.local_context", FALSE);

        s = gst_context_writable_structure (context);
        gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, src->context,
            NULL);
        gst_query_set_context (query, context);
        gst_context_unref (context);

        res = src->context != NULL;
      }
      GST_LOG_OBJECT (src, "context query of type %s %i", context_type, res);

      if (res)
        return res;

      break;
    }
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      res =
          gst_video_info_convert (&src->out_info, src_fmt, src_val, dest_fmt,
          &dest_val);
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);

      return res;
    }
    default:
      break;
  }

  return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
}
Пример #15
0
static gboolean
gst_gl_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
                         GstQuery * query)
{
    gboolean ret = FALSE;
    GstGLMixer *mix = GST_GL_MIXER (agg);
    GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);

    GST_TRACE ("QUERY %" GST_PTR_FORMAT, query);

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CAPS:
    {
        GstCaps *filter, *caps;

        gst_query_parse_caps (query, &filter);
        caps = gst_gl_mixer_pad_sink_getcaps (GST_PAD (bpad), mix, filter);
        gst_query_set_caps_result (query, caps);
        gst_caps_unref (caps);
        ret = TRUE;
        break;
    }
    case GST_QUERY_ACCEPT_CAPS:
    {
        GstCaps *caps;

        gst_query_parse_accept_caps (query, &caps);
        ret = gst_gl_mixer_pad_sink_acceptcaps (GST_PAD (bpad), mix, caps);
        gst_query_set_accept_caps_result (query, ret);
        ret = TRUE;
        break;
    }
    case GST_QUERY_ALLOCATION:
    {
        GstQuery *decide_query = NULL;

        GST_OBJECT_LOCK (mix);
        if (G_UNLIKELY (!mix->priv->negotiated)) {
            GST_DEBUG_OBJECT (mix,
                              "not negotiated yet, can't answer ALLOCATION query");
            GST_OBJECT_UNLOCK (mix);
            return FALSE;
        }
        if ((decide_query = mix->priv->query))
            gst_query_ref (decide_query);
        GST_OBJECT_UNLOCK (mix);

        GST_DEBUG_OBJECT (mix,
                          "calling propose allocation with query %" GST_PTR_FORMAT,
                          decide_query);

        /* pass the query to the propose_allocation vmethod if any */
        ret = gst_gl_mixer_propose_allocation (mix, decide_query, query);

        if (decide_query)
            gst_query_unref (decide_query);

        GST_DEBUG_OBJECT (mix, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query);
        break;
    }
    case GST_QUERY_CONTEXT:
    {
        ret = gst_gl_handle_context_query ((GstElement *) mix, query,
                                           &mix->display, &mix->other_context);
        if (mix->display)
            gst_gl_display_filter_gl_api (mix->display,
                                          mix_class->supported_gl_api);
        break;
    }
    default:
        ret = GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, bpad, query);
        break;
    }

    return ret;
}
Пример #16
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_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
                              GstQuery * query)
{
    gboolean ret = FALSE;
    GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg);
    GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
    GstGLBaseMixerPad *pad = GST_GL_BASE_MIXER_PAD (bpad);

    GST_TRACE ("QUERY %" GST_PTR_FORMAT, query);

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_ALLOCATION:
    {
        GstQuery *decide_query = NULL;

        GST_OBJECT_LOCK (mix);
        if (G_UNLIKELY (!mix->priv->negotiated)) {
            GST_DEBUG_OBJECT (mix,
                              "not negotiated yet, can't answer ALLOCATION query");
            GST_OBJECT_UNLOCK (mix);
            return FALSE;
        }
        if ((decide_query = mix->priv->query))
            gst_query_ref (decide_query);
        GST_OBJECT_UNLOCK (mix);

        GST_DEBUG_OBJECT (mix,
                          "calling propose allocation with query %" GST_PTR_FORMAT,
                          decide_query);

        /* pass the query to the propose_allocation vmethod if any */
        if (mix_class->propose_allocation)
            ret = mix_class->propose_allocation (mix, pad, decide_query, query);
        else
            ret = FALSE;

        if (decide_query)
            gst_query_unref (decide_query);

        GST_DEBUG_OBJECT (mix, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query);
        return ret;
    }
    case GST_QUERY_CONTEXT:
    {
        const gchar *context_type;
        GstContext *context, *old_context;

        ret = gst_gl_handle_context_query ((GstElement *) mix, query,
                                           &mix->display, &mix->priv->other_context);
        if (mix->display)
            gst_gl_display_filter_gl_api (mix->display,
                                          mix_class->supported_gl_api);
        gst_query_parse_context_type (query, &context_type);

        if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
            GstStructure *s;

            gst_query_parse_context (query, &old_context);

            if (old_context)
                context = gst_context_copy (old_context);
            else
                context = gst_context_new ("gst.gl.local_context", FALSE);

            s = gst_context_writable_structure (context);
            gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, mix->context,
                               NULL);
            gst_query_set_context (query, context);
            gst_context_unref (context);

            ret = mix->context != NULL;
        }
        GST_LOG_OBJECT (mix, "context query of type %s %i", context_type, ret);

        if (ret)
            return ret;

        break;
    }
    default:
        break;
    }

    return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, bpad, query);;
}
Пример #19
0
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;
  }
}
Пример #20
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;
    }
}
Пример #21
0
static gboolean
stereosplit_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent);

  GST_DEBUG_OBJECT (split, "sink query %s",
      gst_query_type_get_name (GST_QUERY_TYPE (query)));

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
    {
      const gchar *context_type;
      GstContext *context, *old_context;
      gboolean ret;

      ret = gst_gl_handle_context_query ((GstElement *) split, query,
          &split->display, &split->other_context);
      if (split->display)
        gst_gl_display_filter_gl_api (split->display, SUPPORTED_GL_APIS);
      gst_query_parse_context_type (query, &context_type);

      if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
        GstStructure *s;

        gst_query_parse_context (query, &old_context);

        if (old_context)
          context = gst_context_copy (old_context);
        else
          context = gst_context_new ("gst.gl.local_context", FALSE);

        s = gst_context_writable_structure (context);
        gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, split->context,
            NULL);
        gst_query_set_context (query, context);
        gst_context_unref (context);

        ret = split->context != NULL;
      }
      GST_LOG_OBJECT (split, "context query of type %s %i", context_type, ret);

      if (ret)
        return ret;

      return gst_pad_query_default (pad, parent, query);
    }
    case GST_QUERY_ALLOCATION:
    {
      return stereosplit_propose_allocation (split, query);
    }
    case GST_QUERY_ACCEPT_CAPS:
    {
      GstCaps *possible, *caps;
      gboolean allowed;

      gst_query_parse_accept_caps (query, &caps);

      if (!(possible = gst_pad_query_caps (split->sink_pad, caps)))
        return FALSE;

      allowed = gst_caps_is_subset (caps, possible);
      gst_caps_unref (possible);

      gst_query_set_accept_caps_result (query, allowed);
      return allowed;
    }
    case GST_QUERY_CAPS:
    {
      GstCaps *filter, *left, *right, *combined, *ret, *templ_caps;

      gst_query_parse_caps (query, &filter);

      /* Calculate what downstream can collectively support */
      if (!(left = gst_pad_peer_query_caps (split->left_pad, NULL)))
        return FALSE;
      if (!(right = gst_pad_peer_query_caps (split->right_pad, NULL)))
        return FALSE;

      /* Strip out multiview mode and flags that might break the
       * intersection, since we can convert.
       * We could keep downstream preferred flip/flopping and list
       * separated as preferred in the future which might
       * theoretically allow us an easier conversion, but it's not essential
       */
      left = strip_mview_fields (left, GST_VIDEO_MULTIVIEW_FLAGS_NONE);
      right = strip_mview_fields (right, GST_VIDEO_MULTIVIEW_FLAGS_NONE);

      combined = gst_caps_intersect (left, right);
      gst_caps_unref (left);
      gst_caps_unref (right);

      /* Intersect peer caps with our template formats */
      templ_caps = gst_pad_get_pad_template_caps (split->left_pad);
      ret =
          gst_caps_intersect_full (combined, templ_caps,
          GST_CAPS_INTERSECT_FIRST);
      gst_caps_unref (templ_caps);

      gst_caps_unref (combined);
      combined = ret;

      if (!combined || gst_caps_is_empty (combined)) {
        gst_caps_unref (combined);
        return FALSE;
      }

      /* Convert from the src pad caps to input formats we support */
      ret = stereosplit_transform_caps (split, GST_PAD_SRC, combined, filter);
      gst_caps_unref (combined);
      combined = ret;

      /* Intersect with the sink pad template then */
      templ_caps = gst_pad_get_pad_template_caps (split->sink_pad);
      ret =
          gst_caps_intersect_full (combined, templ_caps,
          GST_CAPS_INTERSECT_FIRST);
      gst_caps_unref (templ_caps);

      GST_LOG_OBJECT (split, "Returning sink pad caps %" GST_PTR_FORMAT, ret);

      gst_query_set_caps_result (query, ret);
      return !gst_caps_is_empty (ret);
    }
    default:
      return gst_pad_query_default (pad, parent, query);
  }
}