diff options
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | sys/v4l2/Makefile.am | 15 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2.c | 5 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element.c | 23 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2element.h | 6 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2xoverlay.c | 178 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2xoverlay.h | 5 | ||||
-rw-r--r-- | sys/v4l2/v4l2-overlay_calls.c | 140 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.h | 10 |
9 files changed, 186 insertions, 227 deletions
@@ -1,5 +1,36 @@ 2004-10-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net> + * sys/v4l/Makefile.am: + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l/gstv4lelement.c: (gst_v4lelement_get_type), + (gst_v4lelement_init), (gst_v4lelement_dispose), + (gst_v4lelement_change_state): + * sys/v4l/gstv4lelement.h: + * sys/v4l/gstv4lxoverlay.c: (gst_v4l_xoverlay_open), + (gst_v4l_xoverlay_close), (idle_refresh), + (gst_v4l_xoverlay_set_xwindow_id): + * sys/v4l/gstv4lxoverlay.h: + * sys/v4l/v4l-overlay_calls.c: + * sys/v4l/v4l_calls.h: + * sys/v4l2/Makefile.am: + * sys/v4l2/gstv4l2.c: (plugin_init): + * sys/v4l2/gstv4l2element.c: (gst_v4l2element_get_type), + (gst_v4l2element_init), (gst_v4l2element_dispose), + (gst_v4l2element_change_state): + * sys/v4l2/gstv4l2element.h: + * sys/v4l2/gstv4l2xoverlay.c: (gst_v4l2_xoverlay_open), + (gst_v4l2_xoverlay_close), (idle_refresh), + (gst_v4l2_xoverlay_set_xwindow_id): + * sys/v4l2/gstv4l2xoverlay.h: + * sys/v4l2/v4l2-overlay_calls.c: + * sys/v4l2/v4l2_calls.h: + Remove client-side overlay handling, use the X-server v4l plugin + for that. Nicer overlay, less code. Also make the plugin + compileable without X (but then without overlay, obviously). + Makes xwindowlistener obsolete, should we remove that? + +2004-10-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net> + * sys/oss/gstosssrc.c: (gst_osssrc_get_time), (gst_osssrc_get), (gst_osssrc_src_query): * sys/oss/gstosssrc.h: diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index b242b34a..89e6b853 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -1,18 +1,27 @@ plugin_LTLIBRARIES = \ libgstvideo4linux2.la +if USE_XVIDEO +xv_source = gstv4l2xoverlay.c +xv_libs = $(X_LIBS) $(XVIDEO_LIBS) +else +xv_source = +xv_libs = +endif + libgstvideo4linux2_la_SOURCES = \ gstv4l2element.c v4l2_calls.c \ - v4l2-overlay_calls.c \ gstv4l2src.c v4l2src_calls.c \ gstv4l2.c \ gstv4l2tuner.c \ - gstv4l2xoverlay.c \ + $(xv_source) \ gstv4l2colorbalance.c libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) libgstvideo4linux2_la_LIBADD = \ $(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la -libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideo4linux2_la_LDFLAGS = \ + $(GST_PLUGIN_LDFLAGS) \ + $(xv_libs) noinst_HEADERS = gstv4l2element.h v4l2_calls.h \ gstv4l2src.h v4l2src_calls.h \ diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c index 194cb077..b81080b2 100644 --- a/sys/v4l2/gstv4l2.c +++ b/sys/v4l2/gstv4l2.c @@ -31,11 +31,6 @@ static gboolean plugin_init (GstPlugin * plugin) { - /* actually, we can survive without it, but I'll create - * that handling later on. */ - if (!gst_library_load ("xwindowlistener")) - return FALSE; - if (!gst_element_register (plugin, "v4l2element", GST_RANK_NONE, GST_TYPE_V4L2ELEMENT) || !gst_element_register (plugin, "v4l2src", diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c index 8326125f..743b3b70 100644 --- a/sys/v4l2/gstv4l2element.c +++ b/sys/v4l2/gstv4l2element.c @@ -28,7 +28,9 @@ #include "v4l2_calls.h" #include "gstv4l2tuner.h" +#ifdef HAVE_XVIDEO #include "gstv4l2xoverlay.h" +#endif #include "gstv4l2colorbalance.h" #include <gst/propertyprobe/propertyprobe.h> @@ -284,11 +286,13 @@ gst_v4l2element_get_type (void) NULL, NULL, }; +#ifdef HAVE_XVIDEO static const GInterfaceInfo v4l2_xoverlay_info = { (GInterfaceInitFunc) gst_v4l2_xoverlay_interface_init, NULL, NULL, }; +#endif static const GInterfaceInfo v4l2_colorbalance_info = { (GInterfaceInitFunc) gst_v4l2_color_balance_interface_init, NULL, @@ -308,8 +312,10 @@ gst_v4l2element_get_type (void) GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info); g_type_add_interface_static (v4l2element_type, GST_TYPE_TUNER, &v4l2_tuner_info); +#ifdef HAVE_XVIDEO g_type_add_interface_static (v4l2element_type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info); +#endif g_type_add_interface_static (v4l2element_type, GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info); g_type_add_interface_static (v4l2element_type, @@ -412,13 +418,10 @@ gst_v4l2element_init (GstV4l2Element * v4l2element) v4l2element->video_fd = -1; v4l2element->buffer = NULL; v4l2element->device = g_strdup ("/dev/video0"); - v4l2element->display = g_strdup (g_getenv ("DISPLAY")); v4l2element->channels = NULL; v4l2element->norms = NULL; v4l2element->colors = NULL; - - v4l2element->overlay = gst_v4l2_xoverlay_new (v4l2element); } @@ -427,14 +430,6 @@ gst_v4l2element_dispose (GObject * object) { GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object); - if (v4l2element->overlay) { - gst_v4l2_xoverlay_free (v4l2element); - } - - if (v4l2element->display) { - g_free (v4l2element->display); - } - g_free (v4l2element->device); v4l2element->device = NULL; g_free (v4l2element->norm); @@ -576,19 +571,21 @@ gst_v4l2element_change_state (GstElement * element) */ switch (GST_STATE_TRANSITION (element)) { case GST_STATE_NULL_TO_READY: - gst_v4l2_set_display (v4l2element); - if (!gst_v4l2_open (v4l2element)) return GST_STATE_FAILURE; +#ifdef HAVE_XVIDEO gst_v4l2_xoverlay_open (v4l2element); +#endif /* emit a signal! whoopie! */ g_signal_emit (G_OBJECT (v4l2element), gst_v4l2element_signals[SIGNAL_OPEN], 0, v4l2element->device); break; case GST_STATE_READY_TO_NULL: +#ifdef HAVE_XVIDEO gst_v4l2_xoverlay_close (v4l2element); +#endif if (!gst_v4l2_close (v4l2element)) return GST_STATE_FAILURE; diff --git a/sys/v4l2/gstv4l2element.h b/sys/v4l2/gstv4l2element.h index 0fadf068..c9e5f347 100644 --- a/sys/v4l2/gstv4l2element.h +++ b/sys/v4l2/gstv4l2element.h @@ -88,6 +88,7 @@ struct v4l2_buffer typedef struct _GstV4l2Element GstV4l2Element; typedef struct _GstV4l2ElementClass GstV4l2ElementClass; +typedef struct _GstV4l2Xv GstV4l2Xv; struct _GstV4l2Element { GstElement element; @@ -110,16 +111,13 @@ struct _GstV4l2Element { GList *colors; /* X-overlay */ - GstXWindowListener *overlay; + GstV4l2Xv *xv; XID xwindow_id; /* properties */ gchar *norm; gchar *channel; gulong frequency; - - /* caching values */ - gchar *display; }; struct _GstV4l2ElementClass { diff --git a/sys/v4l2/gstv4l2xoverlay.c b/sys/v4l2/gstv4l2xoverlay.c index 515d8463..7976b60d 100644 --- a/sys/v4l2/gstv4l2xoverlay.c +++ b/sys/v4l2/gstv4l2xoverlay.c @@ -23,14 +23,26 @@ #include "config.h" #endif +#include <string.h> #include <gst/gst.h> #include <gst/xoverlay/xoverlay.h> -#include <gst/xwindowlistener/xwindowlistener.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <sys/stat.h> #include "gstv4l2xoverlay.h" #include "gstv4l2element.h" #include "v4l2_calls.h" +struct _GstV4l2Xv +{ + Display *dpy; + gint port, idle_id; + GMutex *mutex; +}; + static void gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id); @@ -41,80 +53,152 @@ gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass) klass->set_xwindow_id = gst_v4l2_xoverlay_set_xwindow_id; } -GstXWindowListener * -gst_v4l2_xoverlay_new (GstV4l2Element * v4l2element) +void +gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element) { - GstXWindowListener *xwin = gst_x_window_listener_new (NULL, - (MapWindowFunc) gst_v4l2_enable_overlay, - (SetWindowFunc) gst_v4l2_set_window, - (gpointer) v4l2element); + struct stat s; + GstV4l2Xv *v4l2xv; + const gchar *name = g_getenv ("DISPLAY"); + int ver, rel, req, ev, err, anum, i, id = 0, first_id = 0, min; + XvAdaptorInfo *ai; + Display *dpy; + + /* we need a display, obviously */ + if (!name || !(dpy = XOpenDisplay (name))) { + GST_WARNING ("No $DISPLAY set or failed to open - no overlay"); + return; + } - v4l2element->overlay = xwin; - v4l2element->xwindow_id = 0; + /* find port that belongs to this device */ + if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) { + GST_WARNING ("Xv extension not supported - no overlay"); + XCloseDisplay (dpy); + return; + } + if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) { + GST_WARNING ("Failed to query Xv adaptors"); + XCloseDisplay (dpy); + return; + } + if (fstat (v4l2element->video_fd, &s) < 0) { + GST_ERROR ("Failed to stat() file descriptor: %s", g_strerror (errno)); + XCloseDisplay (dpy); + return; + } + min = s.st_rdev & 0xff; + for (i = 0; i < anum; i++) { + if (!strcmp (ai[i].name, "video4linux")) { + if (first_id == 0) + first_id = ai[i].base_id; + + /* hmm... */ + if (first_id != 0 && ai[i].base_id == first_id + min) + id = ai[i].base_id; + } + } + XvFreeAdaptorInfo (ai); - return xwin; -} + if (id == 0) { + GST_WARNING ("Did not find XvPortID for device - no overlay"); + XCloseDisplay (dpy); + return; + } -void -gst_v4l2_xoverlay_free (GstV4l2Element * v4l2element) -{ - gst_v4l2_xoverlay_close (v4l2element); - g_object_unref (G_OBJECT (v4l2element->overlay)); - v4l2element->overlay = NULL; + v4l2xv = g_new0 (GstV4l2Xv, 1); + v4l2xv->dpy = dpy; + v4l2xv->port = id; + v4l2xv->mutex = g_mutex_new (); + v4l2xv->idle_id = 0; + v4l2element->xv = v4l2xv; + + if (v4l2element->xwindow_id) { + gst_v4l2_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4l2element), + v4l2element->xwindow_id); + } } void -gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element) +gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element) { - GstXWindowListener *xwin = v4l2element->overlay; + GstV4l2Xv *v4l2xv = v4l2element->xv; - if (xwin) { - xwin->display_name = g_strdup (v4l2element->display); + if (!v4l2element->xv) + return; - if (v4l2element->xwindow_id != 0 && - xwin->display_name && xwin->display_name[0] == ':') { - gst_x_window_listener_set_xid (xwin, v4l2element->xwindow_id); - } + if (v4l2element->xwindow_id) { + gst_v4l2_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4l2element), 0); } + + XCloseDisplay (v4l2xv->dpy); + g_mutex_free (v4l2xv->mutex); + if (v4l2xv->idle_id) + g_source_remove (v4l2xv->idle_id); + g_free (v4l2xv); + v4l2element->xv = NULL; } -void -gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element) +static gboolean +idle_refresh (gpointer data) { - GstXWindowListener *xwin = v4l2element->overlay; + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (data); + GstV4l2Xv *v4l2xv = v4l2element->xv; + XWindowAttributes attr; - if (xwin != NULL) { - if (v4l2element->xwindow_id != 0 && - xwin->display_name && xwin->display_name[0] == ':') { - gst_x_window_listener_set_xid (xwin, 0); - } + if (v4l2xv) { + g_mutex_lock (v4l2xv->mutex); + + XGetWindowAttributes (v4l2xv->dpy, v4l2element->xwindow_id, &attr); + XvPutVideo (v4l2xv->dpy, v4l2xv->port, v4l2element->xwindow_id, + DefaultGC (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)), + 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height); - g_free (xwin->display_name); - xwin->display_name = NULL; + v4l2xv->idle_id = 0; + g_mutex_unlock (v4l2xv->mutex); } + + /* once */ + return FALSE; } static void gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id) { GstV4l2Element *v4l2element = GST_V4L2ELEMENT (overlay); - GstXWindowListener *xwin = v4l2element->overlay; + GstV4l2Xv *v4l2xv = v4l2element->xv; + XWindowAttributes attr; + gboolean change = (v4l2element->xwindow_id != xwindow_id); - if (v4l2element->xwindow_id == xwindow_id) { + if (v4l2xv) + g_mutex_lock (v4l2xv->mutex); + + if (change) { + if (v4l2element->xwindow_id) { + XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 0); + XvSelectVideoNotify (v4l2xv->dpy, v4l2element->xwindow_id, 0); + } + + v4l2element->xwindow_id = xwindow_id; + } + + if (!v4l2xv || xwindow_id == 0) { + if (v4l2xv) + g_mutex_unlock (v4l2xv->mutex); return; } - if (gst_element_get_state (GST_ELEMENT (v4l2element)) != GST_STATE_NULL && - v4l2element->xwindow_id != 0 && - xwin != NULL && xwin->display_name && xwin->display_name[0] == ':') { - gst_x_window_listener_set_xid (xwin, 0); + if (change) { + /* draw */ + XvSelectPortNotify (v4l2xv->dpy, v4l2xv->port, 1); + XvSelectVideoNotify (v4l2xv->dpy, v4l2element->xwindow_id, 1); } - v4l2element->xwindow_id = xwindow_id; + XGetWindowAttributes (v4l2xv->dpy, v4l2element->xwindow_id, &attr); + XvPutVideo (v4l2xv->dpy, v4l2xv->port, v4l2element->xwindow_id, + DefaultGC (v4l2xv->dpy, DefaultScreen (v4l2xv->dpy)), + 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height); - if (gst_element_get_state (GST_ELEMENT (v4l2element)) != GST_STATE_NULL && - v4l2element->xwindow_id != 0 && - xwin != NULL && xwin->display_name && xwin->display_name[0] == ':') { - gst_x_window_listener_set_xid (xwin, v4l2element->xwindow_id); - } + if (v4l2xv->idle_id) + g_source_remove (v4l2xv->idle_id); + v4l2xv->idle_id = g_idle_add (idle_refresh, v4l2element); + g_mutex_unlock (v4l2xv->mutex); } diff --git a/sys/v4l2/gstv4l2xoverlay.h b/sys/v4l2/gstv4l2xoverlay.h index cfcdfd35..c59c4536 100644 --- a/sys/v4l2/gstv4l2xoverlay.h +++ b/sys/v4l2/gstv4l2xoverlay.h @@ -31,11 +31,6 @@ G_BEGIN_DECLS void gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass); -GstXWindowListener * - gst_v4l2_xoverlay_new (GstV4l2Element *v4l2element); -void gst_v4l2_xoverlay_free (GstV4l2Element *v4l2element); - -/* signal handlers */ void gst_v4l2_xoverlay_open (GstV4l2Element *v4l2element); void gst_v4l2_xoverlay_close (GstV4l2Element *v4l2element); diff --git a/sys/v4l2/v4l2-overlay_calls.c b/sys/v4l2/v4l2-overlay_calls.c deleted file mode 100644 index 0876879d..00000000 --- a/sys/v4l2/v4l2-overlay_calls.c +++ /dev/null @@ -1,140 +0,0 @@ -/* G-Streamer generic V4L2 element - generic V4L2 overlay handling - * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <string.h> -#include <errno.h> -#include "v4l2_calls.h" - -#define DEBUG(format, args...) \ - GST_DEBUG_OBJECT (\ - GST_ELEMENT(v4l2element), \ - "V4L2-overlay: " format, ##args) - - -/****************************************************** - * gst_v4l2_set_display(): - * calls v4l-conf - * return value: TRUE on success, FALSE on error - ******************************************************/ - -gboolean -gst_v4l2_set_display (GstV4l2Element * v4l2element) -{ - gchar *buff; - - if (v4l2element->display) - g_free (v4l2element->display); - v4l2element->display = g_strdup (g_getenv ("DISPLAY")); - - DEBUG ("trying to set overlay to '%s'", v4l2element->display); - - /* start v4l-conf */ - buff = g_strdup_printf ("v4l-conf -q -c %s -d %s", - v4l2element->device, v4l2element->display); - - switch (system (buff)) { - case -1: - GST_ELEMENT_ERROR (v4l2element, RESOURCE, FAILED, - (_("Could not start v4l-conf.")), GST_ERROR_SYSTEM); - g_free (buff); - return FALSE; - case 0: - break; - default: - GST_ELEMENT_ERROR (v4l2element, RESOURCE, FAILED, - (_("Executing v4l-conf failed.")), GST_ERROR_SYSTEM); - g_free (buff); - return FALSE; - } - - g_free (buff); - return TRUE; -} - - -/****************************************************** - * gst_v4l2_set_window(): - * sets the window where to display the video overlay - * return value: TRUE on success, FALSE on error - ******************************************************/ - -gboolean -gst_v4l2_set_window (GstElement * element, - gint x, gint y, gint w, gint h, struct v4l2_clip * clips, gint num_clips) -{ - struct v4l2_format fmt; - GstV4l2Element *v4l2element = GST_V4L2ELEMENT (element); - - DEBUG ("trying to set video window to %dx%d,%d,%d", x, y, w, h); - GST_V4L2_CHECK_OVERLAY (v4l2element); - GST_V4L2_CHECK_OPEN (v4l2element); - - fmt.type = V4L2_CAP_VIDEO_OVERLAY; - fmt.fmt.win.clipcount = 0; - fmt.fmt.win.w.left = x; - fmt.fmt.win.w.top = y; - fmt.fmt.win.w.width = w; - fmt.fmt.win.w.height = h; - fmt.fmt.win.clips = clips; - fmt.fmt.win.clipcount = num_clips; - fmt.fmt.win.bitmap = NULL; - - if (ioctl (v4l2element->video_fd, VIDIOC_S_FMT, &fmt) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, TOO_LAZY, (NULL), - ("Failed to set the video window: %s", g_strerror (errno))); - return FALSE; - } - - return TRUE; -} - - -/****************************************************** - * gst_v4l_set_overlay(): - * enables/disables actual video overlay display - * return value: TRUE on success, FALSE on error - ******************************************************/ - -gboolean -gst_v4l2_enable_overlay (GstV4l2Element * v4l2element, gboolean enable) -{ - gint doit = enable ? 1 : 0; - - DEBUG ("trying to %s overlay display", enable ? "enable" : "disable"); - GST_V4L2_CHECK_OPEN (v4l2element); - GST_V4L2_CHECK_OVERLAY (v4l2element); - - if (ioctl (v4l2element->video_fd, VIDIOC_OVERLAY, &doit) < 0) { - GST_ELEMENT_ERROR (v4l2element, RESOURCE, TOO_LAZY, (NULL), - ("Failed to %s overlay display: %s", - enable ? "enable" : "disable", g_strerror (errno))); - return FALSE; - } - - return TRUE; -} diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h index 428c57aa..537ca72c 100644 --- a/sys/v4l2/v4l2_calls.h +++ b/sys/v4l2/v4l2_calls.h @@ -118,14 +118,4 @@ gboolean gst_v4l2_set_attribute (GstV4l2Element *v4l2element, int attribute, const int value); -/* overlay */ -gboolean gst_v4l2_set_display (GstV4l2Element *v4l2element); -gboolean gst_v4l2_set_window (GstElement *element, - gint x, gint y, - gint w, gint h, - struct v4l2_clip *clips, - gint num_clips); -gboolean gst_v4l2_enable_overlay (GstV4l2Element *v4l2element, - gboolean enable); - #endif /* __V4L2_CALLS_H__ */ |