Blame gst/overlaycomposition/gstoverlaycomposition.c

Packit Service 4387a0
/* GStreamer
Packit Service 4387a0
 * Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
Packit Service 4387a0
 *
Packit Service 4387a0
 * This library is free software; you can redistribute it and/or
Packit Service 4387a0
 * modify it under the terms of the GNU Library General Public
Packit Service 4387a0
 * License as published by the Free Software Foundation; either
Packit Service 4387a0
 * version 2 of the License, or (at your option) any later version.
Packit Service 4387a0
 *
Packit Service 4387a0
 * This library is distributed in the hope that it will be useful,
Packit Service 4387a0
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4387a0
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4387a0
 * Library General Public License for more details.
Packit Service 4387a0
 *
Packit Service 4387a0
 * You should have received a copy of the GNU Library General Public
Packit Service 4387a0
 * License along with this library; if not, write to the
Packit Service 4387a0
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit Service 4387a0
 * Boston, MA 02110-1301, USA.
Packit Service 4387a0
 */
Packit Service 4387a0
Packit Service 4387a0
/**
Packit Service 4387a0
 * SECTION:element-overlaycomposition
Packit Service 4387a0
 *
Packit Service 4387a0
 * The overlaycomposition element renders an overlay using an application
Packit Service 4387a0
 * provided draw function.
Packit Service 4387a0
 *
Packit Service 4387a0
 * A more interesting example can be found at
Packit Service 4387a0
 * https://cgit.freedesktop.org/gstreamer/gst-plugins-base/tree/tests/examples/overlaycomposition/overlaycomposition.c
Packit Service 4387a0
 *
Packit Service 4387a0
 * <refsect2>
Packit Service 4387a0
 * <title>Example code</title>
Packit Service 4387a0
 * |[
Packit Service 4387a0
 *
Packit Service 4387a0
 * #include <gst/gst.h>
Packit Service 4387a0
 * #include <gst/video/video.h>
Packit Service 4387a0
 *
Packit Service 4387a0
 * ...
Packit Service 4387a0
 *
Packit Service 4387a0
 * typedef struct {
Packit Service 4387a0
 *   gboolean valid;
Packit Service 4387a0
 *   GstVideoInfo info;
Packit Service 4387a0
 * } OverlayState;
Packit Service 4387a0
 *
Packit Service 4387a0
 * ...
Packit Service 4387a0
 *
Packit Service 4387a0
 * static void
Packit Service 4387a0
 * prepare_overlay (GstElement * overlay, GstCaps * caps, gint window_width,
Packit Service 4387a0
 *     gint window_height, gpointer user_data)
Packit Service 4387a0
 * {
Packit Service 4387a0
 *   OverlayState *s = (OverlayState *)user_data;
Packit Service 4387a0
 *
Packit Service 4387a0
 *   if (gst_video_info_from_caps (&s->info, caps))
Packit Service 4387a0
 *     s->valid = TRUE;
Packit Service 4387a0
 * }
Packit Service 4387a0
 *
Packit Service 4387a0
 * static GstVideoOverlayComposition *
Packit Service 4387a0
 * draw_overlay (GstElement * overlay, GstSample * sample, gpointer user_data)
Packit Service 4387a0
 * {
Packit Service 4387a0
 *   OverlayState *s = (OverlayState *)user_data;
Packit Service 4387a0
 *   GstBuffer *buffer;
Packit Service 4387a0
 *   GstVideoOverlayRectangle *rect;
Packit Service 4387a0
 *   GstVideoOverlayComposition *comp;
Packit Service 4387a0
 *   GstVideoInfo info;
Packit Service 4387a0
 *   GstVideoFrame frame;
Packit Service 4387a0
 *   gint x, y;
Packit Service 4387a0
 *   guint8 *data;
Packit Service 4387a0
 *
Packit Service 4387a0
 *   if (!s->valid)
Packit Service 4387a0
 *     return NULL;
Packit Service 4387a0
 *
Packit Service 4387a0
 *   gst_video_info_set_format (&info, GST_VIDEO_FORMAT_BGRA, 16, 16);
Packit Service 4387a0
 *   buffer = gst_buffer_new_and_alloc (info.size);
Packit Service 4387a0
 *   gst_buffer_add_video_meta (buffer, GST_VIDEO_FRAME_FLAG_NONE,
Packit Service 4387a0
 *       GST_VIDEO_INFO_FORMAT(&info),
Packit Service 4387a0
 *       GST_VIDEO_INFO_WIDTH(&info),
Packit Service 4387a0
 *       GST_VIDEO_INFO_HEIGHT(&info));
Packit Service 4387a0
 *
Packit Service 4387a0
 *   gst_video_frame_map (&frame, &info, buffer, GST_MAP_WRITE);
Packit Service 4387a0
 *
Packit Service 4387a0
 *   // Overlay a half-transparent blue 16x16 rectangle in the middle
Packit Service 4387a0
 *   // of the frame
Packit Service 4387a0
 *   data = GST_VIDEO_FRAME_PLANE_DATA(&frame, 0);
Packit Service 4387a0
 *   for (y = 0; y < 16; y++) {
Packit Service 4387a0
 *     guint8 *line = &data[y * GST_VIDEO_FRAME_PLANE_STRIDE (&frame, 0)];
Packit Service 4387a0
 *     for (x = 0; x < 16; x++) {
Packit Service 4387a0
 *       guint8 *pixel = &line[x * 4];
Packit Service 4387a0
 *
Packit Service 4387a0
 *       pixel[0] = 255;
Packit Service 4387a0
 *       pixel[1] = 0;
Packit Service 4387a0
 *       pixel[2] = 0;
Packit Service 4387a0
 *       pixel[3] = 127;
Packit Service 4387a0
 *     }
Packit Service 4387a0
 *   }
Packit Service 4387a0
 *
Packit Service 4387a0
 *   gst_video_frame_unmap (&frame);
Packit Service 4387a0
 *   rect = gst_video_overlay_rectangle_new_raw (buffer,
Packit Service 4387a0
 *       s->info.width / 2 - 8,
Packit Service 4387a0
 *       s->info.height / 2 - 8,
Packit Service 4387a0
 *       16, 16,
Packit Service 4387a0
 *       GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
Packit Service 4387a0
 *   comp = gst_video_overlay_composition_new (rect);
Packit Service 4387a0
 *   gst_video_overlay_rectangle_unref (rect);
Packit Service 4387a0
 *   gst_buffer_unref (buffer);
Packit Service 4387a0
 *
Packit Service 4387a0
 *   return comp;
Packit Service 4387a0
 * }
Packit Service 4387a0
 *
Packit Service 4387a0
 * ...
Packit Service 4387a0
 *
Packit Service 4387a0
 * overlay = gst_element_factory_make ("overlaycomposition", "overlay");
Packit Service 4387a0
 *
Packit Service 4387a0
 * g_signal_connect (overlay, "draw", G_CALLBACK (draw_overlay),
Packit Service 4387a0
 *   overlay_state);
Packit Service 4387a0
 * g_signal_connect (overlay, "caps-changed", 
Packit Service 4387a0
 *   G_CALLBACK (prepare_overlay), overlay_state);
Packit Service 4387a0
 * ...
Packit Service 4387a0
 *
Packit Service 4387a0
 * ]|
Packit Service 4387a0
 * </refsect2>
Packit Service 4387a0
 */
Packit Service 4387a0
Packit Service 4387a0
#if HAVE_CONFIG_H
Packit Service 4387a0
#include "config.h"
Packit Service 4387a0
#endif
Packit Service 4387a0
Packit Service 4387a0
#include <string.h>
Packit Service 4387a0
Packit Service 4387a0
#include "gstoverlaycomposition.h"
Packit Service 4387a0
Packit Service 4387a0
GST_DEBUG_CATEGORY_STATIC (gst_overlay_composition_debug);
Packit Service 4387a0
#define GST_CAT_DEFAULT gst_overlay_composition_debug
Packit Service 4387a0
Packit Service 4387a0
#define OVERLAY_COMPOSITION_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS)
Packit Service 4387a0
Packit Service 4387a0
#define ALL_CAPS OVERLAY_COMPOSITION_CAPS ";" \
Packit Service 4387a0
    GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ALL)
Packit Service 4387a0
Packit Service 4387a0
enum
Packit Service 4387a0
{
Packit Service 4387a0
  SIGNAL_CAPS_CHANGED,
Packit Service 4387a0
  SIGNAL_DRAW,
Packit Service 4387a0
  LAST_SIGNAL
Packit Service 4387a0
};
Packit Service 4387a0
Packit Service 4387a0
static guint overlay_composition_signals[LAST_SIGNAL];
Packit Service 4387a0
Packit Service 4387a0
static GstStaticCaps overlay_composition_caps =
Packit Service 4387a0
GST_STATIC_CAPS (OVERLAY_COMPOSITION_CAPS);
Packit Service 4387a0
Packit Service 4387a0
static gboolean
Packit Service 4387a0
can_blend_caps (GstCaps * incaps)
Packit Service 4387a0
{
Packit Service 4387a0
  gboolean ret;
Packit Service 4387a0
  GstCaps *caps;
Packit Service 4387a0
Packit Service 4387a0
  caps = gst_static_caps_get (&overlay_composition_caps);
Packit Service 4387a0
  ret = gst_caps_is_subset (incaps, caps);
Packit Service 4387a0
  gst_caps_unref (caps);
Packit Service 4387a0
Packit Service 4387a0
  return ret;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
Packit Service 4387a0
    GST_PAD_SRC,
Packit Service 4387a0
    GST_PAD_ALWAYS,
Packit Service 4387a0
    GST_STATIC_CAPS (ALL_CAPS)
Packit Service 4387a0
    );
Packit Service 4387a0
Packit Service 4387a0
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
Packit Service 4387a0
    GST_PAD_SINK,
Packit Service 4387a0
    GST_PAD_ALWAYS,
Packit Service 4387a0
    GST_STATIC_CAPS (ALL_CAPS)
Packit Service 4387a0
    );
Packit Service 4387a0
Packit Service 4387a0
#define parent_class gst_overlay_composition_parent_class
Packit Service 4387a0
G_DEFINE_TYPE (GstOverlayComposition, gst_overlay_composition,
Packit Service 4387a0
    GST_TYPE_ELEMENT);
Packit Service 4387a0
Packit Service 4387a0
static GstFlowReturn gst_overlay_composition_sink_chain (GstPad * pad,
Packit Service 4387a0
    GstObject * parent, GstBuffer * buffer);
Packit Service 4387a0
static gboolean gst_overlay_composition_sink_event (GstPad * pad,
Packit Service 4387a0
    GstObject * parent, GstEvent * event);
Packit Service 4387a0
static gboolean gst_overlay_composition_sink_query (GstPad * pad,
Packit Service 4387a0
    GstObject * parent, GstQuery * query);
Packit Service 4387a0
static gboolean gst_overlay_composition_src_query (GstPad * pad,
Packit Service 4387a0
    GstObject * parent, GstQuery * query);
Packit Service 4387a0
Packit Service 4387a0
static GstStateChangeReturn gst_overlay_composition_change_state (GstElement *
Packit Service 4387a0
    element, GstStateChange transition);
Packit Service 4387a0
Packit Service 4387a0
static void
Packit Service 4387a0
gst_overlay_composition_class_init (GstOverlayCompositionClass * klass)
Packit Service 4387a0
{
Packit Service 4387a0
  GstElementClass *gstelement_class = (GstElementClass *) klass;
Packit Service 4387a0
Packit Service 4387a0
  GST_DEBUG_CATEGORY_INIT (gst_overlay_composition_debug, "overlaycomposition",
Packit Service 4387a0
      0, "Overlay Composition");
Packit Service 4387a0
Packit Service 4387a0
  gst_element_class_set_static_metadata (gstelement_class,
Packit Service 4387a0
      "Overlay Composition", "Filter/Editor/Video",
Packit Service 4387a0
      "Overlay Composition", "Sebastian Dröge <sebastian@centricular.com>");
Packit Service 4387a0
Packit Service 4387a0
  gst_element_class_add_pad_template (gstelement_class,
Packit Service 4387a0
      gst_static_pad_template_get (&src_template));
Packit Service 4387a0
  gst_element_class_add_pad_template (gstelement_class,
Packit Service 4387a0
      gst_static_pad_template_get (&sink_template));
Packit Service 4387a0
Packit Service 4387a0
  gstelement_class->change_state = gst_overlay_composition_change_state;
Packit Service 4387a0
Packit Service 4387a0
  /**
Packit Service 4387a0
   * GstOverlayComposition::draw:
Packit Service 4387a0
   * @overlay: Overlay element emitting the signal.
Packit Service 4387a0
   * @sample: #GstSample containing the current buffer, caps and segment.
Packit Service 4387a0
   *
Packit Service 4387a0
   * This signal is emitted when the overlay should be drawn.
Packit Service 4387a0
   *
Packit Service 4387a0
   * Returns: #GstVideoOverlayComposition or %NULL
Packit Service 4387a0
   */
Packit Service 4387a0
  overlay_composition_signals[SIGNAL_DRAW] =
Packit Service 4387a0
      g_signal_new ("draw",
Packit Service 4387a0
      G_TYPE_FROM_CLASS (klass),
Packit Service 4387a0
      0,
Packit Service 4387a0
      0,
Packit Service 4387a0
      NULL,
Packit Service 4387a0
      NULL,
Packit Service 4387a0
      g_cclosure_marshal_generic,
Packit Service 4387a0
      GST_TYPE_VIDEO_OVERLAY_COMPOSITION, 1, GST_TYPE_SAMPLE);
Packit Service 4387a0
Packit Service 4387a0
  /**
Packit Service 4387a0
   * GstOverlayComposition::caps-changed:
Packit Service 4387a0
   * @overlay: Overlay element emitting the signal.
Packit Service 4387a0
   * @caps: The #GstCaps of the element.
Packit Service 4387a0
   * @window_width: The window render width of downstream, or 0.
Packit Service 4387a0
   * @window_height: The window render height of downstream, or 0.
Packit Service 4387a0
   *
Packit Service 4387a0
   * This signal is emitted when the caps of the element has changed.
Packit Service 4387a0
   *
Packit Service 4387a0
   * The window width and height define the resolution at which the frame is
Packit Service 4387a0
   * going to be rendered in the end by e.g. a video sink (i.e. the window
Packit Service 4387a0
   * size).
Packit Service 4387a0
   */
Packit Service 4387a0
  overlay_composition_signals[SIGNAL_CAPS_CHANGED] =
Packit Service 4387a0
      g_signal_new ("caps-changed",
Packit Service 4387a0
      G_TYPE_FROM_CLASS (klass),
Packit Service 4387a0
      0,
Packit Service 4387a0
      0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 3, GST_TYPE_CAPS,
Packit Service 4387a0
      G_TYPE_UINT, G_TYPE_UINT);
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static void
Packit Service 4387a0
gst_overlay_composition_init (GstOverlayComposition * self)
Packit Service 4387a0
{
Packit Service 4387a0
  self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
Packit Service 4387a0
  gst_pad_set_chain_function (self->sinkpad,
Packit Service 4387a0
      GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_chain));
Packit Service 4387a0
  gst_pad_set_event_function (self->sinkpad,
Packit Service 4387a0
      GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_event));
Packit Service 4387a0
  gst_pad_set_query_function (self->sinkpad,
Packit Service 4387a0
      GST_DEBUG_FUNCPTR (gst_overlay_composition_sink_query));
Packit Service 4387a0
  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
Packit Service 4387a0
Packit Service 4387a0
  self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
Packit Service 4387a0
  gst_pad_set_query_function (self->srcpad,
Packit Service 4387a0
      GST_DEBUG_FUNCPTR (gst_overlay_composition_src_query));
Packit Service 4387a0
  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static GstStateChangeReturn
Packit Service 4387a0
gst_overlay_composition_change_state (GstElement * element,
Packit Service 4387a0
    GstStateChange transition)
Packit Service 4387a0
{
Packit Service 4387a0
  GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (element);
Packit Service 4387a0
  GstStateChangeReturn state_ret;
Packit Service 4387a0
Packit Service 4387a0
  switch (transition) {
Packit Service 4387a0
    default:
Packit Service 4387a0
      break;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  state_ret =
Packit Service 4387a0
      GST_ELEMENT_CLASS (gst_overlay_composition_parent_class)->change_state
Packit Service 4387a0
      (element, transition);
Packit Service 4387a0
  if (state_ret == GST_STATE_CHANGE_FAILURE)
Packit Service 4387a0
    return state_ret;
Packit Service 4387a0
Packit Service 4387a0
  switch (transition) {
Packit Service 4387a0
    case GST_STATE_CHANGE_READY_TO_PAUSED:
Packit Service 4387a0
      gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
Packit Service 4387a0
      break;
Packit Service 4387a0
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Packit Service 4387a0
      memset (&self->info, 0, sizeof (self->info));
Packit Service 4387a0
      self->window_width = self->window_height = 0;
Packit Service 4387a0
      self->attach_compo_to_buffer = FALSE;
Packit Service 4387a0
      if (self->sample) {
Packit Service 4387a0
        gst_sample_unref (self->sample);
Packit Service 4387a0
        self->sample = NULL;
Packit Service 4387a0
      }
Packit Service 4387a0
      gst_caps_replace (&self->caps, NULL);
Packit Service 4387a0
      gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
Packit Service 4387a0
      break;
Packit Service 4387a0
    default:
Packit Service 4387a0
      break;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return state_ret;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
/* Based on gstbasetextoverlay.c */
Packit Service 4387a0
static gboolean
Packit Service 4387a0
gst_overlay_composition_negotiate (GstOverlayComposition * self, GstCaps * caps)
Packit Service 4387a0
{
Packit Service 4387a0
  gboolean upstream_has_meta = FALSE;
Packit Service 4387a0
  gboolean caps_has_meta = FALSE;
Packit Service 4387a0
  gboolean alloc_has_meta = FALSE;
Packit Service 4387a0
  gboolean attach = FALSE;
Packit Service 4387a0
  gboolean ret = TRUE;
Packit Service 4387a0
  guint width, height;
Packit Service 4387a0
  GstCapsFeatures *f;
Packit Service 4387a0
  GstCaps *overlay_caps;
Packit Service 4387a0
  GstQuery *query;
Packit Service 4387a0
  guint alloc_index;
Packit Service 4387a0
Packit Service 4387a0
  GST_DEBUG_OBJECT (self, "performing negotiation");
Packit Service 4387a0
Packit Service 4387a0
  /* Clear any pending reconfigure to avoid negotiating twice */
Packit Service 4387a0
  gst_pad_check_reconfigure (self->srcpad);
Packit Service 4387a0
Packit Service 4387a0
  self->window_width = self->window_height = 0;
Packit Service 4387a0
Packit Service 4387a0
  if (!caps)
Packit Service 4387a0
    caps = gst_pad_get_current_caps (self->sinkpad);
Packit Service 4387a0
  else
Packit Service 4387a0
    gst_caps_ref (caps);
Packit Service 4387a0
Packit Service 4387a0
  if (!caps || gst_caps_is_empty (caps))
Packit Service 4387a0
    goto no_format;
Packit Service 4387a0
Packit Service 4387a0
  /* Check if upstream caps have meta */
Packit Service 4387a0
  if ((f = gst_caps_get_features (caps, 0))) {
Packit Service 4387a0
    upstream_has_meta = gst_caps_features_contains (f,
Packit Service 4387a0
        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  /* Initialize dimensions */
Packit Service 4387a0
  width = self->info.width;
Packit Service 4387a0
  height = self->info.height;
Packit Service 4387a0
Packit Service 4387a0
  if (upstream_has_meta) {
Packit Service 4387a0
    overlay_caps = gst_caps_ref (caps);
Packit Service 4387a0
  } else {
Packit Service 4387a0
    GstCaps *peercaps;
Packit Service 4387a0
Packit Service 4387a0
    /* BaseTransform requires caps for the allocation query to work */
Packit Service 4387a0
    overlay_caps = gst_caps_copy (caps);
Packit Service 4387a0
    f = gst_caps_get_features (overlay_caps, 0);
Packit Service 4387a0
    gst_caps_features_add (f,
Packit Service 4387a0
        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
Packit Service 4387a0
Packit Service 4387a0
    /* Then check if downstream accept overlay composition in caps */
Packit Service 4387a0
    /* FIXME: We should probably check if downstream *prefers* the
Packit Service 4387a0
     * overlay meta, and only enforce usage of it if we can't handle
Packit Service 4387a0
     * the format ourselves and thus would have to drop the overlays.
Packit Service 4387a0
     * Otherwise we should prefer what downstream wants here.
Packit Service 4387a0
     */
Packit Service 4387a0
    peercaps = gst_pad_peer_query_caps (self->srcpad, overlay_caps);
Packit Service 4387a0
    caps_has_meta = !gst_caps_is_empty (peercaps);
Packit Service 4387a0
    gst_caps_unref (peercaps);
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self, "caps have overlay meta %d", caps_has_meta);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  if (upstream_has_meta || caps_has_meta) {
Packit Service 4387a0
    /* Send caps immediatly, it's needed by GstBaseTransform to get a reply
Packit Service 4387a0
     * from allocation query */
Packit Service 4387a0
    ret = gst_pad_set_caps (self->srcpad, overlay_caps);
Packit Service 4387a0
Packit Service 4387a0
    /* First check if the allocation meta has compositon */
Packit Service 4387a0
    query = gst_query_new_allocation (overlay_caps, FALSE);
Packit Service 4387a0
Packit Service 4387a0
    if (!gst_pad_peer_query (self->srcpad, query)) {
Packit Service 4387a0
      /* no problem, we use the query defaults */
Packit Service 4387a0
      GST_DEBUG_OBJECT (self, "ALLOCATION query failed");
Packit Service 4387a0
Packit Service 4387a0
      /* In case we were flushing, mark reconfigure and fail this method,
Packit Service 4387a0
       * will make it retry */
Packit Service 4387a0
      if (GST_PAD_IS_FLUSHING (self->srcpad))
Packit Service 4387a0
        ret = FALSE;
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    alloc_has_meta = gst_query_find_allocation_meta (query,
Packit Service 4387a0
        GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, &alloc_index);
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self, "sink alloc has overlay meta %d", alloc_has_meta);
Packit Service 4387a0
Packit Service 4387a0
    if (alloc_has_meta) {
Packit Service 4387a0
      const GstStructure *params;
Packit Service 4387a0
Packit Service 4387a0
      gst_query_parse_nth_allocation_meta (query, alloc_index, &params);
Packit Service 4387a0
      if (params) {
Packit Service 4387a0
        if (gst_structure_get (params, "width", G_TYPE_UINT, &width,
Packit Service 4387a0
                "height", G_TYPE_UINT, &height, NULL)) {
Packit Service 4387a0
          GST_DEBUG_OBJECT (self, "received window size: %dx%d", width, height);
Packit Service 4387a0
          g_assert (width != 0 && height != 0);
Packit Service 4387a0
        }
Packit Service 4387a0
      }
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_query_unref (query);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  /* Update render size if needed */
Packit Service 4387a0
  self->window_width = width;
Packit Service 4387a0
  self->window_height = height;
Packit Service 4387a0
Packit Service 4387a0
  /* For backward compatibility, we will prefer blitting if downstream
Packit Service 4387a0
   * allocation does not support the meta. In other case we will prefer
Packit Service 4387a0
   * attaching, and will fail the negotiation in the unlikely case we are
Packit Service 4387a0
   * force to blit, but format isn't supported. */
Packit Service 4387a0
Packit Service 4387a0
  if (upstream_has_meta) {
Packit Service 4387a0
    attach = TRUE;
Packit Service 4387a0
  } else if (caps_has_meta) {
Packit Service 4387a0
    if (alloc_has_meta) {
Packit Service 4387a0
      attach = TRUE;
Packit Service 4387a0
    } else {
Packit Service 4387a0
      /* Don't attach unless we cannot handle the format */
Packit Service 4387a0
      attach = !can_blend_caps (caps);
Packit Service 4387a0
    }
Packit Service 4387a0
  } else {
Packit Service 4387a0
    ret = can_blend_caps (caps);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  /* If we attach, then pick the overlay caps */
Packit Service 4387a0
  if (attach) {
Packit Service 4387a0
    GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, overlay_caps);
Packit Service 4387a0
    /* Caps where already sent */
Packit Service 4387a0
  } else if (ret) {
Packit Service 4387a0
    GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, caps);
Packit Service 4387a0
    ret = gst_pad_set_caps (self->srcpad, caps);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  self->attach_compo_to_buffer = attach;
Packit Service 4387a0
Packit Service 4387a0
  if (!ret) {
Packit Service 4387a0
    GST_DEBUG_OBJECT (self, "negotiation failed, schedule reconfigure");
Packit Service 4387a0
    gst_pad_mark_reconfigure (self->srcpad);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  g_signal_emit (self, overlay_composition_signals[SIGNAL_CAPS_CHANGED], 0,
Packit Service 4387a0
      caps, self->window_width, self->window_height, NULL);
Packit Service 4387a0
Packit Service 4387a0
  gst_caps_unref (overlay_caps);
Packit Service 4387a0
  gst_caps_unref (caps);
Packit Service 4387a0
Packit Service 4387a0
  return ret;
Packit Service 4387a0
Packit Service 4387a0
no_format:
Packit Service 4387a0
  {
Packit Service 4387a0
    if (caps)
Packit Service 4387a0
      gst_caps_unref (caps);
Packit Service 4387a0
    gst_pad_mark_reconfigure (self->srcpad);
Packit Service 4387a0
    return FALSE;
Packit Service 4387a0
  }
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static gboolean
Packit Service 4387a0
gst_overlay_composition_sink_event (GstPad * pad, GstObject * parent,
Packit Service 4387a0
    GstEvent * event)
Packit Service 4387a0
{
Packit Service 4387a0
  GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent);
Packit Service 4387a0
  gboolean ret = FALSE;
Packit Service 4387a0
Packit Service 4387a0
  switch (GST_EVENT_TYPE (event)) {
Packit Service 4387a0
    case GST_EVENT_SEGMENT:
Packit Service 4387a0
      gst_event_copy_segment (event, &self->segment);
Packit Service 4387a0
      ret = gst_pad_event_default (pad, parent, event);
Packit Service 4387a0
      break;
Packit Service 4387a0
    case GST_EVENT_CAPS:{
Packit Service 4387a0
      GstCaps *caps;
Packit Service 4387a0
Packit Service 4387a0
      gst_event_parse_caps (event, &caps);
Packit Service 4387a0
      if (!gst_video_info_from_caps (&self->info, caps)) {
Packit Service 4387a0
        gst_event_unref (event);
Packit Service 4387a0
        ret = FALSE;
Packit Service 4387a0
        break;
Packit Service 4387a0
      }
Packit Service 4387a0
Packit Service 4387a0
      if (!gst_overlay_composition_negotiate (self, caps)) {
Packit Service 4387a0
        gst_event_unref (event);
Packit Service 4387a0
        ret = FALSE;
Packit Service 4387a0
        break;
Packit Service 4387a0
      }
Packit Service 4387a0
Packit Service 4387a0
      gst_caps_replace (&self->caps, caps);
Packit Service 4387a0
Packit Service 4387a0
      ret = TRUE;
Packit Service 4387a0
      gst_event_unref (event);
Packit Service 4387a0
Packit Service 4387a0
      break;
Packit Service 4387a0
    }
Packit Service 4387a0
    case GST_EVENT_FLUSH_STOP:
Packit Service 4387a0
      gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
Packit Service 4387a0
      ret = gst_pad_event_default (pad, parent, event);
Packit Service 4387a0
      break;
Packit Service 4387a0
    default:
Packit Service 4387a0
      ret = gst_pad_event_default (pad, parent, event);
Packit Service 4387a0
      break;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return ret;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
/* Based on gstbasetextoverlay.c */
Packit Service 4387a0
/**
Packit Service 4387a0
 * add_feature_and_intersect:
Packit Service 4387a0
 *
Packit Service 4387a0
 * Creates a new #GstCaps containing the (given caps +
Packit Service 4387a0
 * given caps feature) + (given caps intersected by the
Packit Service 4387a0
 * given filter).
Packit Service 4387a0
 *
Packit Service 4387a0
 * Returns: the new #GstCaps
Packit Service 4387a0
 */
Packit Service 4387a0
static GstCaps *
Packit Service 4387a0
add_feature_and_intersect (GstCaps * caps,
Packit Service 4387a0
    const gchar * feature, GstCaps * filter)
Packit Service 4387a0
{
Packit Service 4387a0
  int i, caps_size;
Packit Service 4387a0
  GstCaps *new_caps;
Packit Service 4387a0
Packit Service 4387a0
  new_caps = gst_caps_copy (caps);
Packit Service 4387a0
Packit Service 4387a0
  caps_size = gst_caps_get_size (new_caps);
Packit Service 4387a0
  for (i = 0; i < caps_size; i++) {
Packit Service 4387a0
    GstCapsFeatures *features = gst_caps_get_features (new_caps, i);
Packit Service 4387a0
Packit Service 4387a0
    if (!gst_caps_features_is_any (features)) {
Packit Service 4387a0
      gst_caps_features_add (features, feature);
Packit Service 4387a0
    }
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  gst_caps_append (new_caps, gst_caps_intersect_full (caps,
Packit Service 4387a0
          filter, GST_CAPS_INTERSECT_FIRST));
Packit Service 4387a0
Packit Service 4387a0
  return new_caps;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
/* Based on gstbasetextoverlay.c */
Packit Service 4387a0
/* intersect_by_feature:
Packit Service 4387a0
 *
Packit Service 4387a0
 * Creates a new #GstCaps based on the following filtering rule.
Packit Service 4387a0
 *
Packit Service 4387a0
 * For each individual caps contained in given caps, if the
Packit Service 4387a0
 * caps uses the given caps feature, keep a version of the caps
Packit Service 4387a0
 * with the feature and an another one without. Otherwise, intersect
Packit Service 4387a0
 * the caps with the given filter.
Packit Service 4387a0
 *
Packit Service 4387a0
 * Returns: the new #GstCaps
Packit Service 4387a0
 */
Packit Service 4387a0
static GstCaps *
Packit Service 4387a0
intersect_by_feature (GstCaps * caps, const gchar * feature, GstCaps * filter)
Packit Service 4387a0
{
Packit Service 4387a0
  int i, caps_size;
Packit Service 4387a0
  GstCaps *new_caps;
Packit Service 4387a0
Packit Service 4387a0
  new_caps = gst_caps_new_empty ();
Packit Service 4387a0
Packit Service 4387a0
  caps_size = gst_caps_get_size (caps);
Packit Service 4387a0
  for (i = 0; i < caps_size; i++) {
Packit Service 4387a0
    GstStructure *caps_structure = gst_caps_get_structure (caps, i);
Packit Service 4387a0
    GstCapsFeatures *caps_features =
Packit Service 4387a0
        gst_caps_features_copy (gst_caps_get_features (caps, i));
Packit Service 4387a0
    GstCaps *filtered_caps;
Packit Service 4387a0
    GstCaps *simple_caps =
Packit Service 4387a0
        gst_caps_new_full (gst_structure_copy (caps_structure), NULL);
Packit Service 4387a0
    gst_caps_set_features (simple_caps, 0, caps_features);
Packit Service 4387a0
Packit Service 4387a0
    if (gst_caps_features_contains (caps_features, feature)) {
Packit Service 4387a0
      gst_caps_append (new_caps, gst_caps_copy (simple_caps));
Packit Service 4387a0
Packit Service 4387a0
      gst_caps_features_remove (caps_features, feature);
Packit Service 4387a0
      filtered_caps = gst_caps_ref (simple_caps);
Packit Service 4387a0
    } else {
Packit Service 4387a0
      filtered_caps = gst_caps_intersect_full (simple_caps, filter,
Packit Service 4387a0
          GST_CAPS_INTERSECT_FIRST);
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_caps_unref (simple_caps);
Packit Service 4387a0
    gst_caps_append (new_caps, filtered_caps);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return new_caps;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
/* Based on gstbasetextoverlay.c */
Packit Service 4387a0
static GstCaps *
Packit Service 4387a0
gst_overlay_composition_sink_query_caps (GstOverlayComposition * self,
Packit Service 4387a0
    GstCaps * filter)
Packit Service 4387a0
{
Packit Service 4387a0
  GstCaps *peer_caps = NULL, *caps = NULL, *overlay_filter = NULL;
Packit Service 4387a0
Packit Service 4387a0
  if (filter) {
Packit Service 4387a0
    /* filter caps + composition feature + filter caps
Packit Service 4387a0
     * filtered by the software caps. */
Packit Service 4387a0
    GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps);
Packit Service 4387a0
    overlay_filter = add_feature_and_intersect (filter,
Packit Service 4387a0
        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
Packit Service 4387a0
    gst_caps_unref (sw_caps);
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->sinkpad, "overlay filter %" GST_PTR_FORMAT,
Packit Service 4387a0
        overlay_filter);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  peer_caps = gst_pad_peer_query_caps (self->srcpad, overlay_filter);
Packit Service 4387a0
Packit Service 4387a0
  if (overlay_filter)
Packit Service 4387a0
    gst_caps_unref (overlay_filter);
Packit Service 4387a0
Packit Service 4387a0
  if (peer_caps) {
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->sinkpad, "peer caps  %" GST_PTR_FORMAT, peer_caps);
Packit Service 4387a0
Packit Service 4387a0
    if (gst_caps_is_any (peer_caps)) {
Packit Service 4387a0
      /* if peer returns ANY caps, return filtered src pad template caps */
Packit Service 4387a0
      caps = gst_caps_copy (gst_pad_get_pad_template_caps (self->srcpad));
Packit Service 4387a0
    } else {
Packit Service 4387a0
Packit Service 4387a0
      /* duplicate caps which contains the composition into one version with
Packit Service 4387a0
       * the meta and one without. Filter the other caps by the software caps */
Packit Service 4387a0
      GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps);
Packit Service 4387a0
      caps = intersect_by_feature (peer_caps,
Packit Service 4387a0
          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
Packit Service 4387a0
      gst_caps_unref (sw_caps);
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_caps_unref (peer_caps);
Packit Service 4387a0
Packit Service 4387a0
  } else {
Packit Service 4387a0
    /* no peer, our padtemplate is enough then */
Packit Service 4387a0
    caps = gst_pad_get_pad_template_caps (self->sinkpad);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  if (filter) {
Packit Service 4387a0
    GstCaps *intersection = gst_caps_intersect_full (filter, caps,
Packit Service 4387a0
        GST_CAPS_INTERSECT_FIRST);
Packit Service 4387a0
    gst_caps_unref (caps);
Packit Service 4387a0
    caps = intersection;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  GST_DEBUG_OBJECT (self->sinkpad, "returning  %" GST_PTR_FORMAT, caps);
Packit Service 4387a0
Packit Service 4387a0
  return caps;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
/* Based on gstbasetextoverlay.c */
Packit Service 4387a0
static GstCaps *
Packit Service 4387a0
gst_overlay_composition_src_query_caps (GstOverlayComposition * self,
Packit Service 4387a0
    GstCaps * filter)
Packit Service 4387a0
{
Packit Service 4387a0
  GstCaps *peer_caps = NULL, *caps = NULL, *overlay_filter = NULL;
Packit Service 4387a0
Packit Service 4387a0
  if (filter) {
Packit Service 4387a0
    /* duplicate filter caps which contains the composition into one version
Packit Service 4387a0
     * with the meta and one without. Filter the other caps by the software
Packit Service 4387a0
     * caps */
Packit Service 4387a0
    GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps);
Packit Service 4387a0
    overlay_filter =
Packit Service 4387a0
        intersect_by_feature (filter,
Packit Service 4387a0
        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
Packit Service 4387a0
    gst_caps_unref (sw_caps);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  peer_caps = gst_pad_peer_query_caps (self->sinkpad, overlay_filter);
Packit Service 4387a0
Packit Service 4387a0
  if (overlay_filter)
Packit Service 4387a0
    gst_caps_unref (overlay_filter);
Packit Service 4387a0
Packit Service 4387a0
  if (peer_caps) {
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->srcpad, "peer caps  %" GST_PTR_FORMAT, peer_caps);
Packit Service 4387a0
Packit Service 4387a0
    if (gst_caps_is_any (peer_caps)) {
Packit Service 4387a0
Packit Service 4387a0
      /* if peer returns ANY caps, return filtered sink pad template caps */
Packit Service 4387a0
      caps = gst_caps_copy (gst_pad_get_pad_template_caps (self->sinkpad));
Packit Service 4387a0
Packit Service 4387a0
    } else {
Packit Service 4387a0
Packit Service 4387a0
      /* return upstream caps + composition feature + upstream caps
Packit Service 4387a0
       * filtered by the software caps. */
Packit Service 4387a0
      GstCaps *sw_caps = gst_static_caps_get (&overlay_composition_caps);
Packit Service 4387a0
      caps = add_feature_and_intersect (peer_caps,
Packit Service 4387a0
          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
Packit Service 4387a0
      gst_caps_unref (sw_caps);
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_caps_unref (peer_caps);
Packit Service 4387a0
Packit Service 4387a0
  } else {
Packit Service 4387a0
    /* no peer, our padtemplate is enough then */
Packit Service 4387a0
    caps = gst_pad_get_pad_template_caps (self->srcpad);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  if (filter) {
Packit Service 4387a0
    GstCaps *intersection;
Packit Service 4387a0
Packit Service 4387a0
    intersection =
Packit Service 4387a0
        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
Packit Service 4387a0
    gst_caps_unref (caps);
Packit Service 4387a0
    caps = intersection;
Packit Service 4387a0
  }
Packit Service 4387a0
  GST_DEBUG_OBJECT (self->srcpad, "returning  %" GST_PTR_FORMAT, caps);
Packit Service 4387a0
Packit Service 4387a0
  return caps;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static gboolean
Packit Service 4387a0
gst_overlay_composition_sink_query (GstPad * pad, GstObject * parent,
Packit Service 4387a0
    GstQuery * query)
Packit Service 4387a0
{
Packit Service 4387a0
  GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent);
Packit Service 4387a0
  gboolean ret = FALSE;
Packit Service 4387a0
Packit Service 4387a0
  switch (GST_QUERY_TYPE (query)) {
Packit Service 4387a0
    case GST_QUERY_CAPS:{
Packit Service 4387a0
      GstCaps *filter, *caps;
Packit Service 4387a0
Packit Service 4387a0
      gst_query_parse_caps (query, &filter);
Packit Service 4387a0
      caps = gst_overlay_composition_sink_query_caps (self, filter);
Packit Service 4387a0
      gst_query_set_caps_result (query, caps);
Packit Service 4387a0
      gst_caps_unref (caps);
Packit Service 4387a0
      ret = TRUE;
Packit Service 4387a0
      break;
Packit Service 4387a0
    }
Packit Service 4387a0
    default:
Packit Service 4387a0
      ret = gst_pad_query_default (pad, parent, query);
Packit Service 4387a0
      break;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return ret;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static gboolean
Packit Service 4387a0
gst_overlay_composition_src_query (GstPad * pad, GstObject * parent,
Packit Service 4387a0
    GstQuery * query)
Packit Service 4387a0
{
Packit Service 4387a0
  GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent);
Packit Service 4387a0
  gboolean ret = FALSE;
Packit Service 4387a0
Packit Service 4387a0
  switch (GST_QUERY_TYPE (query)) {
Packit Service 4387a0
    case GST_QUERY_CAPS:{
Packit Service 4387a0
      GstCaps *filter, *caps;
Packit Service 4387a0
Packit Service 4387a0
      gst_query_parse_caps (query, &filter);
Packit Service 4387a0
      caps = gst_overlay_composition_src_query_caps (self, filter);
Packit Service 4387a0
      gst_query_set_caps_result (query, caps);
Packit Service 4387a0
      gst_caps_unref (caps);
Packit Service 4387a0
      ret = TRUE;
Packit Service 4387a0
      break;
Packit Service 4387a0
    }
Packit Service 4387a0
    default:
Packit Service 4387a0
      ret = gst_pad_query_default (pad, parent, query);
Packit Service 4387a0
      break;
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return ret;
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static GstFlowReturn
Packit Service 4387a0
gst_overlay_composition_sink_chain (GstPad * pad, GstObject * parent,
Packit Service 4387a0
    GstBuffer * buffer)
Packit Service 4387a0
{
Packit Service 4387a0
  GstOverlayComposition *self = GST_OVERLAY_COMPOSITION (parent);
Packit Service 4387a0
  GstVideoOverlayComposition *compo = NULL;
Packit Service 4387a0
  GstVideoOverlayCompositionMeta *upstream_compo_meta;
Packit Service 4387a0
Packit Service 4387a0
  if (gst_pad_check_reconfigure (self->srcpad)) {
Packit Service 4387a0
    if (!gst_overlay_composition_negotiate (self, NULL)) {
Packit Service 4387a0
      gst_pad_mark_reconfigure (self->srcpad);
Packit Service 4387a0
      gst_buffer_unref (buffer);
Packit Service 4387a0
      GST_OBJECT_LOCK (self->srcpad);
Packit Service 4387a0
      if (GST_PAD_IS_FLUSHING (self->srcpad)) {
Packit Service 4387a0
        GST_OBJECT_UNLOCK (self->srcpad);
Packit Service 4387a0
        return GST_FLOW_FLUSHING;
Packit Service 4387a0
      }
Packit Service 4387a0
      GST_OBJECT_UNLOCK (self->srcpad);
Packit Service 4387a0
      return GST_FLOW_NOT_NEGOTIATED;
Packit Service 4387a0
    }
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  if (!self->sample) {
Packit Service 4387a0
    self->sample = gst_sample_new (buffer, self->caps, &self->segment, NULL);
Packit Service 4387a0
  } else {
Packit Service 4387a0
    self->sample = gst_sample_make_writable (self->sample);
Packit Service 4387a0
    gst_sample_set_buffer (self->sample, buffer);
Packit Service 4387a0
    gst_sample_set_caps (self->sample, self->caps);
Packit Service 4387a0
    gst_sample_set_segment (self->sample, &self->segment);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  g_signal_emit (self, overlay_composition_signals[SIGNAL_DRAW], 0,
Packit Service 4387a0
      self->sample, &compo;;
Packit Service 4387a0
Packit Service 4387a0
  /* Don't store the buffer in the sample any longer, otherwise it will not
Packit Service 4387a0
   * be writable below as we have one reference in the sample and one in
Packit Service 4387a0
   * this function.
Packit Service 4387a0
   *
Packit Service 4387a0
   * If the sample is not writable itself then the application kept an
Packit Service 4387a0
   * reference itself.
Packit Service 4387a0
   */
Packit Service 4387a0
  if (gst_sample_is_writable (self->sample)) {
Packit Service 4387a0
    gst_sample_set_buffer (self->sample, NULL);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  if (!compo) {
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->sinkpad,
Packit Service 4387a0
        "Application did not provide an overlay composition");
Packit Service 4387a0
    return gst_pad_push (self->srcpad, buffer);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  /* If upstream attached a meta, we can safely add our own things
Packit Service 4387a0
   * in it. Upstream must've checked that downstream supports it */
Packit Service 4387a0
  upstream_compo_meta = gst_buffer_get_video_overlay_composition_meta (buffer);
Packit Service 4387a0
  if (upstream_compo_meta) {
Packit Service 4387a0
    GstVideoOverlayComposition *merged_compo =
Packit Service 4387a0
        gst_video_overlay_composition_copy (upstream_compo_meta->overlay);
Packit Service 4387a0
    guint i, n;
Packit Service 4387a0
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->sinkpad,
Packit Service 4387a0
        "Appending to upstream overlay composition");
Packit Service 4387a0
Packit Service 4387a0
    n = gst_video_overlay_composition_n_rectangles (compo);
Packit Service 4387a0
    for (i = 0; i < n; i++) {
Packit Service 4387a0
      GstVideoOverlayRectangle *rect =
Packit Service 4387a0
          gst_video_overlay_composition_get_rectangle (compo, i);
Packit Service 4387a0
      gst_video_overlay_composition_add_rectangle (merged_compo, rect);
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_video_overlay_composition_unref (compo);
Packit Service 4387a0
    gst_video_overlay_composition_unref (upstream_compo_meta->overlay);
Packit Service 4387a0
    upstream_compo_meta->overlay = merged_compo;
Packit Service 4387a0
  } else if (self->attach_compo_to_buffer) {
Packit Service 4387a0
    GST_DEBUG_OBJECT (self->sinkpad, "Attaching as meta");
Packit Service 4387a0
Packit Service 4387a0
    buffer = gst_buffer_make_writable (buffer);
Packit Service 4387a0
    gst_buffer_add_video_overlay_composition_meta (buffer, compo);
Packit Service 4387a0
    gst_video_overlay_composition_unref (compo);
Packit Service 4387a0
  } else {
Packit Service 4387a0
    GstVideoFrame frame;
Packit Service 4387a0
Packit Service 4387a0
    buffer = gst_buffer_make_writable (buffer);
Packit Service 4387a0
    if (!gst_video_frame_map (&frame, &self->info, buffer, GST_MAP_READWRITE)) {
Packit Service 4387a0
      gst_video_overlay_composition_unref (compo);
Packit Service 4387a0
      goto map_failed;
Packit Service 4387a0
    }
Packit Service 4387a0
Packit Service 4387a0
    gst_video_overlay_composition_blend (compo, &frame);
Packit Service 4387a0
Packit Service 4387a0
    gst_video_frame_unmap (&frame);
Packit Service 4387a0
    gst_video_overlay_composition_unref (compo);
Packit Service 4387a0
  }
Packit Service 4387a0
Packit Service 4387a0
  return gst_pad_push (self->srcpad, buffer);
Packit Service 4387a0
Packit Service 4387a0
map_failed:
Packit Service 4387a0
  {
Packit Service 4387a0
    GST_ERROR_OBJECT (self->sinkpad, "Failed to map buffer");
Packit Service 4387a0
    gst_buffer_unref (buffer);
Packit Service 4387a0
    return GST_FLOW_ERROR;
Packit Service 4387a0
  }
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
static gboolean
Packit Service 4387a0
plugin_init (GstPlugin * plugin)
Packit Service 4387a0
{
Packit Service 4387a0
  return gst_element_register (plugin, "overlaycomposition", GST_RANK_NONE,
Packit Service 4387a0
      GST_TYPE_OVERLAY_COMPOSITION);
Packit Service 4387a0
}
Packit Service 4387a0
Packit Service 4387a0
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
Packit Service 4387a0
    GST_VERSION_MINOR,
Packit Service 4387a0
    overlaycomposition,
Packit Service 4387a0
    "Renders overlays on top of video frames",
Packit Service 4387a0
    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)