mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
v4l2: port to 0.11
This commit is contained in:
parent
a3a253af15
commit
e20d6f0bb5
6 changed files with 93 additions and 238 deletions
|
@ -64,8 +64,8 @@ gst_meta_v4l2_get_info (void)
|
||||||
meta_info =
|
meta_info =
|
||||||
gst_meta_register ("GstMetaV4l2", "GstMetaV4l2",
|
gst_meta_register ("GstMetaV4l2", "GstMetaV4l2",
|
||||||
sizeof (GstMetaV4l2), (GstMetaInitFunction) NULL,
|
sizeof (GstMetaV4l2), (GstMetaInitFunction) NULL,
|
||||||
(GstMetaFreeFunction) NULL, (GstMetaTransformFunction) NULL,
|
(GstMetaFreeFunction) NULL, (GstMetaCopyFunction) NULL,
|
||||||
(GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL);
|
(GstMetaTransformFunction) NULL);
|
||||||
}
|
}
|
||||||
return meta_info;
|
return meta_info;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,6 @@ gst_v4l2_buffer_dispose (GstBuffer * buffer)
|
||||||
/* FIXME: check that the caps didn't change */
|
/* FIXME: check that the caps didn't change */
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
|
GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
|
||||||
gst_buffer_ref (buffer);
|
gst_buffer_ref (buffer);
|
||||||
GST_BUFFER_SIZE (buffer) = 0;
|
|
||||||
pool->buffers[index] = buffer;
|
pool->buffers[index] = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +118,8 @@ gst_v4l2_buffer_dispose (GstBuffer * buffer)
|
||||||
if (!resuscitated) {
|
if (!resuscitated) {
|
||||||
GST_LOG_OBJECT (pool->v4l2elem,
|
GST_LOG_OBJECT (pool->v4l2elem,
|
||||||
"buffer %p (data %p, len %u) not recovered, unmapping",
|
"buffer %p (data %p, len %u) not recovered, unmapping",
|
||||||
buffer, GST_BUFFER_DATA (buffer), meta->vbuffer.length);
|
buffer, meta->mem, meta->vbuffer.length);
|
||||||
v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), meta->vbuffer.length);
|
v4l2_munmap (meta->mem, meta->vbuffer.length);
|
||||||
|
|
||||||
g_object_unref (pool);
|
g_object_unref (pool);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +129,6 @@ static GstBuffer *
|
||||||
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
|
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstBuffer *ret;
|
GstBuffer *ret;
|
||||||
guint8 *mem;
|
|
||||||
GstMetaV4l2 *meta;
|
GstMetaV4l2 *meta;
|
||||||
|
|
||||||
ret = gst_buffer_new ();
|
ret = gst_buffer_new ();
|
||||||
|
@ -163,19 +161,15 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " length: %u", meta->vbuffer.length);
|
GST_LOG_OBJECT (pool->v4l2elem, " length: %u", meta->vbuffer.length);
|
||||||
GST_LOG_OBJECT (pool->v4l2elem, " input: %u", meta->vbuffer.input);
|
GST_LOG_OBJECT (pool->v4l2elem, " input: %u", meta->vbuffer.input);
|
||||||
|
|
||||||
mem = (guint8 *) v4l2_mmap (0, meta->vbuffer.length,
|
meta->mem = v4l2_mmap (0, meta->vbuffer.length,
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
|
PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
|
||||||
meta->vbuffer.m.offset);
|
meta->vbuffer.m.offset);
|
||||||
|
if (meta->mem == MAP_FAILED)
|
||||||
if (mem == MAP_FAILED)
|
|
||||||
goto mmap_failed;
|
goto mmap_failed;
|
||||||
|
|
||||||
GST_BUFFER_DATA (ret) = mem;
|
gst_buffer_take_memory (ret, -1,
|
||||||
GST_BUFFER_SIZE (ret) = meta->vbuffer.length;
|
gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
||||||
|
meta->mem, NULL, meta->vbuffer.length, 0, meta->vbuffer.length));
|
||||||
GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
|
|
||||||
|
|
||||||
gst_buffer_set_caps (ret, caps);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -468,7 +462,7 @@ gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
|
||||||
GstMetaV4l2 *meta = GST_META_V4L2_GET (buf);
|
GstMetaV4l2 *meta = GST_META_V4L2_GET (buf);
|
||||||
|
|
||||||
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
GST_V4L2_BUFFER_POOL_LOCK (pool);
|
||||||
GST_BUFFER_SIZE (buf) = meta->vbuffer.length;
|
gst_buffer_resize (buf, 0, meta->vbuffer.length);
|
||||||
GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
|
GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
|
||||||
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
||||||
}
|
}
|
||||||
|
@ -563,7 +557,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
|
||||||
GST_BUFFER_FLAG_UNSET (pool_buffer, GST_VIDEO_BUFFER_TFF);
|
GST_BUFFER_FLAG_UNSET (pool_buffer, GST_VIDEO_BUFFER_TFF);
|
||||||
|
|
||||||
/* this can change at every frame, esp. with jpeg */
|
/* this can change at every frame, esp. with jpeg */
|
||||||
GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
|
gst_buffer_resize (pool_buffer, 0, buffer.bytesused);
|
||||||
|
|
||||||
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
GST_V4L2_BUFFER_POOL_UNLOCK (pool);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct _GstV4l2BufferPool
|
||||||
struct _GstMetaV4l2 {
|
struct _GstMetaV4l2 {
|
||||||
GstMeta meta;
|
GstMeta meta;
|
||||||
|
|
||||||
|
gpointer mem;
|
||||||
struct v4l2_buffer vbuffer;
|
struct v4l2_buffer vbuffer;
|
||||||
|
|
||||||
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
|
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
|
||||||
|
|
|
@ -29,14 +29,9 @@
|
||||||
#include "gstv4l2colorbalance.h"
|
#include "gstv4l2colorbalance.h"
|
||||||
#include "gstv4l2object.h"
|
#include "gstv4l2object.h"
|
||||||
|
|
||||||
GST_BOILERPLATE (GstV4l2ColorBalanceChannel,
|
#define gst_v4l2_color_balance_channel_parent_class parent_class
|
||||||
gst_v4l2_color_balance_channel,
|
G_DEFINE_TYPE (GstV4l2ColorBalanceChannel,
|
||||||
GstColorBalanceChannel, GST_TYPE_COLOR_BALANCE_CHANNEL);
|
gst_v4l2_color_balance_channel, GST_TYPE_COLOR_BALANCE_CHANNEL);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2_color_balance_channel_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
|
gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
|
||||||
|
@ -45,8 +40,7 @@ gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel,
|
gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel)
|
||||||
GstV4l2ColorBalanceChannelClass * klass)
|
|
||||||
{
|
{
|
||||||
channel->id = (guint32) - 1;
|
channel->id = (guint32) - 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,67 +257,20 @@ GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Radio, gst_v4l2radio);
|
||||||
static void gst_v4l2radio_uri_handler_init (gpointer g_iface,
|
static void gst_v4l2radio_uri_handler_init (gpointer g_iface,
|
||||||
gpointer iface_data);
|
gpointer iface_data);
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_v4l2radio_interface_supported (GstImplementsInterface * iface,
|
|
||||||
GType iface_type)
|
|
||||||
{
|
|
||||||
if (iface_type == GST_TYPE_TUNER)
|
|
||||||
return TRUE;
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2radio_implements_interface_init (GstImplementsInterfaceClass * iface)
|
|
||||||
{
|
|
||||||
iface->supported = gst_v4l2radio_interface_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2radio_tuner_interface_reinit (GstTunerClass * iface)
|
gst_v4l2radio_tuner_interface_reinit (GstTunerClass * iface)
|
||||||
{
|
{
|
||||||
gst_v4l2radio_tuner_interface_init (iface);
|
gst_v4l2radio_tuner_interface_init (iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#define gst_v4l2radio_parent_class parent_class
|
||||||
gst_v4l2radio_interfaces (GType type)
|
G_DEFINE_TYPE_WITH_CODE (GstV4l2Radio, gst_v4l2radio, GST_TYPE_ELEMENT,
|
||||||
{
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
|
||||||
static const GInterfaceInfo urihandler_info = {
|
gst_v4l2radio_uri_handler_init);
|
||||||
(GInterfaceInitFunc) gst_v4l2radio_uri_handler_init,
|
G_IMPLEMENT_INTERFACE (GST_TYPE_TUNER,
|
||||||
NULL,
|
gst_v4l2radio_tuner_interface_reinit);
|
||||||
NULL
|
G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
|
||||||
};
|
gst_v4l2radio_property_probe_interface_init));
|
||||||
|
|
||||||
static const GInterfaceInfo implements_interface_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2radio_implements_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GInterfaceInfo propertyprobe_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2radio_property_probe_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GInterfaceInfo tuner_interface_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2radio_tuner_interface_reinit,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
|
|
||||||
g_type_add_interface_static (type,
|
|
||||||
GST_TYPE_IMPLEMENTS_INTERFACE, &implements_interface_info);
|
|
||||||
|
|
||||||
g_type_add_interface_static (type, GST_TYPE_TUNER, &tuner_interface_info);
|
|
||||||
|
|
||||||
g_type_add_interface_static (type,
|
|
||||||
GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstV4l2Radio, gst_v4l2radio, GstElement, GST_TYPE_ELEMENT,
|
|
||||||
gst_v4l2radio_interfaces);
|
|
||||||
|
|
||||||
static void gst_v4l2radio_set_property (GObject * object, guint prop_id,
|
static void gst_v4l2radio_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -328,24 +281,6 @@ static void gst_v4l2radio_dispose (GObject * object);
|
||||||
static GstStateChangeReturn gst_v4l2radio_change_state (GstElement * element,
|
static GstStateChangeReturn gst_v4l2radio_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2radio_base_init (gpointer gclass)
|
|
||||||
{
|
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (gclass);
|
|
||||||
GstV4l2RadioClass *gstv4l2radio_class = GST_V4L2RADIO_CLASS (gclass);
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (v4l2radio_debug, "v4l2radio", 0,
|
|
||||||
"V4l2 radio element");
|
|
||||||
|
|
||||||
gstv4l2radio_class->v4l2_class_devices = NULL;
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (gstelement_class,
|
|
||||||
"Radio (video4linux2) Tuner",
|
|
||||||
"Tuner",
|
|
||||||
"Controls a Video4Linux2 radio device",
|
|
||||||
"Alexey Chernov <4ernov@gmail.com>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
|
gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -355,6 +290,8 @@ gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
gstelement_class = (GstElementClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->dispose = gst_v4l2radio_dispose;
|
||||||
|
gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2radio_finalize;
|
||||||
gobject_class->set_property = gst_v4l2radio_set_property;
|
gobject_class->set_property = gst_v4l2radio_set_property;
|
||||||
gobject_class->get_property = gst_v4l2radio_get_property;
|
gobject_class->get_property = gst_v4l2radio_get_property;
|
||||||
|
|
||||||
|
@ -368,16 +305,23 @@ gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
|
||||||
"Station frequency in Hz",
|
"Station frequency in Hz",
|
||||||
MIN_FREQUENCY, MAX_FREQUENCY, DEFAULT_FREQUENCY, G_PARAM_READWRITE));
|
MIN_FREQUENCY, MAX_FREQUENCY, DEFAULT_FREQUENCY, G_PARAM_READWRITE));
|
||||||
|
|
||||||
gobject_class->dispose = gst_v4l2radio_dispose;
|
|
||||||
gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2radio_finalize;
|
|
||||||
|
|
||||||
gstelement_class->change_state =
|
gstelement_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_v4l2radio_change_state);
|
GST_DEBUG_FUNCPTR (gst_v4l2radio_change_state);
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"Radio (video4linux2) Tuner",
|
||||||
|
"Tuner",
|
||||||
|
"Controls a Video4Linux2 radio device",
|
||||||
|
"Alexey Chernov <4ernov@gmail.com>");
|
||||||
|
|
||||||
|
klass->v4l2_class_devices = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (v4l2radio_debug, "v4l2radio", 0,
|
||||||
|
"V4l2 radio element");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2radio_init (GstV4l2Radio * filter, GstV4l2RadioClass * gclass)
|
gst_v4l2radio_init (GstV4l2Radio * filter)
|
||||||
{
|
{
|
||||||
filter->v4l2object = gst_v4l2_object_new (GST_ELEMENT (filter),
|
filter->v4l2object = gst_v4l2_object_new (GST_ELEMENT (filter),
|
||||||
V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
|
V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
|
||||||
|
@ -563,13 +507,13 @@ gst_v4l2radio_get_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
/* GstURIHandler interface */
|
/* GstURIHandler interface */
|
||||||
static GstURIType
|
static GstURIType
|
||||||
gst_v4l2radio_uri_get_type (void)
|
gst_v4l2radio_uri_get_type (GType type)
|
||||||
{
|
{
|
||||||
return GST_URI_SRC;
|
return GST_URI_SRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar **
|
static gchar **
|
||||||
gst_v4l2radio_uri_get_protocols (void)
|
gst_v4l2radio_uri_get_protocols (GType type)
|
||||||
{
|
{
|
||||||
static gchar *protocols[] = { (char *) "radio", NULL };
|
static gchar *protocols[] = { (char *) "radio", NULL };
|
||||||
return protocols;
|
return protocols;
|
||||||
|
|
|
@ -89,102 +89,21 @@ GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Src, gst_v4l2src);
|
||||||
static void gst_v4l2src_uri_handler_init (gpointer g_iface,
|
static void gst_v4l2src_uri_handler_init (gpointer g_iface,
|
||||||
gpointer iface_data);
|
gpointer iface_data);
|
||||||
|
|
||||||
static gboolean
|
#define gst_v4l2src_parent_class parent_class
|
||||||
gst_v4l2src_iface_supported (GstImplementsInterface * iface, GType iface_type)
|
G_DEFINE_TYPE_WITH_CODE (GstV4l2Src, gst_v4l2src, GST_TYPE_PUSH_SRC,
|
||||||
{
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_v4l2src_uri_handler_init);
|
||||||
GstV4l2Object *v4l2object = GST_V4L2SRC (iface)->v4l2object;
|
G_IMPLEMENT_INTERFACE (GST_TYPE_TUNER, gst_v4l2src_tuner_interface_init);
|
||||||
|
|
||||||
#ifdef HAVE_XVIDEO
|
#ifdef HAVE_XVIDEO
|
||||||
g_assert (iface_type == GST_TYPE_TUNER ||
|
/* FIXME: does GstXOverlay for v4l2src make sense in a GStreamer context? */
|
||||||
iface_type == GST_TYPE_X_OVERLAY ||
|
G_IMPLEMENT_INTERFACE (GST_TYPE_X_OVERLAY,
|
||||||
iface_type == GST_TYPE_COLOR_BALANCE ||
|
gst_v4l2src_xoverlay_interface_init);
|
||||||
iface_type == GST_TYPE_VIDEO_ORIENTATION);
|
|
||||||
#else
|
|
||||||
g_assert (iface_type == GST_TYPE_TUNER ||
|
|
||||||
iface_type == GST_TYPE_COLOR_BALANCE ||
|
|
||||||
iface_type == GST_TYPE_VIDEO_ORIENTATION);
|
|
||||||
#endif
|
#endif
|
||||||
|
G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
|
||||||
if (v4l2object->video_fd == -1)
|
gst_v4l2src_color_balance_interface_init);
|
||||||
return FALSE;
|
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION,
|
||||||
|
gst_v4l2src_video_orientation_interface_init);
|
||||||
#ifdef HAVE_XVIDEO
|
G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
|
||||||
if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L2_IS_OVERLAY (v4l2object))
|
gst_v4l2src_property_probe_interface_init));
|
||||||
return FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2src_interface_init (GstImplementsInterfaceClass * klass)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* default virtual functions
|
|
||||||
*/
|
|
||||||
klass->supported = gst_v4l2src_iface_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2src_init_interfaces (GType type)
|
|
||||||
{
|
|
||||||
static const GInterfaceInfo urihandler_info = {
|
|
||||||
gst_v4l2src_uri_handler_init,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GInterfaceInfo v4l2iface_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2_tuner_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_tuner_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
#ifdef HAVE_XVIDEO
|
|
||||||
/* FIXME: does GstXOverlay for v4l2src make sense in a GStreamer context? */
|
|
||||||
static const GInterfaceInfo v4l2_xoverlay_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_xoverlay_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
static const GInterfaceInfo v4l2_colorbalance_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_color_balance_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2_videoorientation_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_video_orientation_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
static const GInterfaceInfo v4l2_propertyprobe_info = {
|
|
||||||
(GInterfaceInitFunc) gst_v4l2src_property_probe_interface_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
|
|
||||||
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_VIDEO_ORIENTATION, &v4l2_videoorientation_info);
|
|
||||||
g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
|
|
||||||
&v4l2_propertyprobe_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstV4l2Src, gst_v4l2src, GstPushSrc, GST_TYPE_PUSH_SRC,
|
|
||||||
gst_v4l2src_init_interfaces);
|
|
||||||
|
|
||||||
static void gst_v4l2src_dispose (GObject * object);
|
static void gst_v4l2src_dispose (GObject * object);
|
||||||
static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
|
static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
|
||||||
|
@ -199,7 +118,7 @@ static gboolean gst_v4l2src_unlock (GstBaseSrc * src);
|
||||||
static gboolean gst_v4l2src_unlock_stop (GstBaseSrc * src);
|
static gboolean gst_v4l2src_unlock_stop (GstBaseSrc * src);
|
||||||
static gboolean gst_v4l2src_stop (GstBaseSrc * src);
|
static gboolean gst_v4l2src_stop (GstBaseSrc * src);
|
||||||
static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
|
static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
|
||||||
static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
|
static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter);
|
||||||
static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
|
static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
|
||||||
static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
|
static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
|
||||||
static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
|
static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
|
||||||
|
@ -216,28 +135,6 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf);
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf);
|
gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf);
|
||||||
|
|
||||||
static void
|
|
||||||
gst_v4l2src_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
GstV4l2SrcClass *gstv4l2src_class = GST_V4L2SRC_CLASS (g_class);
|
|
||||||
|
|
||||||
gstv4l2src_class->v4l2_class_devices = NULL;
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (gstelement_class,
|
|
||||||
"Video (video4linux2) Source", "Source/Video",
|
|
||||||
"Reads frames from a Video4Linux2 device",
|
|
||||||
"Edgard Lima <edgard.lima@indt.org.br>,"
|
|
||||||
" Stefan Kost <ensonic@users.sf.net>");
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template
|
|
||||||
(gstelement_class,
|
|
||||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
|
||||||
gst_v4l2_object_get_all_caps ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2src_class_init (GstV4l2SrcClass * klass)
|
gst_v4l2src_class_init (GstV4l2SrcClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -281,6 +178,17 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
|
||||||
"Only use every nth frame", 1, G_MAXINT,
|
"Only use every nth frame", 1, G_MAXINT,
|
||||||
PROP_DEF_DECIMATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
PROP_DEF_DECIMATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (element_class,
|
||||||
|
"Video (video4linux2) Source", "Source/Video",
|
||||||
|
"Reads frames from a Video4Linux2 device",
|
||||||
|
"Edgard Lima <edgard.lima@indt.org.br>,"
|
||||||
|
" Stefan Kost <ensonic@users.sf.net>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template
|
||||||
|
(element_class,
|
||||||
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
gst_v4l2_object_get_all_caps ()));
|
||||||
|
|
||||||
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
|
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
|
||||||
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
|
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
|
||||||
basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
|
basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
|
||||||
|
@ -292,10 +200,14 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
|
||||||
basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
|
basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
|
||||||
|
|
||||||
pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
|
pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
|
||||||
|
|
||||||
|
klass->v4l2_class_devices = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
|
gst_v4l2src_init (GstV4l2Src * v4l2src)
|
||||||
{
|
{
|
||||||
/* fixme: give an update_fps_function */
|
/* fixme: give an update_fps_function */
|
||||||
v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
|
v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
|
||||||
|
@ -441,7 +353,7 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
|
|
||||||
/* first see what is possible on our source pad */
|
/* first see what is possible on our source pad */
|
||||||
thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
|
thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc), NULL);
|
||||||
GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
|
GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
|
||||||
LOG_CAPS (basesrc, thiscaps);
|
LOG_CAPS (basesrc, thiscaps);
|
||||||
|
|
||||||
|
@ -450,7 +362,7 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
|
||||||
goto no_nego_needed;
|
goto no_nego_needed;
|
||||||
|
|
||||||
/* get the peer caps */
|
/* get the peer caps */
|
||||||
peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
|
peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc), thiscaps);
|
||||||
GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
|
GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
|
||||||
LOG_CAPS (basesrc, peercaps);
|
LOG_CAPS (basesrc, peercaps);
|
||||||
if (peercaps && !gst_caps_is_any (peercaps)) {
|
if (peercaps && !gst_caps_is_any (peercaps)) {
|
||||||
|
@ -557,7 +469,7 @@ no_nego_needed:
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_v4l2src_get_caps (GstBaseSrc * src)
|
gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter)
|
||||||
{
|
{
|
||||||
GstV4l2Src *v4l2src = GST_V4L2SRC (src);
|
GstV4l2Src *v4l2src = GST_V4L2SRC (src);
|
||||||
GstCaps *ret;
|
GstCaps *ret;
|
||||||
|
@ -822,9 +734,10 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
||||||
{
|
{
|
||||||
|
GstFlowReturn res;
|
||||||
gint amount;
|
gint amount;
|
||||||
gint ret;
|
gint ret;
|
||||||
|
gpointer data;
|
||||||
gint buffersize;
|
gint buffersize;
|
||||||
|
|
||||||
buffersize = v4l2src->frame_byte_size;
|
buffersize = v4l2src->frame_byte_size;
|
||||||
|
@ -834,6 +747,7 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
||||||
buffersize = GST_BASE_SRC (v4l2src)->blocksize;
|
buffersize = GST_BASE_SRC (v4l2src)->blocksize;
|
||||||
|
|
||||||
*buf = gst_buffer_new_and_alloc (buffersize);
|
*buf = gst_buffer_new_and_alloc (buffersize);
|
||||||
|
data = gst_buffer_map (*buf, NULL, NULL, GST_MAP_WRITE);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE);
|
ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE);
|
||||||
|
@ -849,9 +763,8 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
||||||
goto select_error;
|
goto select_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
amount =
|
amount = v4l2_read (v4l2src->v4l2object->video_fd, data, buffersize);
|
||||||
v4l2_read (v4l2src->v4l2object->video_fd, GST_BUFFER_DATA (*buf),
|
|
||||||
buffersize);
|
|
||||||
if (amount == buffersize) {
|
if (amount == buffersize) {
|
||||||
break;
|
break;
|
||||||
} else if (amount == -1) {
|
} else if (amount == -1) {
|
||||||
|
@ -865,6 +778,8 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
||||||
}
|
}
|
||||||
} while (TRUE);
|
} while (TRUE);
|
||||||
|
|
||||||
|
gst_buffer_unmap (*buf, data, amount);
|
||||||
|
|
||||||
/* we set the buffer metadata in gst_v4l2src_create() */
|
/* we set the buffer metadata in gst_v4l2src_create() */
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -874,20 +789,28 @@ select_error:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
|
||||||
("select error %d: %s (%d)", ret, g_strerror (errno), errno));
|
("select error %d: %s (%d)", ret, g_strerror (errno), errno));
|
||||||
return GST_FLOW_ERROR;
|
res = GST_FLOW_ERROR;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
stopped:
|
stopped:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("stop called");
|
GST_DEBUG ("stop called");
|
||||||
return GST_FLOW_WRONG_STATE;
|
res = GST_FLOW_WRONG_STATE;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
read_error:
|
read_error:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
|
||||||
(_("Error reading %d bytes from device '%s'."),
|
(_("Error reading %d bytes from device '%s'."),
|
||||||
buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
|
buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM);
|
||||||
|
res = GST_FLOW_ERROR;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (*buf, data, 0);
|
||||||
gst_buffer_unref (*buf);
|
gst_buffer_unref (*buf);
|
||||||
return GST_FLOW_ERROR;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,7 +828,7 @@ again:
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (v4l2src->frame_byte_size > 0) {
|
if (v4l2src->frame_byte_size > 0) {
|
||||||
size = GST_BUFFER_SIZE (temp);
|
size = gst_buffer_get_size (temp);
|
||||||
|
|
||||||
/* if size does not match what we expected, try again */
|
/* if size does not match what we expected, try again */
|
||||||
if (size != v4l2src->frame_byte_size) {
|
if (size != v4l2src->frame_byte_size) {
|
||||||
|
@ -1009,13 +932,13 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
|
||||||
|
|
||||||
/* GstURIHandler interface */
|
/* GstURIHandler interface */
|
||||||
static GstURIType
|
static GstURIType
|
||||||
gst_v4l2src_uri_get_type (void)
|
gst_v4l2src_uri_get_type (GType type)
|
||||||
{
|
{
|
||||||
return GST_URI_SRC;
|
return GST_URI_SRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar **
|
static gchar **
|
||||||
gst_v4l2src_uri_get_protocols (void)
|
gst_v4l2src_uri_get_protocols (GType type)
|
||||||
{
|
{
|
||||||
static gchar *protocols[] = { (char *) "v4l2", NULL };
|
static gchar *protocols[] = { (char *) "v4l2", NULL };
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,6 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
|
||||||
"running out of buffers, making a copy to reuse current one");
|
"running out of buffers, making a copy to reuse current one");
|
||||||
}
|
}
|
||||||
*buf = gst_buffer_copy (pool_buffer);
|
*buf = gst_buffer_copy (pool_buffer);
|
||||||
GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
|
|
||||||
/* this will requeue */
|
/* this will requeue */
|
||||||
gst_buffer_unref (pool_buffer);
|
gst_buffer_unref (pool_buffer);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue