Try to improve switch to fullscreen mode.

This commit is contained in:
gb 2010-03-22 16:57:20 +00:00
parent 1c647d1f69
commit 3136cdc991
5 changed files with 100 additions and 77 deletions

View file

@ -39,7 +39,6 @@ libgstvaapi_source_h = \
libgstvaapi_source_priv_h = \
gstvaapidebug.h \
gstvaapiutils.h \
gstvaapiwindow_priv.h \
$(NULL)
libgstvaapi_x11_source_c = \

View file

@ -25,13 +25,26 @@
#include "config.h"
#include "gstvaapiwindow.h"
#include "gstvaapiwindow_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE(GstVaapiWindow, gst_vaapi_window, G_TYPE_OBJECT);
#define GST_VAAPI_WINDOW_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_WINDOW, \
GstVaapiWindowPrivate))
struct _GstVaapiWindowPrivate {
GstVaapiDisplay *display;
guint width;
guint height;
gboolean is_constructed : 1;
guint is_fullscreen : 1;
guint is_fullscreen_changed : 1;
};
enum {
PROP_0,
@ -41,6 +54,25 @@ enum {
PROP_FULLSCREEN
};
static void
gst_vaapi_window_ensure_size(GstVaapiWindow *window)
{
GstVaapiWindowPrivate * const priv = window->priv;
GstVaapiWindowClass * const klass = GST_VAAPI_WINDOW_GET_CLASS(window);
guint display_width, display_height;
if (!priv->is_fullscreen_changed)
return;
if (klass->get_geometry)
klass->get_geometry(window, NULL, NULL, &priv->width, &priv->height);
gst_vaapi_display_get_size(priv->display, &display_width, &display_height);
priv->is_fullscreen_changed = FALSE;
priv->is_fullscreen = (priv->width == display_width &&
priv->height == display_height);
}
static void
gst_vaapi_window_destroy(GstVaapiWindow *window)
{
@ -218,6 +250,7 @@ gst_vaapi_window_init(GstVaapiWindow *window)
priv->height = 1;
priv->is_constructed = FALSE;
priv->is_fullscreen = FALSE;
priv->is_fullscreen_changed = FALSE;
}
/**
@ -281,6 +314,8 @@ gst_vaapi_window_get_fullscreen(GstVaapiWindow *window)
{
g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), FALSE);
gst_vaapi_window_ensure_size(window);
return window->priv->is_fullscreen;
}
@ -291,12 +326,6 @@ gst_vaapi_window_get_fullscreen(GstVaapiWindow *window)
*
* Requests to place the @window in fullscreen or unfullscreen states.
*/
void
_gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
{
window->priv->is_fullscreen = fullscreen;
}
void
gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
{
@ -307,8 +336,10 @@ gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
klass = GST_VAAPI_WINDOW_GET_CLASS(window);
if (window->priv->is_fullscreen != fullscreen && klass->set_fullscreen) {
_gst_vaapi_window_set_fullscreen(window, fullscreen);
klass->set_fullscreen(window, fullscreen);
if (klass->set_fullscreen(window, fullscreen)) {
window->priv->is_fullscreen = fullscreen;
window->priv->is_fullscreen_changed = TRUE;
}
}
}
@ -326,6 +357,8 @@ gst_vaapi_window_get_width(GstVaapiWindow *window)
g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
g_return_val_if_fail(window->priv->is_constructed, 0);
gst_vaapi_window_ensure_size(window);
return window->priv->width;
}
@ -343,6 +376,8 @@ gst_vaapi_window_get_height(GstVaapiWindow *window)
g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
g_return_val_if_fail(window->priv->is_constructed, 0);
gst_vaapi_window_ensure_size(window);
return window->priv->height;
}
@ -360,6 +395,8 @@ gst_vaapi_window_get_size(GstVaapiWindow *window, guint *pwidth, guint *pheight)
g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
g_return_if_fail(window->priv->is_constructed);
gst_vaapi_window_ensure_size(window);
if (pwidth)
*pwidth = window->priv->width;
@ -405,25 +442,17 @@ gst_vaapi_window_set_height(GstVaapiWindow *window, guint height)
*
* Resizes the @window to match the specified @width and @height.
*/
gboolean
_gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
{
if (width == window->priv->width && height == window->priv->height)
return FALSE;
window->priv->width = width;
window->priv->height = height;
return TRUE;
}
void
gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
{
g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
if (!_gst_vaapi_window_set_size(window, width, height))
if (width == window->priv->width && height == window->priv->height)
return;
window->priv->width = width;
window->priv->height = height;
if (window->priv->is_constructed)
GST_VAAPI_WINDOW_GET_CLASS(window)->resize(window, width, height);
}

View file

@ -89,6 +89,9 @@ struct _GstVaapiWindowClass {
void (*destroy)(GstVaapiWindow *window);
gboolean (*show) (GstVaapiWindow *window);
gboolean (*hide) (GstVaapiWindow *window);
gboolean (*get_geometry) (GstVaapiWindow *window,
gint *px, gint *py,
guint *pwidth, guint *pheight);
gboolean (*set_fullscreen)(GstVaapiWindow *window, gboolean fullscreen);
gboolean (*resize) (GstVaapiWindow *window, guint width, guint height);
gboolean (*render) (GstVaapiWindow *window,

View file

@ -1,51 +0,0 @@
/*
* gstvaapiwindow_priv.h - VA window abstraction (private API)
*
* gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef GST_VAAPI_WINDOW_PRIVATE_H
#define GST_VAAPI_WINDOW_PRIVATE_H
#include "config.h"
G_BEGIN_DECLS
#define GST_VAAPI_WINDOW_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_WINDOW, \
GstVaapiWindowPrivate))
struct _GstVaapiWindowPrivate {
GstVaapiDisplay *display;
guint width;
guint height;
gboolean is_constructed : 1;
guint is_fullscreen : 1;
};
void
_gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
attribute_hidden;
gboolean
_gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
attribute_hidden;
G_END_DECLS
#endif /* GST_VAAPI_WINDOW_H */

View file

@ -131,10 +131,8 @@ timed_wait_event(GstVaapiWindow *window, int type, guint64 end_time, XEvent *e)
GST_VAAPI_DISPLAY_LOCK(priv->display);
got_event = XCheckTypedWindowEvent(dpy, priv->xid, type, e);
GST_VAAPI_DISPLAY_UNLOCK(priv->display);
if (got_event) {
g_print("HERE\n");
if (got_event)
return TRUE;
}
g_get_current_time(&now);
now_time = (guint64)now.tv_sec * 1000000 + now.tv_usec;
} while (now_time < end_time);
@ -163,6 +161,10 @@ gst_vaapi_window_x11_show(GstVaapiWindow *window)
wait_event(window, MapNotify);
priv->is_mapped = TRUE;
if (priv->fullscreen_on_map)
gst_vaapi_window_set_fullscreen(window, TRUE);
return TRUE;
}
@ -244,12 +246,30 @@ gst_vaapi_window_x11_destroy(GstVaapiWindow *window)
}
}
static gboolean
gst_vaapi_window_x11_get_geometry(
GstVaapiWindow *window,
gint *px,
gint *py,
guint *pwidth,
guint *pheight)
{
GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
return x11_get_geometry(dpy, priv->xid, px, py, pwidth, pheight);
}
static gboolean
gst_vaapi_window_x11_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
{
GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
XEvent e;
guint width, height;
gboolean has_errors;
GTimeVal now;
guint64 end_time;
GST_VAAPI_DISPLAY_LOCK(priv->display);
x11_trap_errors();
@ -291,9 +311,31 @@ gst_vaapi_window_x11_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
);
}
}
XSync(dpy, False);
has_errors = x11_untrap_errors() != 0;
GST_VAAPI_DISPLAY_UNLOCK(priv->display);
return !has_errors;
if (has_errors)
return FALSE;
/* Try to wait for the completion of the fullscreen mode switch */
if (priv->create_window && priv->is_mapped) {
const guint DELAY = 100000; /* 100 ms */
g_get_current_time(&now);
end_time = DELAY + ((guint64)now.tv_sec * 1000000 + now.tv_usec);
while (timed_wait_event(window, ConfigureNotify, end_time, &e)) {
if (fullscreen) {
gst_vaapi_display_get_size(priv->display, &width, &height);
if (e.xconfigure.width == width && e.xconfigure.height == height)
return TRUE;
}
else {
gst_vaapi_window_get_size(window, &width, &height);
if (e.xconfigure.width != width || e.xconfigure.height != height)
return TRUE;
}
}
}
return FALSE;
}
static gboolean
@ -442,6 +484,7 @@ gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass)
window_class->destroy = gst_vaapi_window_x11_destroy;
window_class->show = gst_vaapi_window_x11_show;
window_class->hide = gst_vaapi_window_x11_hide;
window_class->get_geometry = gst_vaapi_window_x11_get_geometry;
window_class->set_fullscreen = gst_vaapi_window_x11_set_fullscreen;
window_class->resize = gst_vaapi_window_x11_resize;
window_class->render = gst_vaapi_window_x11_render;