| /* 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:gstplayer-videooverlayvideorenderer |
| * @title: GstPlayerVideoOverlayVideoRenderer |
| * @short_description: Player Video Overlay Video Renderer |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include "gstplayer-video-overlay-video-renderer.h" |
| #include "gstplayer.h" |
| |
| #include <gst/video/video.h> |
| |
| struct _GstPlayerVideoOverlayVideoRenderer |
| { |
| GObject parent; |
| |
| GstVideoOverlay *video_overlay; |
| gpointer window_handle; |
| gint x, y, width, height; |
| |
| GstElement *video_sink; /* configured video sink, or NULL */ |
| }; |
| |
| struct _GstPlayerVideoOverlayVideoRendererClass |
| { |
| GObjectClass parent_class; |
| }; |
| |
| static void |
| gst_player_video_overlay_video_renderer_interface_init |
| (GstPlayerVideoRendererInterface * 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 (GstPlayerVideoOverlayVideoRenderer, |
| gst_player_video_overlay_video_renderer, G_TYPE_OBJECT, |
| G_IMPLEMENT_INTERFACE (GST_TYPE_PLAYER_VIDEO_RENDERER, |
| gst_player_video_overlay_video_renderer_interface_init)); |
| |
| static GParamSpec |
| * video_overlay_video_renderer_param_specs |
| [VIDEO_OVERLAY_VIDEO_RENDERER_PROP_LAST] = { NULL, }; |
| |
| static void |
| gst_player_video_overlay_video_renderer_set_property (GObject * object, |
| guint prop_id, const GValue * value, GParamSpec * pspec) |
| { |
| GstPlayerVideoOverlayVideoRenderer *self = |
| GST_PLAYER_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_player_video_overlay_video_renderer_get_property (GObject * object, |
| guint prop_id, GValue * value, GParamSpec * pspec) |
| { |
| GstPlayerVideoOverlayVideoRenderer *self = |
| GST_PLAYER_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_player_video_overlay_video_renderer_finalize (GObject * object) |
| { |
| GstPlayerVideoOverlayVideoRenderer *self = |
| GST_PLAYER_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_player_video_overlay_video_renderer_parent_class)->finalize (object); |
| } |
| |
| static void |
| gst_player_video_overlay_video_renderer_class_init |
| (GstPlayerVideoOverlayVideoRendererClass * klass) |
| { |
| GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
| |
| gobject_class->set_property = |
| gst_player_video_overlay_video_renderer_set_property; |
| gobject_class->get_property = |
| gst_player_video_overlay_video_renderer_get_property; |
| gobject_class->finalize = gst_player_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_player_video_overlay_video_renderer_init |
| (GstPlayerVideoOverlayVideoRenderer * self) |
| { |
| self->x = self->y = self->width = self->height = -1; |
| self->video_sink = NULL; |
| } |
| |
| static GstElement *gst_player_video_overlay_video_renderer_create_video_sink |
| (GstPlayerVideoRenderer * iface, GstPlayer * player) |
| { |
| GstElement *video_overlay; |
| GstPlayerVideoOverlayVideoRenderer *self = |
| GST_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER (iface); |
| |
| if (self->video_overlay) |
| gst_object_unref (self->video_overlay); |
| |
| video_overlay = gst_player_get_pipeline (player); |
| 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_player_video_overlay_video_renderer_interface_init |
| (GstPlayerVideoRendererInterface * iface) |
| { |
| iface->create_video_sink = |
| gst_player_video_overlay_video_renderer_create_video_sink; |
| } |
| |
| /** |
| * gst_player_video_overlay_video_renderer_new: |
| * @window_handle: (allow-none): Window handle to use or %NULL |
| * |
| * Returns: (transfer full): |
| */ |
| GstPlayerVideoRenderer * |
| gst_player_video_overlay_video_renderer_new (gpointer window_handle) |
| { |
| return g_object_new (GST_TYPE_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER, |
| "window-handle", window_handle, NULL); |
| } |
| |
| /** |
| * gst_player_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.12 |
| */ |
| GstPlayerVideoRenderer * |
| gst_player_video_overlay_video_renderer_new_with_sink (gpointer window_handle, |
| GstElement * video_sink) |
| { |
| return g_object_new (GST_TYPE_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER, |
| "window-handle", window_handle, "video-sink", video_sink, NULL); |
| } |
| |
| /** |
| * gst_player_video_overlay_video_renderer_set_window_handle: |
| * @self: #GstPlayerVideoRenderer instance |
| * @window_handle: handle referencing to the platform specific window |
| * |
| * Sets the platform specific window handle into which the video |
| * should be rendered |
| **/ |
| void gst_player_video_overlay_video_renderer_set_window_handle |
| (GstPlayerVideoOverlayVideoRenderer * self, gpointer window_handle) |
| { |
| g_return_if_fail (GST_IS_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER (self)); |
| |
| g_object_set (self, "window-handle", window_handle, NULL); |
| } |
| |
| /** |
| * gst_player_video_overlay_video_renderer_get_window_handle: |
| * @self: #GstPlayerVideoRenderer instance |
| * |
| * Returns: (transfer none): The currently set, platform specific window |
| * handle |
| */ |
| gpointer |
| gst_player_video_overlay_video_renderer_get_window_handle |
| (GstPlayerVideoOverlayVideoRenderer * self) { |
| gpointer window_handle; |
| |
| g_return_val_if_fail (GST_IS_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER (self), |
| NULL); |
| |
| g_object_get (self, "window-handle", &window_handle, NULL); |
| |
| return window_handle; |
| } |
| |
| /** |
| * gst_player_video_overlay_video_renderer_expose: |
| * @self: a #GstPlayerVideoOverlayVideoRenderer instance. |
| * |
| * Tell an overlay that it has been exposed. This will redraw the current frame |
| * in the drawable even if the pipeline is PAUSED. |
| */ |
| void gst_player_video_overlay_video_renderer_expose |
| (GstPlayerVideoOverlayVideoRenderer * self) |
| { |
| g_return_if_fail (GST_IS_PLAYER_VIDEO_OVERLAY_VIDEO_RENDERER (self)); |
| |
| if (self->video_overlay) |
| gst_video_overlay_expose (self->video_overlay); |
| } |
| |
| /** |
| * gst_player_video_overlay_video_renderer_set_render_rectangle: |
| * @self: a #GstPlayerVideoOverlayVideoRenderer 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_player_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_player_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. |
| * |
| */ |
| void gst_player_video_overlay_video_renderer_set_render_rectangle |
| (GstPlayerVideoOverlayVideoRenderer * self, gint x, gint y, gint width, |
| gint height) |
| { |
| g_return_if_fail (GST_IS_PLAYER_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_player_video_overlay_video_renderer_get_render_rectangle: |
| * @self: a #GstPlayerVideoOverlayVideoRenderer 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_player_video_overlay_video_renderer_set_render_rectangle() |
| * for details. |
| * |
| */ |
| void gst_player_video_overlay_video_renderer_get_render_rectangle |
| (GstPlayerVideoOverlayVideoRenderer * self, gint * x, gint * y, |
| gint * width, gint * height) |
| { |
| g_return_if_fail (GST_IS_PLAYER_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; |
| } |