* [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.