summaryrefslogtreecommitdiff
path: root/gst-libs/gst/play/gstplay-video-overlay-video-renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst-libs/gst/play/gstplay-video-overlay-video-renderer.c')
-rw-r--r--gst-libs/gst/play/gstplay-video-overlay-video-renderer.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/gst-libs/gst/play/gstplay-video-overlay-video-renderer.c b/gst-libs/gst/play/gstplay-video-overlay-video-renderer.c
new file mode 100644
index 000000000..f1005bd50
--- /dev/null
+++ b/gst-libs/gst/play/gstplay-video-overlay-video-renderer.c
@@ -0,0 +1,351 @@
+/* GStreamer
+ *
+ * Copyright (C) 2014-2015 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstplay-videooverlayvideorenderer
+ * @title: GstPlayVideoOverlayVideoRenderer
+ * @short_description: Play Video Overlay Video Renderer
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstplay-video-overlay-video-renderer.h"
+#include "gstplay.h"
+
+#include <gst/video/video.h>
+
+struct _GstPlayVideoOverlayVideoRenderer
+{
+ GObject parent;
+
+ GstVideoOverlay *video_overlay;
+ gpointer window_handle;
+ gint x, y, width, height;
+
+ GstElement *video_sink; /* configured video sink, or NULL */
+};
+
+struct _GstPlayVideoOverlayVideoRendererClass
+{
+ GObjectClass parent_class;
+};
+
+static void
+ gst_play_video_overlay_video_renderer_interface_init
+ (GstPlayVideoRendererInterface * iface);
+
+enum
+{
+ VIDEO_OVERLAY_VIDEO_RENDERER_PROP_0,
+ VIDEO_OVERLAY_VIDEO_RENDERER_PROP_WINDOW_HANDLE,
+ VIDEO_OVERLAY_VIDEO_RENDERER_PROP_VIDEO_SINK,
+ VIDEO_OVERLAY_VIDEO_RENDERER_PROP_LAST
+};
+
+G_DEFINE_TYPE_WITH_CODE (GstPlayVideoOverlayVideoRenderer,
+ gst_play_video_overlay_video_renderer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PLAY_VIDEO_RENDERER,
+ gst_play_video_overlay_video_renderer_interface_init));
+
+static GParamSpec
+ * video_overlay_video_renderer_param_specs
+ [VIDEO_OVERLAY_VIDEO_RENDERER_PROP_LAST] = { NULL, };
+
+static void
+gst_play_video_overlay_video_renderer_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstPlayVideoOverlayVideoRenderer *self =
+ GST_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (object);
+
+ switch (prop_id) {
+ case VIDEO_OVERLAY_VIDEO_RENDERER_PROP_WINDOW_HANDLE:
+ self->window_handle = g_value_get_pointer (value);
+ if (self->video_overlay)
+ gst_video_overlay_set_window_handle (self->video_overlay,
+ (guintptr) self->window_handle);
+ break;
+ case VIDEO_OVERLAY_VIDEO_RENDERER_PROP_VIDEO_SINK:
+ self->video_sink = gst_object_ref_sink (g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_play_video_overlay_video_renderer_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstPlayVideoOverlayVideoRenderer *self =
+ GST_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (object);
+
+ switch (prop_id) {
+ case VIDEO_OVERLAY_VIDEO_RENDERER_PROP_WINDOW_HANDLE:
+ g_value_set_pointer (value, self->window_handle);
+ break;
+ case VIDEO_OVERLAY_VIDEO_RENDERER_PROP_VIDEO_SINK:
+ g_value_set_object (value, self->video_sink);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_play_video_overlay_video_renderer_finalize (GObject * object)
+{
+ GstPlayVideoOverlayVideoRenderer *self =
+ GST_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (object);
+
+ if (self->video_overlay)
+ gst_object_unref (self->video_overlay);
+
+ if (self->video_sink)
+ gst_object_unref (self->video_sink);
+
+ G_OBJECT_CLASS
+ (gst_play_video_overlay_video_renderer_parent_class)->finalize (object);
+}
+
+static void
+ gst_play_video_overlay_video_renderer_class_init
+ (GstPlayVideoOverlayVideoRendererClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property =
+ gst_play_video_overlay_video_renderer_set_property;
+ gobject_class->get_property =
+ gst_play_video_overlay_video_renderer_get_property;
+ gobject_class->finalize = gst_play_video_overlay_video_renderer_finalize;
+
+ video_overlay_video_renderer_param_specs
+ [VIDEO_OVERLAY_VIDEO_RENDERER_PROP_WINDOW_HANDLE] =
+ g_param_spec_pointer ("window-handle", "Window Handle",
+ "Window handle to embed the video into",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ video_overlay_video_renderer_param_specs
+ [VIDEO_OVERLAY_VIDEO_RENDERER_PROP_VIDEO_SINK] =
+ g_param_spec_object ("video-sink", "Video Sink",
+ "the video output element to use (NULL = default sink)",
+ GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class,
+ VIDEO_OVERLAY_VIDEO_RENDERER_PROP_LAST,
+ video_overlay_video_renderer_param_specs);
+}
+
+static void
+ gst_play_video_overlay_video_renderer_init
+ (GstPlayVideoOverlayVideoRenderer * self)
+{
+ self->x = self->y = self->width = self->height = -1;
+ self->video_sink = NULL;
+}
+
+static GstElement *gst_play_video_overlay_video_renderer_create_video_sink
+ (GstPlayVideoRenderer * iface, GstPlay * play)
+{
+ GstElement *video_overlay;
+ GstPlayVideoOverlayVideoRenderer *self =
+ GST_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (iface);
+
+ if (self->video_overlay)
+ gst_object_unref (self->video_overlay);
+
+ video_overlay = gst_play_get_pipeline (play);
+ g_return_val_if_fail (GST_IS_VIDEO_OVERLAY (video_overlay), NULL);
+
+ self->video_overlay = GST_VIDEO_OVERLAY (video_overlay);
+
+ gst_video_overlay_set_window_handle (self->video_overlay,
+ (guintptr) self->window_handle);
+ if (self->width != -1 || self->height != -1)
+ gst_video_overlay_set_render_rectangle (self->video_overlay, self->x,
+ self->y, self->width, self->height);
+
+ return self->video_sink;
+}
+
+static void
+ gst_play_video_overlay_video_renderer_interface_init
+ (GstPlayVideoRendererInterface * iface)
+{
+ iface->create_video_sink =
+ gst_play_video_overlay_video_renderer_create_video_sink;
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_new:
+ * @window_handle: (allow-none): Window handle to use or %NULL
+ *
+ * Returns: (transfer full):
+ * Since: 1.20
+ */
+GstPlayVideoRenderer *
+gst_play_video_overlay_video_renderer_new (gpointer window_handle)
+{
+ return g_object_new (GST_TYPE_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER,
+ "window-handle", window_handle, NULL);
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_new_with_sink:
+ * @window_handle: (allow-none): Window handle to use or %NULL
+ * @video_sink: (transfer floating): the custom video_sink element to be set for the video renderer
+ *
+ * Returns: (transfer full):
+ *
+ * Since: 1.20
+ */
+GstPlayVideoRenderer *
+gst_play_video_overlay_video_renderer_new_with_sink (gpointer window_handle,
+ GstElement * video_sink)
+{
+ return g_object_new (GST_TYPE_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER,
+ "window-handle", window_handle, "video-sink", video_sink, NULL);
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_set_window_handle:
+ * @self: #GstPlayVideoRenderer instance
+ * @window_handle: handle referencing to the platform specific window
+ *
+ * Sets the platform specific window handle into which the video
+ * should be rendered
+ * Since: 1.20
+ **/
+void gst_play_video_overlay_video_renderer_set_window_handle
+ (GstPlayVideoOverlayVideoRenderer * self, gpointer window_handle)
+{
+ g_return_if_fail (GST_IS_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (self));
+
+ g_object_set (self, "window-handle", window_handle, NULL);
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_get_window_handle:
+ * @self: #GstPlayVideoRenderer instance
+ *
+ * Returns: (transfer none): The currently set, platform specific window
+ * handle
+ * Since: 1.20
+ */
+gpointer
+ gst_play_video_overlay_video_renderer_get_window_handle
+ (GstPlayVideoOverlayVideoRenderer * self) {
+ gpointer window_handle;
+
+ g_return_val_if_fail (GST_IS_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (self), NULL);
+
+ g_object_get (self, "window-handle", &window_handle, NULL);
+
+ return window_handle;
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_expose:
+ * @self: a #GstPlayVideoOverlayVideoRenderer instance.
+ *
+ * Tell an overlay that it has been exposed. This will redraw the current frame
+ * in the drawable even if the pipeline is PAUSED.
+ * Since: 1.20
+ */
+void gst_play_video_overlay_video_renderer_expose
+ (GstPlayVideoOverlayVideoRenderer * self)
+{
+ g_return_if_fail (GST_IS_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (self));
+
+ if (self->video_overlay)
+ gst_video_overlay_expose (self->video_overlay);
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_set_render_rectangle:
+ * @self: a #GstPlayVideoOverlayVideoRenderer instance
+ * @x: the horizontal offset of the render area inside the window
+ * @y: the vertical offset of the render area inside the window
+ * @width: the width of the render area inside the window
+ * @height: the height of the render area inside the window
+ *
+ * Configure a subregion as a video target within the window set by
+ * gst_play_video_overlay_video_renderer_set_window_handle(). If this is not
+ * used or not supported the video will fill the area of the window set as the
+ * overlay to 100%. By specifying the rectangle, the video can be overlaid to
+ * a specific region of that window only. After setting the new rectangle one
+ * should call gst_play_video_overlay_video_renderer_expose() to force a
+ * redraw. To unset the region pass -1 for the @width and @height parameters.
+ *
+ * This method is needed for non fullscreen video overlay in UI toolkits that
+ * do not support subwindows.
+ *
+ * Since: 1.20
+ */
+void gst_play_video_overlay_video_renderer_set_render_rectangle
+ (GstPlayVideoOverlayVideoRenderer * self, gint x, gint y, gint width,
+ gint height)
+{
+ g_return_if_fail (GST_IS_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (self));
+
+ self->x = x;
+ self->y = y;
+ self->width = width;
+ self->height = height;
+
+ if (self->video_overlay)
+ gst_video_overlay_set_render_rectangle (self->video_overlay,
+ x, y, width, height);
+}
+
+/**
+ * gst_play_video_overlay_video_renderer_get_render_rectangle:
+ * @self: a #GstPlayVideoOverlayVideoRenderer instance
+ * @x: (out) (allow-none): the horizontal offset of the render area inside the window
+ * @y: (out) (allow-none): the vertical offset of the render area inside the window
+ * @width: (out) (allow-none): the width of the render area inside the window
+ * @height: (out) (allow-none): the height of the render area inside the window
+ *
+ * Return the currently configured render rectangle. See gst_play_video_overlay_video_renderer_set_render_rectangle()
+ * for details.
+ *
+ * Since: 1.20
+ */
+void gst_play_video_overlay_video_renderer_get_render_rectangle
+ (GstPlayVideoOverlayVideoRenderer * self, gint * x, gint * y,
+ gint * width, gint * height)
+{
+ g_return_if_fail (GST_IS_PLAY_VIDEO_OVERLAY_VIDEO_RENDERER (self));
+
+ if (x)
+ *x = self->x;
+ if (y)
+ *y = self->y;
+ if (width)
+ *width = self->width;
+ if (height)
+ *height = self->height;
+}