v4l2: port and enable v4l2sink

This commit is contained in:
Wim Taymans 2011-07-08 16:10:47 +02:00
parent b8640c8cd9
commit 7a296af37f
4 changed files with 36 additions and 135 deletions

View file

@ -19,10 +19,7 @@ libgstvideo4linux2_la_SOURCES = gstv4l2.c \
v4l2_calls.c \
v4l2src_calls.c \
$(xv_source)
if BUILD_EXPERIMENTAL
libgstvideo4linux2_la_SOURCES += gstv4l2sink.c
endif
libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \

View file

@ -32,9 +32,7 @@
#include "gstv4l2object.h"
#include "gstv4l2src.h"
#ifdef HAVE_EXPERIMENTAL
#include "gstv4l2sink.h"
#endif
#include "gstv4l2radio.h"
/* #include "gstv4l2jpegsrc.h" */
/* #include "gstv4l2mjpegsrc.h" */
@ -55,10 +53,8 @@ plugin_init (GstPlugin * plugin)
if (!gst_element_register (plugin, "v4l2src", GST_RANK_PRIMARY,
GST_TYPE_V4L2SRC) ||
#ifdef HAVE_EXPERIMENTAL
!gst_element_register (plugin, "v4l2sink", GST_RANK_NONE,
GST_TYPE_V4L2SINK) ||
#endif
!gst_element_register (plugin, "v4l2radio", GST_RANK_NONE,
GST_TYPE_V4L2RADIO) ||
/* !gst_element_register (plugin, "v4l2jpegsrc", */

View file

@ -33,18 +33,11 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug);
G_BEGIN_DECLS
GType gst_v4l2_buffer_get_type (void);
#define GST_TYPE_V4L2_BUFFER (gst_v4l2_buffer_get_type())
#define GST_IS_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER))
#define GST_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER, GstV4l2Buffer))
GType gst_v4l2_buffer_pool_get_type (void);
#define GST_TYPE_V4L2_BUFFER_POOL (gst_v4l2_buffer_pool_get_type())
#define GST_IS_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER_POOL))
#define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool))
typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
typedef struct _GstMetaV4l2 GstMetaV4l2;

View file

@ -98,43 +98,6 @@ GST_IMPLEMENT_V4L2_XOVERLAY_METHODS (GstV4l2Sink, gst_v4l2sink);
#endif
GST_IMPLEMENT_V4L2_VIDORIENT_METHODS (GstV4l2Sink, gst_v4l2sink);
static gboolean
gst_v4l2sink_iface_supported (GstImplementsInterface * iface, GType iface_type)
{
GstV4l2Object *v4l2object = GST_V4L2SINK (iface)->v4l2object;
#ifdef HAVE_XVIDEO
g_assert (iface_type == GST_TYPE_X_OVERLAY ||
iface_type == GST_TYPE_NAVIGATION ||
iface_type == GST_TYPE_COLOR_BALANCE ||
iface_type == GST_TYPE_VIDEO_ORIENTATION || iface_type == GST_TYPE_TUNER);
#else
g_assert (iface_type == GST_TYPE_COLOR_BALANCE ||
iface_type == GST_TYPE_VIDEO_ORIENTATION || iface_type == GST_TYPE_TUNER);
#endif
if (v4l2object->video_fd == -1)
return FALSE;
#ifdef HAVE_XVIDEO
if (!GST_V4L2_IS_OVERLAY (v4l2object)) {
if (iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_NAVIGATION)
return FALSE;
}
#endif
return TRUE;
}
static void
gst_v4l2sink_interface_init (GstImplementsInterfaceClass * klass)
{
/*
* default virtual functions
*/
klass->supported = gst_v4l2sink_iface_supported;
}
#ifdef HAVE_XVIDEO
static void gst_v4l2sink_navigation_send_event (GstNavigation * navigation,
GstStructure * structure);
@ -145,66 +108,20 @@ gst_v4l2sink_navigation_init (GstNavigationInterface * iface)
}
#endif
static void
gst_v4l2sink_init_interfaces (GType type)
{
static const GInterfaceInfo v4l2iface_info = {
(GInterfaceInitFunc) gst_v4l2sink_interface_init,
NULL,
NULL,
};
static const GInterfaceInfo v4l2_tuner_info = {
(GInterfaceInitFunc) gst_v4l2sink_tuner_interface_init,
NULL,
NULL,
};
#define gst_v4l2sink_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstV4l2Sink, gst_v4l2sink, GST_TYPE_VIDEO_SINK,
G_IMPLEMENT_INTERFACE (GST_TYPE_TUNER, gst_v4l2sink_tuner_interface_init);
#ifdef HAVE_XVIDEO
static const GInterfaceInfo v4l2_xoverlay_info = {
(GInterfaceInitFunc) gst_v4l2sink_xoverlay_interface_init,
NULL,
NULL,
};
static const GInterfaceInfo v4l2_navigation_info = {
(GInterfaceInitFunc) gst_v4l2sink_navigation_init,
NULL,
NULL,
};
G_IMPLEMENT_INTERFACE (GST_TYPE_X_OVERLAY,
gst_v4l2sink_xoverlay_interface_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, gst_v4l2sink_navigation_init);
#endif
static const GInterfaceInfo v4l2_colorbalance_info = {
(GInterfaceInitFunc) gst_v4l2sink_color_balance_interface_init,
NULL,
NULL,
};
static const GInterfaceInfo v4l2_videoorientation_info = {
(GInterfaceInitFunc) gst_v4l2sink_video_orientation_interface_init,
NULL,
NULL,
};
static const GInterfaceInfo v4l2_propertyprobe_info = {
(GInterfaceInitFunc) gst_v4l2sink_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);
g_type_add_interface_static (type,
GST_TYPE_NAVIGATION, &v4l2_navigation_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 (GstV4l2Sink, gst_v4l2sink, GstVideoSink,
GST_TYPE_VIDEO_SINK, gst_v4l2sink_init_interfaces);
G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
gst_v4l2sink_color_balance_interface_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION,
gst_v4l2sink_video_orientation_interface_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
gst_v4l2sink_property_probe_interface_init));
static void gst_v4l2sink_dispose (GObject * object);
@ -222,33 +139,15 @@ static GstStateChangeReturn gst_v4l2sink_change_state (GstElement * element,
GstStateChange transition);
/* GstBaseSink methods: */
static GstCaps *gst_v4l2sink_get_caps (GstBaseSink * bsink);
static GstCaps *gst_v4l2sink_get_caps (GstBaseSink * bsink, GstCaps * filter);
static gboolean gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps);
#if 0
static GstFlowReturn gst_v4l2sink_buffer_alloc (GstBaseSink * bsink,
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
#endif
static GstFlowReturn gst_v4l2sink_show_frame (GstBaseSink * bsink,
GstBuffer * buf);
static void
gst_v4l2sink_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
GstV4l2SinkClass *gstv4l2sink_class = GST_V4L2SINK_CLASS (g_class);
gstv4l2sink_class->v4l2_class_devices = NULL;
GST_DEBUG_CATEGORY_INIT (v4l2sink_debug, "v4l2sink", 0, "V4L2 sink element");
gst_element_class_set_details_simple (gstelement_class,
"Video (video4linux2) Sink", "Sink/Video",
"Displays frames on a video4linux2 device", "Rob Clark <rob@ti.com>,");
gst_element_class_add_pad_template
(gstelement_class,
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_v4l2_object_get_all_caps ()));
}
static void
gst_v4l2sink_class_init (GstV4l2SinkClass * klass)
{
@ -314,14 +213,26 @@ gst_v4l2sink_class_init (GstV4l2SinkClass * klass)
"The height of the video crop; default is equal to negotiated image height",
0, 0xffffffff, 0, G_PARAM_READWRITE));
gst_element_class_set_details_simple (element_class,
"Video (video4linux2) Sink", "Sink/Video",
"Displays frames on a video4linux2 device", "Rob Clark <rob@ti.com>,");
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_v4l2_object_get_all_caps ()));
basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps);
basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps);
basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc);
basesink_class->render = GST_DEBUG_FUNCPTR (gst_v4l2sink_show_frame);
klass->v4l2_class_devices = NULL;
GST_DEBUG_CATEGORY_INIT (v4l2sink_debug, "v4l2sink", 0, "V4L2 sink element");
}
static void
gst_v4l2sink_init (GstV4l2Sink * v4l2sink, GstV4l2SinkClass * klass)
gst_v4l2sink_init (GstV4l2Sink * v4l2sink)
{
v4l2sink->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2sink),
V4L2_BUF_TYPE_VIDEO_OUTPUT, DEFAULT_PROP_DEVICE,
@ -642,7 +553,7 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
static GstCaps *
gst_v4l2sink_get_caps (GstBaseSink * bsink)
gst_v4l2sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
{
GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
GstCaps *ret;
@ -769,6 +680,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
return TRUE;
}
#if 0
/* buffer alloc function to implement pad_alloc for upstream element */
static GstFlowReturn
gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
@ -829,6 +741,7 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
return GST_FLOW_ERROR;
}
}
#endif
/* called after A/V sync to render frame */
static GstFlowReturn
@ -839,6 +752,7 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf);
#if 0
if (!GST_IS_V4L2_BUFFER (buf)) {
GstFlowReturn ret;
@ -886,8 +800,9 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
buf = newbuf;
}
#endif
if (!gst_v4l2_buffer_pool_qbuf (v4l2sink->pool, GST_V4L2_BUFFER (buf))) {
if (!gst_v4l2_buffer_pool_qbuf (v4l2sink->pool, buf)) {
return GST_FLOW_ERROR;
}
if (v4l2sink->state == STATE_PENDING_STREAMON) {
@ -907,7 +822,7 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
*/
if (gst_v4l2_buffer_pool_available_buffers (v4l2sink->pool) >
v4l2sink->min_queued_bufs) {
GstV4l2Buffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (v4l2sink->pool);
GstBuffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (v4l2sink->pool);
/* note: if we get a buf, we don't want to use it directly (because
* someone else could still hold a ref).. but instead we release our