v4l2: port to 0.11

This commit is contained in:
Wim Taymans 2011-07-08 12:49:12 +02:00
parent a3a253af15
commit e20d6f0bb5
6 changed files with 93 additions and 238 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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