diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/stream.c | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/lib/stream.c b/lib/stream.c index 1988e7c..63ccb1b 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -60,13 +60,28 @@ static void uvc_stream_uvc_process(void *d) video_source_queue_buffer(stream->src, &buf); } -static int uvc_stream_start(struct uvc_stream *stream) +static void uvc_stream_uvc_process_no_buf(void *d) { + struct uvc_stream *stream = d; struct v4l2_device *sink = uvc_v4l2_device(stream->uvc); - struct video_buffer_set *buffers = NULL; + struct video_buffer buf; int ret; - printf("Starting video stream.\n"); + ret = v4l2_dequeue_buffer(sink, &buf); + if (ret < 0) + return; + + video_source_fill_buffer(stream->src, &buf); + + v4l2_queue_buffer(sink, &buf); +} + + +static int uvc_stream_start_alloc(struct uvc_stream *stream) +{ + struct v4l2_device *sink = uvc_v4l2_device(stream->uvc); + struct video_buffer_set *buffers = NULL; + int ret; /* Allocate and export the buffers on the source. */ ret = video_source_alloc_buffers(stream->src, 4); @@ -116,6 +131,64 @@ error_free_source: return ret; } +static int uvc_stream_start_no_alloc(struct uvc_stream *stream) +{ + struct v4l2_device *sink = uvc_v4l2_device(stream->uvc); + int ret; + unsigned int i; + + /* Allocate buffers on the sink. */ + ret = v4l2_alloc_buffers(sink, V4L2_MEMORY_MMAP, 4); + if (ret < 0) { + printf("Failed to allocate sink buffers: %s (%d)\n", + strerror(-ret), -ret); + return ret; + } + + /* mmap buffers. */ + ret = v4l2_mmap_buffers(sink); + if (ret < 0) { + printf("Failed to query sink buffers: %s (%d)\n", + strerror(-ret), -ret); + return ret; + } + + /* Queue buffers to sink. */ + for (i = 0; i < sink->buffers.nbufs; ++i) { + struct video_buffer buf = { + .index = i, + .size = sink->buffers.buffers[i].size, + .mem = sink->buffers.buffers[i].mem, + }; + + video_source_fill_buffer(stream->src, &buf); + ret = v4l2_queue_buffer(sink, &buf); + if (ret < 0) + return ret; + } + + /* Start the source and sink. */ + video_source_stream_on(stream->src); + ret = v4l2_stream_on(sink); + if (ret < 0) + return ret; + + events_watch_fd(stream->events, sink->fd, EVENT_WRITE, + uvc_stream_uvc_process_no_buf, stream); + + return 0; +} + +static int uvc_stream_start(struct uvc_stream *stream) +{ + printf("Starting video stream.\n"); + + if (stream->src->ops->alloc_buffers) + return uvc_stream_start_alloc(stream); + else + return uvc_stream_start_no_alloc(stream); +} + static int uvc_stream_stop(struct uvc_stream *stream) { struct v4l2_device *sink = uvc_v4l2_device(stream->uvc); @@ -216,5 +289,7 @@ void uvc_stream_set_video_source(struct uvc_stream *stream, { stream->src = src; - video_source_set_buffer_handler(src, uvc_stream_source_process, stream); + if (stream->src->ops->alloc_buffers) + video_source_set_buffer_handler(src, uvc_stream_source_process, + stream); } |