mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
[349/906] can switch xoverlays while playing
Fixes bug #584877 Before this commit calling "gst_x_overlay_set_xwindow_id" more than one time, had no effect. It mainly affects the glimagesink implementation. But on win32 (and CE), some stuff has to be done to release the old parent. And add a switchxoverlay example where the user can click on left/right part of the main window to switch the xoverlay.
This commit is contained in:
parent
47beeb1083
commit
6292d5af16
4 changed files with 111 additions and 48 deletions
|
@ -197,10 +197,37 @@ void
|
|||
gst_gl_window_set_external_window_id (GstGLWindow * window, gulong id)
|
||||
{
|
||||
GstGLWindowPrivate *priv = window->priv;
|
||||
|
||||
//retrieve parent if previously set
|
||||
HWND parent_id = GetProp (priv->internal_win_id, "gl_window_parent_id");
|
||||
|
||||
if (priv->visible) {
|
||||
ShowWindow (priv->internal_win_id, SW_HIDE);
|
||||
priv->visible = FALSE;
|
||||
}
|
||||
|
||||
if (parent_id) {
|
||||
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
|
||||
|
||||
g_debug ("release parent %lud\n", (gulong) parent_id);
|
||||
|
||||
g_assert (parent_proc);
|
||||
|
||||
SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) parent_proc);
|
||||
SetParent (priv->internal_win_id, NULL);
|
||||
|
||||
RemoveProp (parent_id, "gl_window_parent_proc");
|
||||
RemoveProp (priv->internal_win_id, "gl_window_parent_id");
|
||||
}
|
||||
|
||||
//not 0
|
||||
if (id) {
|
||||
WNDPROC window_parent_proc =
|
||||
(WNDPROC) GetWindowLongPtr ((HWND) id, GWL_WNDPROC);
|
||||
RECT rect;
|
||||
|
||||
g_debug ("set parent %lud\n", (gulong) id);
|
||||
|
||||
SetProp (priv->internal_win_id, "gl_window_parent_id", (HWND) id);
|
||||
SetProp ((HWND) id, "gl_window_id", priv->internal_win_id);
|
||||
SetProp ((HWND) id, "gl_window_parent_proc", (WNDPROC) window_parent_proc);
|
||||
|
@ -217,6 +244,11 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, gulong id)
|
|||
SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right,
|
||||
rect.bottom, FALSE);
|
||||
} else {
|
||||
//no parent so the internal window needs borders and system menu
|
||||
SetWindowLongPtr (priv->internal_win_id, GWL_STYLE,
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called in the gl thread */
|
||||
|
|
|
@ -204,14 +204,41 @@ void
|
|||
gst_gl_window_set_external_window_id (GstGLWindow * window, gulong id)
|
||||
{
|
||||
GstGLWindowPrivate *priv = window->priv;
|
||||
|
||||
//retrieve parent if previously set
|
||||
HWND parent_id = GetProp (priv->internal_win_id, "gl_window_parent_id");
|
||||
|
||||
if (priv->visible) {
|
||||
ShowWindow (priv->internal_win_id, SW_HIDE);
|
||||
priv->visible = FALSE;
|
||||
}
|
||||
|
||||
if (parent_id) {
|
||||
WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
|
||||
|
||||
g_debug ("release parent %lud\n", (gulong) parent_id);
|
||||
|
||||
g_assert (parent_proc);
|
||||
|
||||
SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) parent_proc);
|
||||
SetParent (priv->internal_win_id, NULL);
|
||||
|
||||
RemoveProp (parent_id, "gl_window_parent_proc");
|
||||
RemoveProp (priv->internal_win_id, "gl_window_parent_id");
|
||||
}
|
||||
|
||||
//not 0
|
||||
if (id) {
|
||||
WNDPROC window_parent_proc =
|
||||
(WNDPROC) (guint64) GetWindowLongPtr ((HWND) id, GWL_WNDPROC);
|
||||
(WNDPROC) GetWindowLongPtr ((HWND) id, GWL_WNDPROC);
|
||||
RECT rect;
|
||||
|
||||
g_debug ("set parent %lud\n", (gulong) id);
|
||||
|
||||
SetProp (priv->internal_win_id, "gl_window_parent_id", (HWND) id);
|
||||
SetProp ((HWND) id, "gl_window_id", priv->internal_win_id);
|
||||
SetProp ((HWND) id, "gl_window_parent_proc", (WNDPROC) window_parent_proc);
|
||||
SetWindowLongPtr ((HWND) id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc);
|
||||
SetWindowLongPtr ((HWND) id, GWL_WNDPROC, (LONG_PTR) sub_class_proc);
|
||||
|
||||
SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE);
|
||||
SetParent (priv->internal_win_id, (HWND) id);
|
||||
|
@ -224,6 +251,11 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, gulong id)
|
|||
SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right,
|
||||
rect.bottom, FALSE);
|
||||
} else {
|
||||
//no parent so the internal window needs borders and system menu
|
||||
SetWindowLongPtr (priv->internal_win_id, GWL_STYLE,
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called in the gl thread */
|
||||
|
|
|
@ -251,6 +251,7 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink,
|
|||
{
|
||||
glimage_sink->display_name = NULL;
|
||||
glimage_sink->window_id = 0;
|
||||
glimage_sink->new_window_id = 0;
|
||||
glimage_sink->display = NULL;
|
||||
glimage_sink->stored_buffer = NULL;
|
||||
glimage_sink->clientReshapeCallback = NULL;
|
||||
|
@ -416,6 +417,9 @@ gst_glimage_sink_stop (GstBaseSink * bsink)
|
|||
glimage_sink->display = NULL;
|
||||
}
|
||||
|
||||
glimage_sink->window_id = 0;
|
||||
//but do not reset glimage_sink->new_window_id
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -485,7 +489,7 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
glimage_sink->par_n = par_n;
|
||||
glimage_sink->par_d = par_d;
|
||||
|
||||
if (!glimage_sink->window_id)
|
||||
if (!glimage_sink->window_id && !glimage_sink->new_window_id)
|
||||
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink));
|
||||
|
||||
return TRUE;
|
||||
|
@ -510,10 +514,6 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
if (glimage_sink->display == NULL) {
|
||||
glimage_sink->display = g_object_ref (gl_buffer->display);
|
||||
|
||||
if (glimage_sink->window_id)
|
||||
gst_gl_display_set_window_id (glimage_sink->display,
|
||||
glimage_sink->window_id);
|
||||
|
||||
gst_gl_display_set_client_reshape_callback (glimage_sink->display,
|
||||
glimage_sink->clientReshapeCallback);
|
||||
|
||||
|
@ -532,10 +532,6 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
gst_gl_display_create_context (glimage_sink->display,
|
||||
glimage_sink->width, glimage_sink->height, 0);
|
||||
|
||||
if (glimage_sink->window_id)
|
||||
gst_gl_display_set_window_id (glimage_sink->display,
|
||||
glimage_sink->window_id);
|
||||
|
||||
//init colorspace conversion if needed
|
||||
gst_gl_display_init_upload (glimage_sink->display, glimage_sink->format,
|
||||
glimage_sink->width, glimage_sink->height,
|
||||
|
@ -558,6 +554,12 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
//gl_buffer is created in this block, so the gl buffer is already referenced
|
||||
}
|
||||
|
||||
if (glimage_sink->window_id != glimage_sink->new_window_id) {
|
||||
glimage_sink->window_id = glimage_sink->new_window_id;
|
||||
gst_gl_display_set_window_id (glimage_sink->display,
|
||||
glimage_sink->window_id);
|
||||
}
|
||||
|
||||
//the buffer is cleared when an other comes in
|
||||
if (glimage_sink->stored_buffer) {
|
||||
gst_buffer_unref (GST_BUFFER_CAST (glimage_sink->stored_buffer));
|
||||
|
@ -594,11 +596,7 @@ gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, gulong window_id)
|
|||
|
||||
GST_DEBUG ("set_xwindow_id %ld", window_id);
|
||||
|
||||
if (glimage_sink->window_id == window_id)
|
||||
return;
|
||||
|
||||
if (window_id)
|
||||
glimage_sink->window_id = window_id;
|
||||
glimage_sink->new_window_id = window_id;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ struct _GstGLImageSink
|
|||
gchar *display_name;
|
||||
|
||||
gulong window_id;
|
||||
gulong new_window_id;
|
||||
|
||||
//caps
|
||||
GstCaps *caps;
|
||||
|
|
Loading…
Reference in a new issue