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