summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-06-09 12:13:38 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-06-09 19:44:21 +0300
commit1b8f9204db684eff0d52b03c47fa666bf4e495f5 (patch)
tree02fadfefd72b45a6356f36f5442212aa772425bc
parentde8d802f21e002270b0b758835fa25232a31208e (diff)
stream: Use abstract video sources
Replace the manual V4L2 capture implementation by an abstract video_source, provided by the user of the UVC stream. Removes any knowledge of the video source internals from the uvc_stream class, allowing usage of different source types. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--main.c17
-rw-r--r--stream.c158
-rw-r--r--stream.h12
3 files changed, 90 insertions, 97 deletions
diff --git a/main.c b/main.c
index a99659b..70af57f 100644
--- a/main.c
+++ b/main.c
@@ -24,6 +24,7 @@
#include "configfs.h"
#include "events.h"
#include "stream.h"
+#include "v4l2-source.h"
static void usage(const char *argv0)
{
@@ -56,7 +57,7 @@ static void usage(const char *argv0)
/* Necessary for and only used by signal handler. */
static struct events *sigint_events;
-static void sigint_handler(int signal __attribute__((__unused__)))
+static void sigint_handler(int signal)
{
/* Stop the main loop when the user presses CTRL-C */
events_stop(sigint_events);
@@ -68,6 +69,7 @@ int main(int argc, char *argv[])
char *cap_device = "/dev/video1";
struct uvc_function_config *fc;
struct uvc_stream *stream;
+ struct video_source *src = NULL;
struct events events;
int ret = 0;
int opt;
@@ -108,14 +110,24 @@ int main(int argc, char *argv[])
sigint_events = &events;
signal(SIGINT, sigint_handler);
+ /* Create and initialize a video source. */
+ src = v4l2_video_source_create(cap_device);
+ if (src == NULL) {
+ ret = 1;
+ goto done;
+ }
+
+ v4l2_video_source_init(src, &events);
+
/* Create and initialise the stream. */
- stream = uvc_stream_new(fc->video, cap_device);
+ stream = uvc_stream_new(fc->video);
if (stream == NULL) {
ret = 1;
goto done;
}
uvc_stream_set_event_handler(stream, &events);
+ uvc_stream_set_video_source(stream, src);
uvc_stream_init_uvc(stream, fc);
/* Main capture loop */
@@ -124,6 +136,7 @@ int main(int argc, char *argv[])
done:
/* Cleanup */
uvc_stream_delete(stream);
+ video_source_destroy(src);
events_cleanup(&events);
configfs_free_uvc_function(fc);
diff --git a/stream.c b/stream.c
index e08aca7..5e95617 100644
--- a/stream.c
+++ b/stream.c
@@ -25,16 +25,18 @@
#include "stream.h"
#include "uvc.h"
#include "v4l2.h"
+#include "video-buffers.h"
+#include "video-source.h"
/*
* struct uvc_stream - Representation of a UVC stream
- * @cap: V4L2 capture device
+ * @src: video source
* @uvc: UVC V4L2 output device
* @events: struct events containing event information
*/
struct uvc_stream
{
- struct v4l2_device *cap;
+ struct video_source *src;
struct uvc_device *uvc;
struct events *events;
@@ -44,20 +46,15 @@ struct uvc_stream
* Video streaming
*/
-static void capture_video_process(void *d)
+static void uvc_stream_source_process(void *d, struct video_source *src,
+ struct video_buffer *buffer)
{
struct uvc_stream *stream = d;
- struct video_buffer buf;
- int ret;
-
- ret = v4l2_dequeue_buffer(stream->cap, &buf);
- if (ret < 0)
- return;
- v4l2_queue_buffer(stream->uvc->vdev, &buf);
+ v4l2_queue_buffer(stream->uvc->vdev, buffer);
}
-static void uvc_video_process(void *d)
+static void uvc_stream_uvc_process(void *d)
{
struct uvc_stream *stream = d;
struct video_buffer buf;
@@ -67,104 +64,86 @@ static void uvc_video_process(void *d)
if (ret < 0)
return;
- v4l2_queue_buffer(stream->cap, &buf);
+ video_source_queue_buffer(stream->src, &buf);
}
-static int uvc_video_enable(struct uvc_stream *stream, int enable)
+static int uvc_stream_start(struct uvc_stream *stream)
{
- struct v4l2_device *cap = stream->cap;
- struct uvc_device *dev = stream->uvc;
+ struct video_buffer_set *buffers = NULL;
int ret;
- if (!enable) {
- printf("Stopping video stream.\n");
- events_unwatch_fd(stream->events, dev->vdev->fd, EVENT_WRITE);
- v4l2_stream_off(dev->vdev);
- v4l2_free_buffers(dev->vdev);
- return 0;
- }
-
printf("Starting video stream.\n");
- ret = v4l2_alloc_buffers(dev->vdev, V4L2_MEMORY_DMABUF, 4);
+ /* Allocate and export the buffers on the source. */
+ ret = video_source_alloc_buffers(stream->src, 4);
if (ret < 0) {
- printf("Failed to allocate buffers: %s (%d)\n", strerror(-ret), -ret);
+ printf("Failed to allocate source buffers: %s (%d)\n",
+ strerror(-ret), -ret);
return ret;
}
- ret = v4l2_import_buffers(dev->vdev, &cap->buffers);
+ ret = video_source_export_buffers(stream->src, &buffers);
if (ret < 0) {
- printf("Failed to import buffers: %s (%d)\n", strerror(-ret), -ret);
- goto error;
+ printf("Failed to export buffers on source: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto error_free_source;
+ }
+
+ /* Allocate and import the buffers on the sink. */
+ ret = v4l2_alloc_buffers(stream->uvc->vdev, V4L2_MEMORY_DMABUF,
+ buffers->nbufs);
+ if (ret < 0) {
+ printf("Failed to allocate sink buffers: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto error_free_source;
}
- v4l2_stream_on(dev->vdev);
- events_watch_fd(stream->events, dev->vdev->fd, EVENT_WRITE,
- uvc_video_process, stream);
+ ret = v4l2_import_buffers(stream->uvc->vdev, buffers);
+ if (ret < 0) {
+ printf("Failed to import buffers on sink: %s (%d)\n",
+ strerror(-ret), -ret);
+ goto error_free_sink;
+ }
+
+ /* Start the source and sink. */
+ video_source_stream_on(stream->src);
+ v4l2_stream_on(stream->uvc->vdev);
+
+ events_watch_fd(stream->events, stream->uvc->vdev->fd, EVENT_WRITE,
+ uvc_stream_uvc_process, stream);
return 0;
-error:
- v4l2_free_buffers(dev->vdev);
+error_free_sink:
+ v4l2_free_buffers(stream->uvc->vdev);
+error_free_source:
+ video_source_free_buffers(stream->src);
+ if (buffers)
+ video_buffer_set_delete(buffers);
return ret;
}
-static int capture_video_stream(struct uvc_stream *stream, int enable)
+static int uvc_stream_stop(struct uvc_stream *stream)
{
- struct v4l2_device *cap = stream->cap;
- unsigned int i;
- int ret;
-
- if (!enable) {
- printf("Stopping video capture stream.\n");
- events_unwatch_fd(stream->events, cap->fd, EVENT_READ);
- v4l2_stream_off(cap);
- v4l2_free_buffers(cap);
- return 0;
- }
-
- printf("Starting video capture stream.\n");
+ printf("Stopping video stream.\n");
- ret = v4l2_alloc_buffers(cap, V4L2_MEMORY_MMAP, 4);
- if (ret < 0) {
- printf("Failed to allocate capture buffers.\n");
- return ret;
- }
-
- ret = v4l2_export_buffers(cap);
- if (ret < 0) {
- printf("Failed to export buffers.\n");
- goto error;
- }
+ events_unwatch_fd(stream->events, stream->uvc->vdev->fd, EVENT_WRITE);
- for (i = 0; i < cap->buffers.nbufs; ++i) {
- struct video_buffer *buf = &cap->buffers.buffers[i];
+ v4l2_stream_off(stream->uvc->vdev);
+ video_source_stream_off(stream->src);
- ret = v4l2_queue_buffer(cap, buf);
- if (ret < 0)
- goto error;
- }
-
- v4l2_stream_on(cap);
- events_watch_fd(stream->events, cap->fd, EVENT_READ,
- capture_video_process, stream);
+ v4l2_free_buffers(stream->uvc->vdev);
+ video_source_free_buffers(stream->src);
return 0;
-
-error:
- v4l2_free_buffers(cap);
- return ret;
}
void uvc_stream_enable(struct uvc_stream *stream, int enable)
{
- if (enable) {
- capture_video_stream(stream, 1);
- uvc_video_enable(stream, 1);
- } else {
- uvc_video_enable(stream, 0);
- capture_video_stream(stream, 0);
- }
+ if (enable)
+ uvc_stream_start(stream);
+ else
+ uvc_stream_stop(stream);
}
int uvc_stream_set_format(struct uvc_stream *stream,
@@ -180,15 +159,14 @@ int uvc_stream_set_format(struct uvc_stream *stream,
if (ret < 0)
return ret;
- return v4l2_set_format(stream->cap, &fmt);
+ return video_source_set_format(stream->src, &fmt);
}
/* ---------------------------------------------------------------------------
* Stream handling
*/
-struct uvc_stream *uvc_stream_new(const char *uvc_device,
- const char *cap_device)
+struct uvc_stream *uvc_stream_new(const char *uvc_device)
{
struct uvc_stream *stream;
@@ -198,10 +176,6 @@ struct uvc_stream *uvc_stream_new(const char *uvc_device,
memset(stream, 0, sizeof(*stream));
- stream->cap = v4l2_open(cap_device);
- if (stream->cap == NULL)
- goto error;
-
stream->uvc = uvc_open(uvc_device, stream);
if (stream->uvc == NULL)
goto error;
@@ -209,9 +183,6 @@ struct uvc_stream *uvc_stream_new(const char *uvc_device,
return stream;
error:
- if (stream->cap)
- v4l2_close(stream->cap);
-
free(stream);
return NULL;
}
@@ -221,7 +192,6 @@ void uvc_stream_delete(struct uvc_stream *stream)
if (stream == NULL)
return;
- v4l2_close(stream->cap);
uvc_close(stream->uvc);
free(stream);
@@ -239,3 +209,11 @@ void uvc_stream_set_event_handler(struct uvc_stream *stream,
{
stream->events = events;
}
+
+void uvc_stream_set_video_source(struct uvc_stream *stream,
+ struct video_source *src)
+{
+ stream->src = src;
+
+ video_source_set_buffer_handler(src, uvc_stream_source_process, stream);
+}
diff --git a/stream.h b/stream.h
index 6eb6731..38729f8 100644
--- a/stream.h
+++ b/stream.h
@@ -24,22 +24,21 @@ struct events;
struct uvc_function_config;
struct uvc_stream;
struct v4l2_pix_format;
+struct video_source;
/*
* uvc_stream_new - Create a new UVC stream
* @uvc_device: Filename of UVC device node
- * @cap_device: Filename of V4L2 capture device node
*
- * Create a new UVC stream with V4L2 @uvc_device as the output and @cap_device
- * as input.
+ * Create a new UVC stream to handle the UVC function corresponding to the video
+ * device node @uvc_device.
*
* Streams allocated with this function can be deleted with uvc_stream_delete().
*
* On success, returns a pointer to newly allocated and populated struct uvc_stream.
* On failure, returns NULL.
*/
-struct uvc_stream *uvc_stream_new(const char *uvc_device,
- const char *cap_device);
+struct uvc_stream *uvc_stream_new(const char *uvc_device);
/*
* uvc_stream_init_uvc - Initialize a UVC stream
@@ -72,6 +71,9 @@ void uvc_stream_init_uvc(struct uvc_stream *stream,
void uvc_stream_set_event_handler(struct uvc_stream *stream,
struct events *events);
+void uvc_stream_set_video_source(struct uvc_stream *stream,
+ struct video_source *src);
+
/*
* uvc_stream_delete - Delete a UVC stream
* @stream: the UVC stream