Branch data Line data Source code
1 : : /* GStreamer X-based Overlay
2 : : * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 : : *
4 : : * x-overlay.c: X-based overlay interface design
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Library General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Library General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Library General Public
17 : : * License along with this library; if not, write to the
18 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 : : * Boston, MA 02111-1307, USA.
20 : : */
21 : : /**
22 : : * SECTION:gstxoverlay
23 : : * @short_description: Interface for setting/getting a Window on elements
24 : : * supporting it
25 : : *
26 : : * <refsect2>
27 : : * <para>
28 : : * The XOverlay interface is used for 2 main purposes :
29 : : * <itemizedlist>
30 : : * <listitem>
31 : : * <para>
32 : : * To get a grab on the Window where the video sink element is going to render.
33 : : * This is achieved by either being informed about the Window identifier that
34 : : * the video sink element generated, or by forcing the video sink element to use
35 : : * a specific Window identifier for rendering.
36 : : * </para>
37 : : * </listitem>
38 : : * <listitem>
39 : : * <para>
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 : : * </para>
46 : : * </listitem>
47 : : * </itemizedlist>
48 : : * </para>
49 : : * <para>
50 : : * Using the Window created by the video sink is probably the simplest scenario,
51 : : * in some cases, though, it might not be flexible enough for application
52 : : * developers if they need to catch events such as mouse moves and button
53 : : * clicks.
54 : : * </para>
55 : : * <para>
56 : : * Setting a specific Window identifier on the video sink element is the most
57 : : * flexible solution but it has some issues. Indeed the application needs to set
58 : : * its Window identifier at the right time to avoid internal Window creation
59 : : * from the video sink element. To solve this issue a #GstMessage is posted on
60 : : * the bus to inform the application that it should set the Window identifier
61 : : * immediately. Here is an example on how to do that correctly:
62 : : * |[
63 : : * static GstBusSyncReply
64 : : * create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
65 : : * {
66 : : * // ignore anything but 'prepare-xwindow-id' element messages
67 : : * if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
68 : : * return GST_BUS_PASS;
69 : : *
70 : : * if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
71 : : * return GST_BUS_PASS;
72 : : *
73 : : * win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0);
74 : : *
75 : : * XSetWindowBackgroundPixmap (disp, win, None);
76 : : *
77 : : * XMapRaised (disp, win);
78 : : *
79 : : * XSync (disp, FALSE);
80 : : *
81 : : * gst_x_overlay_set_window_handle (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
82 : : * win);
83 : : *
84 : : * gst_message_unref (message);
85 : : *
86 : : * return GST_BUS_DROP;
87 : : * }
88 : : * ...
89 : : * int
90 : : * main (int argc, char **argv)
91 : : * {
92 : : * ...
93 : : * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
94 : : * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline);
95 : : * ...
96 : : * }
97 : : * ]|
98 : : * </para>
99 : : * </refsect2>
100 : : * <refsect2>
101 : : * <title>Two basic usage scenarios</title>
102 : : * <para>
103 : : * There are two basic usage scenarios: in the simplest case, the application
104 : : * knows exactly what particular element is used for video output, which is
105 : : * usually the case when the application creates the videosink to use
106 : : * (e.g. #xvimagesink, #ximagesink, etc.) itself; in this case, the application
107 : : * can just create the videosink element, create and realize the window to
108 : : * render the video on and then call gst_x_overlay_set_window_handle() directly
109 : : * with the XID or native window handle, before starting up the pipeline.
110 : : * </para>
111 : : * <para>
112 : : * In the other and more common case, the application does not know in advance
113 : : * what GStreamer video sink element will be used for video output. This is
114 : : * usually the case when an element such as #autovideosink or #gconfvideosink
115 : : * is used. In this case, the video sink element itself is created
116 : : * asynchronously from a GStreamer streaming thread some time after the
117 : : * pipeline has been started up. When that happens, however, the video sink
118 : : * will need to know right then whether to render onto an already existing
119 : : * application window or whether to create its own window. This is when it
120 : : * posts a prepare-xwindow-id message, and that is also why this message needs
121 : : * to be handled in a sync bus handler which will be called from the streaming
122 : : * thread directly (because the video sink will need an answer right then).
123 : : * </para>
124 : : * <para>
125 : : * As response to the prepare-xwindow-id element message in the bus sync
126 : : * handler, the application may use gst_x_overlay_set_window_handle() to tell
127 : : * the video sink to render onto an existing window surface. At this point the
128 : : * application should already have obtained the window handle / XID, so it
129 : : * just needs to set it. It is generally not advisable to call any GUI toolkit
130 : : * functions or window system functions from the streaming thread in which the
131 : : * prepare-xwindow-id message is handled, because most GUI toolkits and
132 : : * windowing systems are not thread-safe at all and a lot of care would be
133 : : * required to co-ordinate the toolkit and window system calls of the
134 : : * different threads (Gtk+ users please note: prior to Gtk+ 2.18
135 : : * GDK_WINDOW_XID() was just a simple structure access, so generally fine to do
136 : : * within the bus sync handler; this macro was changed to a function call in
137 : : * Gtk+ 2.18 and later, which is likely to cause problems when called from a
138 : : * sync handler; see below for a better approach without GDK_WINDOW_XID()
139 : : * used in the callback).
140 : : * </para>
141 : : * </refsect2>
142 : : * <refsect2>
143 : : * <title>GstXOverlay and Gtk+</title>
144 : : * <para>
145 : : * |[
146 : : * #include <gtk/gtk.h>
147 : : * #ifdef GDK_WINDOWING_X11
148 : : * #include <gdk/gdkx.h> // for GDK_WINDOW_XID
149 : : * #endif
150 : : * ...
151 : : * static gulong video_window_xid = 0;
152 : : * ...
153 : : * static GstBusSyncReply
154 : : * bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
155 : : * {
156 : : * // ignore anything but 'prepare-xwindow-id' element messages
157 : : * if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
158 : : * return GST_BUS_PASS;
159 : : * if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
160 : : * return GST_BUS_PASS;
161 : : *
162 : : * if (video_window_xid != 0) {
163 : : * GstXOverlay *xoverlay;
164 : : *
165 : : * // GST_MESSAGE_SRC (message) will be the video sink element
166 : : * xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (message));
167 : : * gst_x_overlay_set_window_handle (xoverlay, video_window_xid);
168 : : * } else {
169 : : * g_warning ("Should have obtained video_window_xid by now!");
170 : : * }
171 : : *
172 : : * gst_message_unref (message);
173 : : * return GST_BUS_DROP;
174 : : * }
175 : : * ...
176 : : * static void
177 : : * video_widget_realize_cb (GtkWidget * widget, gpointer data)
178 : : * {
179 : : * #if GTK_CHECK_VERSION(2,18,0)
180 : : * // This is here just for pedagogical purposes, GDK_WINDOW_XID will call
181 : : * // it as well in newer Gtk versions
182 : : * if (!gdk_window_ensure_native (widget->window))
183 : : * g_error ("Couldn't create native window needed for GstXOverlay!");
184 : : * #endif
185 : : *
186 : : * #ifdef GDK_WINDOWING_X11
187 : : * video_window_xid = GDK_WINDOW_XID (video_window->window);
188 : : * #endif
189 : : * }
190 : : * ...
191 : : * int
192 : : * main (int argc, char **argv)
193 : : * {
194 : : * GtkWidget *video_window;
195 : : * GtkWidget *app_window;
196 : : * ...
197 : : * app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
198 : : * ...
199 : : * video_window = gtk_drawing_area_new ();
200 : : * g_signal_connect (video_window, "realize",
201 : : * G_CALLBACK (video_widget_realize_cb), NULL);
202 : : * gtk_widget_set_double_buffered (video_window, FALSE);
203 : : * ...
204 : : * // usually the video_window will not be directly embedded into the
205 : : * // application window like this, but there will be many other widgets
206 : : * // and the video window will be embedded in one of them instead
207 : : * gtk_container_add (GTK_CONTAINER (ap_window), video_window);
208 : : * ...
209 : : * // show the GUI
210 : : * gtk_widget_show_all (app_window);
211 : : *
212 : : * // realize window now so that the video window gets created and we can
213 : : * // obtain its XID before the pipeline is started up and the videosink
214 : : * // asks for the XID of the window to render onto
215 : : * gtk_widget_realize (window);
216 : : *
217 : : * // we should have the XID now
218 : : * g_assert (video_window_xid != 0);
219 : : * ...
220 : : * // set up sync handler for setting the xid once the pipeline is started
221 : : * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
222 : : * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL);
223 : : * gst_object_unref (bus);
224 : : * ...
225 : : * gst_element_set_state (pipeline, GST_STATE_PLAYING);
226 : : * ...
227 : : * }
228 : : * ]|
229 : : * </para>
230 : : * </refsect2>
231 : : * <refsect2>
232 : : * <title>GstXOverlay and Qt</title>
233 : : * <para>
234 : : * |[
235 : : * #include <glib.h>
236 : : * #include <gst/gst.h>
237 : : * #include <gst/interfaces/xoverlay.h>
238 : : *
239 : : * #include <QApplication>
240 : : * #include <QTimer>
241 : : * #include <QWidget>
242 : : *
243 : : * int main(int argc, char *argv[])
244 : : * {
245 : : * if (!g_thread_supported ())
246 : : * g_thread_init (NULL);
247 : : *
248 : : * gst_init (&argc, &argv);
249 : : * QApplication app(argc, argv);
250 : : * app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ()));
251 : : *
252 : : * // prepare the pipeline
253 : : *
254 : : * GstElement *pipeline = gst_pipeline_new ("xvoverlay");
255 : : * GstElement *src = gst_element_factory_make ("videotestsrc", NULL);
256 : : * GstElement *sink = gst_element_factory_make ("xvimagesink", NULL);
257 : : * gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
258 : : * gst_element_link (src, sink);
259 : : *
260 : : * // prepare the ui
261 : : *
262 : : * QWidget window;
263 : : * window.resize(320, 240);
264 : : * window.show();
265 : : *
266 : : * WId xwinid = window.winId();
267 : : * gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid);
268 : : *
269 : : * // run the pipeline
270 : : *
271 : : * GstStateChangeReturn sret = gst_element_set_state (pipeline,
272 : : * GST_STATE_PLAYING);
273 : : * if (sret == GST_STATE_CHANGE_FAILURE) {
274 : : * gst_element_set_state (pipeline, GST_STATE_NULL);
275 : : * gst_object_unref (pipeline);
276 : : * // Exit application
277 : : * QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit()));
278 : : * }
279 : : *
280 : : * int ret = app.exec();
281 : : *
282 : : * window.hide();
283 : : * gst_element_set_state (pipeline, GST_STATE_NULL);
284 : : * gst_object_unref (pipeline);
285 : : *
286 : : * return ret;
287 : : * }
288 : : * ]|
289 : : * </para>
290 : : * </refsect2>
291 : : */
292 : :
293 : : #ifdef HAVE_CONFIG_H
294 : : #include "config.h"
295 : : #endif
296 : :
297 : : #include "xoverlay.h"
298 : :
299 : : static void gst_x_overlay_base_init (gpointer g_class);
300 : :
301 : : GType
302 : 64 : gst_x_overlay_get_type (void)
303 : : {
304 : : static GType gst_x_overlay_type = 0;
305 : :
306 [ + + ]: 64 : if (!gst_x_overlay_type) {
307 : : static const GTypeInfo gst_x_overlay_info = {
308 : : sizeof (GstXOverlayClass),
309 : : gst_x_overlay_base_init,
310 : : NULL,
311 : : NULL,
312 : : NULL,
313 : : NULL,
314 : : 0,
315 : : 0,
316 : : NULL,
317 : : };
318 : :
319 : 51 : gst_x_overlay_type = g_type_register_static (G_TYPE_INTERFACE,
320 : : "GstXOverlay", &gst_x_overlay_info, 0);
321 : 51 : g_type_interface_add_prerequisite (gst_x_overlay_type,
322 : : GST_TYPE_IMPLEMENTS_INTERFACE);
323 : : }
324 : :
325 : 64 : return gst_x_overlay_type;
326 : : }
327 : :
328 : : static void
329 : 67 : gst_x_overlay_base_init (gpointer g_class)
330 : : {
331 : :
332 : 67 : }
333 : :
334 : : /**
335 : : * gst_x_overlay_set_xwindow_id:
336 : : * @overlay: a #GstXOverlay to set the XWindow on.
337 : : * @xwindow_id: a #XID referencing the XWindow.
338 : : *
339 : : * This will call the video overlay's set_xwindow_id method. You should
340 : : * use this method to tell to a XOverlay to display video output to a
341 : : * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to
342 : : * stop using that window and create an internal one.
343 : : *
344 : : * Deprecated: Use gst_x_overlay_set_window_handle() instead.
345 : : */
346 : : #ifndef GST_REMOVE_DEPRECATED
347 : : #ifdef GST_DISABLE_DEPRECATED
348 : : void gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id);
349 : : #endif
350 : : void
351 : 0 : gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id)
352 : : {
353 [ # # ]: 0 : GST_WARNING_OBJECT (overlay,
354 : : "Using deprecated gst_x_overlay_set_xwindow_id()");
355 : 0 : gst_x_overlay_set_window_handle (overlay, xwindow_id);
356 : 0 : }
357 : : #endif
358 : :
359 : : /**
360 : : * gst_x_overlay_set_window_handle:
361 : : * @overlay: a #GstXOverlay to set the XWindow on.
362 : : * @xwindow_id: a #XID referencing the XWindow.
363 : : *
364 : : * This will call the video overlay's set_window_handle method. You
365 : : * should use this method to tell to a XOverlay to display video output to a
366 : : * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to
367 : : * stop using that window and create an internal one.
368 : : *
369 : : * Since: 0.10.31
370 : : */
371 : : void
372 : 0 : gst_x_overlay_set_window_handle (GstXOverlay * overlay, guintptr handle)
373 : : {
374 : : GstXOverlayClass *klass;
375 : :
376 [ # # ]: 0 : g_return_if_fail (overlay != NULL);
377 [ # # ]: 0 : g_return_if_fail (GST_IS_X_OVERLAY (overlay));
378 : :
379 : 0 : klass = GST_X_OVERLAY_GET_CLASS (overlay);
380 : :
381 [ # # ]: 0 : if (klass->set_window_handle) {
382 : 0 : klass->set_window_handle (overlay, handle);
383 : : } else {
384 : : #ifndef GST_REMOVE_DEPRECATED
385 : : #ifdef GST_DISABLE_DEPRECATED
386 : : #define set_xwindow_id set_xwindow_id_disabled
387 : : #endif
388 [ # # ]: 0 : if (sizeof (guintptr) <= sizeof (gulong) && klass->set_xwindow_id) {
389 [ # # ]: 0 : GST_WARNING_OBJECT (overlay,
390 : : "Calling deprecated set_xwindow_id() method");
391 : 0 : klass->set_xwindow_id (overlay, handle);
392 : : } else {
393 : 0 : g_warning ("Refusing to cast guintptr to smaller gulong");
394 : : }
395 : : #endif
396 : : }
397 : : }
398 : :
399 : : /**
400 : : * gst_x_overlay_got_xwindow_id:
401 : : * @overlay: a #GstXOverlay which got a XWindow.
402 : : * @xwindow_id: a #XID referencing the XWindow.
403 : : *
404 : : * This will post a "have-xwindow-id" element message on the bus.
405 : : *
406 : : * This function should only be used by video overlay plugin developers.
407 : : *
408 : : * Deprecated: Use gst_x_overlay_got_window_handle() instead.
409 : : */
410 : : #ifndef GST_REMOVE_DEPRECATED
411 : : #ifdef GST_DISABLE_DEPRECATED
412 : : void gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id);
413 : : #endif
414 : : void
415 : 0 : gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id)
416 : : {
417 [ # # ]: 0 : GST_WARNING_OBJECT (overlay,
418 : : "Using deprecated gst_x_overlay_got_xwindow_id()");
419 : 0 : gst_x_overlay_got_window_handle (overlay, xwindow_id);
420 : 0 : }
421 : : #endif
422 : :
423 : : /**
424 : : * gst_x_overlay_got_window_handle:
425 : : * @overlay: a #GstXOverlay which got a window
426 : : * @handle: a platform-specific handle referencing the window
427 : : *
428 : : * This will post a "have-xwindow-id" element message on the bus.
429 : : *
430 : : * This function should only be used by video overlay plugin developers.
431 : : */
432 : : void
433 : 0 : gst_x_overlay_got_window_handle (GstXOverlay * overlay, guintptr handle)
434 : : {
435 : : GstStructure *s;
436 : : GstMessage *msg;
437 : :
438 [ # # ]: 0 : g_return_if_fail (overlay != NULL);
439 [ # # ]: 0 : g_return_if_fail (GST_IS_X_OVERLAY (overlay));
440 : :
441 [ # # ]: 0 : GST_LOG_OBJECT (GST_OBJECT (overlay), "xwindow_id = %p", (gpointer)
442 : : handle);
443 : 0 : s = gst_structure_new ("have-xwindow-id",
444 : : "xwindow-id", G_TYPE_ULONG, (unsigned long) handle,
445 : : "window-handle", G_TYPE_UINT64, (guint64) handle, NULL);
446 : 0 : msg = gst_message_new_element (GST_OBJECT (overlay), s);
447 : 0 : gst_element_post_message (GST_ELEMENT (overlay), msg);
448 : : }
449 : :
450 : : /**
451 : : * gst_x_overlay_prepare_xwindow_id:
452 : : * @overlay: a #GstXOverlay which does not yet have an XWindow.
453 : : *
454 : : * This will post a "prepare-xwindow-id" element message on the bus
455 : : * to give applications an opportunity to call
456 : : * gst_x_overlay_set_xwindow_id() before a plugin creates its own
457 : : * window.
458 : : *
459 : : * This function should only be used by video overlay plugin developers.
460 : : */
461 : : void
462 : 0 : gst_x_overlay_prepare_xwindow_id (GstXOverlay * overlay)
463 : : {
464 : : GstStructure *s;
465 : : GstMessage *msg;
466 : :
467 [ # # ]: 0 : g_return_if_fail (overlay != NULL);
468 [ # # ]: 0 : g_return_if_fail (GST_IS_X_OVERLAY (overlay));
469 : :
470 [ # # ]: 0 : GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xwindow_id");
471 : 0 : s = gst_structure_new ("prepare-xwindow-id", NULL);
472 : 0 : msg = gst_message_new_element (GST_OBJECT (overlay), s);
473 : 0 : gst_element_post_message (GST_ELEMENT (overlay), msg);
474 : : }
475 : :
476 : : /**
477 : : * gst_x_overlay_expose:
478 : : * @overlay: a #GstXOverlay to expose.
479 : : *
480 : : * Tell an overlay that it has been exposed. This will redraw the current frame
481 : : * in the drawable even if the pipeline is PAUSED.
482 : : */
483 : : void
484 : 0 : gst_x_overlay_expose (GstXOverlay * overlay)
485 : : {
486 : : GstXOverlayClass *klass;
487 : :
488 [ # # ]: 0 : g_return_if_fail (overlay != NULL);
489 [ # # ]: 0 : g_return_if_fail (GST_IS_X_OVERLAY (overlay));
490 : :
491 : 0 : klass = GST_X_OVERLAY_GET_CLASS (overlay);
492 : :
493 [ # # ]: 0 : if (klass->expose) {
494 : 0 : klass->expose (overlay);
495 : : }
496 : : }
497 : :
498 : : /**
499 : : * gst_x_overlay_handle_events:
500 : : * @overlay: a #GstXOverlay to expose.
501 : : * @handle_events: a #gboolean indicating if events should be handled or not.
502 : : *
503 : : * Tell an overlay that it should handle events from the window system. These
504 : : * events are forwared upstream as navigation events. In some window system,
505 : : * events are not propagated in the window hierarchy if a client is listening
506 : : * for them. This method allows you to disable events handling completely
507 : : * from the XOverlay.
508 : : *
509 : : * Since: 0.10.12
510 : : */
511 : : void
512 : 0 : gst_x_overlay_handle_events (GstXOverlay * overlay, gboolean handle_events)
513 : : {
514 : : GstXOverlayClass *klass;
515 : :
516 [ # # ]: 0 : g_return_if_fail (overlay != NULL);
517 [ # # ]: 0 : g_return_if_fail (GST_IS_X_OVERLAY (overlay));
518 : :
519 : 0 : klass = GST_X_OVERLAY_GET_CLASS (overlay);
520 : :
521 [ # # ]: 0 : if (klass->handle_events) {
522 : 0 : klass->handle_events (overlay, handle_events);
523 : : }
524 : : }
525 : :
526 : : /**
527 : : * gst_x_overlay_set_render_rectangle:
528 : : * @overlay: a #GstXOverlay
529 : : * @x: the horizontal offset of the render area inside the window
530 : : * @y: the vertical offset of the render area inside the window
531 : : * @width: the width of the render area inside the window
532 : : * @height: the height of the render area inside the window
533 : : *
534 : : * Configure a subregion as a video target within the window set by
535 : : * gst_x_overlay_set_window_handle(). If this is not used or not supported
536 : : * the video will fill the area of the window set as the overlay to 100%.
537 : : * By specifying the rectangle, the video can be overlayed to a specific region
538 : : * of that window only. After setting the new rectangle one should call
539 : : * gst_x_overlay_expose() to force a redraw. To unset the region pass -1 for
540 : : * the @width and @height parameters.
541 : : *
542 : : * This method is needed for non fullscreen video overlay in UI toolkits that
543 : : * do not support subwindows.
544 : : *
545 : : * Returns: %FALSE if not supported by the sink.
546 : : *
547 : : * Since: 0.10.29
548 : : */
549 : : gboolean
550 : 0 : gst_x_overlay_set_render_rectangle (GstXOverlay * overlay,
551 : : gint x, gint y, gint width, gint height)
552 : : {
553 : : GstXOverlayClass *klass;
554 : :
555 [ # # ]: 0 : g_return_val_if_fail (overlay != NULL, FALSE);
556 [ # # ]: 0 : g_return_val_if_fail (GST_IS_X_OVERLAY (overlay), FALSE);
557 [ # # ][ # # ]: 0 : g_return_val_if_fail ((width == -1 && height == -1) ||
[ # # ][ # # ]
558 : : (width > 0 && height > 0), FALSE);
559 : :
560 : 0 : klass = GST_X_OVERLAY_GET_CLASS (overlay);
561 : :
562 [ # # ]: 0 : if (klass->set_render_rectangle) {
563 : 0 : klass->set_render_rectangle (overlay, x, y, width, height);
564 : 0 : return TRUE;
565 : : }
566 : 0 : return FALSE;
567 : : }
|