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