All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] New uAPI for DVB streaming I/O
@ 2015-10-06  9:59 Junghak Sung
  2015-10-06  9:59 ` [PATCH] media: videobuf2: Add new " Junghak Sung
  2015-10-06  9:59 ` [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB Junghak Sung
  0 siblings, 2 replies; 6+ messages in thread
From: Junghak Sung @ 2015-10-06  9:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
	Junghak Sung

Hello everybody,

I would like to introduce a new uAPI for DVB streaming I/O.
Current DVB framework uses ringbuffer mechanism to demux MPEG-2 TS data
and pass it to userspace. However, this mechanism requires extra memory copy
because DVB framework provides only read() system call, which copies the kernel
data in ringbuffer to user-space buffer.
New uAPIs can remove the memory copy by using videobuf2 framework (a.k.a VB2)
which supports ioctl() calls related to streaming I/O, including buffer
allocation and queue management.

In this patch series, I have tried to implement DVB streaming I/O without
breaking existing legacy interfaces and cover all functionalities of
read() system call with new ioctl() calls.
The user scenario is very similar to v4l2's, but belows are different.

1. Support only CAPTURE buffer type with single plane.
2. Support only MMAP memory type.
3. STREAMON will execute automatically when the first buffer is queued.
4. STREANOFF will also execute automatically when dvr or dmxdev_filter
  are released.
5. User can decide not only buffer count but also buffer size by REQBUFS.

New ioctl() calls and data structure are belows - defined in
include/uapi/linux/dvb/dmx.h.

struct dmx_buffer {
	__u32			index;
	__u32			bytesused;
	__u32			offset;
	__u32			length;
	__u32			reserved[4];
};

struct dmx_requestbuffers {
	__u32			count;
	__u32			size;
	__u32			reserved[2];
};

struct dmx_exportbuffer {
	__u32		index;
	__u32		flags;
	__s32		fd;
	__u32		reserved;
};

#define DMX_REQBUFS              _IOWR('o', 60, struct dmx_requestbuffers)
#define DMX_QUERYBUF             _IOWR('o', 61, struct dmx_buffer)
#define DMX_EXPBUF               _IOWR('o', 62, struct dmx_exportbuffer)
#define DMX_QBUF                 _IOWR('o', 63, struct dmx_buffer)
#define DMX_DQBUF                _IOWR('o', 64, struct dmx_buffer)


This patch series is consisted of two parts - kernel changes and test patch
for dvbv5-zap.

1. Kernel changes
It includes implementation of the helper framework for DVB to use Videobuf2
and changes of the DVB framework inside.
If you want to probe this patch, firstly, you should apply the patch for VB2
refactoring before do that.
Please refer to this link for more information about VB2 refactoring.

[1] RFC PATCH v5 - Refactoring Videobuf2 for common use
 http://www.spinics.net/lists/linux-media/msg93810.html

This patch also have been applied to my own git.
[2] jsung/dvb-vb2.git - http://git.linuxtv.org/cgit.cgi/jsung/dvb-vb2.git/
    (branch: dvb-vb2)

2. Patch for testing DVB streaming I/O with dvbv5-zap
You can use '-R' option instead of '-r' to record TS data via DVR, when you
launch the dvbv5-zap application. If you do, dvbv5-zap will use following
ioctl() calls instead of read() system call.

- DMX_REQBUFS : Request kernel to allocate buffers which count and size are
  dedicated by user.
- DMX_QUERYBUF : Get the buffer information like a memory offset which will
  mmap() and be shared with user-space.
- DMX_EXPBUF : Just for testing whether buffer-exporting success or not.
- DMX_QBUF : Pass the buffer to kernel-space.
- DMX_DQBUF : Get back the buffer which may contain TS data gathered by DVR.


Any suggestions and comments are welcome.

Regards,
Junghak

Junghak Sung (1):
  media: videobuf2: Add new uAPI for DVB streaming I/O

 drivers/media/dvb-core/Makefile  |    2 +-
 drivers/media/dvb-core/dmxdev.c  |  189 +++++++++++++++---
 drivers/media/dvb-core/dmxdev.h  |    4 +
 drivers/media/dvb-core/dvb_vb2.c |  406 ++++++++++++++++++++++++++++++++++++++
 drivers/media/dvb-core/dvb_vb2.h |   69 +++++++
 include/uapi/linux/dvb/dmx.h     |   66 ++++++-
 6 files changed, 709 insertions(+), 27 deletions(-)
 create mode 100644 drivers/media/dvb-core/dvb_vb2.c
 create mode 100644 drivers/media/dvb-core/dvb_vb2.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] media: videobuf2: Add new uAPI for DVB streaming I/O
  2015-10-06  9:59 [RFC PATCH] New uAPI for DVB streaming I/O Junghak Sung
@ 2015-10-06  9:59 ` Junghak Sung
  2015-10-06 10:15   ` kbuild test robot
  2015-10-06 10:51   ` kbuild test robot
  2015-10-06  9:59 ` [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB Junghak Sung
  1 sibling, 2 replies; 6+ messages in thread
From: Junghak Sung @ 2015-10-06  9:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
	Junghak Sung

Add new uAPI for DVB to use streaming I/O which is implemented
based on videobuf2.

- DMX_REQBUFS : Request kernel to allocate buffers which count and size
  are dedicated by user.
- DMX_QUERYBUF : Get the buffer information like a memory offset which
  will mmap() and be shared with user-space.
- DMX_EXPBUF : Just for testing whether buffer-exporting success or not.
- DMX_QBUF : Pass the buffer to kernel-space.
- DMX_DQBUF : Get back the buffer which may contain TS data.

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/media/dvb-core/Makefile  |    2 +-
 drivers/media/dvb-core/dmxdev.c  |  189 +++++++++++++++---
 drivers/media/dvb-core/dmxdev.h  |    4 +
 drivers/media/dvb-core/dvb_vb2.c |  406 ++++++++++++++++++++++++++++++++++++++
 drivers/media/dvb-core/dvb_vb2.h |   69 +++++++
 include/uapi/linux/dvb/dmx.h     |   66 ++++++-
 6 files changed, 709 insertions(+), 27 deletions(-)
 create mode 100644 drivers/media/dvb-core/dvb_vb2.c
 create mode 100644 drivers/media/dvb-core/dvb_vb2.h

diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile
index 8f22bcd..9b2e4e9 100644
--- a/drivers/media/dvb-core/Makefile
+++ b/drivers/media/dvb-core/Makefile
@@ -6,6 +6,6 @@ dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
 
 dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
 		 dvb_ca_en50221.o dvb_frontend.o 		\
-		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
+		 $(dvb-net-y) dvb_ringbuffer.o dvb_vb2.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index d0e3f9d..d386abe 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -30,6 +30,7 @@
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include "dmxdev.h"
+#include "dvb_vb2.h"
 
 static int debug;
 
@@ -136,14 +137,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
 		return -ENODEV;
 	}
 
-	if ((file->f_flags & O_ACCMODE) == O_RDWR) {
-		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -EOPNOTSUPP;
-		}
-	}
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+	if (((file->f_flags & O_ACCMODE) == O_RDONLY)
+			|| ((file->f_flags & O_ACCMODE) == O_RDWR)) {
 		void *mem;
 		if (!dvbdev->readers) {
 			mutex_unlock(&dmxdev->mutex);
@@ -155,6 +150,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
 			return -ENOMEM;
 		}
 		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+		dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
+				file->f_flags & O_NONBLOCK);
 		dvbdev->readers--;
 	}
 
@@ -192,7 +189,8 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 		dmxdev->demux->connect_frontend(dmxdev->demux,
 						dmxdev->dvr_orig_fe);
 	}
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+	if (((file->f_flags & O_ACCMODE) == O_RDONLY)
+			|| ((file->f_flags & O_ACCMODE) == O_RDWR)) {
 		dvbdev->readers++;
 		if (dmxdev->dvr_buffer.data) {
 			void *mem = dmxdev->dvr_buffer.data;
@@ -202,6 +200,9 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 			spin_unlock_irq(&dmxdev->lock);
 			vfree(mem);
 		}
+		if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+			dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
+		dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
 	}
 	/* TODO */
 	dvbdev->users--;
@@ -358,7 +359,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 	struct dmxdev_filter *dmxdevfilter = filter->priv;
 	int ret;
 
-	if (dmxdevfilter->buffer.error) {
+	if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)
+			&& dmxdevfilter->buffer.error) {
 		wake_up(&dmxdevfilter->buffer.queue);
 		return 0;
 	}
@@ -369,11 +371,20 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 	}
 	del_timer(&dmxdevfilter->timer);
 	dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
-	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
-				      buffer1_len);
-	if (ret == buffer1_len) {
-		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
-					      buffer2_len);
+
+	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
+		ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
+				buffer1, buffer1_len);
+		if (ret == buffer1_len)
+			ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
+					buffer2, buffer2_len);
+	} else {
+		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
+				buffer1, buffer1_len);
+		if (ret == buffer1_len) {
+			ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
+					buffer2, buffer2_len);
+		}
 	}
 	if (ret < 0)
 		dmxdevfilter->buffer.error = ret;
@@ -391,6 +402,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 {
 	struct dmxdev_filter *dmxdevfilter = feed->priv;
 	struct dvb_ringbuffer *buffer;
+	struct dvb_vb2_ctx *ctx;
 	int ret;
 
 	spin_lock(&dmxdevfilter->dev->lock);
@@ -400,18 +412,29 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 	}
 
 	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
-	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
 		buffer = &dmxdevfilter->buffer;
-	else
+		ctx = &dmxdevfilter->vb2_ctx;
+	} else {
 		buffer = &dmxdevfilter->dev->dvr_buffer;
-	if (buffer->error) {
-		spin_unlock(&dmxdevfilter->dev->lock);
-		wake_up(&buffer->queue);
-		return 0;
+		ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
+	}
+
+	if (dvb_vb2_is_streaming(ctx)) {
+		ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
+		if (ret == buffer1_len)
+			ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
+	} else {
+		if (buffer->error) {
+			spin_unlock(&dmxdevfilter->dev->lock);
+			wake_up(&buffer->queue);
+			return 0;
+		}
+		ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
+		if (ret == buffer1_len)
+			ret = dvb_dmxdev_buffer_write(buffer,
+					buffer2, buffer2_len);
 	}
-	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
-	if (ret == buffer1_len)
-		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
 	if (ret < 0)
 		buffer->error = ret;
 	spin_unlock(&dmxdevfilter->dev->lock);
@@ -750,6 +773,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
 	file->private_data = dmxdevfilter;
 
 	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
+	dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
+			file->f_flags & O_NONBLOCK);
 	dmxdevfilter->type = DMXDEV_TYPE_NONE;
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	init_timer(&dmxdevfilter->timer);
@@ -766,6 +791,10 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
 	mutex_lock(&dmxdev->mutex);
 	mutex_lock(&dmxdevfilter->mutex);
 
+	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
+		dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx);
+	dvb_vb2_release(&dmxdevfilter->vb2_ctx);
+
 	dvb_dmxdev_filter_stop(dmxdevfilter);
 	dvb_dmxdev_filter_reset(dmxdevfilter);
 
@@ -1068,6 +1097,53 @@ static int dvb_demux_do_ioctl(struct file *file,
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_REQBUFS:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_QUERYBUF:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_EXPBUF:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_QBUF:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg);
+		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
+			ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_DQBUF:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -1106,6 +1182,27 @@ static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
 	return mask;
 }
 
+static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct dmxdev_filter *dmxdevfilter = file->private_data;
+	struct dmxdev *dmxdev = dmxdevfilter->dev;
+	int ret;
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+		mutex_unlock(&dmxdev->mutex);
+		return -ERESTARTSYS;
+	}
+	ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma);
+
+	mutex_unlock(&dmxdevfilter->mutex);
+	mutex_unlock(&dmxdev->mutex);
+
+	return ret;
+}
+
 static int dvb_demux_release(struct inode *inode, struct file *file)
 {
 	struct dmxdev_filter *dmxdevfilter = file->private_data;
@@ -1134,6 +1231,7 @@ static const struct file_operations dvb_demux_fops = {
 	.release = dvb_demux_release,
 	.poll = dvb_demux_poll,
 	.llseek = default_llseek,
+	.mmap = dvb_demux_mmap,
 };
 
 static const struct dvb_device dvbdev_demux = {
@@ -1162,6 +1260,28 @@ static int dvb_dvr_do_ioctl(struct file *file,
 		ret = dvb_dvr_set_buffer_size(dmxdev, arg);
 		break;
 
+	case DMX_REQBUFS:
+		ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
+		break;
+
+	case DMX_QUERYBUF:
+		ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg);
+		break;
+
+	case DMX_EXPBUF:
+		ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg);
+		break;
+
+	case DMX_QBUF:
+		ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg);
+		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+			ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx);
+		break;
+
+	case DMX_DQBUF:
+		ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -1189,7 +1309,8 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
 
 	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+	if (((file->f_flags & O_ACCMODE) == O_RDONLY)
+			|| ((file->f_flags & O_ACCMODE) == O_RDWR)) {
 		if (dmxdev->dvr_buffer.error)
 			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
 
@@ -1201,6 +1322,23 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
 	return mask;
 }
 
+static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	int ret;
+
+	if (dmxdev->exit)
+		return -ENODEV;
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma);
+	mutex_unlock(&dmxdev->mutex);
+	return ret;
+}
+
 static const struct file_operations dvb_dvr_fops = {
 	.owner = THIS_MODULE,
 	.read = dvb_dvr_read,
@@ -1210,6 +1348,7 @@ static const struct file_operations dvb_dvr_fops = {
 	.release = dvb_dvr_release,
 	.poll = dvb_dvr_poll,
 	.llseek = default_llseek,
+	.mmap = dvb_dvr_mmap,
 };
 
 static const struct dvb_device dvbdev_dvr = {
diff --git a/drivers/media/dvb-core/dmxdev.h b/drivers/media/dvb-core/dmxdev.h
index 48c6cf9..40983de 100644
--- a/drivers/media/dvb-core/dmxdev.h
+++ b/drivers/media/dvb-core/dmxdev.h
@@ -39,6 +39,7 @@
 #include "dvbdev.h"
 #include "demux.h"
 #include "dvb_ringbuffer.h"
+#include "dvb_vb2.h"
 
 enum dmxdev_type {
 	DMXDEV_TYPE_NONE,
@@ -81,6 +82,7 @@ struct dmxdev_filter {
 	enum dmxdev_state state;
 	struct dmxdev *dev;
 	struct dvb_ringbuffer buffer;
+	struct dvb_vb2_ctx vb2_ctx;
 
 	struct mutex mutex;
 
@@ -108,6 +110,8 @@ struct dmxdev {
 	struct dvb_ringbuffer dvr_buffer;
 #define DVR_BUFFER_SIZE (10*188*1024)
 
+	struct dvb_vb2_ctx dvr_vb2_ctx;
+
 	struct mutex mutex;
 	spinlock_t lock;
 };
diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c
new file mode 100644
index 0000000..1a2dc55
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_vb2.c
@@ -0,0 +1,406 @@
+/*
+ * dvb-vb2.c - dvb-vb2
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * Author: jh1009.sung@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+
+#include "dvbdev.h"
+#include "dvb_vb2.h"
+
+static int vb2_debug;
+module_param(vb2_debug, int, 0644);
+
+#define dprintk(level, fmt, arg...)					      \
+	do {								      \
+		if (vb2_debug >= level)					      \
+			pr_info("vb2: %s: " fmt, __func__, ## arg); \
+	} while (0)
+
+static int _queue_setup(struct vb2_queue *vq, const struct vb2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
+
+	*nbuffers = ctx->buf_cnt;
+	*nplanes = 1;
+	sizes[0] = ctx->buf_siz;
+
+	/*
+	 * videobuf2-vmalloc allocator is context-less so no need to set
+	 * alloc_ctxs array.
+	 */
+
+	dprintk(3, "[%s] count=%d, size=%d\n", ctx->name,
+			*nbuffers, sizes[0]);
+
+	return 0;
+}
+
+static int _buffer_prepare(struct vb2_buffer *vb)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = ctx->buf_siz;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dprintk(1, "[%s] data will not fit into plane (%lu < %lu)\n",
+				ctx->name, vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+static void _buffer_queue(struct vb2_buffer *vb)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct dvb_buffer *buf = container_of(vb, struct dvb_buffer, vb);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&ctx->slock, flags);
+	list_add_tail(&buf->list, &ctx->dvb_q);
+	spin_unlock_irqrestore(&ctx->slock, flags);
+
+	dprintk(3, "[%s]\n", ctx->name);
+}
+
+static int _start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
+
+	dprintk(3, "[%s] count=%d\n", ctx->name, count);
+	return 0;
+}
+
+static void _stop_streaming(struct vb2_queue *vq)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
+
+	dprintk(3, "[%s]\n", ctx->name);
+}
+
+static void _dmxdev_lock(struct vb2_queue *vq)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
+
+	mutex_lock(&ctx->mutex);
+	dprintk(3, "[%s]\n", ctx->name);
+}
+
+static void _dmxdev_unlock(struct vb2_queue *vq)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
+
+	if (mutex_is_locked(&ctx->mutex))
+		mutex_unlock(&ctx->mutex);
+	dprintk(3, "[%s]\n", ctx->name);
+}
+
+static const struct vb2_ops dvb_vb2_qops = {
+	.queue_setup		= _queue_setup,
+	.buf_prepare		= _buffer_prepare,
+	.buf_queue		= _buffer_queue,
+	.start_streaming	= _start_streaming,
+	.stop_streaming		= _stop_streaming,
+	.wait_prepare		= _dmxdev_unlock,
+	.wait_finish		= _dmxdev_lock,
+};
+
+static int _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct dmx_buffer *b = pb;
+
+	b->index = vb->index;
+	b->length = vb->planes[0].length;
+	b->bytesused = vb->planes[0].bytesused;
+	b->offset = vb->planes[0].m.offset;
+	memset(b->reserved, 0, sizeof(b->reserved));
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+static int _fill_vb2_buffer(struct vb2_buffer *vb,
+		const void *pb, struct vb2_plane *planes)
+{
+	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	planes[0].bytesused = 0;
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+static const struct vb2_buf_ops dvb_vb2_buf_ops = {
+	.fill_user_buffer	= _fill_dmx_buffer,
+	.fill_vb2_buffer	= _fill_vb2_buffer,
+};
+
+/*
+ * Videobuf operations
+ */
+int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
+{
+	struct vb2_queue *q = &ctx->vb_q;
+	int ret;
+
+	memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
+	q->type = DVB_BUF_TYPE_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ | VB2_DMABUF;
+	q->drv_priv = ctx;
+	q->buf_struct_size = sizeof(struct dvb_buffer);
+	q->min_buffers_needed = 1;
+	q->ops = &dvb_vb2_qops;
+	q->mem_ops = &vb2_vmalloc_memops;
+	q->buf_ops = &dvb_vb2_buf_ops;
+	q->num_buffers = 0;
+
+	ret = vb2_core_queue_init(q);
+	if (ret) {
+		ctx->state = DVB_VB2_STATE_NONE;
+		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
+		return ret;
+	}
+
+	mutex_init(&ctx->mutex);
+	spin_lock_init(&ctx->slock);
+	INIT_LIST_HEAD(&ctx->dvb_q);
+
+	strncpy(ctx->name, name, DVB_VB2_NAME_MAX);
+	ctx->nonblocking = nonblocking;
+	ctx->state = DVB_VB2_STATE_INIT;
+
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
+{
+	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
+
+	if (ctx->state && DVB_VB2_STATE_INIT)
+		vb2_core_queue_release(q);
+
+	ctx->state = DVB_VB2_STATE_NONE;
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx)
+{
+	struct vb2_queue *q = &ctx->vb_q;
+	int ret;
+
+	ret = vb2_core_streamon(q, q->type);
+	if (ret) {
+		ctx->state = DVB_VB2_STATE_NONE;
+		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
+		return ret;
+	}
+	ctx->state |= DVB_VB2_STATE_STREAMON;
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx)
+{
+	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
+	int ret;
+	int i;
+
+	ctx->state &= ~DVB_VB2_STATE_STREAMON;
+
+	for (i = 0; i < q->num_buffers; ++i) {
+		if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE)
+			vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
+
+	}
+
+	ret = vb2_core_streamoff(q, q->type);
+	if (ret) {
+		ctx->state = DVB_VB2_STATE_NONE;
+		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
+		return ret;
+	}
+	dprintk(3, "[%s]\n", ctx->name);
+
+	return 0;
+}
+
+int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
+{
+	return (ctx->state & DVB_VB2_STATE_STREAMON);
+}
+
+int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
+		const unsigned char *src, int len)
+{
+	unsigned long flags = 0;
+	void *vbuf;
+	int todo = len;
+	unsigned char *psrc = (unsigned char *)src;
+	int ll;
+
+	while (todo) {
+		if (!ctx->buf) {
+			if (list_empty(&ctx->dvb_q)) {
+				dprintk(3, "[%s] Buffer overflow!!!\n",
+						ctx->name);
+				break;
+			}
+
+			spin_lock_irqsave(&ctx->slock, flags);
+			ctx->buf = list_entry(ctx->dvb_q.next,
+					struct dvb_buffer, list);
+			list_del(&ctx->buf->list);
+			ctx->remain = vb2_plane_size(&ctx->buf->vb, 0);
+			ctx->offset = 0;
+			spin_unlock_irqrestore(&ctx->slock, flags);
+		}
+
+		if (!dvb_vb2_is_streaming(ctx)) {
+			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR);
+			ctx->buf = NULL;
+			break;
+		}
+
+		/* Fill buffer */
+		vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0);
+
+		ll = min(todo, ctx->remain);
+		memcpy(vbuf+ctx->offset, psrc, ll);
+		todo -= ll;
+		psrc += ll;
+
+		ctx->remain -= ll;
+		ctx->offset += ll;
+
+		if (ctx->remain == 0) {
+			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
+			ctx->buf = NULL;
+		}
+	}
+
+	if (ctx->nonblocking && ctx->buf) {
+		vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
+		ctx->buf = NULL;
+	}
+
+	if (todo)
+		dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo);
+	else
+		dprintk(3, "[%s]\n", ctx->name);
+
+	return (len - todo);
+}
+
+int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
+{
+	int ret;
+
+	ctx->buf_siz = req->size;
+	ctx->buf_cnt = req->count;
+
+	ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
+	if (ret) {
+		ctx->state = DVB_VB2_STATE_NONE;
+		dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,
+			ctx->buf_cnt, ctx->buf_siz, ret);
+		return ret;
+	}
+	ctx->state |= DVB_VB2_STATE_REQBUFS;
+	dprintk(3, "[%s] count=%d size=%d\n", ctx->name,
+			ctx->buf_cnt, ctx->buf_siz);
+
+	return 0;
+}
+
+int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
+{
+	int ret;
+
+	ret = vb2_core_querybuf(&ctx->vb_q, b->index, b);
+	if (ret) {
+		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
+				b->index, ret);
+		return ret;
+	}
+	dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
+
+	return 0;
+}
+
+int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
+{
+	struct vb2_queue *q = &ctx->vb_q;
+	int ret;
+
+	ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index,
+				0, exp->flags);
+	if (ret) {
+		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
+				exp->index, ret);
+		return ret;
+	}
+	dprintk(3, "[%s] index=%d fd=%d\n", ctx->name, exp->index, exp->fd);
+
+	return 0;
+}
+
+int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
+{
+	int ret;
+
+	ret = vb2_core_qbuf(&ctx->vb_q, b->index, b);
+	if (ret) {
+		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
+				b->index, ret);
+		return ret;
+	}
+	dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
+
+	return 0;
+}
+
+int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
+{
+	int ret;
+
+	ret = vb2_core_dqbuf(&ctx->vb_q, b, ctx->nonblocking);
+	if (ret) {
+		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
+		return ret;
+	}
+	dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
+
+	return 0;
+}
+
+int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = vb2_mmap(&ctx->vb_q, vma);
+	dprintk(3, "[%s] ret=%d\n", ctx->name, ret);
+
+	return 0;
+
+}
diff --git a/drivers/media/dvb-core/dvb_vb2.h b/drivers/media/dvb-core/dvb_vb2.h
new file mode 100644
index 0000000..5c6377d
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_vb2.h
@@ -0,0 +1,69 @@
+/*
+ * dvb-vb2.h - DVB driver helper framework for streaming I/O
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * Author: jh1009.sung@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _DVB_VB2_H
+#define _DVB_VB2_H
+
+#include <linux/mutex.h>
+#include <linux/dvb/dmx.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-vmalloc.h>
+
+enum dvb_buf_type {
+	DVB_BUF_TYPE_CAPTURE        = 1,
+	DVB_BUF_TYPE_OUTPUT         = 2,
+};
+
+#define DVB_VB2_STATE_NONE (0x0)
+#define DVB_VB2_STATE_INIT (0x1)
+#define DVB_VB2_STATE_REQBUFS (0x2)
+#define DVB_VB2_STATE_STREAMON (0x4)
+
+#define DVB_VB2_NAME_MAX (20)
+
+struct dvb_buffer {
+	struct vb2_buffer	vb;
+	struct list_head	list;
+};
+
+struct dvb_vb2_ctx {
+	struct vb2_queue	vb_q;
+	struct mutex		mutex;
+	spinlock_t		slock;
+	struct list_head	dvb_q;
+	struct dvb_buffer	*buf;
+	int	offset;
+	int	remain;
+	int	state;
+	int	buf_siz;
+	int	buf_cnt;
+	int	nonblocking;
+	char	name[DVB_VB2_NAME_MAX+1];
+};
+
+int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int non_blocking);
+int dvb_vb2_release(struct dvb_vb2_ctx *ctx);
+int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx);
+int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx);
+int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx);
+int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
+			const unsigned char *src, int len);
+
+int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req);
+int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
+int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp);
+int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
+int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
+int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma);
+
+#endif /* _DVB_VB2_H */
diff --git a/include/uapi/linux/dvb/dmx.h b/include/uapi/linux/dvb/dmx.h
index 427e489..a8b062d 100644
--- a/include/uapi/linux/dvb/dmx.h
+++ b/include/uapi/linux/dvb/dmx.h
@@ -140,6 +140,64 @@ struct dmx_stc {
 	__u64 stc;		/* output: stc in 'base'*90 kHz units */
 };
 
+/**
+ * struct dmx_buffer - dmx buffer info
+ *
+ * @index:	id number of the buffer
+ * @bytesused:	number of bytes occupied by data in the buffer (payload);
+ * @offset:	for buffers with memory == DMX_MEMORY_MMAP;
+ *		offset from the start of the device memory for this plane,
+ *		(or a "cookie" that should be passed to mmap() as offset)
+ * @length:	size in bytes of the buffer
+ *
+ * Contains data exchanged by application and driver using one of the streaming
+ * I/O methods.
+ */
+struct dmx_buffer {
+	__u32			index;
+	__u32			bytesused;
+	__u32			offset;
+	__u32			length;
+	__u32			reserved[4];
+};
+
+/**
+ * struct dmx_requestbuffers - request dmx buffer information
+ *
+ * @count:	number of requested buffers,
+ * @size:	size in bytes of the requested buffer
+ *
+ * Contains data used for requesting a dmx buffer.
+ * All reserved fields must be set to zero.
+ */
+struct dmx_requestbuffers {
+	__u32			count;
+	__u32			size;
+	__u32			reserved[2];
+};
+
+/**
+ * struct dmx_exportbuffer - export of dmx buffer as DMABUF file descriptor
+ *
+ * @index:	id number of the buffer
+ * @flags:	flags for newly created file, currently only O_CLOEXEC is
+ *		supported, refer to manual of open syscall for more details
+ * @fd:		file descriptor associated with DMABUF (set by driver)
+ *
+ * Contains data used for exporting a dmx buffer as DMABUF file descriptor.
+ * The buffer is identified by a 'cookie' returned by DMX_QUERYBUF
+ * (identical to the cookie used to mmap() the buffer to userspace). All
+ * reserved fields must be set to zero. The field reserved0 is expected to
+ * become a structure 'type' allowing an alternative layout of the structure
+ * content. Therefore this field should not be used for any other extensions.
+ */
+struct dmx_exportbuffer {
+	__u32		index;
+	__u32		flags;
+	__s32		fd;
+	__u32		reserved[5];
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -152,4 +210,10 @@ struct dmx_stc {
 #define DMX_ADD_PID              _IOW('o', 51, __u16)
 #define DMX_REMOVE_PID           _IOW('o', 52, __u16)
 
-#endif /* _UAPI_DVBDMX_H_ */
+#define DMX_REQBUFS              _IOWR('o', 60, struct dmx_requestbuffers)
+#define DMX_QUERYBUF             _IOWR('o', 61, struct dmx_buffer)
+#define DMX_EXPBUF               _IOWR('o', 62, struct dmx_exportbuffer)
+#define DMX_QBUF                 _IOWR('o', 63, struct dmx_buffer)
+#define DMX_DQBUF                _IOWR('o', 64, struct dmx_buffer)
+
+#endif /* _DVBDMX_H_ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB
  2015-10-06  9:59 [RFC PATCH] New uAPI for DVB streaming I/O Junghak Sung
  2015-10-06  9:59 ` [PATCH] media: videobuf2: Add new " Junghak Sung
@ 2015-10-06  9:59 ` Junghak Sung
  2016-05-13 11:56   ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 6+ messages in thread
From: Junghak Sung @ 2015-10-06  9:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon,
	Junghak Sung

Add a new scenario to use streaming I/O for TS recording.

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 include/linux/dvb/dmx.h |   64 ++++++++++++++++
 utils/dvb/dvbv5-zap.c   |  187 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 249 insertions(+), 2 deletions(-)

diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 425a945..66fd43b 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -138,6 +138,64 @@ struct dmx_stc {
 	__u64 stc;		/* output: stc in 'base'*90 kHz units */
 };
 
+/**
+ * struct dmx_buffer - dmx buffer info
+ *
+ * @index:	id number of the buffer
+ * @bytesused:	number of bytes occupied by data in the buffer (payload);
+ * @offset:	for buffers with memory == DMX_MEMORY_MMAP;
+ *		offset from the start of the device memory for this plane,
+ *		(or a "cookie" that should be passed to mmap() as offset)
+ * @length:	size in bytes of the buffer
+ *
+ * Contains data exchanged by application and driver using one of the streaming
+ * I/O methods.
+ */
+struct dmx_buffer {
+	__u32			index;
+	__u32			bytesused;
+	__u32			offset;
+	__u32			length;
+	__u32			reserved[4];
+};
+
+/**
+ * struct dmx_requestbuffers - request dmx buffer information
+ *
+ * @count:	number of requested buffers,
+ * @size:	size in bytes of the requested buffer
+ *
+ * Contains data used for requesting a dmx buffer.
+ * All reserved fields must be set to zero.
+ */
+struct dmx_requestbuffers {
+	__u32			count;
+	__u32			size;
+	__u32			reserved[2];
+};
+
+/**
+ * struct dmx_exportbuffer - export of dmx buffer as DMABUF file descriptor
+ *
+ * @index:	id number of the buffer
+ * @flags:	flags for newly created file, currently only O_CLOEXEC is
+ *		supported, refer to manual of open syscall for more details
+ * @fd:		file descriptor associated with DMABUF (set by driver)
+ *
+ * Contains data used for exporting a dmx buffer as DMABUF file descriptor.
+ * The buffer is identified by a 'cookie' returned by DMX_QUERYBUF
+ * (identical to the cookie used to mmap() the buffer to userspace). All
+ * reserved fields must be set to zero. The field reserved0 is expected to
+ * become a structure 'type' allowing an alternative layout of the structure
+ * content. Therefore this field should not be used for any other extensions.
+ */
+struct dmx_exportbuffer {
+	__u32		index;
+	__u32		flags;
+	__s32		fd;
+	__u32		reserved[5];
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -150,4 +208,10 @@ struct dmx_stc {
 #define DMX_ADD_PID              _IOW('o', 51, __u16)
 #define DMX_REMOVE_PID           _IOW('o', 52, __u16)
 
+#define DMX_REQBUFS              _IOWR('o', 60, struct dmx_requestbuffers)
+#define DMX_QUERYBUF             _IOWR('o', 61, struct dmx_buffer)
+#define DMX_EXPBUF               _IOWR('o', 62, struct dmx_exportbuffer)
+#define DMX_QBUF                 _IOWR('o', 63, struct dmx_buffer)
+#define DMX_DQBUF                _IOWR('o', 64, struct dmx_buffer)
+
 #endif /* _DVBDMX_H_ */
diff --git a/utils/dvb/dvbv5-zap.c b/utils/dvb/dvbv5-zap.c
index 2812166..eac146b 100644
--- a/utils/dvb/dvbv5-zap.c
+++ b/utils/dvb/dvbv5-zap.c
@@ -33,6 +33,7 @@
 #include <signal.h>
 #include <argp.h>
 #include <sys/time.h>
+#include <sys/mman.h>
 
 #include <config.h>
 
@@ -71,6 +72,7 @@ struct arguments {
 	unsigned n_apid, n_vpid, all_pids;
 	enum dvb_file_formats input_format, output_format;
 	unsigned traffic_monitor, low_traffic;
+	unsigned streaming;
 	char *search;
 	const char *cc;
 
@@ -94,6 +96,7 @@ static const struct argp_option options[] = {
 	{"pat",		'p', NULL,			0, N_("add pat and pmt to TS recording (implies -r)"), 0},
 	{"all-pids",	'P', NULL,			0, N_("don't filter any pids. Instead, outputs all of them"), 0 },
 	{"record",	'r', NULL,			0, N_("set up /dev/dvb/adapterX/dvr0 for TS recording"), 0},
+	{"streaming",	'R', NULL,			0, N_("uses streaming I/O for TS recording"), 0},
 	{"silence",	's', NULL,			0, N_("increases silence (can be used more than once)"), 0},
 	{"sat_number",	'S', N_("satellite_number"),	0, N_("satellite number. If not specified, disable DISEqC"), 0},
 	{"timeout",	't', N_("seconds"),		0, N_("timeout for zapping and for recording"), 0},
@@ -449,6 +452,171 @@ static void get_show_stats(struct arguments *args,
 	} while (!timeout_flag && loop);
 }
 
+#define TEST_EXPBUF (1)
+
+#define STREAM_BUF_CNT (10)
+#define STREAM_BUF_SIZ (188*1024)
+
+#define memzero(x) memset(&(x), 0, sizeof(x))
+
+struct stream_ctx {
+	int in_fd;
+	int out_fd;
+	int buf_cnt;
+	int buf_size;
+	char *buf[STREAM_BUF_CNT];
+	int buf_flag[STREAM_BUF_CNT];
+	int exp_buf[STREAM_BUF_CNT];
+	int error;
+};
+
+static int stream_init(struct stream_ctx *sc, int in_fd, int out_fd)
+{
+	struct dmx_requestbuffers req;
+	struct dmx_exportbuffer exp;
+	struct dmx_buffer buf;
+	int ret;
+	int i;
+
+	memset(sc, 0, sizeof(struct stream_ctx));
+	sc->in_fd = in_fd;
+	sc->out_fd = out_fd;
+	sc->buf_size = STREAM_BUF_SIZ;
+	sc->buf_cnt = STREAM_BUF_CNT;
+
+	memzero(req);
+	req.count = sc->buf_cnt;
+	req.size = sc->buf_size;
+
+	ret = ioctl(in_fd, DMX_REQBUFS, &req);
+	if (ret) {
+		PERROR("DMX_REQBUFS failed: error=%d", ret);
+		return ret;
+	}
+
+	if (sc->buf_cnt != req.count) {
+		fprintf(stderr, "buf_cnt %d -> %d changed !!!\n",
+				sc->buf_cnt, req.count);
+		sc->buf_cnt = req.count;
+	}
+
+	for (i = 0; i < sc->buf_cnt; i++) {
+		memzero(buf);
+		buf.index = i;
+
+		ret = ioctl(in_fd, DMX_QUERYBUF, &buf);
+		if (ret) {
+			PERROR("DMX_QUERYBUF failed: buf=%d error=%d", i, ret);
+			return ret;
+		}
+
+		sc->buf[i] = mmap(NULL, buf.length,
+					PROT_READ | PROT_WRITE, MAP_SHARED,
+					in_fd, buf.offset);
+
+		if (sc->buf[i] == MAP_FAILED) {
+			PERROR("Failed to MMAP buffer %d", i);
+			return -1;
+		}
+#if TEST_EXPBUF
+		memzero(exp);
+		exp.index = i;
+		ret = ioctl(in_fd, DMX_EXPBUF, &exp);
+		if (ret) {
+			PERROR("DMX_EXPBUF failed: buf=%d error=%d", i, ret);
+			return ret;
+		}
+		sc->exp_buf[i] = exp.fd;
+		fprintf(stderr, "Export buffer %d (fd=%d)\n",
+				i, sc->exp_buf[i]);
+#endif
+	}
+
+	return 0;
+}
+
+static int stream_qbuf(struct stream_ctx *sc, int n)
+{
+	struct dmx_buffer buf;
+	int ret;
+
+	memzero(buf);
+	buf.index = n;
+
+	ret = ioctl(sc->in_fd, DMX_QBUF, &buf);
+
+	if (ret) {
+		PERROR("DMX_QBUF failed: buf=%d error=%d", n, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int stream_dqbuf(struct stream_ctx *sc, struct dmx_buffer *buf)
+{
+	int ret;
+
+	ret = ioctl(sc->in_fd, DMX_DQBUF, buf);
+
+	if (ret) {
+		PERROR("DMX_DQBUF failed: error=%d", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static void stream_to_file(int in_fd, int out_fd, int timeout, int silent)
+{
+	struct stream_ctx sc;
+	int ret;
+	int n;
+	long long int rc = 0LL;
+
+	ret = stream_init(&sc, in_fd, out_fd);
+	if (ret) {
+		PERROR("[%s] Failed to setup buffers!!!", __func__);
+		sc.error = 1;
+	}
+	fprintf(stderr, "start streaming!!!\n");
+
+	while (timeout_flag == 0 && !sc.error) {
+		n = 0;
+		/* find empty buffer */
+		while (n < sc.buf_cnt && sc.buf_flag[n])
+			n++;
+
+		/* enqueue the empty buffer */
+		if (n < sc.buf_cnt) {
+			ret = stream_qbuf(&sc, n);
+			if (ret)
+				sc.error = 1;
+			else
+				sc.buf_flag[n] = 1;
+		} else {
+			/* if empty buffer is not found, dequeue buffer */
+			struct dmx_buffer b;
+
+			ret = stream_dqbuf(&sc, &b);
+			if (ret)
+				sc.error = 1;
+			else
+			{
+				sc.buf_flag[b.index] = 0;
+				if (sc.out_fd && write(sc.out_fd,
+					sc.buf[b.index], b.bytesused))
+					rc += b.bytesused;
+			}
+		}
+	}
+
+	if (silent < 2) {
+		fprintf(stderr, "copied %lld bytes (%lld Kbytes/sec)\n", rc,
+			rc / (1024 * timeout));
+	}
+}
+
 #define BUFLEN (188 * 256)
 static void copy_to_file(int in_fd, int out_fd, int timeout, int silent)
 {
@@ -503,6 +671,10 @@ static error_t parse_opt(int k, char *optarg, struct argp_state *state)
 	case 'r':
 		args->dvr = 1;
 		break;
+	case 'R':
+		args->dvr = 1;
+		args->streaming = 1;
+		break;
 	case 'p':
 		args->rec_psi = 1;
 		break;
@@ -993,13 +1165,24 @@ int main(int argc, char **argv)
 			get_show_stats(&args, parms, 0);
 
 		if (file_fd >= 0) {
-			if ((dvr_fd = open(args.dvr_dev, O_RDONLY)) < 0) {
+			int flag;
+
+			if (args.streaming)
+				flag = O_RDWR;
+			else
+				flag = O_RDONLY;
+
+			dvr_fd = open(args.dvr_dev, flag);
+			if (dvr_fd < 0) {
 				PERROR(_("failed opening '%s'"), args.dvr_dev);
 				goto err;
 			}
 			if (!timeout_flag)
 				fprintf(stderr, _("Record to file '%s' started\n"), args.filename);
-			copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
+			if (args.streaming)
+				stream_to_file(dvr_fd, file_fd, args.timeout, args.silent);
+			else
+				copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
 		} else {
 			if (!timeout_flag)
 				fprintf(stderr, _("DVR interface '%s' can now be opened\n"), args.dvr_dev);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] media: videobuf2: Add new uAPI for DVB streaming I/O
  2015-10-06  9:59 ` [PATCH] media: videobuf2: Add new " Junghak Sung
@ 2015-10-06 10:15   ` kbuild test robot
  2015-10-06 10:51   ` kbuild test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2015-10-06 10:15 UTC (permalink / raw)
  To: Junghak Sung
  Cc: kbuild-all, linux-media, mchehab, hverkuil, laurent.pinchart,
	sakari.ailus, pawel, inki.dae, sw0312.kim, nenggun.kim,
	sangbae90.lee, rany.kwon, Junghak Sung

[-- Attachment #1: Type: text/plain, Size: 13715 bytes --]

Hi Junghak,

[auto build test ERROR on v4.3-rc4 -- if it's inappropriate base, please ignore]

config: x86_64-rhel (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

>> drivers/media/dvb-core/dvb_vb2.c:32:5: warning: 'struct vb2_format' declared inside parameter list
        unsigned int sizes[], void *alloc_ctxs[])
        ^
>> drivers/media/dvb-core/dvb_vb2.c:32:5: warning: its scope is only this definition or declaration, which is probably not what you want
>> drivers/media/dvb-core/dvb_vb2.c:114:2: warning: initialization from incompatible pointer type
     .queue_setup  = _queue_setup,
     ^
>> drivers/media/dvb-core/dvb_vb2.c:114:2: warning: (near initialization for 'dvb_vb2_qops.queue_setup')
   drivers/media/dvb-core/dvb_vb2.c: In function '_fill_dmx_buffer':
>> drivers/media/dvb-core/dvb_vb2.c:128:15: error: 'struct vb2_buffer' has no member named 'index'
     b->index = vb->index;
                  ^
>> drivers/media/dvb-core/dvb_vb2.c:129:27: error: 'struct vb2_plane' has no member named 'length'
     b->length = vb->planes[0].length;
                              ^
>> drivers/media/dvb-core/dvb_vb2.c:130:30: error: 'struct vb2_plane' has no member named 'bytesused'
     b->bytesused = vb->planes[0].bytesused;
                                 ^
>> drivers/media/dvb-core/dvb_vb2.c:131:27: error: 'struct vb2_plane' has no member named 'm'
     b->offset = vb->planes[0].m.offset;
                              ^
   drivers/media/dvb-core/dvb_vb2.c: In function '_fill_vb2_buffer':
   drivers/media/dvb-core/dvb_vb2.c:143:11: error: 'struct vb2_plane' has no member named 'bytesused'
     planes[0].bytesused = 0;
              ^
   drivers/media/dvb-core/dvb_vb2.c: At top level:
>> drivers/media/dvb-core/dvb_vb2.c:149:21: error: variable 'dvb_vb2_buf_ops' has initializer but incomplete type
    static const struct vb2_buf_ops dvb_vb2_buf_ops = {
                        ^
>> drivers/media/dvb-core/dvb_vb2.c:150:2: error: unknown field 'fill_user_buffer' specified in initializer
     .fill_user_buffer = _fill_dmx_buffer,
     ^
>> drivers/media/dvb-core/dvb_vb2.c:150:2: warning: excess elements in struct initializer
>> drivers/media/dvb-core/dvb_vb2.c:150:2: warning: (near initialization for 'dvb_vb2_buf_ops')
>> drivers/media/dvb-core/dvb_vb2.c:151:2: error: unknown field 'fill_vb2_buffer' specified in initializer
     .fill_vb2_buffer = _fill_vb2_buffer,
     ^
   drivers/media/dvb-core/dvb_vb2.c:151:2: warning: excess elements in struct initializer
   drivers/media/dvb-core/dvb_vb2.c:151:2: warning: (near initialization for 'dvb_vb2_buf_ops')
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_init':
>> drivers/media/dvb-core/dvb_vb2.c:170:3: error: 'struct vb2_queue' has no member named 'buf_ops'
     q->buf_ops = &dvb_vb2_buf_ops;
      ^
>> drivers/media/dvb-core/dvb_vb2.c:173:2: error: implicit declaration of function 'vb2_core_queue_init' [-Werror=implicit-function-declaration]
     ret = vb2_core_queue_init(q);
     ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_release':
>> drivers/media/dvb-core/dvb_vb2.c:198:3: error: implicit declaration of function 'vb2_core_queue_release' [-Werror=implicit-function-declaration]
      vb2_core_queue_release(q);
      ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_stream_on':
>> drivers/media/dvb-core/dvb_vb2.c:211:2: error: implicit declaration of function 'vb2_core_streamon' [-Werror=implicit-function-declaration]
     ret = vb2_core_streamon(q, q->type);
     ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_stream_off':
>> drivers/media/dvb-core/dvb_vb2.c:237:2: error: implicit declaration of function 'vb2_core_streamoff' [-Werror=implicit-function-declaration]
     ret = vb2_core_streamoff(q, q->type);
     ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_reqbufs':
>> drivers/media/dvb-core/dvb_vb2.c:322:2: error: implicit declaration of function 'vb2_core_reqbufs' [-Werror=implicit-function-declaration]
     ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
     ^
>> drivers/media/dvb-core/dvb_vb2.c:322:37: error: 'VB2_MEMORY_MMAP' undeclared (first use in this function)
     ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
                                        ^
   drivers/media/dvb-core/dvb_vb2.c:322:37: note: each undeclared identifier is reported only once for each function it appears in
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_querybuf':

vim +128 drivers/media/dvb-core/dvb_vb2.c

    26			if (vb2_debug >= level)					      \
    27				pr_info("vb2: %s: " fmt, __func__, ## arg); \
    28		} while (0)
    29	
    30	static int _queue_setup(struct vb2_queue *vq, const struct vb2_format *fmt,
    31					unsigned int *nbuffers, unsigned int *nplanes,
  > 32					unsigned int sizes[], void *alloc_ctxs[])
    33	{
    34		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
    35	
    36		*nbuffers = ctx->buf_cnt;
    37		*nplanes = 1;
    38		sizes[0] = ctx->buf_siz;
    39	
    40		/*
    41		 * videobuf2-vmalloc allocator is context-less so no need to set
    42		 * alloc_ctxs array.
    43		 */
    44	
    45		dprintk(3, "[%s] count=%d, size=%d\n", ctx->name,
    46				*nbuffers, sizes[0]);
    47	
    48		return 0;
    49	}
    50	
    51	static int _buffer_prepare(struct vb2_buffer *vb)
    52	{
    53		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
    54		unsigned long size = ctx->buf_siz;
    55	
    56		if (vb2_plane_size(vb, 0) < size) {
    57			dprintk(1, "[%s] data will not fit into plane (%lu < %lu)\n",
    58					ctx->name, vb2_plane_size(vb, 0), size);
    59			return -EINVAL;
    60		}
    61	
    62		vb2_set_plane_payload(vb, 0, size);
    63		dprintk(3, "[%s]\n", ctx->name);
    64	
    65		return 0;
    66	}
    67	
    68	static void _buffer_queue(struct vb2_buffer *vb)
    69	{
    70		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
    71		struct dvb_buffer *buf = container_of(vb, struct dvb_buffer, vb);
    72		unsigned long flags = 0;
    73	
    74		spin_lock_irqsave(&ctx->slock, flags);
    75		list_add_tail(&buf->list, &ctx->dvb_q);
    76		spin_unlock_irqrestore(&ctx->slock, flags);
    77	
    78		dprintk(3, "[%s]\n", ctx->name);
    79	}
    80	
    81	static int _start_streaming(struct vb2_queue *vq, unsigned int count)
    82	{
    83		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
    84	
    85		dprintk(3, "[%s] count=%d\n", ctx->name, count);
    86		return 0;
    87	}
    88	
    89	static void _stop_streaming(struct vb2_queue *vq)
    90	{
    91		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
    92	
    93		dprintk(3, "[%s]\n", ctx->name);
    94	}
    95	
    96	static void _dmxdev_lock(struct vb2_queue *vq)
    97	{
    98		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
    99	
   100		mutex_lock(&ctx->mutex);
   101		dprintk(3, "[%s]\n", ctx->name);
   102	}
   103	
   104	static void _dmxdev_unlock(struct vb2_queue *vq)
   105	{
   106		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
   107	
   108		if (mutex_is_locked(&ctx->mutex))
   109			mutex_unlock(&ctx->mutex);
   110		dprintk(3, "[%s]\n", ctx->name);
   111	}
   112	
   113	static const struct vb2_ops dvb_vb2_qops = {
 > 114		.queue_setup		= _queue_setup,
   115		.buf_prepare		= _buffer_prepare,
   116		.buf_queue		= _buffer_queue,
   117		.start_streaming	= _start_streaming,
   118		.stop_streaming		= _stop_streaming,
   119		.wait_prepare		= _dmxdev_unlock,
   120		.wait_finish		= _dmxdev_lock,
   121	};
   122	
   123	static int _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
   124	{
   125		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
   126		struct dmx_buffer *b = pb;
   127	
 > 128		b->index = vb->index;
 > 129		b->length = vb->planes[0].length;
 > 130		b->bytesused = vb->planes[0].bytesused;
 > 131		b->offset = vb->planes[0].m.offset;
   132		memset(b->reserved, 0, sizeof(b->reserved));
   133		dprintk(3, "[%s]\n", ctx->name);
   134	
   135		return 0;
   136	}
   137	
   138	static int _fill_vb2_buffer(struct vb2_buffer *vb,
   139			const void *pb, struct vb2_plane *planes)
   140	{
   141		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
   142	
 > 143		planes[0].bytesused = 0;
   144		dprintk(3, "[%s]\n", ctx->name);
   145	
   146		return 0;
   147	}
   148	
 > 149	static const struct vb2_buf_ops dvb_vb2_buf_ops = {
 > 150		.fill_user_buffer	= _fill_dmx_buffer,
 > 151		.fill_vb2_buffer	= _fill_vb2_buffer,
   152	};
   153	
   154	/*
   155	 * Videobuf operations
   156	 */
   157	int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
   158	{
   159		struct vb2_queue *q = &ctx->vb_q;
   160		int ret;
   161	
   162		memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
   163		q->type = DVB_BUF_TYPE_CAPTURE;
   164		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ | VB2_DMABUF;
   165		q->drv_priv = ctx;
   166		q->buf_struct_size = sizeof(struct dvb_buffer);
   167		q->min_buffers_needed = 1;
   168		q->ops = &dvb_vb2_qops;
   169		q->mem_ops = &vb2_vmalloc_memops;
 > 170		q->buf_ops = &dvb_vb2_buf_ops;
   171		q->num_buffers = 0;
   172	
 > 173		ret = vb2_core_queue_init(q);
   174		if (ret) {
   175			ctx->state = DVB_VB2_STATE_NONE;
   176			dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
   177			return ret;
   178		}
   179	
   180		mutex_init(&ctx->mutex);
   181		spin_lock_init(&ctx->slock);
   182		INIT_LIST_HEAD(&ctx->dvb_q);
   183	
   184		strncpy(ctx->name, name, DVB_VB2_NAME_MAX);
   185		ctx->nonblocking = nonblocking;
   186		ctx->state = DVB_VB2_STATE_INIT;
   187	
   188		dprintk(3, "[%s]\n", ctx->name);
   189	
   190		return 0;
   191	}
   192	
   193	int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
   194	{
   195		struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
   196	
   197		if (ctx->state && DVB_VB2_STATE_INIT)
 > 198			vb2_core_queue_release(q);
   199	
   200		ctx->state = DVB_VB2_STATE_NONE;
   201		dprintk(3, "[%s]\n", ctx->name);
   202	
   203		return 0;
   204	}
   205	
   206	int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx)
   207	{
   208		struct vb2_queue *q = &ctx->vb_q;
   209		int ret;
   210	
 > 211		ret = vb2_core_streamon(q, q->type);
   212		if (ret) {
   213			ctx->state = DVB_VB2_STATE_NONE;
   214			dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
   215			return ret;
   216		}
   217		ctx->state |= DVB_VB2_STATE_STREAMON;
   218		dprintk(3, "[%s]\n", ctx->name);
   219	
   220		return 0;
   221	}
   222	
   223	int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx)
   224	{
   225		struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
   226		int ret;
   227		int i;
   228	
   229		ctx->state &= ~DVB_VB2_STATE_STREAMON;
   230	
   231		for (i = 0; i < q->num_buffers; ++i) {
   232			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE)
   233				vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);
   234	
   235		}
   236	
 > 237		ret = vb2_core_streamoff(q, q->type);
   238		if (ret) {
   239			ctx->state = DVB_VB2_STATE_NONE;
   240			dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
   241			return ret;
   242		}
   243		dprintk(3, "[%s]\n", ctx->name);
   244	
   245		return 0;
   246	}
   247	
   248	int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
   249	{
   250		return (ctx->state & DVB_VB2_STATE_STREAMON);
   251	}
   252	
   253	int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
   254			const unsigned char *src, int len)
   255	{
   256		unsigned long flags = 0;
   257		void *vbuf;
   258		int todo = len;
   259		unsigned char *psrc = (unsigned char *)src;
   260		int ll;
   261	
   262		while (todo) {
   263			if (!ctx->buf) {
   264				if (list_empty(&ctx->dvb_q)) {
   265					dprintk(3, "[%s] Buffer overflow!!!\n",
   266							ctx->name);
   267					break;
   268				}
   269	
   270				spin_lock_irqsave(&ctx->slock, flags);
   271				ctx->buf = list_entry(ctx->dvb_q.next,
   272						struct dvb_buffer, list);
   273				list_del(&ctx->buf->list);
   274				ctx->remain = vb2_plane_size(&ctx->buf->vb, 0);
   275				ctx->offset = 0;
   276				spin_unlock_irqrestore(&ctx->slock, flags);
   277			}
   278	
   279			if (!dvb_vb2_is_streaming(ctx)) {
   280				vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR);
   281				ctx->buf = NULL;
   282				break;
   283			}
   284	
   285			/* Fill buffer */
   286			vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0);
   287	
   288			ll = min(todo, ctx->remain);
   289			memcpy(vbuf+ctx->offset, psrc, ll);
   290			todo -= ll;
   291			psrc += ll;
   292	
   293			ctx->remain -= ll;
   294			ctx->offset += ll;
   295	
   296			if (ctx->remain == 0) {
   297				vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
   298				ctx->buf = NULL;
   299			}
   300		}
   301	
   302		if (ctx->nonblocking && ctx->buf) {
   303			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
   304			ctx->buf = NULL;
   305		}
   306	
   307		if (todo)
   308			dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo);
   309		else
   310			dprintk(3, "[%s]\n", ctx->name);
   311	
   312		return (len - todo);
   313	}
   314	
   315	int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
   316	{
   317		int ret;
   318	
   319		ctx->buf_siz = req->size;
   320		ctx->buf_cnt = req->count;
   321	
 > 322		ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
   323		if (ret) {
   324			ctx->state = DVB_VB2_STATE_NONE;
   325			dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 35271 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] media: videobuf2: Add new uAPI for DVB streaming I/O
  2015-10-06  9:59 ` [PATCH] media: videobuf2: Add new " Junghak Sung
  2015-10-06 10:15   ` kbuild test robot
@ 2015-10-06 10:51   ` kbuild test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2015-10-06 10:51 UTC (permalink / raw)
  To: Junghak Sung
  Cc: kbuild-all, linux-media, mchehab, hverkuil, laurent.pinchart,
	sakari.ailus, pawel, inki.dae, sw0312.kim, nenggun.kim,
	sangbae90.lee, rany.kwon, Junghak Sung

Hi Junghak,

[auto build test WARNING on v4.3-rc4 -- if it's inappropriate base, please ignore]

reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> drivers/media/dvb-core/dvb_vb2.c:114:35: sparse: incorrect type in initializer (incompatible argument 2 (different base types))
   drivers/media/dvb-core/dvb_vb2.c:114:35:    expected int ( *queue_setup )( ... )
   drivers/media/dvb-core/dvb_vb2.c:114:35:    got int ( static [toplevel] *<noident> )( ... )
   drivers/media/dvb-core/dvb_vb2.c:128:22: sparse: no member 'index' in struct vb2_buffer
   drivers/media/dvb-core/dvb_vb2.c:129:34: sparse: no member 'length' in struct vb2_plane
   drivers/media/dvb-core/dvb_vb2.c:130:37: sparse: no member 'bytesused' in struct vb2_plane
   drivers/media/dvb-core/dvb_vb2.c:131:34: sparse: no member 'm' in struct vb2_plane
   drivers/media/dvb-core/dvb_vb2.c:143:18: sparse: no member 'bytesused' in struct vb2_plane
   drivers/media/dvb-core/dvb_vb2.c:150:10: sparse: unknown field name in initializer
   drivers/media/dvb-core/dvb_vb2.c:151:10: sparse: unknown field name in initializer
   drivers/media/dvb-core/dvb_vb2.c:170:10: sparse: no member 'buf_ops' in struct vb2_queue
   drivers/media/dvb-core/dvb_vb2.c:173:15: sparse: undefined identifier 'vb2_core_queue_init'
   drivers/media/dvb-core/dvb_vb2.c:198:17: sparse: undefined identifier 'vb2_core_queue_release'
   drivers/media/dvb-core/dvb_vb2.c:211:15: sparse: undefined identifier 'vb2_core_streamon'
   drivers/media/dvb-core/dvb_vb2.c:237:15: sparse: undefined identifier 'vb2_core_streamoff'
   drivers/media/dvb-core/dvb_vb2.c:322:15: sparse: undefined identifier 'vb2_core_reqbufs'
   drivers/media/dvb-core/dvb_vb2.c:340:15: sparse: undefined identifier 'vb2_core_querybuf'
   drivers/media/dvb-core/dvb_vb2.c:356:15: sparse: undefined identifier 'vb2_core_expbuf'
   drivers/media/dvb-core/dvb_vb2.c:372:15: sparse: undefined identifier 'vb2_core_qbuf'
   drivers/media/dvb-core/dvb_vb2.c:387:15: sparse: undefined identifier 'vb2_core_dqbuf'
   drivers/media/dvb-core/dvb_vb2.c:32:5: warning: 'struct vb2_format' declared inside parameter list
        unsigned int sizes[], void *alloc_ctxs[])
        ^
   drivers/media/dvb-core/dvb_vb2.c:32:5: warning: its scope is only this definition or declaration, which is probably not what you want
   drivers/media/dvb-core/dvb_vb2.c:114:18: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
     .queue_setup  = _queue_setup,
                     ^
   drivers/media/dvb-core/dvb_vb2.c:114:18: note: (near initialization for 'dvb_vb2_qops.queue_setup')
   drivers/media/dvb-core/dvb_vb2.c: In function '_fill_dmx_buffer':
   drivers/media/dvb-core/dvb_vb2.c:128:15: error: 'struct vb2_buffer' has no member named 'index'
     b->index = vb->index;
                  ^
   drivers/media/dvb-core/dvb_vb2.c:129:27: error: 'struct vb2_plane' has no member named 'length'
     b->length = vb->planes[0].length;
                              ^
   drivers/media/dvb-core/dvb_vb2.c:130:30: error: 'struct vb2_plane' has no member named 'bytesused'
     b->bytesused = vb->planes[0].bytesused;
                                 ^
   drivers/media/dvb-core/dvb_vb2.c:131:27: error: 'struct vb2_plane' has no member named 'm'
     b->offset = vb->planes[0].m.offset;
                              ^
   drivers/media/dvb-core/dvb_vb2.c: In function '_fill_vb2_buffer':
   drivers/media/dvb-core/dvb_vb2.c:143:11: error: 'struct vb2_plane' has no member named 'bytesused'
     planes[0].bytesused = 0;
              ^
   drivers/media/dvb-core/dvb_vb2.c: At top level:
   drivers/media/dvb-core/dvb_vb2.c:149:21: error: variable 'dvb_vb2_buf_ops' has initializer but incomplete type
    static const struct vb2_buf_ops dvb_vb2_buf_ops = {
                        ^
   drivers/media/dvb-core/dvb_vb2.c:150:2: error: unknown field 'fill_user_buffer' specified in initializer
     .fill_user_buffer = _fill_dmx_buffer,
     ^
   drivers/media/dvb-core/dvb_vb2.c:150:22: warning: excess elements in struct initializer
     .fill_user_buffer = _fill_dmx_buffer,
                         ^
   drivers/media/dvb-core/dvb_vb2.c:150:22: note: (near initialization for 'dvb_vb2_buf_ops')
   drivers/media/dvb-core/dvb_vb2.c:151:2: error: unknown field 'fill_vb2_buffer' specified in initializer
     .fill_vb2_buffer = _fill_vb2_buffer,
     ^
   drivers/media/dvb-core/dvb_vb2.c:151:21: warning: excess elements in struct initializer
     .fill_vb2_buffer = _fill_vb2_buffer,
                        ^
   drivers/media/dvb-core/dvb_vb2.c:151:21: note: (near initialization for 'dvb_vb2_buf_ops')
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_init':
   drivers/media/dvb-core/dvb_vb2.c:170:3: error: 'struct vb2_queue' has no member named 'buf_ops'
     q->buf_ops = &dvb_vb2_buf_ops;
      ^
   drivers/media/dvb-core/dvb_vb2.c:173:8: error: implicit declaration of function 'vb2_core_queue_init' [-Werror=implicit-function-declaration]
     ret = vb2_core_queue_init(q);
           ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_release':
   drivers/media/dvb-core/dvb_vb2.c:198:3: error: implicit declaration of function 'vb2_core_queue_release' [-Werror=implicit-function-declaration]
      vb2_core_queue_release(q);
      ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_stream_on':
   drivers/media/dvb-core/dvb_vb2.c:211:8: error: implicit declaration of function 'vb2_core_streamon' [-Werror=implicit-function-declaration]
     ret = vb2_core_streamon(q, q->type);
           ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_stream_off':
   drivers/media/dvb-core/dvb_vb2.c:237:8: error: implicit declaration of function 'vb2_core_streamoff' [-Werror=implicit-function-declaration]
     ret = vb2_core_streamoff(q, q->type);
           ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_reqbufs':
   drivers/media/dvb-core/dvb_vb2.c:322:8: error: implicit declaration of function 'vb2_core_reqbufs' [-Werror=implicit-function-declaration]
     ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
           ^
   drivers/media/dvb-core/dvb_vb2.c:322:37: error: 'VB2_MEMORY_MMAP' undeclared (first use in this function)
     ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
                                        ^
   drivers/media/dvb-core/dvb_vb2.c:322:37: note: each undeclared identifier is reported only once for each function it appears in
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_querybuf':
   drivers/media/dvb-core/dvb_vb2.c:340:8: error: implicit declaration of function 'vb2_core_querybuf' [-Werror=implicit-function-declaration]
     ret = vb2_core_querybuf(&ctx->vb_q, b->index, b);
           ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_expbuf':
   drivers/media/dvb-core/dvb_vb2.c:356:8: error: implicit declaration of function 'vb2_core_expbuf' [-Werror=implicit-function-declaration]
     ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index,
           ^
   drivers/media/dvb-core/dvb_vb2.c: In function 'dvb_vb2_qbuf':
   drivers/media/dvb-core/dvb_vb2.c:372:8: error: implicit declaration of function 'vb2_core_qbuf' [-Werror=implicit-function-declaration]
     ret = vb2_core_qbuf(&ctx->vb_q, b->index, b);

vim +114 drivers/media/dvb-core/dvb_vb2.c

    98		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
    99	
   100		mutex_lock(&ctx->mutex);
   101		dprintk(3, "[%s]\n", ctx->name);
   102	}
   103	
   104	static void _dmxdev_unlock(struct vb2_queue *vq)
   105	{
   106		struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
   107	
   108		if (mutex_is_locked(&ctx->mutex))
   109			mutex_unlock(&ctx->mutex);
   110		dprintk(3, "[%s]\n", ctx->name);
   111	}
   112	
   113	static const struct vb2_ops dvb_vb2_qops = {
 > 114		.queue_setup		= _queue_setup,
   115		.buf_prepare		= _buffer_prepare,
   116		.buf_queue		= _buffer_queue,
   117		.start_streaming	= _start_streaming,
   118		.stop_streaming		= _stop_streaming,
   119		.wait_prepare		= _dmxdev_unlock,
   120		.wait_finish		= _dmxdev_lock,
   121	};
   122	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB
  2015-10-06  9:59 ` [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB Junghak Sung
@ 2016-05-13 11:56   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 6+ messages in thread
From: Mauro Carvalho Chehab @ 2016-05-13 11:56 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Tue, 06 Oct 2015 18:59:02 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Add a new scenario to use streaming I/O for TS recording.
> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>


Due to some changes that happened after the VB2 split changes got merged,
this patch doesn't compile anymore.

The enclosed diff should make it build yet.

I intend to fold it with the original patch and do some tests,
in order to make this work merged some day upstream.

Regards,
Mauro

diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c
index 1a2dc5516c4e..5b1bcc80880f 100644
--- a/drivers/media/dvb-core/dvb_vb2.c
+++ b/drivers/media/dvb-core/dvb_vb2.c
@@ -27,7 +27,7 @@ module_param(vb2_debug, int, 0644);
 			pr_info("vb2: %s: " fmt, __func__, ## arg); \
 	} while (0)
 
-static int _queue_setup(struct vb2_queue *vq, const struct vb2_format *fmt,
+static int _queue_setup(struct vb2_queue *vq,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
@@ -120,7 +120,7 @@ static const struct vb2_ops dvb_vb2_qops = {
 	.wait_finish		= _dmxdev_lock,
 };
 
-static int _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
+static void _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
 {
 	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct dmx_buffer *b = pb;
@@ -131,8 +131,6 @@ static int _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
 	b->offset = vb->planes[0].m.offset;
 	memset(b->reserved, 0, sizeof(b->reserved));
 	dprintk(3, "[%s]\n", ctx->name);
-
-	return 0;
 }
 
 static int _fill_vb2_buffer(struct vb2_buffer *vb,
@@ -335,14 +333,7 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
 
 int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
-	int ret;
-
-	ret = vb2_core_querybuf(&ctx->vb_q, b->index, b);
-	if (ret) {
-		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
-				b->index, ret);
-		return ret;
-	}
+	vb2_core_querybuf(&ctx->vb_q, b->index, b);
 	dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
 
 	return 0;
@@ -384,7 +375,7 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
 	int ret;
 
-	ret = vb2_core_dqbuf(&ctx->vb_q, b, ctx->nonblocking);
+	ret = vb2_core_dqbuf(&ctx->vb_q, NULL, b, ctx->nonblocking);
 	if (ret) {
 		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 		return ret;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-05-13 11:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-06  9:59 [RFC PATCH] New uAPI for DVB streaming I/O Junghak Sung
2015-10-06  9:59 ` [PATCH] media: videobuf2: Add new " Junghak Sung
2015-10-06 10:15   ` kbuild test robot
2015-10-06 10:51   ` kbuild test robot
2015-10-06  9:59 ` [PATCH] media: v4l-utils: dvbv5: Streaming I/O for DVB Junghak Sung
2016-05-13 11:56   ` Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.