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