gstreamer_video/auto/
video_overlay.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
4// DO NOT EDIT
5
6use crate::ffi;
7use glib::{prelude::*, translate::*};
8
9glib::wrapper! {
10    /// The [`VideoOverlay`][crate::VideoOverlay] interface is used for 2 main purposes :
11    ///
12    /// * To get a grab on the Window where the video sink element is going to render.
13    ///  This is achieved by either being informed about the Window identifier that
14    ///  the video sink element generated, or by forcing the video sink element to use
15    ///  a specific Window identifier for rendering.
16    /// * To force a redrawing of the latest video frame the video sink element
17    ///  displayed on the Window. Indeed if the [`gst::Pipeline`][crate::gst::Pipeline] is in [`gst::State::Paused`][crate::gst::State::Paused]
18    ///  state, moving the Window around will damage its content. Application
19    ///  developers will want to handle the Expose events themselves and force the
20    ///  video sink element to refresh the Window's content.
21    ///
22    /// Using the Window created by the video sink is probably the simplest scenario,
23    /// in some cases, though, it might not be flexible enough for application
24    /// developers if they need to catch events such as mouse moves and button
25    /// clicks.
26    ///
27    /// Setting a specific Window identifier on the video sink element is the most
28    /// flexible solution but it has some issues. Indeed the application needs to set
29    /// its Window identifier at the right time to avoid internal Window creation
30    /// from the video sink element. To solve this issue a [`gst::Message`][crate::gst::Message] is posted on
31    /// the bus to inform the application that it should set the Window identifier
32    /// immediately. Here is an example on how to do that correctly:
33    ///
34    /// ```text
35    /// static GstBusSyncReply
36    /// create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
37    /// {
38    ///  // ignore anything but 'prepare-window-handle' element messages
39    ///  if (!gst_is_video_overlay_prepare_window_handle_message (message))
40    ///    return GST_BUS_PASS;
41    ///
42    ///  win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0);
43    ///
44    ///  XSetWindowBackgroundPixmap (disp, win, None);
45    ///
46    ///  XMapRaised (disp, win);
47    ///
48    ///  XSync (disp, FALSE);
49    ///
50    ///  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)),
51    ///      win);
52    ///
53    ///  gst_message_unref (message);
54    ///
55    ///  return GST_BUS_DROP;
56    /// }
57    /// ...
58    /// int
59    /// main (int argc, char **argv)
60    /// {
61    /// ...
62    ///  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
63    ///  gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline,
64    ///         NULL);
65    /// ...
66    /// }
67    /// ```
68    ///
69    /// ## Two basic usage scenarios
70    ///
71    /// There are two basic usage scenarios: in the simplest case, the application
72    /// uses `playbin` or `playsink` or knows exactly what particular element is used
73    /// for video output, which is usually the case when the application creates
74    /// the videosink to use (e.g. `xvimagesink`, `ximagesink`, etc.) itself; in this
75    /// case, the application can just create the videosink element, create and
76    /// realize the window to render the video on and then
77    /// call [`VideoOverlayExtManual::set_window_handle()`][crate::prelude::VideoOverlayExtManual::set_window_handle()] directly with the XID or native
78    /// window handle, before starting up the pipeline.
79    /// As `playbin` and `playsink` implement the video overlay interface and proxy
80    /// it transparently to the actual video sink even if it is created later, this
81    /// case also applies when using these elements.
82    ///
83    /// In the other and more common case, the application does not know in advance
84    /// what GStreamer video sink element will be used for video output. This is
85    /// usually the case when an element such as `autovideosink` is used.
86    /// In this case, the video sink element itself is created
87    /// asynchronously from a GStreamer streaming thread some time after the
88    /// pipeline has been started up. When that happens, however, the video sink
89    /// will need to know right then whether to render onto an already existing
90    /// application window or whether to create its own window. This is when it
91    /// posts a prepare-window-handle message, and that is also why this message needs
92    /// to be handled in a sync bus handler which will be called from the streaming
93    /// thread directly (because the video sink will need an answer right then).
94    ///
95    /// As response to the prepare-window-handle element message in the bus sync
96    /// handler, the application may use [`VideoOverlayExtManual::set_window_handle()`][crate::prelude::VideoOverlayExtManual::set_window_handle()] to tell
97    /// the video sink to render onto an existing window surface. At this point the
98    /// application should already have obtained the window handle / XID, so it
99    /// just needs to set it. It is generally not advisable to call any GUI toolkit
100    /// functions or window system functions from the streaming thread in which the
101    /// prepare-window-handle message is handled, because most GUI toolkits and
102    /// windowing systems are not thread-safe at all and a lot of care would be
103    /// required to co-ordinate the toolkit and window system calls of the
104    /// different threads (Gtk+ users please note: prior to Gtk+ 2.18
105    /// `GDK_WINDOW_XID` was just a simple structure access, so generally fine to do
106    /// within the bus sync handler; this macro was changed to a function call in
107    /// Gtk+ 2.18 and later, which is likely to cause problems when called from a
108    /// sync handler; see below for a better approach without `GDK_WINDOW_XID`
109    /// used in the callback).
110    ///
111    /// ## GstVideoOverlay and Gtk+
112    ///
113    ///
114    /// ```text
115    /// #include <gst/video/videooverlay.h>
116    /// #include <gtk/gtk.h>
117    /// #ifdef GDK_WINDOWING_X11
118    /// #include <gdk/gdkx.h>  // for GDK_WINDOW_XID
119    /// #endif
120    /// #ifdef GDK_WINDOWING_WIN32
121    /// #include <gdk/gdkwin32.h>  // for GDK_WINDOW_HWND
122    /// #endif
123    /// ...
124    /// static guintptr video_window_handle = 0;
125    /// ...
126    /// static GstBusSyncReply
127    /// bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
128    /// {
129    ///  // ignore anything but 'prepare-window-handle' element messages
130    ///  if (!gst_is_video_overlay_prepare_window_handle_message (message))
131    ///    return GST_BUS_PASS;
132    ///
133    ///  if (video_window_handle != 0) {
134    ///    GstVideoOverlay *overlay;
135    ///
136    ///    // GST_MESSAGE_SRC (message) will be the video sink element
137    ///    overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message));
138    ///    gst_video_overlay_set_window_handle (overlay, video_window_handle);
139    ///  } else {
140    ///    g_warning ("Should have obtained video_window_handle by now!");
141    ///  }
142    ///
143    ///  gst_message_unref (message);
144    ///  return GST_BUS_DROP;
145    /// }
146    /// ...
147    /// static void
148    /// video_widget_realize_cb (GtkWidget * widget, gpointer data)
149    /// {
150    /// #if GTK_CHECK_VERSION(2,18,0)
151    ///   // Tell Gtk+/Gdk to create a native window for this widget instead of
152    ///   // drawing onto the parent widget.
153    ///   // This is here just for pedagogical purposes, GDK_WINDOW_XID will call
154    ///   // it as well in newer Gtk versions
155    ///   if (!gdk_window_ensure_native (widget->window))
156    ///     g_error ("Couldn't create native window needed for GstVideoOverlay!");
157    /// #endif
158    ///
159    /// #ifdef GDK_WINDOWING_X11
160    ///   {
161    ///     gulong xid = GDK_WINDOW_XID (gtk_widget_get_window (video_window));
162    ///     video_window_handle = xid;
163    ///   }
164    /// #endif
165    /// #ifdef GDK_WINDOWING_WIN32
166    ///   {
167    ///     HWND wnd = GDK_WINDOW_HWND (gtk_widget_get_window (video_window));
168    ///     video_window_handle = (guintptr) wnd;
169    ///   }
170    /// #endif
171    /// }
172    /// ...
173    /// int
174    /// main (int argc, char **argv)
175    /// {
176    ///   GtkWidget *video_window;
177    ///   GtkWidget *app_window;
178    ///   ...
179    ///   app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
180    ///   ...
181    ///   video_window = gtk_drawing_area_new ();
182    ///   g_signal_connect (video_window, "realize",
183    ///       G_CALLBACK (video_widget_realize_cb), NULL);
184    ///   gtk_widget_set_double_buffered (video_window, FALSE);
185    ///   ...
186    ///   // usually the video_window will not be directly embedded into the
187    ///   // application window like this, but there will be many other widgets
188    ///   // and the video window will be embedded in one of them instead
189    ///   gtk_container_add (GTK_CONTAINER (ap_window), video_window);
190    ///   ...
191    ///   // show the GUI
192    ///   gtk_widget_show_all (app_window);
193    ///
194    ///   // realize window now so that the video window gets created and we can
195    ///   // obtain its XID/HWND before the pipeline is started up and the videosink
196    ///   // asks for the XID/HWND of the window to render onto
197    ///   gtk_widget_realize (video_window);
198    ///
199    ///   // we should have the XID/HWND now
200    ///   g_assert (video_window_handle != 0);
201    ///   ...
202    ///   // set up sync handler for setting the xid once the pipeline is started
203    ///   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
204    ///   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL,
205    ///       NULL);
206    ///   gst_object_unref (bus);
207    ///   ...
208    ///   gst_element_set_state (pipeline, GST_STATE_PLAYING);
209    ///   ...
210    /// }
211    /// ```
212    ///
213    /// ## GstVideoOverlay and Qt
214    ///
215    ///
216    /// ```text
217    /// #include <glib.h>;
218    /// #include <gst/gst.h>;
219    /// #include <gst/video/videooverlay.h>;
220    ///
221    /// #include <QApplication>;
222    /// #include <QTimer>;
223    /// #include <QWidget>;
224    ///
225    /// int main(int argc, char *argv[])
226    /// {
227    ///   if (!g_thread_supported ())
228    ///     g_thread_init (NULL);
229    ///
230    ///   gst_init (&argc, &argv);
231    ///   QApplication app(argc, argv);
232    ///   app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ()));
233    ///
234    ///   // prepare the pipeline
235    ///
236    ///   GstElement *pipeline = gst_pipeline_new ("xvoverlay");
237    ///   GstElement *src = gst_element_factory_make ("videotestsrc", NULL);
238    ///   GstElement *sink = gst_element_factory_make ("xvimagesink", NULL);
239    ///   gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
240    ///   gst_element_link (src, sink);
241    ///
242    ///   // prepare the ui
243    ///
244    ///   QWidget window;
245    ///   window.resize(320, 240);
246    ///   window.show();
247    ///
248    ///   WId xwinid = window.winId();
249    ///   gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), xwinid);
250    ///
251    ///   // run the pipeline
252    ///
253    ///   GstStateChangeReturn sret = gst_element_set_state (pipeline,
254    ///       GST_STATE_PLAYING);
255    ///   if (sret == GST_STATE_CHANGE_FAILURE) {
256    ///     gst_element_set_state (pipeline, GST_STATE_NULL);
257    ///     gst_object_unref (pipeline);
258    ///     // Exit application
259    ///     QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit()));
260    ///   }
261    ///
262    ///   int ret = app.exec();
263    ///
264    ///   window.hide();
265    ///   gst_element_set_state (pipeline, GST_STATE_NULL);
266    ///   gst_object_unref (pipeline);
267    ///
268    ///   return ret;
269    /// }
270    /// ```
271    ///
272    /// # Implements
273    ///
274    /// [`VideoOverlayExt`][trait@crate::prelude::VideoOverlayExt], [`VideoOverlayExtManual`][trait@crate::prelude::VideoOverlayExtManual]
275    #[doc(alias = "GstVideoOverlay")]
276    pub struct VideoOverlay(Interface<ffi::GstVideoOverlay, ffi::GstVideoOverlayInterface>);
277
278    match fn {
279        type_ => || ffi::gst_video_overlay_get_type(),
280    }
281}
282
283impl VideoOverlay {
284    pub const NONE: Option<&'static VideoOverlay> = None;
285
286    //#[doc(alias = "gst_video_overlay_install_properties")]
287    //pub fn install_properties(oclass: /*Ignored*/&mut glib::ObjectClass, last_prop_id: i32) {
288    //    unsafe { TODO: call ffi:gst_video_overlay_install_properties() }
289    //}
290}
291
292unsafe impl Send for VideoOverlay {}
293unsafe impl Sync for VideoOverlay {}
294
295/// Trait containing all [`struct@VideoOverlay`] methods.
296///
297/// # Implementors
298///
299/// [`VideoOverlay`][struct@crate::VideoOverlay]
300pub trait VideoOverlayExt: IsA<VideoOverlay> + 'static {
301    /// Tell an overlay that it has been exposed. This will redraw the current frame
302    /// in the drawable even if the pipeline is PAUSED.
303    #[doc(alias = "gst_video_overlay_expose")]
304    fn expose(&self) {
305        unsafe {
306            ffi::gst_video_overlay_expose(self.as_ref().to_glib_none().0);
307        }
308    }
309
310    //#[doc(alias = "gst_video_overlay_got_window_handle")]
311    //fn got_window_handle(&self, handle: /*Unimplemented*/Basic: UIntPtr) {
312    //    unsafe { TODO: call ffi:gst_video_overlay_got_window_handle() }
313    //}
314
315    /// Tell an overlay that it should handle events from the window system. These
316    /// events are forwarded upstream as navigation events. In some window system,
317    /// events are not propagated in the window hierarchy if a client is listening
318    /// for them. This method allows you to disable events handling completely
319    /// from the [`VideoOverlay`][crate::VideoOverlay].
320    /// ## `handle_events`
321    /// a `gboolean` indicating if events should be handled or not.
322    #[doc(alias = "gst_video_overlay_handle_events")]
323    fn handle_events(&self, handle_events: bool) {
324        unsafe {
325            ffi::gst_video_overlay_handle_events(
326                self.as_ref().to_glib_none().0,
327                handle_events.into_glib(),
328            );
329        }
330    }
331
332    /// This will post a "prepare-window-handle" element message on the bus
333    /// to give applications an opportunity to call
334    /// [`VideoOverlayExtManual::set_window_handle()`][crate::prelude::VideoOverlayExtManual::set_window_handle()] before a plugin creates its own
335    /// window.
336    ///
337    /// This function should only be used by video overlay plugin developers.
338    #[doc(alias = "gst_video_overlay_prepare_window_handle")]
339    fn prepare_window_handle(&self) {
340        unsafe {
341            ffi::gst_video_overlay_prepare_window_handle(self.as_ref().to_glib_none().0);
342        }
343    }
344
345    /// Configure a subregion as a video target within the window set by
346    /// [`VideoOverlayExtManual::set_window_handle()`][crate::prelude::VideoOverlayExtManual::set_window_handle()]. If this is not used or not supported
347    /// the video will fill the area of the window set as the overlay to 100%.
348    /// By specifying the rectangle, the video can be overlayed to a specific region
349    /// of that window only. After setting the new rectangle one should call
350    /// [`expose()`][Self::expose()] to force a redraw. To unset the region pass -1 for
351    /// the `width` and `height` parameters.
352    ///
353    /// This method is needed for non fullscreen video overlay in UI toolkits that
354    /// do not support subwindows.
355    /// ## `x`
356    /// the horizontal offset of the render area inside the window
357    /// ## `y`
358    /// the vertical offset of the render area inside the window
359    /// ## `width`
360    /// the width of the render area inside the window
361    /// ## `height`
362    /// the height of the render area inside the window
363    ///
364    /// # Returns
365    ///
366    /// [`false`] if not supported by the sink.
367    #[doc(alias = "gst_video_overlay_set_render_rectangle")]
368    fn set_render_rectangle(
369        &self,
370        x: i32,
371        y: i32,
372        width: i32,
373        height: i32,
374    ) -> Result<(), glib::error::BoolError> {
375        unsafe {
376            glib::result_from_gboolean!(
377                ffi::gst_video_overlay_set_render_rectangle(
378                    self.as_ref().to_glib_none().0,
379                    x,
380                    y,
381                    width,
382                    height
383                ),
384                "Failed to set render rectangle"
385            )
386        }
387    }
388}
389
390impl<O: IsA<VideoOverlay>> VideoOverlayExt for O {}