The #GstVideoOverlay interface is used for 2 main purposes :
To get a grab on the Window where the video sink element is going to render. This is achieved by either being informed about the Window identifier that the video sink element generated, or by forcing the video sink element to use a specific Window identifier for rendering.
To force a redrawing of the latest video frame the video sink element displayed on the Window. Indeed if the #GstPipeline is in #GST_STATE_PAUSED state, moving the Window around will damage its content. Application developers will want to handle the Expose events themselves and force the video sink element to refresh the Window's content.
A plugin drawing video output in a video window will need to have that
window at one stage or another. Passive mode simply means that no window
has been given to the plugin before that stage, so the plugin created the
window by itself. In that case the plugin is responsible of destroying
that window when it's not needed any more and it has to tell the
applications that a window has been created so that the application can
use it. This is done using the have-window-handle
message that can be posted from the plugin with the
gst_video_overlay_got_window_handle
method.
As you probably guessed already active mode just means sending a video
window to the plugin so that video output goes there. This is done using
the gst_video_overlay_set_window_handle
method.
It is possible to switch from one mode to another at any moment, so the plugin implementing this interface has to handle all cases. There are only 2 methods that plugins writers have to implement and they most probably look like that :
static void gst_my_filter_set_window_handle (GstVideoOverlay *overlay, guintptr handle) { GstMyFilter *my_filter = GST_MY_FILTER (overlay); if (my_filter->window) gst_my_filter_destroy_window (my_filter->window); my_filter->window = handle; } static void gst_my_filter_xoverlay_init (GstVideoOverlayClass *iface) { iface->set_window_handle = gst_my_filter_set_window_handle; }
You will also need to use the interface methods to post messages when needed such as when receiving a CAPS event where you will know the video geometry and maybe create the window.
static MyFilterWindow * gst_my_filter_window_create (GstMyFilter *my_filter, gint width, gint height) { MyFilterWindow *window = g_new (MyFilterWindow, 1); ... gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (my_filter), window->win); } /* called from the event handler for CAPS events */ static gboolean gst_my_filter_sink_set_caps (GstMyFilter *my_filter, GstCaps *caps) { gint width, height; gboolean ret; ... ret = gst_structure_get_int (structure, "width", &width); ret &= gst_structure_get_int (structure, "height", &height); if (!ret) return FALSE; gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (my_filter)); if (!my_filter->window) my_filter->window = gst_my_filter_create_window (my_filter, width, height); ... }