mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
V4L2 ported to 0.10.
Original commit message from CVS: V4L2 ported to 0.10.
This commit is contained in:
parent
87da9d5115
commit
c0dbf25683
18 changed files with 1524 additions and 1420 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
2006-03-11 Edgard Lima <edgard.lima@indt.org.br>
|
||||||
|
|
||||||
|
* configure.ac:
|
||||||
|
* sys/Makefile.am:
|
||||||
|
* sys/v4l2/Makefile.am:
|
||||||
|
* sys/v4l2/gstv4l2.c:
|
||||||
|
* sys/v4l2/gstv4l2colorbalance.h:
|
||||||
|
* sys/v4l2/gstv4l2element.c:
|
||||||
|
* sys/v4l2/gstv4l2element.h:
|
||||||
|
* sys/v4l2/gstv4l2src.c:
|
||||||
|
* sys/v4l2/gstv4l2src.h:
|
||||||
|
* sys/v4l2/gstv4l2tuner.c:
|
||||||
|
* sys/v4l2/gstv4l2tuner.h:
|
||||||
|
* sys/v4l2/gstv4l2xoverlay.c:
|
||||||
|
* sys/v4l2/gstv4l2xoverlay.h:
|
||||||
|
* sys/v4l2/v4l2_calls.c:
|
||||||
|
* sys/v4l2/v4l2_calls.h:
|
||||||
|
* sys/v4l2/v4l2src_calls.c:
|
||||||
|
* sys/v4l2/v4l2src_calls.h:
|
||||||
|
V4L2 ported to 0.10.
|
||||||
|
|
||||||
2006-03-11 Tim-Philipp Müller <tim at centricular dot net>
|
2006-03-11 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
92
configure.ac
92
configure.ac
|
@ -641,6 +641,97 @@ GST_CHECK_FEATURE(TAGLIB, [taglib ID3v2 tag writer], taglib, [
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl *** XVideo ***
|
||||||
|
dnl Look for the PIC library first, Debian requires it.
|
||||||
|
dnl Check debian-devel archives for gory details.
|
||||||
|
dnl 20020110:
|
||||||
|
dnl At the moment XFree86 doesn't distribute shared libXv due
|
||||||
|
dnl to unstable API. On many platforms you CAN NOT link a shared
|
||||||
|
dnl lib to a static non-PIC lib. This is what the xvideo GStreamer
|
||||||
|
dnl plug-in wants to do. So Debian distributes a PIC compiled
|
||||||
|
dnl version of the static lib for plug-ins to link to when it is
|
||||||
|
dnl inappropriate to link the main application to libXv directly.
|
||||||
|
dnl FIXME: add check if this platform can support linking to a
|
||||||
|
dnl non-PIC libXv, if not then don not use Xv.
|
||||||
|
dnl FIXME: perhaps warn user if they have a shared libXv since
|
||||||
|
dnl this is an error until XFree86 starts shipping one
|
||||||
|
|
||||||
|
dnl Check for Xv extension
|
||||||
|
translit(dnm, m, l) AM_CONDITIONAL(USE_XVIDEO, true)
|
||||||
|
GST_CHECK_FEATURE(XVIDEO, [X11 XVideo extensions],
|
||||||
|
[xvimagesink], [
|
||||||
|
if test x$HAVE_X = xyes; then
|
||||||
|
AC_CHECK_LIB(Xv_pic, XvQueryExtension,
|
||||||
|
HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
|
||||||
|
$X_LIBS -lXext)
|
||||||
|
|
||||||
|
if test x$HAVE_XVIDEO = xyes; then
|
||||||
|
XVIDEO_LIBS="-lXv_pic -lXext"
|
||||||
|
AC_SUBST(XVIDEO_LIBS)
|
||||||
|
else
|
||||||
|
dnl try again using something else if we didn't find it first
|
||||||
|
if test x$HAVE_XVIDEO = xno; then
|
||||||
|
AC_CHECK_LIB(Xv, XvQueryExtension,
|
||||||
|
HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
|
||||||
|
$X_LIBS -lXext)
|
||||||
|
|
||||||
|
if test x$HAVE_XVIDEO = xyes; then
|
||||||
|
XVIDEO_LIBS="-lXv -lXext"
|
||||||
|
AC_SUBST(XVIDEO_LIBS)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl *** Video 4 Linux 2 ***
|
||||||
|
dnl for information about the header/define, see sys/v4l2/gstv4l2element.h
|
||||||
|
dnl renamed to GST_V4L2 because of some conflict with kernel headers
|
||||||
|
translit(dnm, m, l) AM_CONDITIONAL(USE_GST_V4L2, true)
|
||||||
|
GST_CHECK_FEATURE(GST_V4L2, [Video 4 Linux 2], v4l2src, [
|
||||||
|
HAVE_GST_V4L2="no"
|
||||||
|
if test "$HAVE_X" = "yes"
|
||||||
|
then
|
||||||
|
AC_MSG_CHECKING([Checking for uptodate v4l2 installation])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#define _LINUX_TIME_H
|
||||||
|
#define __user
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#if defined(V4L2_MAJOR_VERSION) || defined(V4L2_MINOR_VERSION)
|
||||||
|
#error too early v4l2 version or no v4l2 at all
|
||||||
|
#endif
|
||||||
|
], [
|
||||||
|
return 0;
|
||||||
|
], [ HAVE_GST_V4L2="yes" && AC_MSG_RESULT(yes)],
|
||||||
|
[ HAVE_GST_V4L2="no" && AC_MSG_RESULT(no) &&
|
||||||
|
AC_CHECK_HEADER(linux/videodev2.h,
|
||||||
|
[ AC_MSG_WARN([video4linux2 headers were found, but they're old. Please update v4l2 to compile the v4l2 plugins])],
|
||||||
|
[ AC_MSG_WARN([video4linux2 was not found])])
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
dnl check for missing v4l2_buffer declaration (see #135919)
|
||||||
|
if [ test x$HAVE_GST_V4L2 = xyes ]; then
|
||||||
|
MISSING_DECL=0
|
||||||
|
AC_MSG_CHECKING(struct v4l2_buffer declaration)
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#define _LINUX_TIME_H
|
||||||
|
#define __user
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
],[
|
||||||
|
struct v4l2_buffer buf;
|
||||||
|
buf.index = 0;
|
||||||
|
return 0;
|
||||||
|
], [ AC_MSG_RESULT(yes) ], [ MISSING_DECL=1 && AC_MSG_RESULT(no) ])
|
||||||
|
if [ test x$MISSING_DECL = x1 ]; then
|
||||||
|
AC_DEFINE(GST_V4L2_MISSING_BUFDECL, 1, [struct v4l2_buffer missing])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
dnl also add builddir include for enumtypes and marshal
|
dnl also add builddir include for enumtypes and marshal
|
||||||
GST_CFLAGS="-I\$(top_srcdir)/gst-libs -I\$(top_builddir)/gst-libs $GST_CFLAGS $GST_ERROR"
|
GST_CFLAGS="-I\$(top_srcdir)/gst-libs -I\$(top_builddir)/gst-libs $GST_CFLAGS $GST_ERROR"
|
||||||
|
@ -716,6 +807,7 @@ gst/xingheader/Makefile
|
||||||
sys/Makefile
|
sys/Makefile
|
||||||
sys/glsink/Makefile
|
sys/glsink/Makefile
|
||||||
sys/ximagesrc/Makefile
|
sys/ximagesrc/Makefile
|
||||||
|
sys/v4l2/Makefile
|
||||||
examples/Makefile
|
examples/Makefile
|
||||||
examples/directfb/Makefile
|
examples/directfb/Makefile
|
||||||
ext/Makefile
|
ext/Makefile
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
# QCAM_DIR=
|
# QCAM_DIR=
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if USE_GST_V4L2
|
if USE_GST_V4L2
|
||||||
# V4L2_DIR=v4l2
|
V4L2_DIR=v4l2
|
||||||
# else
|
else
|
||||||
# V4L2_DIR=
|
V4L2_DIR=
|
||||||
# endif
|
endif
|
||||||
|
|
||||||
# if USE_VCD
|
# if USE_VCD
|
||||||
# VCD_DIR=vcd
|
# VCD_DIR=vcd
|
||||||
|
@ -40,6 +40,6 @@ else
|
||||||
XIMAGESRC_DIR=
|
XIMAGESRC_DIR=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS = $(GL_DIR) $(XIMAGESRC_DIR)
|
SUBDIRS = $(GL_DIR) $(XIMAGESRC_DIR) $(V4L2_DIR)
|
||||||
|
|
||||||
DIST_SUBDIRS = glsink ximagesrc
|
DIST_SUBDIRS = glsink ximagesrc v4l2
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
plugin_LTLIBRARIES = \
|
plugin_LTLIBRARIES = libgstvideo4linux2.la
|
||||||
libgstvideo4linux2.la
|
|
||||||
|
|
||||||
if USE_XVIDEO
|
if USE_XVIDEO
|
||||||
xv_source = gstv4l2xoverlay.c
|
xv_source = gstv4l2xoverlay.c
|
||||||
|
@ -10,18 +9,19 @@ xv_libs =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libgstvideo4linux2_la_SOURCES = \
|
libgstvideo4linux2_la_SOURCES = \
|
||||||
gstv4l2element.c v4l2_calls.c \
|
|
||||||
gstv4l2src.c v4l2src_calls.c \
|
|
||||||
gstv4l2.c \
|
gstv4l2.c \
|
||||||
|
gstv4l2colorbalance.c \
|
||||||
|
gstv4l2element.c \
|
||||||
|
gstv4l2src.c \
|
||||||
gstv4l2tuner.c \
|
gstv4l2tuner.c \
|
||||||
$(xv_source) \
|
v4l2_calls.c \
|
||||||
gstv4l2colorbalance.c
|
v4l2src_calls.c $(xv_source)
|
||||||
libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS)
|
|
||||||
|
libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_LIBS_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
|
||||||
|
libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstvideo4linux2_la_LIBADD = \
|
libgstvideo4linux2_la_LIBADD = \
|
||||||
$(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la
|
-lgstinterfaces-$(GST_MAJORMINOR) \
|
||||||
libgstvideo4linux2_la_LDFLAGS = \
|
$(GST_BASE_LIBS) $(GST_LIBS) $(xv_libs)
|
||||||
$(GST_PLUGIN_LDFLAGS) \
|
|
||||||
$(xv_libs)
|
|
||||||
|
|
||||||
noinst_HEADERS = gstv4l2element.h v4l2_calls.h \
|
noinst_HEADERS = gstv4l2element.h v4l2_calls.h \
|
||||||
gstv4l2src.h v4l2src_calls.h \
|
gstv4l2src.h v4l2src_calls.h \
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/* G-Streamer Video4linux2 video-capture plugin
|
/* GStreamer
|
||||||
* Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
*
|
||||||
|
* gstv4l2.c: plugin for v4l2 elements
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -21,20 +24,31 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
#include "gst/gst-i18n-plugin.h"
|
#include "gst/gst-i18n-plugin.h"
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include "gstv4l2element.h"
|
#include "gstv4l2element.h"
|
||||||
#include "gstv4l2src.h"
|
#include "gstv4l2src.h"
|
||||||
|
/* #include "gstv4l2jpegsrc.h" */
|
||||||
|
/* #include "gstv4l2mjpegsrc.h" */
|
||||||
|
/* #include "gstv4l2mjpegsink.h" */
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY (v4l2_debug); /* used in v4l2_calls.c and v4l2src_calls.c */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
if (!gst_element_register (plugin, "v4l2element",
|
GST_DEBUG_CATEGORY_INIT (v4l2_debug, "v4l2", 0, "V4L2 API calls");
|
||||||
GST_RANK_NONE, GST_TYPE_V4L2ELEMENT) ||
|
|
||||||
!gst_element_register (plugin, "v4l2src",
|
if (!gst_element_register (plugin, "v4l2src", GST_RANK_NONE,
|
||||||
GST_RANK_NONE, GST_TYPE_V4L2SRC))
|
GST_TYPE_V4L2SRC))
|
||||||
|
/* !gst_element_register (plugin, "v4l2jpegsrc", */
|
||||||
|
/* GST_RANK_NONE, GST_TYPE_V4L2JPEGSRC) || */
|
||||||
|
/* !gst_element_register (plugin, "v4l2mjpegsrc", */
|
||||||
|
/* GST_RANK_NONE, GST_TYPE_V4L2MJPEGSRC) || */
|
||||||
|
/* !gst_element_register (plugin, "v4l2mjpegsink", */
|
||||||
|
/* GST_RANK_NONE, GST_TYPE_V4L2MJPEGSINK)) */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
#ifdef ENABLE_NLS
|
#ifdef ENABLE_NLS
|
||||||
|
@ -48,5 +62,5 @@ plugin_init (GstPlugin * plugin)
|
||||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||||
GST_VERSION_MINOR,
|
GST_VERSION_MINOR,
|
||||||
"video4linux2",
|
"video4linux2",
|
||||||
"elements for Video 4 Linux 2",
|
"elements for Video 4 Linux",
|
||||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define __GST_V4L2_COLOR_BALANCE_H__
|
#define __GST_V4L2_COLOR_BALANCE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/colorbalance/colorbalance.h>
|
#include <gst/interfaces/colorbalance.h>
|
||||||
#include "v4l2_calls.h"
|
#include "v4l2_calls.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -32,10 +32,10 @@ G_BEGIN_DECLS
|
||||||
(gst_v4l2_color_balance_channel_get_type ())
|
(gst_v4l2_color_balance_channel_get_type ())
|
||||||
#define GST_V4L2_COLOR_BALANCE_CHANNEL(obj) \
|
#define GST_V4L2_COLOR_BALANCE_CHANNEL(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
|
||||||
GstV4l2ColorBalanceChannel))
|
GstV4l2ColorBalanceChannel))
|
||||||
#define GST_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
|
#define GST_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
|
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
|
||||||
GstV4l2ColorBalanceChannelClass))
|
GstV4l2ColorBalanceChannelClass))
|
||||||
#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL(obj) \
|
#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL))
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL))
|
||||||
#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
|
#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
|
||||||
|
@ -51,8 +51,8 @@ typedef struct _GstV4l2ColorBalanceChannelClass {
|
||||||
GstColorBalanceChannelClass parent;
|
GstColorBalanceChannelClass parent;
|
||||||
} GstV4l2ColorBalanceChannelClass;
|
} GstV4l2ColorBalanceChannelClass;
|
||||||
|
|
||||||
GType gst_v4l2_color_balance_channel_get_type (void);
|
GType gst_v4l2_color_balance_channel_get_type (void);
|
||||||
|
|
||||||
void gst_v4l2_color_balance_interface_init (GstColorBalanceClass *klass);
|
void gst_v4l2_color_balance_interface_init (GstColorBalanceClass *klass);
|
||||||
|
|
||||||
#endif /* __GST_V4L2_COLOR_BALANCE_H__ */
|
#endif /* __GST_V4L2_COLOR_BALANCE_H__ */
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/* G-Streamer generic V4L2 element
|
/* GStreamer
|
||||||
* Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
*
|
||||||
|
* gstv4l2element.c: base class for V4L2 elements
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -25,6 +28,9 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gst/interfaces/propertyprobe.h>
|
||||||
|
|
||||||
#include "v4l2_calls.h"
|
#include "v4l2_calls.h"
|
||||||
#include "gstv4l2tuner.h"
|
#include "gstv4l2tuner.h"
|
||||||
|
@ -33,55 +39,37 @@
|
||||||
#endif
|
#endif
|
||||||
#include "gstv4l2colorbalance.h"
|
#include "gstv4l2colorbalance.h"
|
||||||
|
|
||||||
#include <gst/propertyprobe/propertyprobe.h>
|
|
||||||
|
|
||||||
/* elementfactory details */
|
|
||||||
static GstElementDetails gst_v4l2element_details = {
|
|
||||||
"Generic video4linux2 Element",
|
|
||||||
"Generic/Video",
|
|
||||||
"Generic plugin for handling common video4linux2 calls",
|
|
||||||
"Ronald Bultje <rbultje@ronald.bitfreak.net>"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* V4l2Element signals and args */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* FILL ME */
|
|
||||||
SIGNAL_OPEN,
|
|
||||||
SIGNAL_CLOSE,
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
PROP_0,
|
||||||
ARG_DEVICE,
|
PROP_DEVICE,
|
||||||
ARG_DEVICE_NAME,
|
PROP_DEVICE_NAME,
|
||||||
ARG_NORM,
|
PROP_FLAGS,
|
||||||
ARG_CHANNEL,
|
PROP_STD,
|
||||||
ARG_FREQUENCY,
|
PROP_INPUT,
|
||||||
ARG_FLAGS
|
PROP_FREQUENCY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void gst_v4l2element_class_init (GstV4l2ElementClass * klass);
|
static void gst_v4l2element_init_interfaces (GType type);
|
||||||
static void gst_v4l2element_base_init (GstV4l2ElementClass * klass);
|
|
||||||
static void gst_v4l2element_init (GstV4l2Element * v4lelement);
|
GST_BOILERPLATE_FULL (GstV4l2Element, gst_v4l2element, GstPushSrc,
|
||||||
static void gst_v4l2element_dispose (GObject * object);
|
GST_TYPE_PUSH_SRC, gst_v4l2element_init_interfaces)
|
||||||
static void gst_v4l2element_set_property (GObject * object,
|
|
||||||
|
|
||||||
|
static void gst_v4l2element_dispose (GObject * object);
|
||||||
|
static void gst_v4l2element_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_v4l2element_get_property (GObject * object,
|
static void gst_v4l2element_get_property (GObject * object,
|
||||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||||
static GstStateChangeReturn
|
static gboolean gst_v4l2element_start (GstBaseSrc * src);
|
||||||
gst_v4l2element_change_state (GstElement * element, GstStateChange transition);
|
static gboolean gst_v4l2element_stop (GstBaseSrc * src);
|
||||||
|
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static gboolean
|
||||||
static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 };
|
gst_v4l2_iface_supported (GstImplementsInterface * iface,
|
||||||
|
GType iface_type)
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_v4l2_iface_supported (GstImplementsInterface * iface, GType iface_type)
|
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (iface);
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (iface);
|
||||||
|
|
||||||
|
@ -104,7 +92,6 @@ gst_v4l2_iface_supported (GstImplementsInterface * iface, GType iface_type)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_interface_init (GstImplementsInterfaceClass * klass)
|
gst_v4l2_interface_init (GstImplementsInterfaceClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -112,7 +99,6 @@ gst_v4l2_interface_init (GstImplementsInterfaceClass * klass)
|
||||||
klass->supported = gst_v4l2_iface_supported;
|
klass->supported = gst_v4l2_iface_supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const GList *
|
static const GList *
|
||||||
gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
|
gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +119,7 @@ gst_v4l2_class_probe_devices (GstV4l2ElementClass * klass, gboolean check)
|
||||||
static GList *devices = NULL;
|
static GList *devices = NULL;
|
||||||
|
|
||||||
if (!init && !check) {
|
if (!init && !check) {
|
||||||
gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
|
gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
|
||||||
gint base, n, fd;
|
gint base, n, fd;
|
||||||
|
|
||||||
while (devices) {
|
while (devices) {
|
||||||
|
@ -148,8 +134,7 @@ gst_v4l2_class_probe_devices (GstV4l2ElementClass * klass, gboolean check)
|
||||||
for (n = 0; n < 64; n++) {
|
for (n = 0; n < 64; n++) {
|
||||||
for (base = 0; dev_base[base] != NULL; base++) {
|
for (base = 0; dev_base[base] != NULL; base++) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
gchar *device = g_strdup_printf ("%s%d",
|
gchar *device = g_strdup_printf ("%s%d", dev_base[base], n);
|
||||||
dev_base[base], n);
|
|
||||||
|
|
||||||
/* does the /dev/ entry exist at all? */
|
/* does the /dev/ entry exist at all? */
|
||||||
if (stat (device, &s) == 0) {
|
if (stat (device, &s) == 0) {
|
||||||
|
@ -181,7 +166,7 @@ gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
|
||||||
GstV4l2ElementClass *klass = GST_V4L2ELEMENT_GET_CLASS (probe);
|
GstV4l2ElementClass *klass = GST_V4L2ELEMENT_GET_CLASS (probe);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_DEVICE:
|
case PROP_DEVICE:
|
||||||
gst_v4l2_class_probe_devices (klass, FALSE);
|
gst_v4l2_class_probe_devices (klass, FALSE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -198,7 +183,7 @@ gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_DEVICE:
|
case PROP_DEVICE:
|
||||||
ret = !gst_v4l2_class_probe_devices (klass, TRUE);
|
ret = !gst_v4l2_class_probe_devices (klass, TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -243,7 +228,7 @@ gst_v4l2_probe_get_values (GstPropertyProbe * probe,
|
||||||
GValueArray *array = NULL;
|
GValueArray *array = NULL;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_DEVICE:
|
case PROP_DEVICE:
|
||||||
array = gst_v4l2_class_list_devices (klass);
|
array = gst_v4l2_class_list_devices (klass);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -254,7 +239,6 @@ gst_v4l2_probe_get_values (GstPropertyProbe * probe,
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_property_probe_interface_init (GstPropertyProbeInterface * iface)
|
gst_v4l2_property_probe_interface_init (GstPropertyProbeInterface * iface)
|
||||||
{
|
{
|
||||||
|
@ -264,75 +248,6 @@ gst_v4l2_property_probe_interface_init (GstPropertyProbeInterface * iface)
|
||||||
iface->get_values = gst_v4l2_probe_get_values;
|
iface->get_values = gst_v4l2_probe_get_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GType
|
|
||||||
gst_v4l2element_get_type (void)
|
|
||||||
{
|
|
||||||
static GType v4l2element_type = 0;
|
|
||||||
|
|
||||||
if (!v4l2element_type) {
|
|
||||||
static const GTypeInfo v4l2element_info = {
|
|
||||||
sizeof (GstV4l2ElementClass),
|
|
||||||
(GBaseInitFunc) gst_v4l2element_base_init,
|
|
||||||
NULL,
|
|
||||||
(GClassInitFunc) gst_v4l2element_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstV4l2Element),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_v4l2element_init,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2iface_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2_tuner_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2_tuner_interface_init,
|
|
||||||
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,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2_propertyprobe_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2_property_probe_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
v4l2element_type =
|
|
||||||
g_type_register_static (GST_TYPE_ELEMENT,
|
|
||||||
"GstV4l2Element", &v4l2element_info, 0);
|
|
||||||
|
|
||||||
g_type_add_interface_static (v4l2element_type,
|
|
||||||
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,
|
|
||||||
GST_TYPE_PROPERTY_PROBE, &v4l2_propertyprobe_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
return v4l2element_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
|
#define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
|
||||||
GType
|
GType
|
||||||
gst_v4l2_device_get_type (void)
|
gst_v4l2_device_get_type (void)
|
||||||
|
@ -341,16 +256,13 @@ gst_v4l2_device_get_type (void)
|
||||||
|
|
||||||
if (v4l2_device_type == 0) {
|
if (v4l2_device_type == 0) {
|
||||||
static const GFlagsValue values[] = {
|
static const GFlagsValue values[] = {
|
||||||
{V4L2_CAP_VIDEO_CAPTURE, "CAPTURE",
|
{V4L2_CAP_VIDEO_CAPTURE, "CAPTURE", "Device can capture"},
|
||||||
"Device can capture"},
|
{V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK", "Device can playback"},
|
||||||
{V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK",
|
{V4L2_CAP_VIDEO_OVERLAY, "OVERLAY", "Device can do overlay"},
|
||||||
"Device can playback"},
|
|
||||||
{V4L2_CAP_VIDEO_OVERLAY, "OVERLAY",
|
{V4L2_CAP_TUNER, "TUNER", "Device has a tuner"},
|
||||||
"Device can do overlay"},
|
{V4L2_CAP_AUDIO, "AUDIO", "Device handles audio"},
|
||||||
{V4L2_CAP_TUNER, "TUNER",
|
|
||||||
"Device has a tuner"},
|
|
||||||
{V4L2_CAP_AUDIO, "AUDIO",
|
|
||||||
"Device handles audio"},
|
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -362,73 +274,108 @@ gst_v4l2_device_get_type (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2element_base_init (GstV4l2ElementClass * klass)
|
gst_v4l2element_init_interfaces (GType type)
|
||||||
{
|
{
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
static const GInterfaceInfo v4l2iface_info = {
|
||||||
|
(GInterfaceInitFunc) gst_v4l2_interface_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
static const GInterfaceInfo v4l2_tuner_info = {
|
||||||
|
(GInterfaceInitFunc) gst_v4l2_tuner_interface_init,
|
||||||
|
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,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
static const GInterfaceInfo v4l2_propertyprobe_info = {
|
||||||
|
(GInterfaceInitFunc) gst_v4l2_property_probe_interface_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
g_type_add_interface_static (type,
|
||||||
|
GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
|
||||||
|
g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
|
||||||
|
#ifdef HAVE_XVIDEO
|
||||||
|
g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
|
||||||
|
#endif
|
||||||
|
g_type_add_interface_static (type,
|
||||||
|
GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
|
||||||
|
g_type_add_interface_static (type,
|
||||||
|
GST_TYPE_PROPERTY_PROBE, &v4l2_propertyprobe_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_v4l2element_base_init (gpointer g_class)
|
||||||
|
{
|
||||||
|
GstV4l2ElementClass *klass = GST_V4L2ELEMENT_CLASS (g_class);
|
||||||
|
|
||||||
klass->devices = NULL;
|
klass->devices = NULL;
|
||||||
|
|
||||||
gst_element_class_set_details (gstelement_class, &gst_v4l2element_details);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2element_class_init (GstV4l2ElementClass * klass)
|
gst_v4l2element_class_init (GstV4l2ElementClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class;
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
GstBaseSrcClass *basesrc_class;
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
basesrc_class = (GstBaseSrcClass *) klass;
|
||||||
g_object_class_install_property (gobject_class, ARG_DEVICE,
|
|
||||||
g_param_spec_string ("device", "Device", "Device location",
|
|
||||||
NULL, G_PARAM_READWRITE));
|
|
||||||
g_object_class_install_property (gobject_class, ARG_DEVICE_NAME,
|
|
||||||
g_param_spec_string ("device_name", "Device name",
|
|
||||||
"Name of the device", NULL, G_PARAM_READABLE));
|
|
||||||
g_object_class_install_property (gobject_class, ARG_FLAGS,
|
|
||||||
g_param_spec_flags ("flags", "Flags", "Device type flags",
|
|
||||||
GST_TYPE_V4L2_DEVICE_FLAGS, 0, G_PARAM_READABLE));
|
|
||||||
g_object_class_install_property (gobject_class, ARG_NORM,
|
|
||||||
g_param_spec_string ("norm", "norm",
|
|
||||||
"Norm to use", NULL, G_PARAM_READWRITE));
|
|
||||||
g_object_class_install_property (gobject_class, ARG_CHANNEL,
|
|
||||||
g_param_spec_string ("channel", "channel",
|
|
||||||
"input/output to switch to", NULL, G_PARAM_READWRITE));
|
|
||||||
g_object_class_install_property (gobject_class, ARG_FREQUENCY,
|
|
||||||
g_param_spec_ulong ("frequency", "frequency",
|
|
||||||
"frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
|
|
||||||
|
|
||||||
/* signals */
|
|
||||||
gst_v4l2element_signals[SIGNAL_OPEN] =
|
|
||||||
g_signal_new ("open", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
|
||||||
G_STRUCT_OFFSET (GstV4l2ElementClass, open),
|
|
||||||
NULL, NULL, g_cclosure_marshal_VOID__STRING,
|
|
||||||
G_TYPE_NONE, 1, G_TYPE_STRING);
|
|
||||||
gst_v4l2element_signals[SIGNAL_CLOSE] =
|
|
||||||
g_signal_new ("close", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
|
||||||
G_STRUCT_OFFSET (GstV4l2ElementClass, close),
|
|
||||||
NULL, NULL, g_cclosure_marshal_VOID__STRING,
|
|
||||||
G_TYPE_NONE, 1, G_TYPE_STRING);
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_v4l2element_set_property;
|
gobject_class->set_property = gst_v4l2element_set_property;
|
||||||
gobject_class->get_property = gst_v4l2element_get_property;
|
gobject_class->get_property = gst_v4l2element_get_property;
|
||||||
gobject_class->dispose = gst_v4l2element_dispose;
|
|
||||||
|
|
||||||
gstelement_class->change_state = gst_v4l2element_change_state;
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE,
|
||||||
|
g_param_spec_string ("device", "Device", "Device location",
|
||||||
|
NULL, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME,
|
||||||
|
g_param_spec_string ("device_name", "Device name", "Name of the device",
|
||||||
|
NULL, G_PARAM_READABLE));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
|
||||||
|
g_param_spec_flags ("flags", "Flags", "Device type flags",
|
||||||
|
GST_TYPE_V4L2_DEVICE_FLAGS, 0, G_PARAM_READABLE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_STD,
|
||||||
|
g_param_spec_string ("std", "std",
|
||||||
|
"standard (norm) to use", NULL, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_INPUT,
|
||||||
|
g_param_spec_string ("input", "input",
|
||||||
|
"input/output (channel) to switch to", NULL, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_FREQUENCY,
|
||||||
|
g_param_spec_ulong ("frequency", "frequency",
|
||||||
|
"frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
basesrc_class->start = gst_v4l2element_start;
|
||||||
|
basesrc_class->stop = gst_v4l2element_stop;
|
||||||
|
|
||||||
|
gobject_class->dispose = gst_v4l2element_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2element_init (GstV4l2Element * v4l2element)
|
gst_v4l2element_init (GstV4l2Element * v4l2element, GstV4l2ElementClass * klass)
|
||||||
{
|
{
|
||||||
/* some default values */
|
/* some default values */
|
||||||
v4l2element->video_fd = -1;
|
v4l2element->video_fd = -1;
|
||||||
v4l2element->buffer = NULL;
|
v4l2element->buffer = NULL;
|
||||||
v4l2element->device = g_strdup ("/dev/video0");
|
v4l2element->videodev = g_strdup ("/dev/video0");
|
||||||
|
|
||||||
v4l2element->channels = NULL;
|
v4l2element->stds = NULL;
|
||||||
v4l2element->norms = NULL;
|
v4l2element->inputs = NULL;
|
||||||
v4l2element->colors = NULL;
|
v4l2element->colors = NULL;
|
||||||
|
|
||||||
|
v4l2element->xwindow_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,35 +384,29 @@ gst_v4l2element_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
|
||||||
|
|
||||||
g_free (v4l2element->device);
|
if (v4l2element->videodev) {
|
||||||
v4l2element->device = NULL;
|
g_free (v4l2element->videodev);
|
||||||
g_free (v4l2element->norm);
|
v4l2element->videodev = NULL;
|
||||||
v4l2element->norm = NULL;
|
}
|
||||||
g_free (v4l2element->channel);
|
|
||||||
v4l2element->channel = NULL;
|
|
||||||
|
|
||||||
if (((GObjectClass *) parent_class)->dispose)
|
if (((GObjectClass *) parent_class)->dispose)
|
||||||
((GObjectClass *) parent_class)->dispose (object);
|
((GObjectClass *) parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2element_set_property (GObject * object,
|
gst_v4l2element_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element;
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_V4L2ELEMENT (object));
|
|
||||||
v4l2element = GST_V4L2ELEMENT (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_DEVICE:
|
case PROP_DEVICE:
|
||||||
if (!GST_V4L2_IS_OPEN (v4l2element)) {
|
if (v4l2element->videodev)
|
||||||
if (v4l2element->device)
|
g_free (v4l2element->videodev);
|
||||||
g_free (v4l2element->device);
|
v4l2element->videodev = g_strdup (g_value_get_string (value));
|
||||||
v4l2element->device = g_value_dup_string (value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ARG_NORM:
|
case PROP_STD:
|
||||||
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
||||||
GstTuner *tuner = GST_TUNER (v4l2element);
|
GstTuner *tuner = GST_TUNER (v4l2element);
|
||||||
GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner,
|
GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner,
|
||||||
|
@ -475,12 +416,12 @@ gst_v4l2element_set_property (GObject * object,
|
||||||
gst_tuner_set_norm (tuner, norm);
|
gst_tuner_set_norm (tuner, norm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_free (v4l2element->norm);
|
g_free (v4l2element->std);
|
||||||
v4l2element->norm = g_value_dup_string (value);
|
v4l2element->std = g_value_dup_string (value);
|
||||||
g_object_notify (object, "norm");
|
g_object_notify (object, "std");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_CHANNEL:
|
case PROP_INPUT:
|
||||||
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
||||||
GstTuner *tuner = GST_TUNER (v4l2element);
|
GstTuner *tuner = GST_TUNER (v4l2element);
|
||||||
GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
|
GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
|
||||||
|
@ -490,12 +431,12 @@ gst_v4l2element_set_property (GObject * object,
|
||||||
gst_tuner_set_channel (tuner, channel);
|
gst_tuner_set_channel (tuner, channel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_free (v4l2element->channel);
|
g_free (v4l2element->input);
|
||||||
v4l2element->channel = g_value_dup_string (value);
|
v4l2element->input = g_value_dup_string (value);
|
||||||
g_object_notify (object, "channel");
|
g_object_notify (object, "input");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_FREQUENCY:
|
case PROP_FREQUENCY:
|
||||||
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
||||||
GstTuner *tuner = GST_TUNER (v4l2element);
|
GstTuner *tuner = GST_TUNER (v4l2element);
|
||||||
GstTunerChannel *channel = gst_tuner_get_channel (tuner);
|
GstTunerChannel *channel = gst_tuner_get_channel (tuner);
|
||||||
|
@ -520,39 +461,40 @@ static void
|
||||||
gst_v4l2element_get_property (GObject * object,
|
gst_v4l2element_get_property (GObject * object,
|
||||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element;
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_V4L2ELEMENT (object));
|
|
||||||
v4l2element = GST_V4L2ELEMENT (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_DEVICE:
|
case PROP_DEVICE:
|
||||||
g_value_set_string (value, v4l2element->device);
|
g_value_set_string (value, v4l2element->videodev);
|
||||||
break;
|
break;
|
||||||
case ARG_DEVICE_NAME:{
|
case PROP_DEVICE_NAME:{
|
||||||
gchar *new = NULL;
|
gchar *new = NULL;
|
||||||
|
|
||||||
if (GST_V4L2_IS_OPEN (v4l2element))
|
if (GST_V4L2_IS_OPEN (v4l2element))
|
||||||
new = v4l2element->vcap.card;
|
new = (gchar *) v4l2element->vcap.card;
|
||||||
g_value_set_string (value, new);
|
g_value_set_string (value, new);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARG_FLAGS:{
|
case PROP_FLAGS:{
|
||||||
guint flags = 0;
|
guint flags = 0;
|
||||||
|
|
||||||
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
if (GST_V4L2_IS_OPEN (v4l2element)) {
|
||||||
flags |= v4l2element->vcap.capabilities & 0x30007;
|
flags |= v4l2element->vcap.capabilities &
|
||||||
|
(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
|
||||||
|
V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
|
||||||
|
if (v4l2element->vcap.capabilities & V4L2_CAP_AUDIO)
|
||||||
|
flags |= V4L2_FBUF_CAP_CHROMAKEY;
|
||||||
}
|
}
|
||||||
g_value_set_flags (value, flags);
|
g_value_set_flags (value, flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARG_NORM:
|
case PROP_STD:
|
||||||
g_value_set_string (value, v4l2element->norm);
|
g_value_set_string (value, v4l2element->std);
|
||||||
break;
|
break;
|
||||||
case ARG_CHANNEL:
|
case PROP_INPUT:
|
||||||
g_value_set_string (value, v4l2element->channel);
|
g_value_set_string (value, v4l2element->input);
|
||||||
break;
|
break;
|
||||||
case ARG_FREQUENCY:
|
case PROP_FREQUENCY:
|
||||||
g_value_set_ulong (value, v4l2element->frequency);
|
g_value_set_ulong (value, v4l2element->frequency);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -561,48 +503,32 @@ gst_v4l2element_get_property (GObject * object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
static GstStateChangeReturn
|
gst_v4l2element_start (GstBaseSrc * src)
|
||||||
gst_v4l2element_change_state (GstElement * element, GstStateChange transition)
|
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element;
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (src);
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_V4L2ELEMENT (element), GST_STATE_CHANGE_FAILURE);
|
if (!gst_v4l2_open (v4l2element))
|
||||||
|
return FALSE;
|
||||||
v4l2element = GST_V4L2ELEMENT (element);
|
|
||||||
|
|
||||||
/* if going down into NULL state, close the device if it's open
|
|
||||||
* if going to READY, open the device (and set some options)
|
|
||||||
*/
|
|
||||||
switch (transition) {
|
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
|
||||||
if (!gst_v4l2_open (v4l2element))
|
|
||||||
return GST_STATE_CHANGE_FAILURE;
|
|
||||||
|
|
||||||
#ifdef HAVE_XVIDEO
|
#ifdef HAVE_XVIDEO
|
||||||
gst_v4l2_xoverlay_open (v4l2element);
|
gst_v4l2_xoverlay_start (v4l2element);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* emit a signal! whoopie! */
|
return TRUE;
|
||||||
g_signal_emit (G_OBJECT (v4l2element),
|
}
|
||||||
gst_v4l2element_signals[SIGNAL_OPEN], 0, v4l2element->device);
|
|
||||||
break;
|
static gboolean
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
gst_v4l2element_stop (GstBaseSrc * src)
|
||||||
#ifdef HAVE_XVIDEO
|
{
|
||||||
gst_v4l2_xoverlay_close (v4l2element);
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (src);
|
||||||
#endif
|
|
||||||
|
#ifdef HAVE_XVIDEO
|
||||||
if (!gst_v4l2_close (v4l2element))
|
gst_v4l2_xoverlay_stop (v4l2element);
|
||||||
return GST_STATE_CHANGE_FAILURE;
|
#endif
|
||||||
|
|
||||||
/* emit yet another signal! wheehee! */
|
if (!gst_v4l2_close (v4l2element))
|
||||||
g_signal_emit (G_OBJECT (v4l2element),
|
return FALSE;
|
||||||
gst_v4l2element_signals[SIGNAL_CLOSE], 0, v4l2element->device);
|
|
||||||
break;
|
return TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
|
||||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
|
||||||
|
|
||||||
return GST_STATE_CHANGE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/* G-Streamer generic V4L2 element
|
/* GStreamer
|
||||||
* Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
*
|
||||||
|
* gstv4l2element.h: base class for V4L2 elements
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -20,9 +23,6 @@
|
||||||
#ifndef __GST_V4L2ELEMENT_H__
|
#ifndef __GST_V4L2ELEMENT_H__
|
||||||
#define __GST_V4L2ELEMENT_H__
|
#define __GST_V4L2ELEMENT_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <gst/xwindowlistener/xwindowlistener.h>
|
|
||||||
|
|
||||||
/* Because of some really cool feature in video4linux1, also known as
|
/* Because of some really cool feature in video4linux1, also known as
|
||||||
* 'not including sys/types.h and sys/time.h', we had to include it
|
* 'not including sys/types.h and sys/time.h', we had to include it
|
||||||
* ourselves. In all their intelligence, these people decided to fix
|
* ourselves. In all their intelligence, these people decided to fix
|
||||||
|
@ -36,104 +36,87 @@
|
||||||
* errors here, check your linux/time.h && sys/time.h header setup.
|
* errors here, check your linux/time.h && sys/time.h header setup.
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <linux/types.h>
|
|
||||||
#define _LINUX_TIME_H
|
#define _LINUX_TIME_H
|
||||||
#define __user
|
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
/*
|
#include <gst/gst.h>
|
||||||
* See bug #135919, the Suse9 (and Mandrake10) videodev2 headers
|
#include <gst/base/gstpushsrc.h>
|
||||||
* contain a bug where (for userspace applications) the v4l2_buffer
|
|
||||||
* struct is not declared, so applications have to declare it.
|
|
||||||
* Declaration straightly ripped out from <linux/videodev2.h>.
|
|
||||||
*/
|
|
||||||
#ifdef GST_V4L2_MISSING_BUFDECL
|
|
||||||
struct v4l2_buffer
|
|
||||||
{
|
|
||||||
__u32 index;
|
|
||||||
enum v4l2_buf_type type;
|
|
||||||
__u32 bytesused;
|
|
||||||
__u32 flags;
|
|
||||||
enum v4l2_field field;
|
|
||||||
struct timeval timestamp;
|
|
||||||
struct v4l2_timecode timecode;
|
|
||||||
__u32 sequence;
|
|
||||||
|
|
||||||
/* memory location */
|
|
||||||
enum v4l2_memory memory;
|
|
||||||
union {
|
|
||||||
__u32 offset;
|
|
||||||
unsigned long userptr;
|
|
||||||
} m;
|
|
||||||
__u32 length;
|
|
||||||
|
|
||||||
__u32 reserved[2];
|
|
||||||
};
|
|
||||||
#endif /* GST_V4L2_MISSING_BUFDECL */
|
|
||||||
|
|
||||||
|
|
||||||
#define GST_TYPE_V4L2ELEMENT \
|
G_BEGIN_DECLS
|
||||||
(gst_v4l2element_get_type())
|
|
||||||
#define GST_V4L2ELEMENT(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_V4L2ELEMENT, GstV4l2Element))
|
|
||||||
#define GST_V4L2ELEMENT_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
|
|
||||||
#define GST_IS_V4L2ELEMENT(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_V4L2ELEMENT))
|
|
||||||
#define GST_IS_V4L2ELEMENT_CLASS(obj) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_V4L2ELEMENT))
|
|
||||||
#define GST_V4L2ELEMENT_GET_CLASS(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
|
|
||||||
|
|
||||||
|
#define GST_TYPE_V4L2ELEMENT \
|
||||||
|
(gst_v4l2element_get_type())
|
||||||
|
#define GST_V4L2ELEMENT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2ELEMENT,GstV4l2Element))
|
||||||
|
#define GST_V4L2ELEMENT_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2ELEMENT,GstV4l2ElementClass))
|
||||||
|
#define GST_IS_V4L2ELEMENT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2ELEMENT))
|
||||||
|
#define GST_IS_V4L2ELEMENT_CLASS(obj) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2ELEMENT))
|
||||||
|
#define GST_V4L2ELEMENT_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
|
||||||
|
|
||||||
typedef struct _GstV4l2Element GstV4l2Element;
|
typedef struct _GstV4l2Element GstV4l2Element;
|
||||||
typedef struct _GstV4l2ElementClass GstV4l2ElementClass;
|
typedef struct _GstV4l2ElementClass GstV4l2ElementClass;
|
||||||
typedef struct _GstV4l2Xv GstV4l2Xv;
|
typedef struct _GstV4l2Xv GstV4l2Xv;
|
||||||
|
|
||||||
struct _GstV4l2Element {
|
struct _GstV4l2Element {
|
||||||
GstElement element;
|
GstPushSrc element;
|
||||||
|
|
||||||
/* the video device */
|
/* the video device */
|
||||||
char *device;
|
char *videodev;
|
||||||
|
|
||||||
/* the video-device's file descriptor */
|
/* the video-device's file descriptor */
|
||||||
gint video_fd;
|
gint video_fd;
|
||||||
|
|
||||||
/* the video buffer (mmap()'ed) */
|
/* the video buffer (mmap()'ed) */
|
||||||
guint8 **buffer;
|
guint8 **buffer;
|
||||||
|
|
||||||
/* the video-device's capabilities */
|
/* the video device's capabilities */
|
||||||
struct v4l2_capability vcap;
|
struct v4l2_capability vcap;
|
||||||
|
|
||||||
/* the toys available to us */
|
/* the video device's window properties */
|
||||||
GList *channels;
|
struct v4l2_window vwin;
|
||||||
GList *norms;
|
|
||||||
GList *colors;
|
|
||||||
|
|
||||||
/* X-overlay */
|
/* some more info about the current input's capabilities */
|
||||||
GstV4l2Xv *xv;
|
struct v4l2_input vinput;
|
||||||
XID xwindow_id;
|
|
||||||
|
|
||||||
/* properties */
|
/* lists... */
|
||||||
gchar *norm;
|
GList *colors;
|
||||||
gchar *channel;
|
GList *stds;
|
||||||
gulong frequency;
|
GList *inputs;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gchar *std;
|
||||||
|
gchar *input;
|
||||||
|
gulong frequency;
|
||||||
|
|
||||||
|
|
||||||
|
/* X-overlay */
|
||||||
|
GstV4l2Xv *xv;
|
||||||
|
gulong xwindow_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2ElementClass {
|
struct _GstV4l2ElementClass {
|
||||||
GstElementClass parent_class;
|
GstPushSrcClass parent_class;
|
||||||
|
|
||||||
/* probed devices */
|
/* probed devices */
|
||||||
GList *devices;
|
GList *devices;
|
||||||
|
|
||||||
/* signals */
|
/* actions */
|
||||||
void (*open) (GstElement *element,
|
gboolean (*get_attribute) (GstElement *element,
|
||||||
const gchar *device);
|
const gchar *attr_name,
|
||||||
void (*close) (GstElement *element,
|
int *value);
|
||||||
const gchar *device);
|
gboolean (*set_attribute) (GstElement *element,
|
||||||
|
const gchar *attr_name,
|
||||||
|
const int value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GType gst_v4l2element_get_type(void);
|
||||||
|
|
||||||
GType gst_v4l2element_get_type (void);
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_V4L2ELEMENT_H__ */
|
#endif /* __GST_V4L2ELEMENT_H__ */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,8 @@
|
||||||
/* G-Streamer Video4linux2 video-capture plugin
|
/* GStreamer
|
||||||
* Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
*
|
||||||
|
* gstv4l2src.h: BT8x8/V4L2 video source element
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -20,6 +23,7 @@
|
||||||
#ifndef __GST_V4L2SRC_H__
|
#ifndef __GST_V4L2SRC_H__
|
||||||
#define __GST_V4L2SRC_H__
|
#define __GST_V4L2SRC_H__
|
||||||
|
|
||||||
|
|
||||||
#include <gstv4l2element.h>
|
#include <gstv4l2element.h>
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
|
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
|
||||||
|
@ -27,83 +31,86 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
|
||||||
#define GST_V4L2_MAX_BUFFERS 16
|
#define GST_V4L2_MAX_BUFFERS 16
|
||||||
#define GST_V4L2_MIN_BUFFERS 2
|
#define GST_V4L2_MIN_BUFFERS 2
|
||||||
|
|
||||||
#define GST_TYPE_V4L2SRC \
|
G_BEGIN_DECLS
|
||||||
(gst_v4l2src_get_type())
|
|
||||||
#define GST_V4L2SRC(obj) \
|
#define GST_TYPE_V4L2SRC \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2SRC,GstV4l2Src))
|
(gst_v4l2src_get_type())
|
||||||
#define GST_V4L2SRC_CLASS(klass) \
|
#define GST_V4L2SRC(obj) \
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2SRC,GstV4l2SrcClass))
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2SRC,GstV4l2Src))
|
||||||
#define GST_IS_V4L2SRC(obj) \
|
#define GST_V4L2SRC_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC))
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2SRC,GstV4l2SrcClass))
|
||||||
#define GST_IS_V4L2SRC_CLASS(obj) \
|
#define GST_IS_V4L2SRC(obj) \
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC))
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC))
|
||||||
|
#define GST_IS_V4L2SRC_CLASS(obj) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
|
||||||
|
typedef struct _GstV4l2Buffer GstV4l2Buffer;
|
||||||
|
typedef struct _GstV4l2Src GstV4l2Src;
|
||||||
|
typedef struct _GstV4l2SrcClass GstV4l2SrcClass;
|
||||||
|
|
||||||
typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
|
|
||||||
typedef struct _GstV4l2Buffer GstV4l2Buffer;
|
|
||||||
typedef struct _GstV4l2Src GstV4l2Src;
|
|
||||||
typedef struct _GstV4l2SrcClass GstV4l2SrcClass;
|
|
||||||
|
|
||||||
/* global info */
|
/* global info */
|
||||||
struct _GstV4l2BufferPool {
|
struct _GstV4l2BufferPool {
|
||||||
GstAtomicInt refcount; /* number of users: 1 for every buffer, 1 for element */
|
gint refcount; /* number of users: 1 for every buffer, 1 for element */
|
||||||
gint video_fd;
|
gint video_fd;
|
||||||
guint buffer_count;
|
guint buffer_count;
|
||||||
GstV4l2Buffer * buffers;
|
GstV4l2Buffer * buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2Buffer {
|
struct _GstV4l2Buffer {
|
||||||
struct v4l2_buffer buffer;
|
struct v4l2_buffer buffer;
|
||||||
guint8 * start;
|
guint8 * start;
|
||||||
guint length;
|
guint length;
|
||||||
GstAtomicInt refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */
|
gint refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */
|
||||||
GstV4l2BufferPool * pool;
|
GstV4l2BufferPool * pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2Src {
|
enum
|
||||||
GstV4l2Element v4l2element;
|
{
|
||||||
|
QUEUE_STATE_ERROR = -1,
|
||||||
|
QUEUE_STATE_READY_FOR_QUEUE, /* the frame is ready to be queued for capture */
|
||||||
|
QUEUE_STATE_QUEUED, /* the frame is queued for capture */
|
||||||
|
QUEUE_STATE_SYNCED /* the frame is captured */
|
||||||
|
};
|
||||||
|
|
||||||
/* pads */
|
|
||||||
GstPad *srcpad;
|
|
||||||
|
|
||||||
/* internal lists */
|
struct _GstV4l2Src
|
||||||
GSList *formats; /* list of available capture formats */
|
{
|
||||||
|
GstV4l2Element v4l2element;
|
||||||
|
|
||||||
/* buffers */
|
/* pads */
|
||||||
GstV4l2BufferPool *pool;
|
GstPad *srcpad;
|
||||||
|
|
||||||
struct v4l2_requestbuffers breq;
|
/* internal lists */
|
||||||
struct v4l2_format format;
|
GSList *formats; /* list of available capture formats */
|
||||||
|
|
||||||
/* True if we want to stop */
|
/* buffers */
|
||||||
gboolean quit, is_capturing;
|
GstV4l2BufferPool *pool;
|
||||||
|
|
||||||
/* A/V sync... frame counter and internal cache */
|
struct v4l2_requestbuffers breq;
|
||||||
gulong handled;
|
struct v4l2_format format;
|
||||||
gint need_writes;
|
|
||||||
GstBuffer *cached_buffer;
|
|
||||||
gulong last_seq;
|
|
||||||
|
|
||||||
/* clock */
|
/* True if we want to stop */
|
||||||
GstClock *clock;
|
gboolean quit, is_capturing;
|
||||||
|
|
||||||
/* time to substract from clock time to get back to timestamp */
|
|
||||||
GstClockTime substract_time;
|
|
||||||
|
|
||||||
/* how are we going to push buffers? */
|
gint offset;
|
||||||
gboolean use_fixed_fps;
|
|
||||||
|
/* how are we going to push buffers? */
|
||||||
|
gboolean use_fixed_fps;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstV4l2SrcClass {
|
struct _GstV4l2SrcClass
|
||||||
GstV4l2ElementClass parent_class;
|
{
|
||||||
|
GstV4l2ElementClass parent_class;
|
||||||
void (*frame_capture) (GObject *object);
|
|
||||||
void (*frame_drop) (GObject *object);
|
|
||||||
void (*frame_insert) (GObject *object);
|
|
||||||
void (*frame_lost) (GObject *object,
|
|
||||||
gint num_lost);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GType gst_v4l2src_get_type(void);
|
GType gst_v4l2src_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GST_V4L2SRC_H__ */
|
#endif /* __GST_V4L2SRC_H__ */
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/tuner/tuner.h>
|
|
||||||
|
|
||||||
#include "gstv4l2tuner.h"
|
#include "gstv4l2tuner.h"
|
||||||
#include "gstv4l2element.h"
|
#include "gstv4l2element.h"
|
||||||
|
@ -156,13 +155,8 @@ gst_v4l2_tuner_interface_init (GstTunerClass * klass)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
|
gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element));
|
|
||||||
GstPadDirection dir = GST_PAD_UNKNOWN;
|
GstPadDirection dir = GST_PAD_UNKNOWN;
|
||||||
|
|
||||||
/* get direction */
|
|
||||||
if (pads && g_list_length ((GList *) pads) == 1)
|
|
||||||
dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
|
|
||||||
|
|
||||||
return (dir == GST_PAD_SINK);
|
return (dir == GST_PAD_SINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +166,7 @@ gst_v4l2_tuner_contains_channel (GstV4l2Element * v4l2element,
|
||||||
{
|
{
|
||||||
const GList *item;
|
const GList *item;
|
||||||
|
|
||||||
for (item = v4l2element->channels; item != NULL; item = item->next)
|
for (item = v4l2element->inputs; item != NULL; item = item->next)
|
||||||
if (item->data == v4l2channel)
|
if (item->data == v4l2channel)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -183,7 +177,7 @@ static const GList *
|
||||||
gst_v4l2_tuner_list_channels (GstTuner * mixer)
|
gst_v4l2_tuner_list_channels (GstTuner * mixer)
|
||||||
{
|
{
|
||||||
/* ... or output, if we're a sink... */
|
/* ... or output, if we're a sink... */
|
||||||
return GST_V4L2ELEMENT (mixer)->channels;
|
return GST_V4L2ELEMENT (mixer)->inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -201,7 +195,7 @@ gst_v4l2_tuner_set_channel (GstTuner * mixer, GstTunerChannel * channel)
|
||||||
gst_v4l2_set_output (v4l2element, v4l2channel->index) :
|
gst_v4l2_set_output (v4l2element, v4l2channel->index) :
|
||||||
gst_v4l2_set_input (v4l2element, v4l2channel->index)) {
|
gst_v4l2_set_input (v4l2element, v4l2channel->index)) {
|
||||||
gst_tuner_channel_changed (mixer, channel);
|
gst_tuner_channel_changed (mixer, channel);
|
||||||
g_object_notify (G_OBJECT (v4l2element), "channel");
|
g_object_notify (G_OBJECT (v4l2element), "input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +215,7 @@ gst_v4l2_tuner_get_channel (GstTuner * mixer)
|
||||||
else
|
else
|
||||||
gst_v4l2_get_input (v4l2element, &channel);
|
gst_v4l2_get_input (v4l2element, &channel);
|
||||||
|
|
||||||
for (item = v4l2element->channels; item != NULL; item = item->next) {
|
for (item = v4l2element->inputs; item != NULL; item = item->next) {
|
||||||
if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index)
|
if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index)
|
||||||
return (GstTunerChannel *) item->data;
|
return (GstTunerChannel *) item->data;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +229,7 @@ gst_v4l2_tuner_contains_norm (GstV4l2Element * v4l2element,
|
||||||
{
|
{
|
||||||
const GList *item;
|
const GList *item;
|
||||||
|
|
||||||
for (item = v4l2element->norms; item != NULL; item = item->next)
|
for (item = v4l2element->stds; item != NULL; item = item->next)
|
||||||
if (item->data == v4l2norm)
|
if (item->data == v4l2norm)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -245,7 +239,7 @@ gst_v4l2_tuner_contains_norm (GstV4l2Element * v4l2element,
|
||||||
static const GList *
|
static const GList *
|
||||||
gst_v4l2_tuner_list_norms (GstTuner * mixer)
|
gst_v4l2_tuner_list_norms (GstTuner * mixer)
|
||||||
{
|
{
|
||||||
return GST_V4L2ELEMENT (mixer)->norms;
|
return GST_V4L2ELEMENT (mixer)->stds;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -260,7 +254,7 @@ gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm)
|
||||||
|
|
||||||
if (gst_v4l2_set_norm (v4l2element, v4l2norm->index)) {
|
if (gst_v4l2_set_norm (v4l2element, v4l2norm->index)) {
|
||||||
gst_tuner_norm_changed (mixer, norm);
|
gst_tuner_norm_changed (mixer, norm);
|
||||||
g_object_notify (G_OBJECT (v4l2element), "norm");
|
g_object_notify (G_OBJECT (v4l2element), "std");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +270,7 @@ gst_v4l2_tuner_get_norm (GstTuner * mixer)
|
||||||
|
|
||||||
gst_v4l2_get_norm (v4l2element, &norm);
|
gst_v4l2_get_norm (v4l2element, &norm);
|
||||||
|
|
||||||
for (item = v4l2element->norms; item != NULL; item = item->next) {
|
for (item = v4l2element->stds; item != NULL; item = item->next) {
|
||||||
if (norm == GST_V4L2_TUNER_NORM (item->data)->index)
|
if (norm == GST_V4L2_TUNER_NORM (item->data)->index)
|
||||||
return (GstTunerNorm *) item->data;
|
return (GstTunerNorm *) item->data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define __GST_V4L2_TUNER_H__
|
#define __GST_V4L2_TUNER_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/tuner/tuner.h>
|
#include <gst/interfaces/tuner.h>
|
||||||
|
|
||||||
#include "gstv4l2element.h"
|
#include "gstv4l2element.h"
|
||||||
|
|
||||||
|
@ -33,10 +33,10 @@ G_BEGIN_DECLS
|
||||||
(gst_v4l2_tuner_channel_get_type ())
|
(gst_v4l2_tuner_channel_get_type ())
|
||||||
#define GST_V4L2_TUNER_CHANNEL(obj) \
|
#define GST_V4L2_TUNER_CHANNEL(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_CHANNEL, \
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_CHANNEL, \
|
||||||
GstV4l2TunerChannel))
|
GstV4l2TunerChannel))
|
||||||
#define GST_V4L2_TUNER_CHANNEL_CLASS(klass) \
|
#define GST_V4L2_TUNER_CHANNEL_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_CHANNEL, \
|
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_CHANNEL, \
|
||||||
GstV4l2TunerChannelClass))
|
GstV4l2TunerChannelClass))
|
||||||
#define GST_IS_V4L2_TUNER_CHANNEL(obj) \
|
#define GST_IS_V4L2_TUNER_CHANNEL(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_CHANNEL))
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_CHANNEL))
|
||||||
#define GST_IS_V4L2_TUNER_CHANNEL_CLASS(klass) \
|
#define GST_IS_V4L2_TUNER_CHANNEL_CLASS(klass) \
|
||||||
|
@ -58,10 +58,10 @@ typedef struct _GstV4l2TunerChannelClass {
|
||||||
(gst_v4l2_tuner_norm_get_type ())
|
(gst_v4l2_tuner_norm_get_type ())
|
||||||
#define GST_V4L2_TUNER_NORM(obj) \
|
#define GST_V4L2_TUNER_NORM(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_NORM, \
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_NORM, \
|
||||||
GstV4l2TunerNorm))
|
GstV4l2TunerNorm))
|
||||||
#define GST_V4L2_TUNER_NORM_CLASS(klass) \
|
#define GST_V4L2_TUNER_NORM_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_NORM, \
|
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_NORM, \
|
||||||
GstV4l2TunerNormClass))
|
GstV4l2TunerNormClass))
|
||||||
#define GST_IS_V4L2_TUNER_NORM(obj) \
|
#define GST_IS_V4L2_TUNER_NORM(obj) \
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_NORM))
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_NORM))
|
||||||
#define GST_IS_V4L2_TUNER_NORM_CLASS(klass) \
|
#define GST_IS_V4L2_TUNER_NORM_CLASS(klass) \
|
||||||
|
@ -77,9 +77,9 @@ typedef struct _GstV4l2TunerNormClass {
|
||||||
GstTunerNormClass parent;
|
GstTunerNormClass parent;
|
||||||
} GstV4l2TunerNormClass;
|
} GstV4l2TunerNormClass;
|
||||||
|
|
||||||
GType gst_v4l2_tuner_channel_get_type (void);
|
GType gst_v4l2_tuner_channel_get_type (void);
|
||||||
GType gst_v4l2_tuner_norm_get_type (void);
|
GType gst_v4l2_tuner_norm_get_type (void);
|
||||||
|
|
||||||
void gst_v4l2_tuner_interface_init (GstTunerClass *klass);
|
void gst_v4l2_tuner_interface_init (GstTunerClass *klass);
|
||||||
|
|
||||||
#endif /* __GST_V4L2_TUNER_H__ */
|
#endif /* __GST_V4L2_TUNER_H__ */
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/xoverlay/xoverlay.h>
|
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/extensions/Xv.h>
|
#include <X11/extensions/Xv.h>
|
||||||
|
@ -59,13 +58,14 @@ gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass)
|
||||||
"V4L2 XOverlay interface debugging");
|
"V4L2 XOverlay interface debugging");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
|
gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
GstV4l2Xv *v4l2xv;
|
GstV4l2Xv *v4l2xv;
|
||||||
const gchar *name = g_getenv ("DISPLAY");
|
const gchar *name = g_getenv ("DISPLAY");
|
||||||
int ver, rel, req, ev, err, anum, i, id = 0, first_id = 0, min;
|
unsigned int ver, rel, req, ev, err, anum;
|
||||||
|
int i, id = 0, first_id = 0, min;
|
||||||
XvAdaptorInfo *ai;
|
XvAdaptorInfo *ai;
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
|
|
||||||
|
@ -75,6 +75,13 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First let's check that XVideo extension is available */
|
||||||
|
if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) {
|
||||||
|
GST_WARNING ("Xv extension not available - no overlay");
|
||||||
|
XCloseDisplay (dpy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* find port that belongs to this device */
|
/* find port that belongs to this device */
|
||||||
if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
|
if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
|
||||||
GST_WARNING ("Xv extension not supported - no overlay");
|
GST_WARNING ("Xv extension not supported - no overlay");
|
||||||
|
@ -93,7 +100,7 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
|
||||||
}
|
}
|
||||||
min = s.st_rdev & 0xff;
|
min = s.st_rdev & 0xff;
|
||||||
for (i = 0; i < anum; i++) {
|
for (i = 0; i < anum; i++) {
|
||||||
if (!strcmp (ai[i].name, "video4linux")) {
|
if (!strcmp (ai[i].name, "video4linux2")) {
|
||||||
if (first_id == 0)
|
if (first_id == 0)
|
||||||
first_id = ai[i].base_id;
|
first_id = ai[i].base_id;
|
||||||
|
|
||||||
|
@ -123,7 +130,7 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element)
|
gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
GstV4l2Xv *v4l2xv = v4l2element->xv;
|
GstV4l2Xv *v4l2xv = v4l2element->xv;
|
||||||
|
@ -143,6 +150,20 @@ gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element)
|
||||||
v4l2element->xv = NULL;
|
v4l2element->xv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_v4l2_xoverlay_start (GstV4l2Element * v4l2element)
|
||||||
|
{
|
||||||
|
if (v4l2element->xwindow_id) {
|
||||||
|
gst_v4l2_xoverlay_open (v4l2element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_v4l2_xoverlay_stop (GstV4l2Element * v4l2element)
|
||||||
|
{
|
||||||
|
gst_v4l2_xoverlay_close (v4l2element);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
idle_refresh (gpointer data)
|
idle_refresh (gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -170,12 +191,17 @@ static void
|
||||||
gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
|
gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
|
||||||
{
|
{
|
||||||
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (overlay);
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (overlay);
|
||||||
GstV4l2Xv *v4l2xv = v4l2element->xv;
|
GstV4l2Xv *v4l2xv;
|
||||||
XWindowAttributes attr;
|
XWindowAttributes attr;
|
||||||
gboolean change = (v4l2element->xwindow_id != xwindow_id);
|
gboolean change = (v4l2element->xwindow_id != xwindow_id);
|
||||||
|
|
||||||
GST_LOG_OBJECT (v4l2element, "Setting XID to %lx", (gulong) xwindow_id);
|
GST_LOG_OBJECT (v4l2element, "Setting XID to %lx", (gulong) xwindow_id);
|
||||||
|
|
||||||
|
if (!v4l2element->xv && GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
gst_v4l2_xoverlay_open (v4l2element);
|
||||||
|
|
||||||
|
v4l2xv = v4l2element->xv;
|
||||||
|
|
||||||
if (v4l2xv)
|
if (v4l2xv)
|
||||||
g_mutex_lock (v4l2xv->mutex);
|
g_mutex_lock (v4l2xv->mutex);
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,15 @@
|
||||||
#define __GST_V4L2_X_OVERLAY_H__
|
#define __GST_V4L2_X_OVERLAY_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/xoverlay/xoverlay.h>
|
#include <gst/interfaces/xoverlay.h>
|
||||||
|
|
||||||
#include "gstv4l2element.h"
|
#include "gstv4l2element.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass);
|
void gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass);
|
||||||
|
|
||||||
void gst_v4l2_xoverlay_open (GstV4l2Element *v4l2element);
|
void gst_v4l2_xoverlay_start (GstV4l2Element *v4l2element);
|
||||||
void gst_v4l2_xoverlay_close (GstV4l2Element *v4l2element);
|
void gst_v4l2_xoverlay_stop (GstV4l2Element *v4l2element);
|
||||||
|
|
||||||
#endif /* __GST_V4L2_X_OVERLAY_H__ */
|
#endif /* __GST_V4L2_X_OVERLAY_H__ */
|
||||||
|
|
|
@ -36,11 +36,8 @@
|
||||||
|
|
||||||
#include "gstv4l2src.h"
|
#include "gstv4l2src.h"
|
||||||
|
|
||||||
#define DEBUG(format, args...) \
|
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
||||||
GST_DEBUG_OBJECT (\
|
#define GST_CAT_DEFAULT v4l2_debug
|
||||||
GST_ELEMENT(v4l2element), \
|
|
||||||
"V4L2: " format, ##args)
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
* gst_v4l2_get_capabilities():
|
* gst_v4l2_get_capabilities():
|
||||||
|
@ -48,16 +45,16 @@
|
||||||
* return value: TRUE on success, FALSE on error
|
* return value: TRUE on success, FALSE on error
|
||||||
******************************************************/
|
******************************************************/
|
||||||
|
|
||||||
static gboolean
|
gboolean
|
||||||
gst_v4l2_get_capabilities (GstV4l2Element * v4l2element)
|
gst_v4l2_get_capabilities (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
DEBUG ("getting capabilities");
|
GST_DEBUG ("getting capabilities");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ERROR_OBJECT (v4l2element, "Error getting %s capabilities: %s",
|
||||||
("Error getting %s capabilities: %s",
|
v4l2element->videodev, g_strerror (errno));
|
||||||
v4l2element->device, g_strerror (errno)));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,16 +72,11 @@ static gboolean
|
||||||
gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
gint n;
|
gint n;
|
||||||
const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element));
|
|
||||||
GstPadDirection dir = GST_PAD_UNKNOWN;
|
GstPadDirection dir = GST_PAD_UNKNOWN;
|
||||||
|
|
||||||
DEBUG ("getting enumerations");
|
GST_DEBUG ("getting enumerations");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
GST_V4L2_CHECK_OPEN (v4l2element);
|
||||||
|
|
||||||
/* sinks have outputs, all others have inputs */
|
|
||||||
if (pads && g_list_length ((GList *) pads) == 1)
|
|
||||||
dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
|
|
||||||
|
|
||||||
if (dir != GST_PAD_SINK) {
|
if (dir != GST_PAD_SINK) {
|
||||||
/* and now, the inputs */
|
/* and now, the inputs */
|
||||||
for (n = 0;; n++) {
|
for (n = 0;; n++) {
|
||||||
|
@ -99,14 +91,14 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
else {
|
else {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get %d in input enumeration for %s: %s",
|
("Failed to get %d in input enumeration for %s: %s",
|
||||||
n, v4l2element->device, g_strerror (errno)));
|
n, v4l2element->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
|
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
|
||||||
channel = GST_TUNER_CHANNEL (v4l2channel);
|
channel = GST_TUNER_CHANNEL (v4l2channel);
|
||||||
channel->label = g_strdup (input.name);
|
channel->label = g_strdup ((const gchar *) input.name);
|
||||||
channel->flags = GST_TUNER_CHANNEL_INPUT;
|
channel->flags = GST_TUNER_CHANNEL_INPUT;
|
||||||
v4l2channel->index = n;
|
v4l2channel->index = n;
|
||||||
if (input.type == V4L2_INPUT_TYPE_TUNER) {
|
if (input.type == V4L2_INPUT_TYPE_TUNER) {
|
||||||
|
@ -119,7 +111,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get tuner %d settings on %s: %s",
|
("Failed to get tuner %d settings on %s: %s",
|
||||||
input.tuner, v4l2element->device, g_strerror (errno)));
|
input.tuner, v4l2element->videodev, g_strerror (errno)));
|
||||||
g_object_unref (G_OBJECT (channel));
|
g_object_unref (G_OBJECT (channel));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +130,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
channel->flags |= GST_TUNER_CHANNEL_AUDIO;
|
channel->flags |= GST_TUNER_CHANNEL_AUDIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2element->channels =
|
v4l2element->inputs =
|
||||||
g_list_append (v4l2element->channels, (gpointer) channel);
|
g_list_append (v4l2element->inputs, (gpointer) channel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* outputs */
|
/* outputs */
|
||||||
|
@ -155,14 +147,14 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
else {
|
else {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get %d in output enumeration for %s: %s",
|
("Failed to get %d in output enumeration for %s: %s",
|
||||||
n, v4l2element->device, g_strerror (errno)));
|
n, v4l2element->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
|
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
|
||||||
channel = GST_TUNER_CHANNEL (v4l2channel);
|
channel = GST_TUNER_CHANNEL (v4l2channel);
|
||||||
channel->label = g_strdup (output.name);
|
channel->label = g_strdup ((const gchar *) output.name);
|
||||||
channel->flags = GST_TUNER_CHANNEL_OUTPUT;
|
channel->flags = GST_TUNER_CHANNEL_OUTPUT;
|
||||||
v4l2channel->index = n;
|
v4l2channel->index = n;
|
||||||
if (output.audioset) {
|
if (output.audioset) {
|
||||||
|
@ -173,8 +165,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
channel->flags |= GST_TUNER_CHANNEL_AUDIO;
|
channel->flags |= GST_TUNER_CHANNEL_AUDIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2element->channels =
|
v4l2element->inputs =
|
||||||
g_list_append (v4l2element->channels, (gpointer) channel);
|
g_list_append (v4l2element->inputs, (gpointer) channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,19 +183,19 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
else {
|
else {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get %d in norm enumeration for %s: %s",
|
("Failed to get %d in norm enumeration for %s: %s",
|
||||||
n, v4l2element->device, g_strerror (errno)));
|
n, v4l2element->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2norm = g_object_new (GST_TYPE_V4L2_TUNER_NORM, NULL);
|
v4l2norm = g_object_new (GST_TYPE_V4L2_TUNER_NORM, NULL);
|
||||||
norm = GST_TUNER_NORM (v4l2norm);
|
norm = GST_TUNER_NORM (v4l2norm);
|
||||||
norm->label = g_strdup (standard.name);
|
norm->label = g_strdup ((const gchar *) standard.name);
|
||||||
norm->fps = (gfloat) standard.frameperiod.denominator /
|
gst_value_set_fraction (&norm->framerate,
|
||||||
standard.frameperiod.numerator;
|
standard.frameperiod.denominator, standard.frameperiod.numerator);
|
||||||
v4l2norm->index = standard.id;
|
v4l2norm->index = standard.id;
|
||||||
|
|
||||||
v4l2element->norms = g_list_append (v4l2element->norms, (gpointer) norm);
|
v4l2element->stds = g_list_append (v4l2element->stds, (gpointer) norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and lastly, controls+menus (if appropriate) */
|
/* and lastly, controls+menus (if appropriate) */
|
||||||
|
@ -226,7 +218,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
} else {
|
} else {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get %d in control enumeration for %s: %s",
|
("Failed to get %d in control enumeration for %s: %s",
|
||||||
n, v4l2element->device, g_strerror (errno)));
|
n, v4l2element->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +242,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
/* we only handle these for now */
|
/* we only handle these for now */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG ("ControlID %s (%d) unhandled, FIXME", control.name, n);
|
GST_DEBUG ("ControlID %s (%d) unhandled, FIXME", control.name, n);
|
||||||
control.id++;
|
control.id++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +251,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
|
|
||||||
v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
|
v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
|
||||||
channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
|
channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
|
||||||
channel->label = g_strdup (control.name);
|
channel->label = g_strdup ((const gchar *) control.name);
|
||||||
v4l2channel->index = n;
|
v4l2channel->index = n;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -276,7 +268,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
else {
|
else {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
||||||
("Failed to get %d in menu enumeration for %s: %s",
|
("Failed to get %d in menu enumeration for %s: %s",
|
||||||
n, v4l2element->device, g_strerror (errno)));
|
n, v4l2element->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,15 +305,15 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
|
||||||
static void
|
static void
|
||||||
gst_v4l2_empty_lists (GstV4l2Element * v4l2element)
|
gst_v4l2_empty_lists (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
DEBUG ("deleting enumerations");
|
GST_DEBUG ("deleting enumerations");
|
||||||
|
|
||||||
g_list_foreach (v4l2element->channels, (GFunc) g_object_unref, NULL);
|
g_list_foreach (v4l2element->inputs, (GFunc) g_object_unref, NULL);
|
||||||
g_list_free (v4l2element->channels);
|
g_list_free (v4l2element->inputs);
|
||||||
v4l2element->channels = NULL;
|
v4l2element->inputs = NULL;
|
||||||
|
|
||||||
g_list_foreach (v4l2element->norms, (GFunc) g_object_unref, NULL);
|
g_list_foreach (v4l2element->stds, (GFunc) g_object_unref, NULL);
|
||||||
g_list_free (v4l2element->norms);
|
g_list_free (v4l2element->stds);
|
||||||
v4l2element->norms = NULL;
|
v4l2element->stds = NULL;
|
||||||
|
|
||||||
g_list_foreach (v4l2element->colors, (GFunc) g_object_unref, NULL);
|
g_list_foreach (v4l2element->colors, (GFunc) g_object_unref, NULL);
|
||||||
g_list_free (v4l2element->colors);
|
g_list_free (v4l2element->colors);
|
||||||
|
@ -337,27 +329,27 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element)
|
||||||
GstTunerChannel *channel = NULL;
|
GstTunerChannel *channel = NULL;
|
||||||
GstTuner *tuner = GST_TUNER (v4l2element);
|
GstTuner *tuner = GST_TUNER (v4l2element);
|
||||||
|
|
||||||
if (v4l2element->norm)
|
if (v4l2element->std)
|
||||||
norm = gst_tuner_find_norm_by_name (tuner, v4l2element->norm);
|
norm = gst_tuner_find_norm_by_name (tuner, v4l2element->std);
|
||||||
if (norm) {
|
if (norm) {
|
||||||
gst_tuner_set_norm (tuner, norm);
|
gst_tuner_set_norm (tuner, norm);
|
||||||
} else {
|
} else {
|
||||||
norm = GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2element)));
|
norm = GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2element)));
|
||||||
v4l2element->norm = g_strdup (norm->label);
|
v4l2element->std = g_strdup (norm->label);
|
||||||
gst_tuner_norm_changed (tuner, norm);
|
gst_tuner_norm_changed (tuner, norm);
|
||||||
g_object_notify (G_OBJECT (v4l2element), "norm");
|
g_object_notify (G_OBJECT (v4l2element), "std");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v4l2element->channel)
|
if (v4l2element->input)
|
||||||
channel = gst_tuner_find_channel_by_name (tuner, v4l2element->channel);
|
channel = gst_tuner_find_channel_by_name (tuner, v4l2element->input);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
gst_tuner_set_channel (tuner, channel);
|
gst_tuner_set_channel (tuner, channel);
|
||||||
} else {
|
} else {
|
||||||
channel =
|
channel =
|
||||||
GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER (v4l2element)));
|
GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER (v4l2element)));
|
||||||
v4l2element->channel = g_strdup (channel->label);
|
v4l2element->input = g_strdup (channel->label);
|
||||||
gst_tuner_channel_changed (tuner, channel);
|
gst_tuner_channel_changed (tuner, channel);
|
||||||
g_object_notify (G_OBJECT (v4l2element), "channel");
|
g_object_notify (G_OBJECT (v4l2element), "input");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
|
if (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
|
||||||
|
@ -378,27 +370,27 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element)
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
* gst_v4l2_open():
|
* gst_v4l2_open():
|
||||||
* open the video device (v4l2element->device)
|
* open the video device (v4l2element->videodev)
|
||||||
* return value: TRUE on success, FALSE on error
|
* return value: TRUE on success, FALSE on error
|
||||||
******************************************************/
|
******************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_open (GstV4l2Element * v4l2element)
|
gst_v4l2_open (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
DEBUG ("Trying to open device %s", v4l2element->device);
|
GST_DEBUG ("Trying to open device %s", v4l2element->videodev);
|
||||||
GST_V4L2_CHECK_NOT_OPEN (v4l2element);
|
GST_V4L2_CHECK_NOT_OPEN (v4l2element);
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
||||||
|
|
||||||
/* be sure we have a device */
|
/* be sure we have a device */
|
||||||
if (!v4l2element->device)
|
if (!v4l2element->videodev)
|
||||||
v4l2element->device = g_strdup ("/dev/video");
|
v4l2element->videodev = g_strdup ("/dev/video");
|
||||||
|
|
||||||
/* open the device */
|
/* open the device */
|
||||||
v4l2element->video_fd = open (v4l2element->device, O_RDWR);
|
v4l2element->video_fd = open (v4l2element->videodev, O_RDWR);
|
||||||
if (!GST_V4L2_IS_OPEN (v4l2element)) {
|
if (!GST_V4L2_IS_OPEN (v4l2element)) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, OPEN_READ_WRITE,
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, OPEN_READ_WRITE,
|
||||||
(_("Could not open device \"%s\" for reading and writing."),
|
(_("Could not open device \"%s\" for reading and writing."),
|
||||||
v4l2element->device), GST_ERROR_SYSTEM);
|
v4l2element->videodev), GST_ERROR_SYSTEM);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +403,7 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
|
||||||
if (GST_IS_V4L2SRC (v4l2element) &&
|
if (GST_IS_V4L2SRC (v4l2element) &&
|
||||||
!(v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
|
!(v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND,
|
GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND,
|
||||||
(_("Device \"%s\" is not a capture device."), v4l2element->device),
|
(_("Device \"%s\" is not a capture device."), v4l2element->videodev),
|
||||||
("Capabilities: 0x%x", v4l2element->vcap.capabilities));
|
("Capabilities: 0x%x", v4l2element->vcap.capabilities));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -424,7 +416,7 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
|
||||||
gst_v4l2_set_defaults (v4l2element);
|
gst_v4l2_set_defaults (v4l2element);
|
||||||
|
|
||||||
GST_INFO_OBJECT (v4l2element, "Opened device '%s' (%s) successfully\n",
|
GST_INFO_OBJECT (v4l2element, "Opened device '%s' (%s) successfully\n",
|
||||||
v4l2element->vcap.card, v4l2element->device);
|
v4l2element->vcap.card, v4l2element->videodev);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -450,7 +442,7 @@ error:
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_close (GstV4l2Element * v4l2element)
|
gst_v4l2_close (GstV4l2Element * v4l2element)
|
||||||
{
|
{
|
||||||
DEBUG ("Trying to close %s", v4l2element->device);
|
GST_DEBUG ("Trying to close %s", v4l2element->videodev);
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
GST_V4L2_CHECK_OPEN (v4l2element);
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
||||||
|
|
||||||
|
@ -474,13 +466,14 @@ gst_v4l2_close (GstV4l2Element * v4l2element)
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
|
gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
|
||||||
{
|
{
|
||||||
DEBUG ("getting norm");
|
GST_DEBUG ("getting norm");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get the current norm for device %s: %s",
|
"Failed to get the current norm for device %s: %s",
|
||||||
v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,14 +490,16 @@ gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
|
gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
|
||||||
{
|
{
|
||||||
DEBUG ("trying to set norm to %llx", norm);
|
GST_DEBUG ("trying to set norm to %llx", norm);
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
return FALSE;
|
||||||
|
if (!GST_V4L2_IS_ACTIVE (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to set norm 0x%llx for device %s: %s",
|
"Failed to set norm 0x%llx for device %s: %s", norm,
|
||||||
norm, v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,13 +518,14 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
|
||||||
{
|
{
|
||||||
gint n;
|
gint n;
|
||||||
|
|
||||||
DEBUG ("trying to get input");
|
GST_DEBUG ("trying to get input");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get current input on device %s: %s",
|
"Failed to get current input on device %s: %s", v4l2element->videodev,
|
||||||
v4l2element->device, g_strerror (errno)));
|
g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,14 +544,15 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
|
gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
|
||||||
{
|
{
|
||||||
DEBUG ("trying to set input to %d", input);
|
GST_DEBUG ("trying to set input to %d", input);
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
return FALSE;
|
||||||
|
if (!GST_V4L2_IS_ACTIVE (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element, "Failed to set input %d on device %s: %s",
|
||||||
("Failed to set input %d on device %s: %s",
|
input, v4l2element->videodev, g_strerror (errno));
|
||||||
input, v4l2element->device, g_strerror (errno)));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,13 +571,14 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
|
||||||
{
|
{
|
||||||
gint n;
|
gint n;
|
||||||
|
|
||||||
DEBUG ("trying to get output");
|
GST_DEBUG ("trying to get output");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get current output on device %s: %s",
|
"Failed to get current output on device %s: %s", v4l2element->videodev,
|
||||||
v4l2element->device, g_strerror (errno)));
|
g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,14 +597,16 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
|
gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
|
||||||
{
|
{
|
||||||
DEBUG ("trying to set output to %d", output);
|
GST_DEBUG ("trying to set output to %d", output);
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
return FALSE;
|
||||||
|
if (!GST_V4L2_IS_ACTIVE (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to set output %d on device %s: %s",
|
"Failed to set current output on device %s to %d: %s",
|
||||||
output, v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, output, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,16 +627,17 @@ gst_v4l2_get_frequency (GstV4l2Element * v4l2element,
|
||||||
struct v4l2_frequency freq;
|
struct v4l2_frequency freq;
|
||||||
GstTunerChannel *channel;
|
GstTunerChannel *channel;
|
||||||
|
|
||||||
DEBUG ("getting current tuner frequency");
|
GST_DEBUG ("getting current tuner frequency");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
|
channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
|
||||||
|
|
||||||
freq.tuner = tunernum;
|
freq.tuner = tunernum;
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get current tuner frequency for device %s: %s",
|
"Failed to get current tuner frequency for device %s: %s",
|
||||||
v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,9 +660,11 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
|
||||||
struct v4l2_frequency freq;
|
struct v4l2_frequency freq;
|
||||||
GstTunerChannel *channel;
|
GstTunerChannel *channel;
|
||||||
|
|
||||||
DEBUG ("setting current tuner frequency to %lu", frequency);
|
GST_DEBUG ("setting current tuner frequency to %lu", frequency);
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
|
return FALSE;
|
||||||
|
if (!GST_V4L2_IS_ACTIVE (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
|
channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
|
||||||
|
|
||||||
|
@ -671,9 +674,9 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
|
||||||
freq.frequency = frequency / channel->freq_multiplicator;
|
freq.frequency = frequency / channel->freq_multiplicator;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to set tuner frequency to %lu for device %s: %s",
|
"Failed to set current tuner frequency for device %s to %lu: %s",
|
||||||
frequency, v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, frequency, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,14 +696,15 @@ gst_v4l2_signal_strength (GstV4l2Element * v4l2element,
|
||||||
{
|
{
|
||||||
struct v4l2_tuner tuner;
|
struct v4l2_tuner tuner;
|
||||||
|
|
||||||
DEBUG ("trying to get signal strength");
|
GST_DEBUG ("trying to get signal strength");
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
tuner.index = tunernum;
|
tuner.index = tunernum;
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get signal strength for device %s: %s",
|
"Failed to get signal strength for device %s: %s",
|
||||||
v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,16 +726,17 @@ gst_v4l2_get_attribute (GstV4l2Element * v4l2element,
|
||||||
{
|
{
|
||||||
struct v4l2_control control;
|
struct v4l2_control control;
|
||||||
|
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
DEBUG ("getting value of attribute %d", attribute_num);
|
GST_DEBUG ("getting value of attribute %d", attribute_num);
|
||||||
|
|
||||||
control.id = attribute_num;
|
control.id = attribute_num;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to get value for control %d on device %s: %s",
|
"Failed to get value for control %d on device %s: %s", attribute_num,
|
||||||
attribute_num, v4l2element->device, g_strerror (errno)));
|
v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,17 +758,18 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element,
|
||||||
{
|
{
|
||||||
struct v4l2_control control;
|
struct v4l2_control control;
|
||||||
|
|
||||||
GST_V4L2_CHECK_OPEN (v4l2element);
|
if (!GST_V4L2_IS_OPEN (v4l2element))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
DEBUG ("setting value of attribute %d to %d", attribute_num, value);
|
GST_DEBUG ("setting value of attribute %d to %d", attribute_num, value);
|
||||||
|
|
||||||
control.id = attribute_num;
|
control.id = attribute_num;
|
||||||
control.value = value;
|
control.value = value;
|
||||||
|
|
||||||
if (ioctl (v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
|
if (ioctl (v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
|
GST_WARNING_OBJECT (v4l2element,
|
||||||
("Failed to set value %d for control %d on device %s: %s",
|
"Failed to set value %d for control %d on device %s: %s", value,
|
||||||
value, attribute_num, v4l2element->device, g_strerror (errno)));
|
attribute_num, v4l2element->videodev, g_strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,96 +26,98 @@
|
||||||
|
|
||||||
/* simple check whether the device is open */
|
/* simple check whether the device is open */
|
||||||
#define GST_V4L2_IS_OPEN(element) \
|
#define GST_V4L2_IS_OPEN(element) \
|
||||||
(element->video_fd > 0)
|
(GST_V4L2ELEMENT(element)->video_fd > 0)
|
||||||
|
|
||||||
/* check whether the device is 'active' */
|
/* check whether the device is 'active' */
|
||||||
#define GST_V4L2_IS_ACTIVE(element) \
|
#define GST_V4L2_IS_ACTIVE(element) \
|
||||||
(element->buffer != NULL)
|
(GST_V4L2ELEMENT(element)->buffer != NULL)
|
||||||
|
|
||||||
#define GST_V4L2_IS_OVERLAY(element) \
|
#define GST_V4L2_IS_OVERLAY(element) \
|
||||||
(element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
|
(GST_V4L2ELEMENT(element)->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
|
||||||
|
|
||||||
/* checks whether the current v4lelement has already been open()'ed or not */
|
/* checks whether the current v4lelement has already been open()'ed or not */
|
||||||
#define GST_V4L2_CHECK_OPEN(element) \
|
#define GST_V4L2_CHECK_OPEN(element) \
|
||||||
if (!GST_V4L2_IS_OPEN(element)) \
|
if (!GST_V4L2_IS_OPEN(element)) \
|
||||||
{ \
|
{ \
|
||||||
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
||||||
(_("Device is not open.")), (NULL)); \
|
(_("Device is not open.")), (NULL)); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checks whether the current v4lelement is close()'ed or whether it is still open */
|
/* checks whether the current v4lelement is close()'ed or whether it is still open */
|
||||||
#define GST_V4L2_CHECK_NOT_OPEN(element) \
|
#define GST_V4L2_CHECK_NOT_OPEN(element) \
|
||||||
if (GST_V4L2_IS_OPEN(element)) \
|
if (GST_V4L2_IS_OPEN(element)) \
|
||||||
{ \
|
{ \
|
||||||
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
||||||
(_("Device is open.")), (NULL)); \
|
(_("Device is open.")), (NULL)); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checks whether the current v4lelement does video overlay */
|
/* checks whether the current v4lelement does video overlay */
|
||||||
#define GST_V4L2_CHECK_OVERLAY(element) \
|
#define GST_V4L2_CHECK_OVERLAY(element) \
|
||||||
if (!GST_V4L2_IS_OVERLAY(element)) \
|
if (!GST_V4L2_IS_OVERLAY(element)) \
|
||||||
{ \
|
{ \
|
||||||
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
|
||||||
(NULL), ("Device cannot handle overlay")); \
|
(NULL), ("Device cannot handle overlay")); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checks whether we're in capture mode or not */
|
/* checks whether we're in capture mode or not */
|
||||||
#define GST_V4L2_CHECK_ACTIVE(element) \
|
#define GST_V4L2_CHECK_ACTIVE(element) \
|
||||||
if (!GST_V4L2_IS_ACTIVE(element)) \
|
if (!GST_V4L2_IS_ACTIVE(element)) \
|
||||||
{ \
|
{ \
|
||||||
GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
|
GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
|
||||||
(NULL), ("Device is not in streaming mode")); \
|
(NULL), ("Device is not in streaming mode")); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checks whether we're out of capture mode or not */
|
/* checks whether we're out of capture mode or not */
|
||||||
#define GST_V4L2_CHECK_NOT_ACTIVE(element) \
|
#define GST_V4L2_CHECK_NOT_ACTIVE(element) \
|
||||||
if (GST_V4L2_IS_ACTIVE(element)) \
|
if (GST_V4L2_IS_ACTIVE(element)) \
|
||||||
{ \
|
{ \
|
||||||
GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
|
GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
|
||||||
(NULL), ("Device is in streaming mode")); \
|
(NULL), ("Device is in streaming mode")); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* open/close the device */
|
/* open/close the device */
|
||||||
gboolean gst_v4l2_open (GstV4l2Element *v4l2element);
|
gboolean gst_v4l2_open (GstV4l2Element *v4l2element);
|
||||||
gboolean gst_v4l2_close (GstV4l2Element *v4l2element);
|
gboolean gst_v4l2_close (GstV4l2Element *v4l2element);
|
||||||
|
|
||||||
/* norm/input/output */
|
/* norm/input/output */
|
||||||
gboolean gst_v4l2_get_norm (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_get_norm (GstV4l2Element *v4l2element,
|
||||||
v4l2_std_id *norm);
|
v4l2_std_id *norm);
|
||||||
gboolean gst_v4l2_set_norm (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_set_norm (GstV4l2Element *v4l2element,
|
||||||
v4l2_std_id norm);
|
v4l2_std_id norm);
|
||||||
gboolean gst_v4l2_get_input (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_get_input (GstV4l2Element *v4l2element,
|
||||||
gint *input);
|
gint *input);
|
||||||
gboolean gst_v4l2_set_input (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_set_input (GstV4l2Element *v4l2element,
|
||||||
gint input);
|
gint input);
|
||||||
gboolean gst_v4l2_get_output (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_get_output (GstV4l2Element *v4l2element,
|
||||||
gint *output);
|
gint *output);
|
||||||
gboolean gst_v4l2_set_output (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_set_output (GstV4l2Element *v4l2element,
|
||||||
gint output);
|
gint output);
|
||||||
|
|
||||||
/* frequency control */
|
/* frequency control */
|
||||||
gboolean gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
|
||||||
gint tunernum,
|
gint tunernum,
|
||||||
gulong *frequency);
|
gulong *frequency);
|
||||||
gboolean gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
|
||||||
gint tunernum,
|
gint tunernum,
|
||||||
gulong frequency);
|
gulong frequency);
|
||||||
gboolean gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
|
||||||
gint tunernum,
|
gint tunernum,
|
||||||
gulong *signal);
|
gulong *signal);
|
||||||
|
|
||||||
/* attribute control */
|
/* attribute control */
|
||||||
gboolean gst_v4l2_get_attribute (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_get_attribute (GstV4l2Element *v4l2element,
|
||||||
int attribute,
|
int attribute,
|
||||||
int *value);
|
int *value);
|
||||||
gboolean gst_v4l2_set_attribute (GstV4l2Element *v4l2element,
|
gboolean gst_v4l2_set_attribute (GstV4l2Element *v4l2element,
|
||||||
int attribute,
|
int attribute,
|
||||||
const int value);
|
const int value);
|
||||||
|
|
||||||
|
gboolean gst_v4l2_get_capabilities (GstV4l2Element * v4l2element);
|
||||||
|
|
||||||
#endif /* __V4L2_CALLS_H__ */
|
#endif /* __V4L2_CALLS_H__ */
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gstv4l2tuner.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
|
||||||
#define GST_CAT_DEFAULT v4l2src_debug
|
#define GST_CAT_DEFAULT v4l2src_debug
|
||||||
|
|
||||||
/* lalala... */
|
/* lalala... */
|
||||||
|
@ -40,9 +43,9 @@
|
||||||
#define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
|
#define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
|
||||||
|
|
||||||
#define DEBUG(format, args...) \
|
#define DEBUG(format, args...) \
|
||||||
GST_CAT_DEBUG_OBJECT (\
|
GST_CAT_DEBUG_OBJECT (\
|
||||||
v4l2src_debug, v4l2src, \
|
v4l2src_debug, v4l2src, \
|
||||||
"V4L2SRC: " format, ##args)
|
"V4L2SRC: " format, ##args)
|
||||||
|
|
||||||
/* On some systems MAP_FAILED seems to be missing */
|
/* On some systems MAP_FAILED seems to be missing */
|
||||||
#ifndef MAP_FAILED
|
#ifndef MAP_FAILED
|
||||||
|
@ -76,12 +79,12 @@ gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
|
||||||
} else {
|
} else {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
||||||
("failed to get number %d in pixelformat enumeration for %s: %s",
|
("failed to get number %d in pixelformat enumeration for %s: %s",
|
||||||
n, GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
|
n, GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
g_free (format);
|
g_free (format);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (v4l2src, "got format %" GST_FOURCC_FORMAT,
|
GST_LOG_OBJECT (v4l2src, "got format" GST_FOURCC_FORMAT,
|
||||||
GST_FOURCC_ARGS (format->pixelformat));
|
GST_FOURCC_ARGS (format->pixelformat));
|
||||||
v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
|
v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +125,7 @@ gst_v4l2src_queue_frame (GstV4l2Src * v4l2src, guint i)
|
||||||
&v4l2src->pool->buffers[i].buffer) < 0) {
|
&v4l2src->pool->buffers[i].buffer) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
|
||||||
(_("Could not write to device \"%s\"."),
|
(_("Could not write to device \"%s\"."),
|
||||||
GST_V4L2ELEMENT (v4l2src)->device),
|
GST_V4L2ELEMENT (v4l2src)->videodev),
|
||||||
("Error queueing buffer %u on device %s", i, g_strerror (errno)));
|
("Error queueing buffer %u on device %s", i, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -145,13 +148,46 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
|
||||||
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
while (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0) {
|
while (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0) {
|
||||||
/* if the sync() got interrupted, we can retry */
|
/* if the sync() got interrupted, we can retry */
|
||||||
if (errno != EINTR) {
|
switch (errno) {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
case EAGAIN:
|
||||||
("could not sync on a buffer on device %s: %s",
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
||||||
GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
|
("Non-blocking I/O has been selected using O_NONBLOCK and"
|
||||||
return -1;
|
" no buffer was in the outgoing queue. device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
||||||
|
("The buffer type is not supported, or the index is out of bounds,"
|
||||||
|
" or no buffers have been allocated yet, or the userptr"
|
||||||
|
" or length are invalid. device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
break;
|
||||||
|
case ENOMEM:
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
||||||
|
("isufficient memory to enqueue a user pointer buffer. device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
break;
|
||||||
|
case EIO:
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
||||||
|
("VIDIOC_DQBUF failed due to an internal error."
|
||||||
|
" Can also indicate temporary problems like signal loss."
|
||||||
|
" Note the driver might dequeue an (empty) buffer despite"
|
||||||
|
" returning an error, or even stop capturing."
|
||||||
|
" device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
break;
|
||||||
|
case EINTR:
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
|
||||||
|
("could not sync on a buffer on device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_DEBUG_OBJECT (v4l2src, "grab got interrupted");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (v4l2src, "grab got interrupted");
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (v4l2src, "grabbed frame %d", buffer.index);
|
GST_LOG_OBJECT (v4l2src, "grabbed frame %d", buffer.index);
|
||||||
|
@ -178,7 +214,7 @@ gst_v4l2src_get_capture (GstV4l2Src * v4l2src)
|
||||||
&v4l2src->format) < 0) {
|
&v4l2src->format) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
||||||
("failed to get pixelformat for device %s: %s",
|
("failed to get pixelformat for device %s: %s",
|
||||||
GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,8 +249,8 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
|
||||||
&v4l2src->format) < 0) {
|
&v4l2src->format) < 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
|
||||||
("failed to set pixelformat to %s @ %dx%d for device %s: %s",
|
("failed to set pixelformat to %s @ %dx%d for device %s: %s",
|
||||||
fmt->description, width, height, GST_V4L2ELEMENT (v4l2src)->device,
|
fmt->description, width, height,
|
||||||
g_strerror (errno)));
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,72 +285,92 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
|
||||||
v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
|
v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
|
||||||
}
|
}
|
||||||
v4l2src->breq.type = v4l2src->format.type;
|
v4l2src->breq.type = v4l2src->format.type;
|
||||||
v4l2src->breq.memory = V4L2_MEMORY_MMAP;
|
if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_STREAMING) {
|
||||||
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS,
|
v4l2src->breq.memory = V4L2_MEMORY_MMAP;
|
||||||
&v4l2src->breq) < 0) {
|
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS,
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
&v4l2src->breq) < 0) {
|
||||||
(_("Could not get buffers from device \"%s\"."),
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
||||||
GST_V4L2ELEMENT (v4l2src)->device),
|
(_("Could not get buffers from device \"%s\"."),
|
||||||
("error requesting %d buffers: %s", v4l2src->breq.count,
|
GST_V4L2ELEMENT (v4l2src)->videodev),
|
||||||
g_strerror (errno)));
|
("error requesting %d buffers: %s", v4l2src->breq.count,
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
|
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
|
||||||
(_("Could not get enough buffers from device \"%s\"."),
|
|
||||||
GST_V4L2ELEMENT (v4l2src)->device),
|
|
||||||
("we received %d, we want at least %d", v4l2src->breq.count,
|
|
||||||
GST_V4L2_MIN_BUFFERS));
|
|
||||||
v4l2src->breq.count = buffers;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (v4l2src->breq.count != buffers)
|
|
||||||
g_object_notify (G_OBJECT (v4l2src), "num_buffers");
|
|
||||||
|
|
||||||
GST_INFO_OBJECT (v4l2src,
|
|
||||||
"Got %d buffers (%" GST_FOURCC_FORMAT ") of size %d KB\n",
|
|
||||||
v4l2src->breq.count,
|
|
||||||
GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat),
|
|
||||||
v4l2src->format.fmt.pix.sizeimage / 1024);
|
|
||||||
|
|
||||||
/* Map the buffers */
|
|
||||||
v4l2src->pool = g_new (GstV4l2BufferPool, 1);
|
|
||||||
gst_atomic_int_init (&v4l2src->pool->refcount, 1);
|
|
||||||
v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd;
|
|
||||||
v4l2src->pool->buffer_count = v4l2src->breq.count;
|
|
||||||
v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count);
|
|
||||||
|
|
||||||
for (n = 0; n < v4l2src->breq.count; n++) {
|
|
||||||
GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n];
|
|
||||||
|
|
||||||
gst_atomic_int_init (&buffer->refcount, 1);
|
|
||||||
buffer->pool = v4l2src->pool;
|
|
||||||
buffer->buffer.index = n;
|
|
||||||
buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
||||||
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF,
|
|
||||||
&buffer->buffer) < 0) {
|
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
|
||||||
("Could not get buffer properties of buffer %d: %s", n,
|
|
||||||
g_strerror (errno)));
|
g_strerror (errno)));
|
||||||
gst_v4l2src_capture_deinit (v4l2src);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
buffer->start =
|
GST_LOG_OBJECT (v4l2src, "using default mmap method");
|
||||||
mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
|
} else if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_READWRITE) {
|
||||||
GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset);
|
v4l2src->breq.memory = 0;
|
||||||
if (buffer->start == MAP_FAILED) {
|
GST_INFO_OBJECT (v4l2src, "using fallback read method");
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
} else {
|
||||||
("Could not mmap video buffer %d: %s", n, g_strerror (errno)));
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
||||||
buffer->start = 0;
|
(_("the driver of device \"%s\" is broken."),
|
||||||
gst_v4l2src_capture_deinit (v4l2src);
|
GST_V4L2ELEMENT (v4l2src)->videodev),
|
||||||
|
("no supported read capability from %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v4l2src->breq.memory > 0) {
|
||||||
|
if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
||||||
|
(_("Could not get enough buffers from device \"%s\"."),
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev),
|
||||||
|
("we received %d, we want at least %d", v4l2src->breq.count,
|
||||||
|
GST_V4L2_MIN_BUFFERS));
|
||||||
|
v4l2src->breq.count = buffers;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
buffer->length = buffer->buffer.length;
|
if (v4l2src->breq.count != buffers)
|
||||||
if (!gst_v4l2src_queue_frame (v4l2src, n)) {
|
g_object_notify (G_OBJECT (v4l2src), "num_buffers");
|
||||||
gst_v4l2src_capture_deinit (v4l2src);
|
|
||||||
return FALSE;
|
GST_INFO_OBJECT (v4l2src,
|
||||||
|
"Got %d buffers (" GST_FOURCC_FORMAT ") of size %d KB\n",
|
||||||
|
v4l2src->breq.count,
|
||||||
|
GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat),
|
||||||
|
v4l2src->format.fmt.pix.sizeimage / 1024);
|
||||||
|
|
||||||
|
/* Map the buffers */
|
||||||
|
GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
|
||||||
|
|
||||||
|
v4l2src->pool = g_new (GstV4l2BufferPool, 1);
|
||||||
|
g_atomic_int_set (&v4l2src->pool->refcount, 1);
|
||||||
|
v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd;
|
||||||
|
v4l2src->pool->buffer_count = v4l2src->breq.count;
|
||||||
|
v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count);
|
||||||
|
|
||||||
|
for (n = 0; n < v4l2src->breq.count; n++) {
|
||||||
|
GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n];
|
||||||
|
|
||||||
|
g_atomic_int_set (&buffer->refcount, 1);
|
||||||
|
buffer->pool = v4l2src->pool;
|
||||||
|
buffer->buffer.index = n;
|
||||||
|
buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF,
|
||||||
|
&buffer->buffer) < 0) {
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
||||||
|
("Could not get buffer properties of buffer %d: %s", n,
|
||||||
|
g_strerror (errno)));
|
||||||
|
gst_v4l2src_capture_deinit (v4l2src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
buffer->start =
|
||||||
|
mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset);
|
||||||
|
if (buffer->start == MAP_FAILED) {
|
||||||
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
||||||
|
("Could not mmap video buffer %d: %s", n, g_strerror (errno)));
|
||||||
|
buffer->start = 0;
|
||||||
|
gst_v4l2src_capture_deinit (v4l2src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
buffer->length = buffer->buffer.length;
|
||||||
|
if (!gst_v4l2src_queue_frame (v4l2src, n)) {
|
||||||
|
gst_v4l2src_capture_deinit (v4l2src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (v4l2src, "no buffer pool used");
|
||||||
|
v4l2src->pool = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_V4L2_SET_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_SET_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
||||||
|
@ -338,17 +394,19 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
|
||||||
|
|
||||||
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
||||||
if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
|
if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
|
||||||
gst_pad_renegotiate (v4l2src->srcpad);
|
/* gst_pad_renegotiate (v4l2src->srcpad); FIX: is it still required in 0.10 */
|
||||||
}
|
}
|
||||||
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
||||||
|
|
||||||
v4l2src->quit = FALSE;
|
v4l2src->quit = FALSE;
|
||||||
|
|
||||||
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) {
|
if (v4l2src->breq.memory != 0) {
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL),
|
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) {
|
||||||
("Error starting streaming capture from device %s: %s",
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL),
|
||||||
GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
|
("Error starting streaming capture from device %s: %s",
|
||||||
return FALSE;
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2src->is_capturing = TRUE;
|
v4l2src->is_capturing = TRUE;
|
||||||
|
@ -372,13 +430,16 @@ gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
|
||||||
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
||||||
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
||||||
|
|
||||||
/* we actually need to sync on all queued buffers but not
|
if (v4l2src->breq.memory != 0) {
|
||||||
* on the non-queued ones */
|
/* we actually need to sync on all queued buffers but not
|
||||||
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF, &type) < 0) {
|
* on the non-queued ones */
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL),
|
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF,
|
||||||
("Error stopping streaming capture from device %s: %s",
|
&type) < 0) {
|
||||||
GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL),
|
||||||
return FALSE;
|
("Error stopping streaming capture from device %s: %s",
|
||||||
|
GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make an optional pending wait stop */
|
/* make an optional pending wait stop */
|
||||||
|
@ -394,16 +455,18 @@ gst_v4l2src_buffer_pool_free (GstV4l2BufferPool * pool, gboolean do_close)
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
for (i = 0; i < pool->buffer_count; i++) {
|
for (i = 0; i < pool->buffer_count; i++) {
|
||||||
gst_atomic_int_destroy (&pool->buffers[i].refcount);
|
g_atomic_int_set (&pool->buffers[i].refcount, 0);
|
||||||
munmap (pool->buffers[i].start, pool->buffers[i].length);
|
munmap (pool->buffers[i].start, pool->buffers[i].length);
|
||||||
}
|
}
|
||||||
g_free (pool->buffers);
|
g_free (pool->buffers);
|
||||||
gst_atomic_int_destroy (&pool->refcount);
|
g_atomic_int_set (&pool->refcount, 0);
|
||||||
if (do_close)
|
if (do_close)
|
||||||
close (pool->video_fd);
|
close (pool->video_fd);
|
||||||
g_free (pool);
|
g_free (pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_v4l2src_free_buffer (GstBuffer * buffer)
|
gst_v4l2src_free_buffer (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
@ -411,18 +474,21 @@ gst_v4l2src_free_buffer (GstBuffer * buffer)
|
||||||
|
|
||||||
GST_LOG ("freeing buffer %p (nr. %d)", buffer, buf->buffer.index);
|
GST_LOG ("freeing buffer %p (nr. %d)", buffer, buf->buffer.index);
|
||||||
|
|
||||||
if (!gst_atomic_int_dec_and_test (&buf->refcount)) {
|
if (!g_atomic_int_dec_and_test (&buf->refcount)) {
|
||||||
/* we're still in use, add to queue again
|
/* we're still in use, add to queue again
|
||||||
note: this might fail because the device is already stopped (race) */
|
note: this might fail because the device is already stopped (race) */
|
||||||
if (ioctl (buf->pool->video_fd, VIDIOC_QBUF, &buf->buffer) < 0)
|
if (ioctl (buf->pool->video_fd, VIDIOC_QBUF, &buf->buffer) < 0)
|
||||||
GST_INFO ("readding to queue failed, assuming video device is stopped");
|
GST_INFO ("readding to queue failed, assuming video device is stopped");
|
||||||
}
|
}
|
||||||
if (gst_atomic_int_dec_and_test (&buf->pool->refcount)) {
|
if (g_atomic_int_dec_and_test (&buf->pool->refcount)) {
|
||||||
/* we're last thing that used all this */
|
/* we're last thing that used all this */
|
||||||
gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
|
gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
* gst_v4l2src_capture_deinit():
|
* gst_v4l2src_capture_deinit():
|
||||||
* deinitialize the capture system
|
* deinitialize the capture system
|
||||||
|
@ -432,31 +498,44 @@ gst_v4l2src_free_buffer (GstBuffer * buffer)
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
|
gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
|
||||||
{
|
{
|
||||||
gint i, dequeue = 0;
|
gint i;
|
||||||
|
gboolean try_reinit = FALSE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
|
GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
|
||||||
|
|
||||||
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
|
||||||
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
|
||||||
|
|
||||||
/* free the buffers */
|
if (v4l2src->pool) {
|
||||||
for (i = 0; i < v4l2src->breq.count; i++) {
|
/* free the buffers */
|
||||||
if (gst_atomic_int_dec_and_test (&v4l2src->pool->buffers[i].refcount))
|
for (i = 0; i < v4l2src->breq.count; i++) {
|
||||||
dequeue++;
|
if (g_atomic_int_dec_and_test (&v4l2src->pool->buffers[i].refcount)) {
|
||||||
|
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF,
|
||||||
|
&v4l2src->pool->buffers[i].buffer) < 0)
|
||||||
|
GST_WARNING_OBJECT (v4l2src,
|
||||||
|
"Could not dequeue buffer on uninitialization: %s - will try reinit instead",
|
||||||
|
g_strerror (errno));
|
||||||
|
try_reinit = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_atomic_int_dec_and_test (&v4l2src->pool->refcount)) {
|
||||||
|
/* we're last thing that used all this */
|
||||||
|
gst_v4l2src_buffer_pool_free (v4l2src->pool, FALSE);
|
||||||
|
}
|
||||||
|
v4l2src->pool = NULL;
|
||||||
|
/* This is our second try to get the buffers dequeued.
|
||||||
|
* Since buffers are normally dequeued automatically when capturing is
|
||||||
|
* stopped, but may be enqueued before capturing has started, you get
|
||||||
|
* a problem when you abort before capturing started but have enqueued
|
||||||
|
* the buffers. We avoid that by starting/stopping capturing once so
|
||||||
|
* they get auto-dequeued.
|
||||||
|
*/
|
||||||
|
if (try_reinit) {
|
||||||
|
if (!gst_v4l2src_capture_start (v4l2src) ||
|
||||||
|
!gst_v4l2src_capture_stop (v4l2src))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < dequeue; i++) {
|
|
||||||
struct v4l2_buffer buffer;
|
|
||||||
|
|
||||||
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
||||||
if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0)
|
|
||||||
GST_WARNING_OBJECT (v4l2src,
|
|
||||||
"Could not dequeue buffer on uninitialization");
|
|
||||||
}
|
|
||||||
if (gst_atomic_int_dec_and_test (&v4l2src->pool->refcount)) {
|
|
||||||
/* we're last thing that used all this */
|
|
||||||
gst_v4l2src_buffer_pool_free (v4l2src->pool, FALSE);
|
|
||||||
}
|
|
||||||
v4l2src->pool = NULL;
|
|
||||||
|
|
||||||
GST_V4L2_SET_INACTIVE (GST_V4L2ELEMENT (v4l2src));
|
GST_V4L2_SET_INACTIVE (GST_V4L2ELEMENT (v4l2src));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -474,8 +553,7 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
|
||||||
{
|
{
|
||||||
struct v4l2_format fmt;
|
struct v4l2_format fmt;
|
||||||
|
|
||||||
GST_LOG_OBJECT (v4l2src,
|
GST_LOG_OBJECT (v4l2src, "getting size limits with format " GST_FOURCC_FORMAT,
|
||||||
"getting size limits with format %" GST_FOURCC_FORMAT,
|
|
||||||
GST_FOURCC_ARGS (format->pixelformat));
|
GST_FOURCC_ARGS (format->pixelformat));
|
||||||
|
|
||||||
/* get size delimiters */
|
/* get size delimiters */
|
||||||
|
@ -511,3 +589,212 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d)
|
||||||
|
{
|
||||||
|
v4l2_std_id std;
|
||||||
|
const GList *item;
|
||||||
|
|
||||||
|
if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!gst_v4l2_get_norm (GST_V4L2ELEMENT (v4l2src), &std))
|
||||||
|
return FALSE;
|
||||||
|
for (item = GST_V4L2ELEMENT (v4l2src)->stds; item != NULL; item = item->next) {
|
||||||
|
GstV4l2TunerNorm *v4l2norm = item->data;
|
||||||
|
|
||||||
|
if (v4l2norm->index == std) {
|
||||||
|
*fps_n =
|
||||||
|
gst_value_get_fraction_numerator (&GST_TUNER_NORM (v4l2norm)->
|
||||||
|
framerate);
|
||||||
|
*fps_d =
|
||||||
|
gst_value_get_fraction_denominator (&GST_TUNER_NORM (v4l2norm)->
|
||||||
|
framerate);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
/* get a list of possible framerates
|
||||||
|
* this is only done for webcams;
|
||||||
|
* other devices return NULL here.
|
||||||
|
* this function takes a LONG time to execute.
|
||||||
|
*/
|
||||||
|
GValue *
|
||||||
|
gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src)
|
||||||
|
{
|
||||||
|
gint fps_index;
|
||||||
|
struct video_window *vwin = &GST_V4L2ELEMENT (v4l2src)->vwin;
|
||||||
|
GstV4l2Element *v4l2element = GST_V4L2ELEMENT (v4l2src);
|
||||||
|
|
||||||
|
/* check if we have vwin window properties giving a framerate,
|
||||||
|
* as is done for webcams
|
||||||
|
* See http://www.smcc.demon.nl/webcam/api.html
|
||||||
|
* which is used for the Philips and qce-ga drivers */
|
||||||
|
fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */
|
||||||
|
|
||||||
|
/* webcams have a non-zero fps_index */
|
||||||
|
if (fps_index == 0) {
|
||||||
|
GST_DEBUG_OBJECT (v4l2src, "fps_index is 0, no webcam");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (v4l2src, "fps_index is %d, so webcam", fps_index);
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GValue *list = NULL;
|
||||||
|
GValue value = { 0 };
|
||||||
|
|
||||||
|
/* webcam detected, so try all framerates and return a list */
|
||||||
|
|
||||||
|
list = g_new0 (GValue, 1);
|
||||||
|
g_value_init (list, GST_TYPE_LIST);
|
||||||
|
|
||||||
|
/* index of 16 corresponds to 15 fps */
|
||||||
|
GST_DEBUG_OBJECT (v4l2src, "device reports fps of %d/%d (%.4f)",
|
||||||
|
fps_index * 15, 16, fps_index * 15.0 / 16);
|
||||||
|
for (i = 0; i < 63; ++i) {
|
||||||
|
/* set bits 16 to 21 to 0 */
|
||||||
|
vwin->flags &= (0x3F00 - 1);
|
||||||
|
/* set bits 16 to 21 to the index */
|
||||||
|
vwin->flags |= i << 16;
|
||||||
|
if (gst_v4l2_set_window_properties (v4l2element)) {
|
||||||
|
/* setting it succeeded. FIXME: get it and check. */
|
||||||
|
g_value_init (&value, GST_TYPE_FRACTION);
|
||||||
|
gst_value_set_fraction (&value, i * 15, 16);
|
||||||
|
gst_value_list_append_value (list, &value);
|
||||||
|
g_value_unset (&value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FIXME: set back the original fps_index */
|
||||||
|
vwin->flags &= (0x3F00 - 1);
|
||||||
|
vwin->flags |= fps_index << 16;
|
||||||
|
gst_v4l2_set_window_properties (v4l2element);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GST_TYPE_V4L2SRC_BUFFER (gst_v4l2src_buffer_get_type())
|
||||||
|
#define GST_IS_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2SRC_BUFFER))
|
||||||
|
#define GST_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2SRC_BUFFER, GstV4l2SrcBuffer))
|
||||||
|
|
||||||
|
typedef struct _GstV4l2SrcBuffer
|
||||||
|
{
|
||||||
|
GstBuffer buffer;
|
||||||
|
|
||||||
|
GstV4l2Buffer *buf;
|
||||||
|
} GstV4l2SrcBuffer;
|
||||||
|
|
||||||
|
static void gst_v4l2src_buffer_class_init (gpointer g_class,
|
||||||
|
gpointer class_data);
|
||||||
|
static void gst_v4l2src_buffer_init (GTypeInstance * instance,
|
||||||
|
gpointer g_class);
|
||||||
|
static void gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer);
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_v4l2src_buffer_get_type (void)
|
||||||
|
{
|
||||||
|
static GType _gst_v4l2src_buffer_type;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (_gst_v4l2src_buffer_type == 0)) {
|
||||||
|
static const GTypeInfo v4l2src_buffer_info = {
|
||||||
|
sizeof (GstBufferClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
gst_v4l2src_buffer_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstV4l2SrcBuffer),
|
||||||
|
0,
|
||||||
|
gst_v4l2src_buffer_init,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
_gst_v4l2src_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
||||||
|
"GstV4l2SrcBuffer", &v4l2src_buffer_info, 0);
|
||||||
|
}
|
||||||
|
return _gst_v4l2src_buffer_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_v4l2src_buffer_class_init (gpointer g_class, gpointer class_data)
|
||||||
|
{
|
||||||
|
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
||||||
|
|
||||||
|
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
||||||
|
gst_v4l2src_buffer_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_v4l2src_buffer_init (GTypeInstance * instance, gpointer g_class)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer)
|
||||||
|
{
|
||||||
|
GstV4l2Buffer *buf = v4l2src_buffer->buf;
|
||||||
|
|
||||||
|
if (buf) {
|
||||||
|
|
||||||
|
GST_LOG ("freeing buffer %p (nr. %d)", buf, buf->buffer.index);
|
||||||
|
|
||||||
|
if (!g_atomic_int_dec_and_test (&buf->refcount)) {
|
||||||
|
/* we're still in use, add to queue again
|
||||||
|
note: this might fail because the device is already stopped (race) */
|
||||||
|
if (ioctl (buf->pool->video_fd, VIDIOC_QBUF, &buf->buffer) < 0)
|
||||||
|
GST_INFO ("readding to queue failed, assuming video device is stopped");
|
||||||
|
}
|
||||||
|
if (g_atomic_int_dec_and_test (&buf->pool->refcount)) {
|
||||||
|
/* we're last thing that used all this */
|
||||||
|
gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a V4l2Src buffer from our mmap'd data area */
|
||||||
|
GstBuffer *
|
||||||
|
gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data,
|
||||||
|
GstV4l2Buffer * srcbuf)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
gint fps_n, fps_d;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (v4l2src, "creating buffer %d");
|
||||||
|
|
||||||
|
g_return_val_if_fail (gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d), NULL);
|
||||||
|
|
||||||
|
buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4L2SRC_BUFFER);
|
||||||
|
|
||||||
|
GST_V4L2SRC_BUFFER (buf)->buf = srcbuf;
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
GST_BUFFER_DATA (buf) = g_malloc (size);
|
||||||
|
} else {
|
||||||
|
GST_BUFFER_DATA (buf) = data;
|
||||||
|
}
|
||||||
|
GST_BUFFER_SIZE (buf) = size;
|
||||||
|
|
||||||
|
GST_BUFFER_TIMESTAMP (buf) =
|
||||||
|
gst_clock_get_time (GST_ELEMENT (v4l2src)->clock);
|
||||||
|
GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4l2src)->base_time;
|
||||||
|
|
||||||
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
|
||||||
|
GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND,
|
||||||
|
fps_n, fps_d);
|
||||||
|
|
||||||
|
/* the negotiate() method already set caps on the source pad */
|
||||||
|
gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4l2src)));
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
|
@ -24,30 +24,38 @@
|
||||||
#include "v4l2_calls.h"
|
#include "v4l2_calls.h"
|
||||||
|
|
||||||
|
|
||||||
gboolean gst_v4l2src_get_capture (GstV4l2Src *v4l2src);
|
gboolean gst_v4l2src_get_capture (GstV4l2Src *v4l2src);
|
||||||
gboolean gst_v4l2src_set_capture (GstV4l2Src *v4l2src,
|
gboolean gst_v4l2src_set_capture (GstV4l2Src *v4l2src,
|
||||||
struct v4l2_fmtdesc *fmt,
|
struct v4l2_fmtdesc *fmt,
|
||||||
gint width,
|
gint width,
|
||||||
gint height);
|
gint height);
|
||||||
gboolean gst_v4l2src_capture_init (GstV4l2Src *v4l2src);
|
gboolean gst_v4l2src_capture_init (GstV4l2Src *v4l2src);
|
||||||
gboolean gst_v4l2src_capture_start (GstV4l2Src *v4l2src);
|
gboolean gst_v4l2src_capture_start (GstV4l2Src *v4l2src);
|
||||||
gint gst_v4l2src_grab_frame (GstV4l2Src *v4l2src);
|
gint gst_v4l2src_grab_frame (GstV4l2Src *v4l2src);
|
||||||
guint8 * gst_v4l2src_get_buffer (GstV4l2Src *v4l2src,
|
|
||||||
gint num);
|
|
||||||
gboolean gst_v4l2src_queue_frame (GstV4l2Src *v4l2src,
|
|
||||||
guint i);
|
|
||||||
gboolean gst_v4l2src_capture_stop (GstV4l2Src *v4l2src);
|
|
||||||
gboolean gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src);
|
|
||||||
|
|
||||||
gboolean gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src);
|
gboolean gst_v4l2src_queue_frame (GstV4l2Src *v4l2src,
|
||||||
gboolean gst_v4l2src_clear_format_list (GstV4l2Src *v4l2src);
|
guint i);
|
||||||
|
gboolean gst_v4l2src_capture_stop (GstV4l2Src *v4l2src);
|
||||||
|
gboolean gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src);
|
||||||
|
|
||||||
|
gboolean gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src);
|
||||||
|
gboolean gst_v4l2src_clear_format_list (GstV4l2Src *v4l2src);
|
||||||
|
|
||||||
/* hacky */
|
/* hacky */
|
||||||
gboolean gst_v4l2src_get_size_limits (GstV4l2Src *v4l2src,
|
gboolean gst_v4l2src_get_size_limits (GstV4l2Src *v4l2src,
|
||||||
struct v4l2_fmtdesc *fmt,
|
struct v4l2_fmtdesc *fmt,
|
||||||
gint *min_w, gint *max_w,
|
gint *min_w, gint *max_w,
|
||||||
gint *min_h, gint *max_h);
|
gint *min_h, gint *max_h);
|
||||||
|
|
||||||
void gst_v4l2src_free_buffer (GstBuffer *buffer);
|
void gst_v4l2src_free_buffer (GstBuffer *buffer);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d);
|
||||||
|
|
||||||
|
GValue * gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src);
|
||||||
|
|
||||||
|
GstBuffer * gst_v4l2src_buffer_new (GstV4l2Src * v4l2src,
|
||||||
|
guint size, guint8 * data,
|
||||||
|
GstV4l2Buffer * srcbuf);
|
||||||
|
|
||||||
#endif /* __V4L2SRC_CALLS_H__ */
|
#endif /* __V4L2SRC_CALLS_H__ */
|
||||||
|
|
Loading…
Reference in a new issue