sys/: Remove client-side overlay handling, use the X-server v4l plugin for that. Nicer overlay, less code. Also make ...

Original commit message from CVS:
* 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?
This commit is contained in:
Ronald S. Bultje 2004-10-25 08:51:14 +00:00
parent 815a07e5b1
commit cd177c8577
9 changed files with 190 additions and 262 deletions

View file

@ -1,3 +1,34 @@
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),

View file

@ -1,19 +1,28 @@
plugin_LTLIBRARIES = libgstvideo4linux.la
if USE_XVIDEO
xv_source = gstv4lxoverlay.c
xv_libs = $(X_LIBS) $(XVIDEO_LIBS)
else
xv_source =
xv_libs =
endif
libgstvideo4linux_la_SOURCES = \
gstv4lelement.c v4l_calls.c \
v4l-overlay_calls.c \
gstv4lsrc.c v4lsrc_calls.c \
gstv4lmjpegsrc.c v4lmjpegsrc_calls.c \
gstv4lmjpegsink.c v4lmjpegsink_calls.c \
gstv4l.c \
gstv4ltuner.c \
gstv4lxoverlay.c \
$(xv_source) \
gstv4lcolorbalance.c
libgstvideo4linux_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS)
libgstvideo4linux_la_LIBADD = \
$(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la
libgstvideo4linux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstvideo4linux_la_LDFLAGS = \
$(GST_PLUGIN_LDFLAGS) \
$(xv_libs)
noinst_HEADERS = gstv4lelement.h v4l_calls.h \
gstv4lsrc.h v4lsrc_calls.h \

View file

@ -34,19 +34,11 @@
#include "gstv4lmjpegsink.h"
GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */
GST_DEBUG_CATEGORY_EXTERN (v4loverlay_debug);
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls");
GST_DEBUG_CATEGORY_INIT (v4loverlay_debug, "v4loverlay", 0,
"V4L overlay calls");
/* 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, "v4lelement",
GST_RANK_NONE, GST_TYPE_V4LELEMENT) ||

View file

@ -32,7 +32,9 @@
#include <string.h>
#include "v4l_calls.h"
#include "gstv4ltuner.h"
#ifdef HAVE_XVIDEO
#include "gstv4lxoverlay.h"
#endif
#include "gstv4lcolorbalance.h"
#include <gst/propertyprobe/propertyprobe.h>
@ -295,11 +297,13 @@ gst_v4lelement_get_type (void)
NULL,
NULL,
};
#ifdef HAVE_XVIDEO
static const GInterfaceInfo v4l_xoverlay_info = {
(GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
NULL,
NULL,
};
#endif
static const GInterfaceInfo v4l_colorbalance_info = {
(GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
NULL,
@ -318,8 +322,10 @@ gst_v4lelement_get_type (void)
GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
g_type_add_interface_static (v4lelement_type,
GST_TYPE_TUNER, &v4l_tuner_info);
#ifdef HAVE_XVIDEO
g_type_add_interface_static (v4lelement_type,
GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
#endif
g_type_add_interface_static (v4lelement_type,
GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
g_type_add_interface_static (v4lelement_type,
@ -390,13 +396,12 @@ gst_v4lelement_init (GstV4lElement * v4lelement)
v4lelement->video_fd = -1;
v4lelement->buffer = NULL;
v4lelement->videodev = g_strdup ("/dev/video0");
v4lelement->display = g_strdup (g_getenv ("DISPLAY"));
v4lelement->norms = NULL;
v4lelement->channels = NULL;
v4lelement->colors = NULL;
v4lelement->overlay = gst_v4l_xoverlay_new (v4lelement);
v4lelement->xwindow_id = 0;
}
@ -405,12 +410,6 @@ gst_v4lelement_dispose (GObject * object)
{
GstV4lElement *v4lelement = GST_V4LELEMENT (object);
gst_v4l_xoverlay_free (v4lelement);
if (v4lelement->display) {
g_free (v4lelement->display);
}
if (v4lelement->videodev) {
g_free (v4lelement->videodev);
}
@ -497,19 +496,21 @@ gst_v4lelement_change_state (GstElement * element)
*/
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
gst_v4l_set_overlay (v4lelement);
if (!gst_v4l_open (v4lelement))
return GST_STATE_FAILURE;
#ifdef HAVE_XVIDEO
gst_v4l_xoverlay_open (v4lelement);
#endif
g_signal_emit (G_OBJECT (v4lelement),
gst_v4lelement_signals[SIGNAL_OPEN], 0, v4lelement->videodev);
break;
case GST_STATE_READY_TO_NULL:
#ifdef HAVE_XVIDEO
gst_v4l_xoverlay_close (v4lelement);
#endif
if (!gst_v4l_close (v4lelement))
return GST_STATE_FAILURE;

View file

@ -60,6 +60,7 @@ G_BEGIN_DECLS
typedef struct _GstV4lElement GstV4lElement;
typedef struct _GstV4lElementClass GstV4lElementClass;
typedef struct _GstV4lXv GstV4lXv;
struct _GstV4lElement {
GstElement element;
@ -88,11 +89,8 @@ struct _GstV4lElement {
GList *channels;
/* X-overlay */
GstXWindowListener *overlay;
XID xwindow_id;
/* caching values */
gchar *display;
GstV4lXv *xv;
gulong xwindow_id;
};
struct _GstV4lElementClass {

View file

@ -24,14 +24,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 "gstv4lxoverlay.h"
#include "gstv4lelement.h"
#include "v4l_calls.h"
struct _GstV4lXv
{
Display *dpy;
gint port, idle_id;
GMutex *mutex;
};
static void gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay,
XID xwindow_id);
@ -42,80 +54,152 @@ gst_v4l_xoverlay_interface_init (GstXOverlayClass * klass)
klass->set_xwindow_id = gst_v4l_xoverlay_set_xwindow_id;
}
GstXWindowListener *
gst_v4l_xoverlay_new (GstV4lElement * v4lelement)
{
GstXWindowListener *xwin = gst_x_window_listener_new (NULL,
(MapWindowFunc) gst_v4l_enable_overlay,
(SetWindowFunc) gst_v4l_set_window,
(gpointer) v4lelement);
v4lelement->overlay = xwin;
v4lelement->xwindow_id = 0;
return xwin;
}
void
gst_v4l_xoverlay_free (GstV4lElement * v4lelement)
{
gst_v4l_xoverlay_close (v4lelement);
g_object_unref (G_OBJECT (v4lelement->overlay));
v4lelement->overlay = NULL;
}
void
gst_v4l_xoverlay_open (GstV4lElement * v4lelement)
{
GstXWindowListener *xwin = v4lelement->overlay;
struct stat s;
GstV4lXv *v4lxv;
const gchar *name = g_getenv ("DISPLAY");
int ver, rel, req, ev, err, anum, i, id = 0, first_id = 0, min;
XvAdaptorInfo *ai;
Display *dpy;
if (xwin != NULL) {
xwin->display_name = g_strdup (v4lelement->display);
/* we need a display, obviously */
if (!name || !(dpy = XOpenDisplay (name))) {
GST_WARNING ("No $DISPLAY set or failed to open - no overlay");
return;
}
if (v4lelement->xwindow_id != 0 &&
xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, v4lelement->xwindow_id);
/* 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 (v4lelement->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);
if (id == 0) {
GST_WARNING ("Did not find XvPortID for device - no overlay");
XCloseDisplay (dpy);
return;
}
v4lxv = g_new0 (GstV4lXv, 1);
v4lxv->dpy = dpy;
v4lxv->port = id;
v4lxv->mutex = g_mutex_new ();
v4lxv->idle_id = 0;
v4lelement->xv = v4lxv;
if (v4lelement->xwindow_id) {
gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement),
v4lelement->xwindow_id);
}
}
void
gst_v4l_xoverlay_close (GstV4lElement * v4lelement)
{
GstXWindowListener *xwin = v4lelement->overlay;
GstV4lXv *v4lxv = v4lelement->xv;
if (xwin != NULL) {
if (v4lelement->xwindow_id != 0 &&
xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, 0);
}
if (!v4lelement->xv)
return;
g_free (xwin->display_name);
xwin->display_name = NULL;
if (v4lelement->xwindow_id) {
gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement), 0);
}
XCloseDisplay (v4lxv->dpy);
g_mutex_free (v4lxv->mutex);
if (v4lxv->idle_id)
g_source_remove (v4lxv->idle_id);
g_free (v4lxv);
v4lelement->xv = NULL;
}
static gboolean
idle_refresh (gpointer data)
{
GstV4lElement *v4lelement = GST_V4LELEMENT (data);
GstV4lXv *v4lxv = v4lelement->xv;
XWindowAttributes attr;
if (v4lxv) {
g_mutex_lock (v4lxv->mutex);
XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
v4lxv->idle_id = 0;
g_mutex_unlock (v4lxv->mutex);
}
/* once */
return FALSE;
}
static void
gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
{
GstV4lElement *v4lelement = GST_V4LELEMENT (overlay);
GstXWindowListener *xwin = v4lelement->overlay;
GstV4lXv *v4lxv = v4lelement->xv;
XWindowAttributes attr;
gboolean change = (v4lelement->xwindow_id != xwindow_id);
if (v4lelement->xwindow_id == xwindow_id) {
if (v4lxv)
g_mutex_lock (v4lxv->mutex);
if (change) {
if (v4lelement->xwindow_id) {
XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 0);
XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 0);
}
v4lelement->xwindow_id = xwindow_id;
}
if (!v4lxv || xwindow_id == 0) {
if (v4lxv)
g_mutex_unlock (v4lxv->mutex);
return;
}
if (gst_element_get_state (GST_ELEMENT (v4lelement)) != GST_STATE_NULL &&
v4lelement->xwindow_id != 0 &&
xwin && xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, 0);
if (change) {
/* draw */
XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 1);
XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 1);
}
v4lelement->xwindow_id = xwindow_id;
XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
if (gst_element_get_state (GST_ELEMENT (v4lelement)) != GST_STATE_NULL &&
v4lelement->xwindow_id != 0 &&
xwin && xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, v4lelement->xwindow_id);
}
if (v4lxv->idle_id)
g_source_remove (v4lxv->idle_id);
v4lxv->idle_id = g_idle_add (idle_refresh, v4lelement);
g_mutex_unlock (v4lxv->mutex);
}

View file

@ -32,11 +32,6 @@ G_BEGIN_DECLS
void gst_v4l_xoverlay_interface_init (GstXOverlayClass *klass);
GstXWindowListener *
gst_v4l_xoverlay_new (GstV4lElement *v4lelement);
void gst_v4l_xoverlay_free (GstV4lElement *v4lelement);
/* signal handlers */
void gst_v4l_xoverlay_open (GstV4lElement *v4lelement);
void gst_v4l_xoverlay_close (GstV4lElement *v4lelement);

View file

@ -1,171 +0,0 @@
/* GStreamer
*
* v4l-overlay_calls.c: calls for generic V4L overlay handling
*
* Copyright (C) 2001-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 <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include "v4l_calls.h"
GST_DEBUG_CATEGORY (v4loverlay_debug);
#define GST_CAT_DEFAULT v4loverlay_debug
/******************************************************
* gst_v4l_set_overlay():
* calls v4l-conf
* return value: TRUE on success, FALSE on error
******************************************************/
gboolean
gst_v4l_set_overlay (GstV4lElement * v4lelement)
{
gchar *buff;
gchar *path;
gint ret;
if (v4lelement->display)
g_free (v4lelement->display);
v4lelement->display = g_strdup (g_getenv ("DISPLAY"));
GST_DEBUG_OBJECT (v4lelement, "setting display to '%s'", v4lelement->display);
GST_V4L_CHECK_NOT_OPEN (v4lelement);
if (!v4lelement->display || v4lelement->display[0] != ':')
return FALSE;
/* start v4l-conf */
path = g_find_program_in_path ("v4l-conf");
if (!path) {
GST_ELEMENT_ERROR (v4lelement, RESOURCE, FAILED,
(_("Program 'v4l-conf' missing from path.")),
("Cannot set XVideo overlay mode."));
return FALSE;
}
g_free (path);
buff = g_strdup_printf ("v4l-conf -q -c %s -d %s",
v4lelement->videodev, v4lelement->display);
ret = system (buff);
switch (ret) {
case -1:
GST_ELEMENT_ERROR (v4lelement, RESOURCE, FAILED,
(_("Could not start v4l-conf.")), GST_ERROR_SYSTEM);
g_free (buff);
return FALSE;
case 0:
break;
default:
{
/* if we get here, the system command did not fail but v4l-conf
* returned an error code, we just warn for now because it is not
* always fatal (like not having overlay support) */
gint status = WEXITSTATUS (ret);
GST_WARNING_OBJECT (v4lelement, "v4l-conf returned %d.", status);
g_free (buff);
return TRUE;
}
}
g_free (buff);
return TRUE;
}
/******************************************************
* gst_v4l_set_window():
* sets the window where to display the video overlay
* return value: TRUE on success, FALSE on error
******************************************************/
gboolean
gst_v4l_set_window (GstElement * element,
gint x, gint y, gint w, gint h, struct video_clip * clips, gint num_clips)
{
GstV4lElement *v4lelement = GST_V4LELEMENT (element);
struct video_window vwin;
GST_DEBUG_OBJECT (v4lelement,
"setting video window to position (x,y/wxh) = %d,%d/%dx%d", x, y, w, h);
GST_V4L_CHECK_OPEN (v4lelement);
GST_V4L_CHECK_OVERLAY (v4lelement);
vwin.x = x;
vwin.y = y;
vwin.width = w;
vwin.height = h;
vwin.flags = 0;
if (clips && !(v4lelement->vcap.type & VID_TYPE_CLIPPING)) {
GST_DEBUG_OBJECT (v4lelement, "Device \'%s\' doesn't do clipping",
v4lelement->videodev ? v4lelement->videodev : "/dev/video");
vwin.clips = 0;
} else {
vwin.clips = clips;
vwin.clipcount = num_clips;
}
if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &vwin) < 0) {
GST_ELEMENT_ERROR (v4lelement, RESOURCE, TOO_LAZY, (NULL),
("Failed to set the video window: %s", g_strerror (errno)));
return FALSE;
}
return TRUE;
}
/******************************************************
* gst_v4l_enable_overlay():
* enables/disables actual video overlay display
* return value: TRUE on success, FALSE on error
******************************************************/
gboolean
gst_v4l_enable_overlay (GstV4lElement * v4lelement, gboolean enable)
{
gint doit = enable ? 1 : 0;
GST_DEBUG_OBJECT (v4lelement, "%s overlay",
enable ? "enabling" : "disabling");
GST_V4L_CHECK_OPEN (v4lelement);
GST_V4L_CHECK_OVERLAY (v4lelement);
if (ioctl (v4lelement->video_fd, VIDIOCCAPTURE, &doit) < 0) {
GST_ELEMENT_ERROR (v4lelement, RESOURCE, TOO_LAZY, (NULL),
("Failed to %s overlay display: %s",
enable ? "enable" : "disable", g_strerror (errno)));
return FALSE;
}
return TRUE;
}

View file

@ -144,17 +144,6 @@ gboolean gst_v4l_set_audio (GstV4lElement *v4lelement,
GstV4lAudioType type,
gint value);
/* overlay */
gboolean gst_v4l_set_overlay (GstV4lElement *v4lelement);
gboolean gst_v4l_set_window (GstElement *element,
gint x, gint y,
gint w, gint h,
struct video_clip *clips,
gint num_clips);
gboolean gst_v4l_enable_overlay (GstV4lElement *v4lelement,
gboolean enable);
#ifdef __cplusplus
}
#endif /* __cplusplus */