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:15 +00:00
parent b41cdefc05
commit 8033e68ba9
9 changed files with 188 additions and 229 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,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 \

View file

@ -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",

View file

@ -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;

View file

@ -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 {

View file

@ -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)
{
GstXWindowListener *xwin = gst_x_window_listener_new (NULL,
(MapWindowFunc) gst_v4l2_enable_overlay,
(SetWindowFunc) gst_v4l2_set_window,
(gpointer) v4l2element);
v4l2element->overlay = xwin;
v4l2element->xwindow_id = 0;
return xwin;
}
void
gst_v4l2_xoverlay_free (GstV4l2Element * v4l2element)
{
gst_v4l2_xoverlay_close (v4l2element);
g_object_unref (G_OBJECT (v4l2element->overlay));
v4l2element->overlay = NULL;
}
void
gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
{
GstXWindowListener *xwin = v4l2element->overlay;
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;
if (xwin) {
xwin->display_name = g_strdup (v4l2element->display);
/* we need a display, obviously */
if (!name || !(dpy = XOpenDisplay (name))) {
GST_WARNING ("No $DISPLAY set or failed to open - no overlay");
return;
}
if (v4l2element->xwindow_id != 0 &&
xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, v4l2element->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 (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);
if (id == 0) {
GST_WARNING ("Did not find XvPortID for device - no overlay");
XCloseDisplay (dpy);
return;
}
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_close (GstV4l2Element * v4l2element)
{
GstXWindowListener *xwin = v4l2element->overlay;
GstV4l2Xv *v4l2xv = v4l2element->xv;
if (xwin != NULL) {
if (v4l2element->xwindow_id != 0 &&
xwin->display_name && xwin->display_name[0] == ':') {
gst_x_window_listener_set_xid (xwin, 0);
}
if (!v4l2element->xv)
return;
g_free (xwin->display_name);
xwin->display_name = NULL;
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;
}
static gboolean
idle_refresh (gpointer data)
{
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (data);
GstV4l2Xv *v4l2xv = v4l2element->xv;
XWindowAttributes attr;
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);
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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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__ */