void MediaPlayerPrivateGStreamerBase::handleNeedContextMessage(GstMessage* message)
{
#if USE(GSTREAMER_GL)
    const gchar* contextType;
    gst_message_parse_context_type(message, &contextType);

    if (!ensureGstGLContext())
        return;

    if (!g_strcmp0(contextType, GST_GL_DISPLAY_CONTEXT_TYPE)) {
        GstContext* displayContext = gst_context_new(GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
        gst_context_set_gl_display(displayContext, m_glDisplay.get());
        gst_element_set_context(GST_ELEMENT(message->src), displayContext);
        return;
    }

    if (!g_strcmp0(contextType, "gst.gl.app_context")) {
        GstContext* appContext = gst_context_new("gst.gl.app_context", TRUE);
        GstStructure* structure = gst_context_writable_structure(appContext);
        gst_structure_set(structure, "context", GST_GL_TYPE_CONTEXT, m_glContext.get(), nullptr);
        gst_element_set_context(GST_ELEMENT(message->src), appContext);
        return;
    }
#else
    UNUSED_PARAM(message);
#endif // USE(GSTREAMER_GL)
}
static gboolean
sync_bus_call (GstBus * bus, GstMessage * msg, gpointer data)
{
  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_NEED_CONTEXT:
    {
      const gchar *context_type;

      gst_message_parse_context_type (msg, &context_type);
      g_print ("got need context %s\n", context_type);

      if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
        GstContext *display_context =
            gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
        gst_context_set_gl_display (display_context, sdl_gl_display);
        gst_element_set_context (GST_ELEMENT (msg->src), display_context);
        return TRUE;
      } else if (g_strcmp0 (context_type, "gst.gl.app_context") == 0) {
        GstContext *app_context = gst_context_new ("gst.gl.app_context", TRUE);
        GstStructure *s = gst_context_writable_structure (app_context);
        gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, sdl_context,
            NULL);
        gst_element_set_context (GST_ELEMENT (msg->src), app_context);
        return TRUE;
      }
      break;
    }
    default:
      break;
  }
  return FALSE;
}
Example #3
0
gboolean
gst_vulkan_ensure_element_data (gpointer element,
    GstVulkanDisplay ** display_ptr, GstVulkanInstance ** instance_ptr)
{
  g_return_val_if_fail (element != NULL, FALSE);
  g_return_val_if_fail (display_ptr != NULL, FALSE);
  g_return_val_if_fail (instance_ptr != NULL, FALSE);

  /*  1) Check if the element already has a context of the specific
   *     type.
   */
  if (!*instance_ptr) {
    GError *error = NULL;

    gst_vulkan_global_context_query (element,
        GST_VULKAN_INSTANCE_CONTEXT_TYPE_STR);

    /* Neighbour found and it updated the display */
    if (!*instance_ptr) {
      GstContext *context;

      /* If no neighboor, or application not interested, use system default */
      *instance_ptr = gst_vulkan_instance_new ();

      context = gst_context_new (GST_VULKAN_INSTANCE_CONTEXT_TYPE_STR, TRUE);
      gst_context_set_vulkan_instance (context, *instance_ptr);

      _vk_context_propagate (element, context);
    }

    if (!gst_vulkan_instance_open (*instance_ptr, &error)) {
      GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
          ("Failed to create vulkan instance"), ("%s", error->message));
      g_clear_error (&error);
      return FALSE;
    }
  }

  if (!*display_ptr) {
    _vk_display_context_query (element, display_ptr);

    /* Neighbour found and it updated the display */
    if (!*display_ptr) {
      GstContext *context;

      /* instance is required before the display */
      g_return_val_if_fail (*instance_ptr != NULL, FALSE);

      /* If no neighboor, or application not interested, use system default */
      *display_ptr = gst_vulkan_display_new (*instance_ptr);

      context = gst_context_new (GST_VULKAN_DISPLAY_CONTEXT_TYPE_STR, TRUE);
      gst_context_set_vulkan_display (context, *display_ptr);

      _vk_context_propagate (element, context);
    }
  }

  return *display_ptr != NULL && *instance_ptr != NULL;
}
Example #4
0
gboolean
gst_gl_handle_context_query (GstElement * element, GstQuery * query,
    GstGLDisplay ** display)
{
  gboolean res = FALSE;
  const gchar *context_type;
  GstContext *context, *old_context;

  g_return_val_if_fail (element != NULL, FALSE);
  g_return_val_if_fail (query != NULL, FALSE);
  g_return_val_if_fail (display != NULL, FALSE);

  gst_query_parse_context_type (query, &context_type);

  if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);

    gst_context_set_gl_display (context, *display);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = *display != NULL;
  }

  return res;
}
gboolean
gst_vulkan_instance_handle_context_query (GstElement * element,
    GstQuery * query, GstVulkanInstance ** instance)
{
  gboolean res = FALSE;
  const gchar *context_type;
  GstContext *context, *old_context;

  g_return_val_if_fail (element != NULL, FALSE);
  g_return_val_if_fail (query != NULL, FALSE);
  g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT, FALSE);
  g_return_val_if_fail (instance != NULL, FALSE);

  gst_query_parse_context_type (query, &context_type);

  if (g_strcmp0 (context_type, GST_VULKAN_INSTANCE_CONTEXT_TYPE_STR) == 0) {
    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new (GST_VULKAN_INSTANCE_CONTEXT_TYPE_STR, TRUE);

    gst_context_set_vulkan_instance (context, *instance);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = *instance != NULL;
  }

  return res;
}
static GstStateChangeReturn
gst_context_element_change_state (GstElement * element,
    GstStateChange transition)
{
  GstContextElement *celement = (GstContextElement *) element;

  if (transition == GST_STATE_CHANGE_NULL_TO_READY) {
    GstContext *context;
    GstMessage *msg;
    gboolean have_foobar = celement->have_foobar;

    if (celement->set_before_ready && !have_foobar)
      return GST_STATE_CHANGE_FAILURE;
    else if (celement->set_before_ready)
      return
          GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state
          (element, transition);

    if (celement->set_from_need_context && have_foobar)
      return GST_STATE_CHANGE_FAILURE;

    if (!have_foobar) {
      /* Here we would first query downstream for a context but we have no pads */
      msg = gst_message_new_need_context (GST_OBJECT (element), "foobar");
      gst_element_post_message (element, msg);

      have_foobar = celement->have_foobar;
    }

    if (celement->set_from_need_context && !have_foobar)
      return GST_STATE_CHANGE_FAILURE;
    else if (celement->set_from_need_context)
      return
          GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state
          (element, transition);

    if (celement->create_self && have_foobar)
      return GST_STATE_CHANGE_FAILURE;

    if (!have_foobar) {
      context = gst_context_new ("foobar", FALSE);
      gst_element_set_context (element, context);
      msg =
          gst_message_new_have_context (GST_OBJECT (element),
          gst_context_ref (context));
      gst_element_post_message (element, msg);
      gst_context_unref (context);
    }
    return
        GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state
        (element, transition);
  }

  return
      GST_ELEMENT_CLASS (gst_context_element_parent_class)->change_state
      (element, transition);
}
GstContext *
gst_vaapi_video_context_new_with_display (GstVaapiDisplay * display,
    gboolean persistent)
{
  GstContext *context;

  context = gst_context_new (GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME, persistent);
  gst_vaapi_video_context_set_display (context, display);
  return context;
}
Example #8
0
/**
 * gstbt_audio_tempo_context_new:
 * @bpm: beats per minute
 * @tpb: ticks per beat
 * @stpb: sub-ticks per beat
 *
 * The values of @bpm and @tpb define the meassure and speed of an audio track.
 * Elements (mostly sources) use these value to configure how the quantise
 * controller events and size their buffers. Elements can also use this for
 * tempo synced effects.
 *
 * When using controllers one can also use @stpb to achieve smoother modulation.
 *
 * Returns: a new persistent context that can be send to the pipeline
 */
GstContext *
gstbt_audio_tempo_context_new (guint bpm, guint tpb, guint stpb)
{
  GstContext *ctx = gst_context_new (GSTBT_AUDIO_TEMPO_TYPE, TRUE);
  GstStructure *s = gst_context_writable_structure (ctx);
  gst_structure_set (s,
      "beats-per-minute", G_TYPE_UINT, bpm,
      "ticks-per-beat", G_TYPE_UINT, tpb,
      "subticks-per-beat", G_TYPE_UINT, stpb, NULL);
  return ctx;
}
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);
}
Example #10
0
static GstContext *gub_provide_graphic_context_egl(GUBGraphicContextEGL *gcontext, const gchar *type)
{
    GstContext *context = NULL;

    gub_log("Providing context. gub_context=%p, type=%s", gcontext, type);

    if (!gcontext) return NULL;

    if (type != NULL) {
        if (g_strcmp0(type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
            context = gst_context_new(GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
            gst_context_set_gl_display(context, gcontext->display);
        }
        else if (g_strcmp0(type, "gst.gl.app_context") == 0) {
            GstStructure *s;
            context = gst_context_new("gst.gl.app_context", TRUE);
            s = gst_context_writable_structure(context);
            gst_structure_set(s, "context", GST_GL_TYPE_CONTEXT, gcontext->gl, NULL);
        }
        else if (g_strcmp0(type, "gst.gl.local_context") == 0) {
            GstGLContext *local_context = gst_gl_context_new(gcontext->display);
            GError *error = NULL;
            gst_gl_context_create(local_context, gcontext->gl, &error);
            if (error) {
                gub_log("Cannot create local context: %s", error->message);
                g_error_free(error);
            }
            else {
                GstStructure *s;
                context = gst_context_new("gst.gl.local_context", TRUE);
                s = gst_context_writable_structure(context);
                gst_structure_set(s, "context", GST_GL_TYPE_CONTEXT, local_context, NULL);
            }
        }
    }
    return context;
}
Example #11
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;
}
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);
  }
}
static GstBusSyncReply
sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
{
  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT) {
    const gchar *type;
    GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message));
    GstContext *context;

    fail_unless (gst_message_parse_context_type (message, &type));
    fail_unless_equals_string (type, "foobar");
    context = gst_context_new ("foobar", FALSE);
    gst_element_set_context (element, context);
    gst_context_unref (context);
  }

  return GST_BUS_PASS;
}
Example #14
0
/*  4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT
 *     message.
 */
static void
gst_gl_display_context_propagate (GstElement * element, GstGLDisplay * display)
{
  GstContext *context;
  GstMessage *msg;

  if (!display) {
    GST_ERROR_OBJECT (element, "Could not get GL display connection");
    return;
  }

  context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
  gst_context_set_gl_display (context, display);

  GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
      "posting have context (%p) message with display (%p)", context, display);
  msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
  gst_element_post_message (GST_ELEMENT_CAST (element), msg);
}
Example #15
0
/**
 * gst_gl_handle_context_query:
 * @element: a #GstElement
 * @query: a #GstQuery of type %GST_QUERY_CONTEXT
 * @display: (transfer none) (nullable): a #GstGLDisplay
 * @context: (transfer none) (nullable): a #GstGLContext
 * @other_context: (transfer none) (nullable): application provided #GstGLContext
 *
 * Returns: Whether the @query was successfully responded to from the passed
 *          @display, @context, and @other_context.
 */
gboolean
gst_gl_handle_context_query (GstElement * element, GstQuery * query,
    GstGLDisplay * display, GstGLContext * gl_context,
    GstGLContext * other_context)
{
  const gchar *context_type;
  GstContext *context, *old_context;

  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
  g_return_val_if_fail (display == NULL || GST_IS_GL_DISPLAY (display), FALSE);
  g_return_val_if_fail (gl_context == NULL
      || GST_IS_GL_CONTEXT (gl_context), FALSE);
  g_return_val_if_fail (other_context == NULL
      || GST_IS_GL_CONTEXT (other_context), FALSE);

  GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query);
  gst_query_parse_context_type (query, &context_type);

  if (display && g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);

    gst_context_set_gl_display (context, display);
    gst_query_set_context (query, context);
    gst_context_unref (context);
    GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT
        " on %" GST_PTR_FORMAT, display, query);

    return TRUE;
  }
#if GST_GL_HAVE_WINDOW_X11
  else if (display && g_strcmp0 (context_type, "gst.x11.display.handle") == 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.x11.display.handle", TRUE);

    if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_X11) {
      Display *x11_display = (Display *) gst_gl_display_get_handle (display);

      if (x11_display) {
        s = gst_context_writable_structure (context);
        gst_structure_set (s, "display", G_TYPE_POINTER, x11_display, NULL);

        gst_query_set_context (query, context);
        gst_context_unref (context);

        GST_DEBUG_OBJECT (element, "successfully set x11 display %p (from %"
            GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, x11_display, display,
            query);

        return TRUE;
      }
    }
  }
#endif
#if GST_GL_HAVE_WINDOW_WAYLAND
  else if (display
      && g_strcmp0 (context_type, "GstWaylandDisplayHandleContextType") == 0) {
    GstStructure *s;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("GstWaylandDisplayHandleContextType", TRUE);

    if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WAYLAND) {
      struct wl_display *wayland_display =
          (struct wl_display *) gst_gl_display_get_handle (display);

      if (wayland_display) {
        s = gst_context_writable_structure (context);
        gst_structure_set (s, "display", G_TYPE_POINTER, wayland_display, NULL);

        gst_query_set_context (query, context);
        gst_context_unref (context);

        GST_DEBUG_OBJECT (element, "successfully set wayland display %p (from %"
            GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, wayland_display, display,
            query);

        return TRUE;
      }
    }
  }
#endif
  else if (other_context && g_strcmp0 (context_type, "gst.gl.app_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.app_context", TRUE);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, other_context, NULL);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    GST_DEBUG_OBJECT (element, "successfully set application GL context %"
        GST_PTR_FORMAT " on %" GST_PTR_FORMAT, other_context, query);

    return TRUE;
  } else if (gl_context
      && 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", TRUE);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, gl_context, NULL);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    GST_DEBUG_OBJECT (element, "successfully set GL context %"
        GST_PTR_FORMAT " on %" GST_PTR_FORMAT, gl_context, query);

    return TRUE;
  }

  return FALSE;
}
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);
}
Example #17
0
gboolean
gst_gl_handle_context_query (GstElement * element, GstQuery * query,
    GstGLDisplay ** display, GstGLContext ** other_context)
{
  gboolean res = FALSE;
  const gchar *context_type;
  GstContext *context, *old_context;

  g_return_val_if_fail (element != NULL, FALSE);
  g_return_val_if_fail (query != NULL, FALSE);
  g_return_val_if_fail (display != NULL, FALSE);
  g_return_val_if_fail (other_context != NULL, FALSE);

  gst_query_parse_context_type (query, &context_type);

  if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);

    gst_context_set_gl_display (context, *display);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = *display != NULL;
  }
#if GST_GL_HAVE_WINDOW_X11
  else if (g_strcmp0 (context_type, "gst.x11.display.handle") == 0) {
    GstStructure *s;
    Display *x11_display = NULL;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("gst.x11.display.handle", TRUE);

    if (*display
        && ((*display)->type & GST_GL_DISPLAY_TYPE_X11) ==
        GST_GL_DISPLAY_TYPE_X11)
      x11_display = (Display *) gst_gl_display_get_handle (*display);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "display", G_TYPE_POINTER, x11_display, NULL);

    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = x11_display != NULL;
  }
#endif
#if GST_GL_HAVE_WINDOW_WAYLAND
  else if (g_strcmp0 (context_type, "GstWaylandDisplayHandleContextType") == 0) {
    GstStructure *s;
    struct wl_display *wayland_display = NULL;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("GstWaylandDisplayHandleContextType", TRUE);

    if (*display
        && ((*display)->type & GST_GL_DISPLAY_TYPE_WAYLAND) ==
        GST_GL_DISPLAY_TYPE_WAYLAND)
      wayland_display =
          (struct wl_display *) gst_gl_display_get_handle (*display);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "display", G_TYPE_POINTER, wayland_display, NULL);

    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = wayland_display != NULL;
  }
#endif
  else if (g_strcmp0 (context_type, "gst.gl.app_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.app_context", TRUE);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, *other_context, NULL);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    res = *other_context != NULL;
  }

  return res;
}
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);
  }
}
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);;
}