This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:

Subject: dvbv5: streaming support using videobuf2 for DVR and auto-scan
Author:  Satendra Singh Thakur <[email protected]>
Date:    Wed Dec 27 09:10:22 2017 +0530

Ported an older patch (details given below) to latest v4l-utils:
 commit 6049ea8bd64f (Statically linking libdvbv5 must
 include -ludev) v4l-utils
 -Added videobuf2 code for auto-scan
-Enhanced queueing logic
--Enqueue all bufs in the begining, dequeue one buf
--Consume it, enqueue it again and so on..
-Added a common dvb-vb2 lib for following streaming APIs.
--initializatioin, deinitialization: unmap and dequeue
--enqueue buf, dequeue buf
--export buf, stream_to_file
--xioctl for repeated ioctl calling
-Added comments to functions
-This code could not be tested so far

Original patch:
https://patchwork.linuxtv.org/patch/31612/

Signed-off-by: Junghak Sung <[email protected]>
Signed-off-by: Geunyoung Kim <[email protected]>
Acked-by: Seung-Woo Kim <[email protected]>
Acked-by: Inki Dae <[email protected]>
Signed-off-by: Satendra Singh Thakur <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Acked-by: Mauro Carvalho Chehab <[email protected]>

 lib/include/libdvbv5/dvb-dev.h |   8 +
 lib/include/libdvbv5/dvb-vb2.h | 147 +++++++++++++++++++
 lib/libdvbv5/dvb-scan.c        | 100 +++++++++++--
 lib/libdvbv5/dvb-vb2.c         | 325 +++++++++++++++++++++++++++++++++++++++++
 lib/libdvbv5/meson.build       |   2 +
 utils/dvb/dvbv5-zap.c          |  30 +++-
 6 files changed, 599 insertions(+), 13 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=a69f2cb9c96347af5746b05955bcd2d9561ec014
diff --git a/lib/include/libdvbv5/dvb-dev.h b/lib/include/libdvbv5/dvb-dev.h
index 6b4d7483a3fc..3fdf7a0941a7 100644
--- a/lib/include/libdvbv5/dvb-dev.h
+++ b/lib/include/libdvbv5/dvb-dev.h
@@ -308,6 +308,14 @@ struct dvb_open_descriptor *dvb_dev_open(struct dvb_device 
*dvb,
  * closed.
  */
 void dvb_dev_close(struct dvb_open_descriptor *open_dev);
+/**
+ * @brief Gets open file descriptor of a dvb device
+ * @ingroup dvb_device
+ *
+ * @param open_dev     Points to the struct dvb_open_descriptor
+ * @return Retuns fd on success, -1 otherwise.
+ */
+int dvb_dev_get_fd(struct dvb_open_descriptor *open_dev);
 
 /**
  * @brief returns fd from a local device
diff --git a/lib/include/libdvbv5/dvb-vb2.h b/lib/include/libdvbv5/dvb-vb2.h
new file mode 100644
index 000000000000..e66b9efe3de4
--- /dev/null
+++ b/lib/include/libdvbv5/dvb-vb2.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017-2018 - Mauro Carvalho Chehab
+ * Copyright (c) 2017-2018 - Junghak Sung <[email protected]>
+ * Copyright (c) 2017-2018 - Satendra Singh Thakur <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation version 2.1 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to 
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ */
+#ifndef _LIBVB2_H
+#define _LIBVB2_H
+
+#include <stdint.h>
+#include <linux/dvb/dmx.h>
+
+/**
+ * @file dvb-vb2.h
+ * @ingroup frontend_scan
+ * @brief Provides interfaces to videobuf2 streaming for DVB.
+ * @copyright GNU Lesser General Public License version 2.1 (LGPLv2.1)
+ * @author Satendra Singh Thakur
+ *
+ * @par Bug Report
+ * Please submit bug reports and patches to [email protected]
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define memzero(x) memset(&(x), 0, sizeof(x))
+
+/**Max count of the buffers*/
+#define MAX_STREAM_BUF_CNT     10
+
+/**
+ * struct stream_ctx - Streaming context
+ *
+ * @param in_fd                File descriptor of streaming device
+ * @param out_fd       File descriptor of output file
+ * @param buf_cnt      Count of the buffers to be queued/dequeued
+ * @param buf_size     Size of one such buffer
+ * @param buf          Pointer to array of buffers
+ * @param buf_flags    Array of boolean flags corresponding to buffers
+ * @param exp_fd       Array of file descriptors of exported buffers
+ * @param error                Error flag
+ */
+struct stream_ctx {
+       int in_fd;
+       int out_fd;
+       int buf_cnt;
+       int buf_size;
+       unsigned char *buf[MAX_STREAM_BUF_CNT];
+       int buf_flag[MAX_STREAM_BUF_CNT];
+       int exp_fd[MAX_STREAM_BUF_CNT];
+       int error;
+};
+/**
+ * stream_qbuf - Enqueues a buffer specified by index n
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param idx          Index of the buffer
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_qbuf(struct stream_ctx *sc, int idx);
+
+/**
+ * sream_dqbuf - Dequeues a buffer specified by buf argument
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param buf          Pointer to &struct dmx_buffer
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_dqbuf(struct stream_ctx *sc, struct dmx_buffer *buf);
+/**
+ * sream_expbuf - Exports a buffer specified by buf argument
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param idx          Index of the buffer
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_expbuf(struct stream_ctx *sc, int idx);
+/**
+ * stream_init - Requests number of buffers from memory
+ * Gets pointer to the buffers from driver, mmaps those buffers
+ * and stores them in an array
+ * Also, optionally exports those buffers
+ *
+ * @param sc           Context for streaming management
+ * @param in_fd                File descriptor of the streaming device
+ * @param buf_size     Size of the buffer
+ * @param buf_cnt      Number of buffers
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_init(struct stream_ctx *sc, int in_fd, int buf_size, int buf_cnt);
+
+/**
+ * @struct dvb_table_filter
+ * @brief De-initiazes streaming
+ * @ingroup frontend_scan
+ *
+ * @param sc           Pointer to &struct stream_ctx
+ */
+void stream_deinit(struct stream_ctx *sc);
+/**
+ * stream_to_file - Implements enqueue and dequeue logic
+ * First enqueues all the available buffers then dequeues
+ * one buffer, again enqueues it and so on.
+ *
+ * @param in_fd                File descriptor of the streaming device
+ * @param out_fd       File descriptor of output file
+ * @param timeout      Timeout in seconds
+ * @param dbg_level    Debug flag
+ * @param exit_flag    Flag to exit
+ *
+ * @return void
+ */
+void stream_to_file(int in_fd, int out_fd, int timeout, int dbg_level,
+                       int *exit_flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libdvbv5/dvb-scan.c b/lib/libdvbv5/dvb-scan.c
index fcf2eba71e71..053ee137ef9f 100644
--- a/lib/libdvbv5/dvb-scan.c
+++ b/lib/libdvbv5/dvb-scan.c
@@ -72,6 +72,28 @@
 
 # define N_(string) string
 
+#define PERROR(x...)                                                    \
+       do {                                                            \
+               fprintf(stderr, "ERROR: ");                             \
+               fprintf(stderr, x);                                     \
+               fprintf(stderr, " (%s)\n", strerror(errno));            \
+       } while (0)
+
+
+/**Videobuf2 streaming
+ * Comment VB2 macro to disable the streaming code
+ */
+#define VB2
+
+#ifdef VB2
+#include <sys/mman.h>
+#include <libdvbv5/dvb-vb2.h>
+#define STREAM_BUF_CNT (4)
+#define STREAM_BUF_SIZ (DVB_MAX_PAYLOAD_PACKET_SIZE)
+
+struct stream_ctx sc = {0,};
+#endif
+
 static int dvb_poll(struct dvb_v5_fe_parms_priv *parms, int fd, unsigned int 
seconds)
 {
        fd_set set;
@@ -331,7 +353,8 @@ int dvb_read_sections(struct dvb_v5_fe_parms *__p, int 
dmx_fd,
        if (parms->p.verbose)
                dvb_log(_("%s: waiting for table ID 0x%02x, program ID 0x%02x"),
                        __func__, sect->tid, sect->pid);
-
+#ifdef VB2
+#else
        buf = calloc(DVB_MAX_PAYLOAD_PACKET_SIZE, 1);
        if (!buf) {
                dvb_logerr(_("%s: out of memory"), __func__);
@@ -339,7 +362,7 @@ int dvb_read_sections(struct dvb_v5_fe_parms *__p, int 
dmx_fd,
                dvb_table_filter_free(sect);
                return -1;
        }
-
+#endif
 
        do {
                int available;
@@ -359,7 +382,23 @@ int dvb_read_sections(struct dvb_v5_fe_parms *__p, int 
dmx_fd,
                        ret = -1;
                        break;
                }
+#ifdef VB2
+               struct dmx_buffer b;
+               memset(&b, 0, sizeof(b));
+
+               ret = stream_dqbuf(&sc, &b);
+               if (ret < 0) {
+                       sc.error = 1;
+                       break;
+               }
+               else {
+                       sc.buf_flag[b.index] = 0;
+                       buf = sc.buf[b.index];
+                       buf_length = b.bytesused;
+               }
+#else
                buf_length = read(dmx_fd, buf, DVB_MAX_PAYLOAD_PACKET_SIZE);
+#endif
 
                if (!buf_length) {
                        dvb_logerr(_("%s: buf returned an empty buffer"), 
__func__);
@@ -380,8 +419,24 @@ int dvb_read_sections(struct dvb_v5_fe_parms *__p, int 
dmx_fd,
                }
 
                ret = dvb_parse_section(parms, sect, buf, buf_length);
+#ifdef VB2
+               /**enqueue the buffer again*/
+               if (!ret) {
+                       if (stream_qbuf(&sc, b.index) < 0) {
+                               sc.error = 1;
+                               break;
+                       }
+                       else
+                               sc.buf_flag[b.index] = 1;
+               }
+
+#endif
        } while (!ret);
+
+#ifdef VB2
+#else
        free(buf);
+#endif
        dvb_dmx_stop(dmx_fd);
        dvb_table_filter_free(sect);
 
@@ -459,9 +514,22 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
 
        struct dvb_v5_descriptors *dvb_scan_handler;
 
+#ifdef VB2
+       rc = stream_init(&sc, dmx_fd, STREAM_BUF_SIZ, STREAM_BUF_CNT);
+       if (rc < 0) {
+               PERROR("stream_init failed: error %d, %s\n",
+                               errno, strerror(errno));
+               /** We dont know what failed during stream_init
+                * reqbufs, mmap or  qbuf. We will call stream_deinit
+                * to delete the mapping which might have been created
+                */
+               goto ret_null;
+       }
+#endif
+
        dvb_scan_handler = dvb_scan_alloc_handler_table(delivery_system);
        if (!dvb_scan_handler)
-               return NULL;
+               goto ret_null;
 
        if (!timeout_multiply)
                timeout_multiply = 1;
@@ -515,11 +583,11 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                              (void **)&dvb_scan_handler->pat,
                              pat_pmt_time * timeout_multiply);
        if (parms->p.abort)
-               return dvb_scan_handler;
+               goto ret_handler;
        if (rc < 0) {
                dvb_logerr(_("error while waiting for PAT table"));
                dvb_scan_free_handler_table(dvb_scan_handler);
-               return NULL;
+               goto ret_null;
        }
        if (parms->p.verbose)
                dvb_table_pat_print(&parms->p, dvb_scan_handler->pat);
@@ -531,7 +599,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                                      (void **)&dvb_scan_handler->vct,
                                      vct_time * timeout_multiply);
                if (parms->p.abort)
-                       return dvb_scan_handler;
+                       goto ret_handler;
                if (rc < 0)
                        dvb_logerr(_("error while waiting for VCT table"));
                else if (parms->p.verbose)
@@ -561,7 +629,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                                      pat_pmt_time * timeout_multiply);
                if (parms->p.abort) {
                        dvb_scan_handler->num_program = num_pmt + 1;
-                       return dvb_scan_handler;
+                       goto ret_handler;
                }
                if (rc < 0) {
                        dvb_logerr(_("error while reading the PMT table for 
service 0x%04x"),
@@ -582,7 +650,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                              (void **)&dvb_scan_handler->nit,
                              nit_time * timeout_multiply);
        if (parms->p.abort)
-               return dvb_scan_handler;
+               goto ret_handler;
        if (rc < 0)
                dvb_logerr(_("error while reading the NIT table"));
        else if (parms->p.verbose)
@@ -595,7 +663,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                                (void **)&dvb_scan_handler->sdt,
                                sdt_time * timeout_multiply);
                if (parms->p.abort)
-                       return dvb_scan_handler;
+                       goto ret_handler;
                if (rc < 0)
                        dvb_logerr(_("error while reading the SDT table"));
                else if (parms->p.verbose)
@@ -611,7 +679,7 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                                      (void **)&dvb_scan_handler->nit,
                                      nit_time * timeout_multiply);
                if (parms->p.abort)
-                       return dvb_scan_handler;
+                       goto ret_handler;
                if (rc < 0)
                        dvb_logerr(_("error while reading the NIT table"));
                else if (parms->p.verbose)
@@ -622,13 +690,23 @@ struct dvb_v5_descriptors *dvb_get_ts_tables(struct 
dvb_v5_fe_parms *__p,
                                (void **)&dvb_scan_handler->sdt,
                                sdt_time * timeout_multiply);
                if (parms->p.abort)
-                       return dvb_scan_handler;
+                       goto ret_handler;
                if (rc < 0)
                        dvb_logerr(_("error while reading the SDT table"));
                else if (parms->p.verbose)
                        dvb_table_sdt_print(&parms->p, dvb_scan_handler->sdt);
        }
 
+ret_null:
+#ifdef VB2
+       stream_deinit(&sc);
+#endif
+       return NULL;
+
+ret_handler:
+#ifdef VB2
+       stream_deinit(&sc);
+#endif
        return dvb_scan_handler;
 }
 
diff --git a/lib/libdvbv5/dvb-vb2.c b/lib/libdvbv5/dvb-vb2.c
new file mode 100644
index 000000000000..9617d1b16730
--- /dev/null
+++ b/lib/libdvbv5/dvb-vb2.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2017-2018 - Mauro Carvalho Chehab
+ * Copyright (c) 2017-2018 - Junghak Sung <[email protected]>
+ * Copyright (c) 2017-2018 - Satendra Singh Thakur <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation version 2.1 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to 
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ */
+
+/******************************************************************************
+ * Implements videobuf2 streaming APIs for DVB
+ *****************************************************************************/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <sys/mman.h>
+#include <libdvbv5/dvb-vb2.h>
+
+#define PERROR(x...)                                                    \
+       do {                                                            \
+               fprintf(stderr, "ERROR: ");                             \
+               fprintf(stderr, x);                                     \
+               fprintf(stderr, " (%s)\n", strerror(errno));            \
+       } while (0)
+
+/**These 2 params are for DVR*/
+#define STREAM_BUF_CNT (10)
+#define STREAM_BUF_SIZ (188*1024)
+/*Sleep time for retry, in case ioctl fails*/
+#define SLEEP_US       1000
+
+static inline int xioctl(int fd, unsigned long int cmd, void *arg)
+{
+       int ret;
+       struct timespec stime, etime;
+       long long etimell = 0, stimell = 0;
+       clock_gettime(CLOCK_MONOTONIC, &stime);
+       do {
+               ret = ioctl(fd, cmd, arg);
+               if (ret < 0 && (errno == EINTR || errno == EAGAIN)) {
+                       clock_gettime(CLOCK_MONOTONIC, &etime);
+                       etimell = (long long) etime.tv_sec * 1000000000 +
+                                       etime.tv_nsec;
+                       stimell = (long long) (stime.tv_sec + 1 /*1 sec wait*/)
+                                       * 1000000000 + stime.tv_nsec;
+                       if (etimell > stimell)
+                               break;
+                       /*wait for some time to prevent cpu hogging*/
+                       usleep(SLEEP_US);
+                       continue;
+               }
+               else
+                       break;
+       } while (1);
+
+        return ret;
+}
+
+
+/**
+ * stream_qbuf - Enqueues a buffer specified by index
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param idx          Index of the buffer
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_qbuf(struct stream_ctx *sc, int idx)
+{
+       struct dmx_buffer buf;
+       int ret;
+
+       memzero(buf);
+       buf.index = idx;
+
+       ret = xioctl(sc->in_fd, DMX_QBUF, &buf);
+       if (ret < 0) {
+               PERROR("DMX_QBUF failed: error=%d", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+/**
+ * stream_dqbuf - Dequeues a buffer specified by index
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param buf          Pointer to &struct dmx_buffer
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_dqbuf(struct stream_ctx *sc, struct dmx_buffer *buf)
+{
+       int ret;
+
+       ret = xioctl(sc->in_fd, DMX_DQBUF, buf);
+       if (ret < 0) {
+               PERROR("DMX_DQBUF failed: error=%d", ret);
+               return ret;
+       }
+
+       return ret;
+}
+/**
+ * sream_expbuf - Exports a buffer specified by buf argument
+ *
+ * @param sc           Context for streaming management
+ *                     Pointer to &struct stream_ctx
+ * @param idx          Buffer index
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_expbuf(struct stream_ctx *sc, int idx)
+{
+       int ret;
+       struct dmx_exportbuffer exp;
+       memzero(exp);
+       exp.index = idx;
+       ret = ioctl(sc->in_fd, DMX_EXPBUF, &exp);
+       if (ret) {
+               PERROR("DMX_EXPBUF failed: buf=%d error=%d", idx, ret);
+               return ret;
+       }
+       sc->exp_fd[idx] = exp.fd;
+       fprintf(stderr, "Export buffer %d (fd=%d)\n",
+                       idx, sc->exp_fd[idx]);
+       return ret;
+}
+/**
+ * stream_init - Requests number of buffers from memory
+ * Gets pointer to the buffers from driver, mmaps those buffers
+ * and stores them in an array
+ * Also, optionally exports those buffers
+ *
+ * @param sc           Context for streaming management
+ * @param in_fd                File descriptor of the streaming device
+ * @param buf_size     Size of the buffer
+ * @param buf_cnt      Count of the buffers
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+int stream_init(struct stream_ctx *sc, int in_fd, int buf_size, int buf_cnt)
+{
+       struct dmx_requestbuffers req;
+       struct dmx_buffer buf;
+       int ret;
+       int i;
+
+       memset(sc, 0, sizeof(struct stream_ctx));
+       sc->in_fd = in_fd;
+       sc->buf_size = buf_size;
+       sc->buf_cnt = buf_cnt;
+
+       memzero(req);
+       req.count = sc->buf_cnt;
+       req.size = sc->buf_size;
+
+       ret = xioctl(in_fd, DMX_REQBUFS, &req);
+       if (ret) {
+               PERROR("DMX_REQBUFS failed: error=%d", ret);
+               return ret;
+       }
+
+       if (sc->buf_cnt != req.count) {
+               PERROR("buf_cnt %d -> %d changed !!!", sc->buf_cnt, req.count);
+               sc->buf_cnt = req.count;
+       }
+
+       for (i = 0; i < sc->buf_cnt; i++) {
+               memzero(buf);
+               buf.index = i;
+
+               ret = xioctl(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;
+               }
+               /**enqueue the buffers*/
+               ret = stream_qbuf(sc, i);
+               if (ret) {
+                       PERROR("stream_qbuf failed: buf=%d error=%d", i, ret);
+                       return ret;
+               }
+
+               sc->buf_flag[i] = 1;
+       }
+
+       return 0;
+}
+
+/**
+ * stream_deinit - Dequeues and unmaps the buffers
+ *
+ * @param sc - Context for streaming management
+ *
+ * @return At return, it returns a negative value if error or
+ * zero on success.
+ */
+void stream_deinit(struct stream_ctx *sc)
+{
+       struct dmx_buffer buf;
+       int ret;
+       int i;
+
+       for (i = 0; i < sc->buf_cnt; i++) {
+               memzero(buf);
+               buf.index = i;
+
+               if (sc->buf_flag[i]) {
+                       ret = stream_dqbuf(sc, &buf);
+                       if (ret) {
+                               PERROR("stream_dqbuf failed: buf=%d error=%d",
+                                        i, ret);
+                       }
+               }
+               ret = munmap(sc->buf[i], sc->buf_size);
+               if (ret) {
+                       PERROR("munmap failed: buf=%d error=%d", i, ret);
+               }
+
+       }
+
+       return;
+}
+
+/**
+ * stream_to_file - Implements enqueue and dequeue logic
+ * First enqueues all the available buffers then dequeues
+ * one buffer, again enqueues it and so on.
+ *
+ * @param in_fd                File descriptor of the streaming device
+ * @param out_fd       File descriptor of output file
+ * @param timeout      Timeout in seconds
+ * @param dbg_level    Debug flag
+ * @param exit_flag    Flag to exit
+ *
+ * @return void
+ */
+void stream_to_file(int in_fd, int out_fd, int timeout, int dbg_level,
+                       int *exit_flag)
+{
+       struct stream_ctx sc;
+       int ret;
+       long long int rc = 0LL;
+
+       ret = stream_init(&sc, in_fd, STREAM_BUF_SIZ, STREAM_BUF_CNT);
+       if (ret < 0) {
+               PERROR("[%s] Failed to setup buffers!!!", __func__);
+               sc.error = 1;
+               return;
+       }
+       fprintf(stderr, "start streaming!!!\n");
+       sc.out_fd = out_fd;
+
+       while (!*exit_flag  && !sc.error) {
+               /* dequeue the buffer */
+               struct dmx_buffer b;
+
+               memzero(b);
+               ret = stream_dqbuf(&sc, &b);
+               if (ret < 0) {
+                       sc.error = 1;
+                       break;
+               }
+               else {
+                       sc.buf_flag[b.index] = 0;
+                       ret = write(sc.out_fd, sc.buf[b.index],
+                                       b.bytesused);
+                       if (ret < 0) {
+                               PERROR("Write failed err=%d", ret);
+                               break;
+                       } else
+                               rc += b.bytesused;
+               }
+
+               /* enqueue the buffer */
+               ret = stream_qbuf(&sc, b.index);
+               if (ret < 0)
+                       sc.error = 1;
+               else
+                       sc.buf_flag[b.index] = 1;
+       }
+       if (dbg_level < 2) {
+               fprintf(stderr, "copied %lld bytes (%lld Kbytes/sec)\n", rc,
+                       rc / (1024 * timeout));
+       }
+       stream_deinit(&sc);
+}
diff --git a/lib/libdvbv5/meson.build b/lib/libdvbv5/meson.build
index 4530cc64ffdb..f4976ce074ab 100644
--- a/lib/libdvbv5/meson.build
+++ b/lib/libdvbv5/meson.build
@@ -40,6 +40,7 @@ libdvbv5_sources = files(
     'dvb-legacy-channel-format.c',
     'dvb-log.c',
     'dvb-sat.c',
+    'dvb-vb2.c',
     'dvb-scan.c',
     'dvb-v5-std.c',
     'dvb-v5.c',
@@ -105,6 +106,7 @@ libdvbv5_api = files(
     '../include/libdvbv5/dvb-frontend.h',
     '../include/libdvbv5/dvb-log.h',
     '../include/libdvbv5/dvb-sat.h',
+    '../include/libdvbv5/dvb-vb2.h',
     '../include/libdvbv5/dvb-scan.h',
     '../include/libdvbv5/dvb-v5-std.h',
     '../include/libdvbv5/eit.h',
diff --git a/utils/dvb/dvbv5-zap.c b/utils/dvb/dvbv5-zap.c
index 5f84e101c41f..7ff1d3d141c7 100644
--- a/utils/dvb/dvbv5-zap.c
+++ b/utils/dvb/dvbv5-zap.c
@@ -47,6 +47,7 @@
 #include <signal.h>
 #include <argp.h>
 #include <sys/time.h>
+#include <sys/mman.h>
 #include <time.h>
 
 #ifdef ENABLE_NLS
@@ -68,6 +69,7 @@
 #include "libdvbv5/dvb-scan.h"
 #include "libdvbv5/header.h"
 #include "libdvbv5/countries.h"
+#include "libdvbv5/dvb-vb2.h"
 
 #define CHANNEL_FILE   "channels.conf"
 #define PROGRAM_NAME   "dvbv5-zap"
@@ -93,6 +95,7 @@ struct arguments {
        unsigned n_apid, n_vpid, extra_pids, all_pids;
        enum dvb_file_formats input_format, output_format;
        unsigned traffic_monitor, low_traffic, non_human, port;
+       unsigned int streaming;
        char *search, *server;
        const char *cc;
 
@@ -116,6 +119,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},
@@ -636,6 +640,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;
@@ -1382,14 +1390,32 @@ int main(int argc, char **argv)
                        get_show_stats(stderr, &args, parms, 0);
 
                if (file_fd >= 0) {
-                       dvr_fd = dvb_dev_open(dvb, args.dvr_dev, O_RDONLY);
+                       int flag, fd;
+
+                       if (args.streaming)
+                               flag = O_RDWR;
+                       else
+                               flag = O_RDONLY;
+
+                       dvr_fd = dvb_dev_open(dvb, args.dvr_dev, flag);
                        if (!dvr_fd) {
                                ERROR("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) {
+                               fd = dvb_dev_get_fd(dvr_fd);
+                               if (fd < 0) {
+                                       ERROR("Invalid fd for '%s'",
+                                               args.dvr_dev);
+                                       goto err;
+                               }
+                               stream_to_file(fd, file_fd, args.timeout,
+                                               args.silent, &timeout_flag);
+                       } else
+                               copy_to_file(dvr_fd, file_fd, args.timeout,
+                                               args.silent);
                } else if (args.server && args.port) {
                        struct stat st;
                        if (stat(args.dvr_pipe, &st) == -1) {
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to