Commit f19cfbda authored by Rob Clark's avatar Rob Clark Committed by Sebastian Dröge

v4l2: Add v4l2sink element

This also does the following changes:
(1) pull the bufferpool code out into gstv4l2bufferpool.c, and make a
    bit more generic so it can be used both for v4l2src and v4l2sink
(2) move some of the device probing/configuration/caps stuff into
    gstv4l2object.c so it does not have to be duplicated between
    v4l2src and v4l2sink

Fixes bug #590280.
parent 56850099
......@@ -12,7 +12,9 @@ plugin_LTLIBRARIES = libgstvideo4linux2.la
libgstvideo4linux2_la_SOURCES = gstv4l2.c \
gstv4l2colorbalance.c \
gstv4l2object.c \
gstv4l2bufferpool.c \
gstv4l2src.c \
gstv4l2sink.c \
gstv4l2tuner.c \
gstv4l2vidorient.c \
v4l2_calls.c \
......@@ -31,6 +33,7 @@ libgstvideo4linux2_la_LIBTOOLFLAGS = --tag=disable-static
libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
$(GST_BASE_LIBS) \
$(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
-lgstinterfaces-$(GST_MAJORMINOR) \
$(GST_LIBS) \
$(xv_libs) \
......
......@@ -31,6 +31,7 @@
#include "gstv4l2object.h"
#include "gstv4l2src.h"
#include "gstv4l2sink.h"
/* #include "gstv4l2jpegsrc.h" */
/* #include "gstv4l2mjpegsrc.h" */
/* #include "gstv4l2mjpegsink.h" */
......@@ -44,13 +45,16 @@ plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (v4l2_debug, "v4l2", 0, "V4L2 API calls");
if (!gst_element_register (plugin, "v4l2src", GST_RANK_PRIMARY,
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)) */
GST_TYPE_V4L2SRC) ||
!gst_element_register (plugin, "v4l2sink", GST_RANK_PRIMARY,
GST_TYPE_V4L2SINK) ||
/* !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)) */
FALSE)
return FALSE;
#ifdef ENABLE_NLS
......
This diff is collapsed.
/* GStreamer
*
* Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
* 2006 Edgard Lima <edgard.lima@indt.org.br>
* 2009 Texas Instruments, Inc - http://www.ti.com/
*
* gstv4l2src.h: BT8x8/V4L2 source element
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GSTV4L2BUFFER_H__
#define __GSTV4L2BUFFER_H__
#include <gst/gst.h>
#include "v4l2_calls.h"
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 _GstV4l2Buffer GstV4l2Buffer;
struct _GstV4l2BufferPool
{
GstMiniObject parent;
GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */
gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */
enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
GMutex *lock;
gboolean running; /* with lock */
gint num_live_buffers; /* number of buffers not with driver (capture) or not in avail buffer pool (display) */
GAsyncQueue* avail_buffers;/* pool of available buffers, not with the driver and which aren't held outside the bufferpool */
gint video_fd; /* a dup(2) of the v4l2object's video_fd */
guint buffer_count;
GstV4l2Buffer **buffers;
};
struct _GstV4l2Buffer {
GstBuffer buffer;
struct v4l2_buffer vbuffer;
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
/* FIXME: do we really want to fix this if GstV4l2Buffer/Pool is shared
* between v4l2src and v4l2sink??
*/
GstV4l2BufferPool *pool;
};
G_END_DECLS
void gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool);
GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type);
GstV4l2Buffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking);
gboolean gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool *pool, GstV4l2Buffer *buf);
GstV4l2Buffer *gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool *pool);
gint gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool *pool);
#define GST_V4L2_BUFFER_POOL_LOCK(pool) g_mutex_lock ((pool)->lock)
#define GST_V4L2_BUFFER_POOL_UNLOCK(pool) g_mutex_unlock ((pool)->lock)
#endif /* __GSTV4L2BUFFER_H__ */
This diff is collapsed.
......@@ -51,6 +51,16 @@
#include <gst/interfaces/propertyprobe.h>
/* size of v4l2 buffer pool in streaming case */
#define GST_V4L2_MAX_BUFFERS 16
#define GST_V4L2_MIN_BUFFERS 1
/* max frame width/height */
#define GST_V4L2_MAX_SIZE (1<<15) /* 2^15 == 32768 */
G_BEGIN_DECLS
#define GST_V4L2_OBJECT(obj) (GstV4l2Object *)(obj)
......@@ -77,6 +87,8 @@ struct _GstV4l2Object {
/* the video buffer (mmap()'ed) */
guint8 **buffer;
enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */
/* the video device's capabilities */
struct v4l2_capability vcap;
......@@ -87,6 +99,8 @@ struct _GstV4l2Object {
struct v4l2_input vinput;
/* lists... */
GSList *formats; /* list of available capture formats */
GList *colors;
GList *norms;
GList *channels;
......@@ -121,13 +135,16 @@ GType gst_v4l2_object_get_type (void);
/* create/destroy */
GstV4l2Object * gst_v4l2_object_new (GstElement * element,
enum v4l2_buf_type type,
char *default_device,
GstV4l2GetInOutFunction get_in_out_func,
GstV4l2SetInOutFunction set_in_out_func,
GstV4l2UpdateFpsFunction update_fps_func);
void gst_v4l2_object_destroy (GstV4l2Object * v4l2object);
/* properties */
void gst_v4l2_object_install_properties_helper (GObjectClass *gobject_class);
void gst_v4l2_object_install_properties_helper (GObjectClass *gobject_class, const char *default_device);
gboolean gst_v4l2_object_set_property_helper (GstV4l2Object *v4l2object,
guint prop_id, const GValue * value,
......@@ -152,6 +169,26 @@ GValueArray* gst_v4l2_probe_get_values (GstPropertyProbe * probe, guint pro
const GParamSpec * pspec,
GList ** klass_devices);
GstCaps* gst_v4l2_object_probe_caps_for_format (GstV4l2Object *v4l2object, guint32 pixelformat,
const GstStructure * template);
gboolean gst_v4l2_object_get_caps_info (GstV4l2Object *v4l2object, GstCaps *caps,
struct v4l2_fmtdesc **format, gint *w, gint *h,
guint *fps_n, guint *fps_d, guint *size);
GSList* gst_v4l2_object_get_format_list (GstV4l2Object *v4l2object);
GstCaps* gst_v4l2_object_get_all_caps (void);
GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height);
gboolean gst_v4l2_object_start_streaming (GstV4l2Object *v4l2object);
gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object);
#define GST_IMPLEMENT_V4L2_PROBE_METHODS(Type_Class, interface_as_function) \
\
static void \
......
This diff is collapsed.
/* GStreamer
*
* Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/
*
* Description: V4L2 sink element
* Created on: Jul 2, 2009
* Author: Rob Clark <rob@ti.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GSTV4L2SINK_H__
#define __GSTV4L2SINK_H__
#include <gst/video/gstvideosink.h>
#include <gstv4l2object.h>
#include <gstv4l2bufferpool.h>
GST_DEBUG_CATEGORY_EXTERN (v4l2sink_debug);
G_BEGIN_DECLS
#define GST_TYPE_V4L2SINK \
(gst_v4l2sink_get_type())
#define GST_V4L2SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_V4L2SINK, GstV4l2Sink))
#define GST_V4L2SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_V4L2SINK, GstV4l2SinkClass))
#define GST_IS_V4L2SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_V4L2SINK))
#define GST_IS_V4L2SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_V4L2SINK))
typedef struct _GstV4l2Sink GstV4l2Sink;
typedef struct _GstV4l2SinkClass GstV4l2SinkClass;
struct _GstV4l2Sink {
GstVideoSink videosink;
/*< private >*/
GstV4l2Object * v4l2object;
GstCaps *probed_caps; /* all supported caps of underlying v4l2 device */
GstCaps *current_caps; /* the current negotiated caps */
GstV4l2BufferPool *pool;
guint32 num_buffers;
/**
* field to store requested overlay-top/left/width/height props:
* note, could maybe be combined with 'vwin' field in GstV4l2Object?
*/
struct v4l2_rect overlay;
/**
* bitmask to track which 'overlay' fields user has requested by
* setting properties:
*/
guint8 overlay_fields_set;
guint8 state;
};
struct _GstV4l2SinkClass {
GstVideoSinkClass parent_class;
GList *v4l2_class_devices;
};
GType gst_v4l2sink_get_type(void);
G_END_DECLS
#endif /* __GSTV4L2SINK_H__ */
This diff is collapsed.
......@@ -25,16 +25,10 @@
#define __GST_V4L2SRC_H__
#include <gstv4l2object.h>
#include <gstv4l2bufferpool.h>
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
/* size of v4l2 buffer pool in streaming case */
#define GST_V4L2_MAX_BUFFERS 16
#define GST_V4L2_MIN_BUFFERS 1
/* max frame width/height */
#define GST_V4L2_MAX_SIZE (1<<15) /* 2^15 == 32768 */
G_BEGIN_DECLS
#define GST_TYPE_V4L2SRC \
......@@ -48,34 +42,10 @@ G_BEGIN_DECLS
#define GST_IS_V4L2SRC_CLASS(klass) \
(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;
/* global info */
struct _GstV4l2BufferPool
{
GstMiniObject parent;
GMutex *lock;
gboolean running; /* with lock */
gint num_live_buffers; /* with lock */
gint video_fd; /* a dup(2) of the v4l2object's video_fd */
guint buffer_count;
GstV4l2Buffer **buffers; /* with lock; buffers[n] is NULL that buffer has been
* dequeued and pushed out */
};
struct _GstV4l2Buffer {
GstBuffer buffer;
struct v4l2_buffer vbuffer;
/* FIXME: have GstV4l2Src* instead, as this has GstV4l2BufferPool* */
GstV4l2BufferPool *pool;
};
/**
* GstV4l2Src:
......@@ -93,9 +63,6 @@ struct _GstV4l2Src
/* pads */
GstCaps *probed_caps;
/* internal lists */
GSList *formats; /* list of available capture formats */
/* buffer handling */
GstV4l2BufferPool *pool;
......
......@@ -46,6 +46,9 @@
#include "gstv4l2colorbalance.h"
#include "gstv4l2src.h"
#include "gstv4l2sink.h"
#include "gst/gst-i18n-plugin.h"
/* Those are ioctl calls */
#ifndef V4L2_CID_HCENTER
......@@ -449,10 +452,14 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
goto error;
/* do we need to be a capture device? */
if (GST_IS_V4L2SRC (v4l2object) &&
if (GST_IS_V4L2SRC (v4l2object->element) &&
!(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
goto not_capture;
if (GST_IS_V4L2SINK (v4l2object->element) &&
!(v4l2object->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT))
goto not_output;
/* create enumerations, posts errors. */
if (!gst_v4l2_fill_lists (v4l2object))
goto error;
......@@ -497,6 +504,14 @@ not_capture:
("Capabilities: 0x%x", v4l2object->vcap.capabilities));
goto error;
}
not_output:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a output device."),
v4l2object->videodev),
("Capabilities: 0x%x", v4l2object->vcap.capabilities));
goto error;
}
error:
{
if (GST_V4L2_IS_OPEN (v4l2object)) {
......
......@@ -25,18 +25,20 @@
#define __V4L2_CALLS_H__
#include "gstv4l2object.h"
#include "gst/gst-i18n-plugin.h"
#ifdef HAVE_LIBV4L2
#include <libv4l2.h>
# include <libv4l2.h>
#else
#define v4l2_fd_open(fd, flags) (fd)
#define v4l2_close close
#define v4l2_dup dup
#define v4l2_ioctl ioctl
#define v4l2_read read
#define v4l2_mmap mmap
#define v4l2_munmap munmap
# include <sys/ioctl.h>
# include <linux/videodev.h>
# include <linux/videodev2.h>
# define v4l2_fd_open(fd, flags) (fd)
# define v4l2_close close
# define v4l2_dup dup
# define v4l2_ioctl ioctl
# define v4l2_read read
# define v4l2_mmap mmap
# define v4l2_munmap munmap
#endif
/* simple check whether the device is open */
......@@ -137,4 +139,43 @@ gboolean gst_v4l2_set_attribute (GstV4l2Object *v4l2object,
gboolean gst_v4l2_get_capabilities (GstV4l2Object * v4l2object);
/* note: in case this is a build with TTIF logging, we can optimize slightly
* and avoid the gst_caps_to_string() in case logging isn't enabled by using
* the TTIF_TRACE_ARG_PROCESSOR feature of ttif_trace_fprintf():
*/
#ifdef GST_LOG_OVER_TTIF
# define LOG_CAPS(obj, caps) G_STMT_START { \
if (caps) { \
static TTIF_TRACE_ARG_PROCESSOR proc = { \
.convert = (char (*)(void *))gst_caps_to_string, \
.free = (void (*)(char *))g_free \
}; \
GST_DEBUG_OBJECT (obj, "%s: %qs", #caps, &proc, (caps)); \
} else { \
GST_DEBUG_OBJECT (obj, "null"); \
} \
} G_STMT_END
#else
# define LOG_CAPS(obj, caps) G_STMT_START { \
if (caps) { \
gchar *capstr = gst_caps_to_string (caps); \
GST_DEBUG_OBJECT (obj, "%s: %s", #caps, capstr); \
g_free (capstr); \
} else { \
GST_DEBUG_OBJECT (obj, "null"); \
} \
} G_STMT_END
#endif
/* note: the omapzoom kernel v4l2 display driver deviates from the v4l2 API
* spec in a few areas. For example, we must always have one buffer with
* the driver before STREAMON until after STREAMOFF. And some interfaces,
* such as rotation (and mirroring?) are different.
*
* this is only a temporary hack, as we should switch to the new driver soon
*/
#define OMAPZOOM
#endif /* __V4L2_CALLS_H__ */
This diff is collapsed.
......@@ -41,10 +41,5 @@ GstFlowReturn gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer **buf)
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);
GstCaps* gst_v4l2src_probe_caps_for_format (GstV4l2Src * v4l2src, guint32 pixelformat,
const GstStructure *template);
#endif /* __V4L2SRC_CALLS_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment