diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-06-09 12:13:38 +0300 | 
|---|---|---|
| committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-06-09 19:44:21 +0300 | 
| commit | 1b8f9204db684eff0d52b03c47fa666bf4e495f5 (patch) | |
| tree | 02fadfefd72b45a6356f36f5442212aa772425bc | |
| parent | de8d802f21e002270b0b758835fa25232a31208e (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.c | 17 | ||||
| -rw-r--r-- | stream.c | 158 | ||||
| -rw-r--r-- | stream.h | 12 | 
3 files changed, 90 insertions, 97 deletions
| @@ -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); @@ -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); +} @@ -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 | 
