From patchwork Thu Jun 5 10:58:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 894361 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F27A32E659 for ; Thu, 5 Jun 2025 10:59:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121160; cv=none; b=RIDrtt0mGoLRWoRBUxjVWtKRXjge1bGYwNJrhzT4FP4K6XWIYyYuQ1Gox9sTHht3J4d4C+l1gehBu5w3yHq3OcciZY8ka0/d8QAlpFCxqjvxyPmqaiI6zRUMW7/qZqrfFRm/qNvumZQC3hHOj6fISjmNtE+iRAND7U1fkjm1REs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121160; c=relaxed/simple; bh=UhZNnWixgQeuQSFXU8+6Euj9HbrFwzTuqeNDavBlU+8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CuumLJ2NE3NBdEBsIR6hfFecFebVuoNhFh8lIERTkQc11JkDqJGfzo4OzZydRIdMtN1HaPPPNBhnNwZFR5X5JGH+EmX3DAZ2I4tYZAqwbK0fBVRkLBrbbmvVej5Q3lL2TeRZ3PQhkDk7gIhnVWyXO9qHpa4UctFh+hNAQEBar64= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75708C4CEEB; Thu, 5 Jun 2025 10:59:16 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , Junghak Sung , Geunyoung Kim , Seung-Woo Kim , Inki Dae , Satendra Singh Thakur , Hans Verkuil Subject: [PATCH 1/9] dvbv5: streaming support using videobuf2 for DVR and auto-scan Date: Thu, 5 Jun 2025 12:58:24 +0200 Message-ID: <9ca7405af29f2167ebe4bec93443eff60faaa09f.1749121112.git.hverkuil@xs4all.nl> X-Mailer: git-send-email 2.47.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Satendra Singh Thakur 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 Signed-off-by: Geunyoung Kim Acked-by: Seung-Woo Kim Acked-by: Inki Dae Signed-off-by: Satendra Singh Thakur Signed-off-by: Hans Verkuil --- 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(-) create mode 100644 lib/include/libdvbv5/dvb-vb2.h create mode 100644 lib/libdvbv5/dvb-vb2.c diff --git a/lib/include/libdvbv5/dvb-dev.h b/lib/include/libdvbv5/dvb-dev.h index 6b4d7483..3fdf7a09 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 00000000..e66b9efe --- /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 + * Copyright (c) 2017-2018 - Satendra Singh Thakur + * + * 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 +#include + +/** + * @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 linux-media@vger.kernel.org + */ + + +#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 fcf2eba7..053ee137 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 +#include +#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 00000000..9617d1b1 --- /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 + * Copyright (c) 2017-2018 - Satendra Singh Thakur + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 8f5929fc..eedb1ead 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 5f84e101..7ff1d3d1 100644 --- a/utils/dvb/dvbv5-zap.c +++ b/utils/dvb/dvbv5-zap.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #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) { From patchwork Thu Jun 5 10:58:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 894360 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7876215198 for ; Thu, 5 Jun 2025 10:59:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121161; cv=none; b=e3hBvbLYOGgtp0FCi3W/cwlr//zt58P4yu2WHSqVCo121JVvHfLPj/wgyD3RoGMTca49G98qbA0iB+JpPk6hWoScGjkw6W+u6I0XCy9R0GctAiE742N/vrO6CUD2wycMlRZnlZjRj9A+ESxDl4Zuw2Ft5Driy1NB45Hdpjd/I8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121161; c=relaxed/simple; bh=ijnPPM8yMOI/1lvjw2ErVpRsvusPGrSKkTD/uQcZ7zE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EqjyVdPmQuSOKUfs0nAZiOKpyTY+g7MrcRCvPBVruk5mogLXA0zQLcaBI2onR+vaU2cF6vBHUoHEFyfcLHys7RYXeNLxGXCYpjP8b/ISBAFXu41wDyk2IEKF/PdFSiukTsyIhdtYDGpb55TdA+TEOa1brsur8EVxdssOE7Pkh9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4A7AFC4CEEF; Thu, 5 Jun 2025 10:59:20 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , Hans Verkuil Subject: [PATCH 3/9] dvb-vb2: add dvb_v5_stream_alloc/free Date: Thu, 5 Jun 2025 12:58:26 +0200 Message-ID: <64dbdb597c17dcb87dbd7016df3f0eba19996f74.1749121112.git.hverkuil@xs4all.nl> X-Mailer: git-send-email 2.47.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add new functions to allocate/free a stream context. Signed-off-by: Hans Verkuil --- lib/include/libdvbv5/dvb-vb2.h | 14 +++++++++ lib/libdvbv5/dvb-vb2.c | 57 ++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/lib/include/libdvbv5/dvb-vb2.h b/lib/include/libdvbv5/dvb-vb2.h index 26b73fbf..cef046e8 100644 --- a/lib/include/libdvbv5/dvb-vb2.h +++ b/lib/include/libdvbv5/dvb-vb2.h @@ -101,6 +101,13 @@ int dvb_v5_stream_dqbuf(struct dvb_v5_stream_ctx *sc, struct dmx_buffer *buf); */ int dvb_v5_stream_expbuf(struct dvb_v5_stream_ctx *sc, int idx); +/** + * dvb_v5_stream_alloc - Allocate stream context + * + * @return a stream context or NULL. + */ +struct dvb_v5_stream_ctx *dvb_v5_stream_alloc(void); + /** * dvb_v5_stream_init - Requests number of buffers from memory * Gets pointer to the buffers from driver, mmaps those buffers @@ -124,6 +131,13 @@ int dvb_v5_stream_init(struct dvb_v5_stream_ctx *sc, int in_fd, int buf_size, in */ void dvb_v5_stream_deinit(struct dvb_v5_stream_ctx *sc); +/** + * dvb_v5_stream_free - Free stream context + * + * @param sc - Context for streaming management + */ +void dvb_v5_stream_free(struct dvb_v5_stream_ctx *sc); + /** * dvb_v5_stream_to_file - Implements enqueue and dequeue logic * First enqueues all the available buffers then dequeues diff --git a/lib/libdvbv5/dvb-vb2.c b/lib/libdvbv5/dvb-vb2.c index 8678a767..56a35f81 100644 --- a/lib/libdvbv5/dvb-vb2.c +++ b/lib/libdvbv5/dvb-vb2.c @@ -155,6 +155,17 @@ int dvb_v5_stream_expbuf(struct dvb_v5_stream_ctx *sc, int idx) idx, sc->exp_fd[idx]); return ret; } + +/** + * dvb_v5_stream_alloc - Allocate stream context + * + * @return a stream context or NULL. + */ +struct dvb_v5_stream_ctx *dvb_v5_stream_alloc(void) +{ + return calloc(1, sizeof(struct dvb_v5_stream_ctx)); +} + /** * dvb_v5_stream_init - Requests number of buffers from memory * Gets pointer to the buffers from driver, mmaps those buffers @@ -262,6 +273,16 @@ void dvb_v5_stream_deinit(struct dvb_v5_stream_ctx *sc) return; } +/** + * dvb_v5_stream_free - Free stream context + * + * @param sc - Context for streaming management + */ +void dvb_v5_stream_free(struct dvb_v5_stream_ctx *sc) +{ + free(sc); +} + /** * dvb_v5_stream_to_file - Implements enqueue and dequeue logic * First enqueues all the available buffers then dequeues @@ -278,33 +299,36 @@ void dvb_v5_stream_deinit(struct dvb_v5_stream_ctx *sc) void dvb_v5_stream_to_file(int in_fd, int out_fd, int timeout, int dbg_level, int *exit_flag) { - struct dvb_v5_stream_ctx sc; - int ret; + struct dvb_v5_stream_ctx *sc = dvb_v5_stream_alloc(); long long int rc = 0LL; + int ret; - ret = dvb_v5_stream_init(&sc, in_fd, STREAM_BUF_SIZ, STREAM_BUF_CNT); + if (!sc) { + PERROR("[%s] Failed to allocate stream context", __func__); + return; + } + ret = dvb_v5_stream_init(sc, in_fd, STREAM_BUF_SIZ, STREAM_BUF_CNT); if (ret < 0) { - PERROR("[%s] Failed to setup buffers!!!", __func__); - sc.error = 1; + PERROR("[%s] Failed to initialize stream context", __func__); + dvb_v5_stream_free(sc); return; } fprintf(stderr, "start streaming!!!\n"); - sc.out_fd = out_fd; + sc->out_fd = out_fd; - while (!*exit_flag && !sc.error) { + while (!*exit_flag && !sc->error) { /* dequeue the buffer */ struct dmx_buffer b; memzero(b); - ret = dvb_v5_stream_dqbuf(&sc, &b); + ret = dvb_v5_stream_dqbuf(sc, &b); if (ret < 0) { - sc.error = 1; + sc->error = 1; break; } else { - sc.buf_flag[b.index] = 0; - ret = write(sc.out_fd, sc.buf[b.index], - b.bytesused); + 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; @@ -313,15 +337,16 @@ void dvb_v5_stream_to_file(int in_fd, int out_fd, int timeout, int dbg_level, } /* enqueue the buffer */ - ret = dvb_v5_stream_qbuf(&sc, b.index); + ret = dvb_v5_stream_qbuf(sc, b.index); if (ret < 0) - sc.error = 1; + sc->error = 1; else - sc.buf_flag[b.index] = 1; + sc->buf_flag[b.index] = 1; } if (dbg_level < 2) { fprintf(stderr, "copied %lld bytes (%lld Kbytes/sec)\n", rc, rc / (1024 * timeout)); } - dvb_v5_stream_deinit(&sc); + dvb_v5_stream_deinit(sc); + dvb_v5_stream_free(sc); } From patchwork Thu Jun 5 10:58:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 894359 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B01C215198 for ; Thu, 5 Jun 2025 10:59:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121164; cv=none; b=tXyE9gML4Ea+hi4wHfDCl7NoVIGpSZ3+Gl/QiiVg+TdNMsVkN6Op6RJs4d8zqz9tvjhO12JeAWtqEsAsCNlIl11MhN4USv9HhZMwzeQahni31PMwBXtqoMyOyjvU7aULT0np8+nguYnVG1GrPQSvSLHw7kIioM40X1SqJofi7rs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121164; c=relaxed/simple; bh=YC4VDKzycm13ypD4eoM3F6cYTlKbtGsznt47M5PjvkI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BV0IlgVnYf4vL6FabV5P9HkiWnyntNEc3A4LAHXxOd5atCLwmD2eAHzGVNzUxDAqGSL3Kq/m+0bmH9q3OkcJf7LncanXWtC4loH5n1IewW9j4pzEzgOMAwvBaZDKi+QlMlFTwzfLD6NX5ou7Xd5gHk8AqHxwxm6AJXNqjiya/QE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id F015DC4CEE7; Thu, 5 Jun 2025 10:59:22 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , Hans Verkuil Subject: [PATCH 5/9] dvbv5-scan: add -R streaming option Date: Thu, 5 Jun 2025 12:58:28 +0200 Message-ID: <2d1cdb4d25c3ee0b8efb2be26a4bb43fabffd09d.1749121112.git.hverkuil@xs4all.nl> X-Mailer: git-send-email 2.47.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the --streaming/-R option to enable streaming I/O. Signed-off-by: Hans Verkuil --- utils/dvb/dvbv5-scan.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/utils/dvb/dvbv5-scan.c b/utils/dvb/dvbv5-scan.c index c84c90fd..b4ff8fc3 100644 --- a/utils/dvb/dvbv5-scan.c +++ b/utils/dvb/dvbv5-scan.c @@ -48,6 +48,7 @@ #include "libdvbv5/dvb-dev.h" #include "libdvbv5/dvb-v5-std.h" #include "libdvbv5/dvb-scan.h" +#include "libdvbv5/dvb-vb2.h" #include "libdvbv5/countries.h" #define PROGRAM_NAME "dvbv5-scan" @@ -80,6 +81,7 @@ static const struct argp_option options[] = { {"wait", 'W', N_("time"), 0, N_("adds additional wait time for DISEqC command completion"), 0}, {"nit", 'N', NULL, 0, N_("use data from NIT table on the output file"), 0}, {"get_frontend",'G', NULL, 0, N_("use data from get_frontend on the output file"), 0}, + {"streaming", 'R', NULL, 0, N_("uses streaming I/O"), 0}, {"verbose", 'v', NULL, 0, N_("be (very) verbose"), 0}, {"output", 'o', N_("file"), 0, N_("output filename (default: ") DEFAULT_OUTPUT ")", 0}, {"file-freqs-only", 'F', NULL, 0, N_("don't use the other frequencies discovered during scan"), 0}, @@ -95,6 +97,7 @@ static const struct argp_option options[] = { }; static int verbose = 0; +static int streaming = 0; #define CHANNEL_FILE "channels.conf" #define ERROR(x...) \ @@ -394,6 +397,9 @@ static error_t parse_opt(int k, char *optarg, struct argp_state *state) case 'p': args->other_nit++; break; + case 'R': + streaming++; + break; case 'v': verbose++; break; @@ -521,6 +527,9 @@ int main(int argc, char **argv) dvb_dev_set_log(dvb, verbose, NULL); dvb_dev_find(dvb, NULL, NULL); parms = dvb->fe_parms; + if (streaming) { + parms->stream_ctx = dvb_v5_stream_alloc(); + } dvb_dev = dvb_dev_seek_by_adapter(dvb, args.adapter_dmx, args.demux, DVB_DEVICE_DEMUX); if (!dvb_dev) { @@ -559,6 +568,10 @@ int main(int argc, char **argv) err = run_scan(&args, dvb); + if (streaming) { + dvb_v5_stream_free(parms->stream_ctx); + parms->stream_ctx = NULL; + } dvb_dev_free(dvb); return err; From patchwork Thu Jun 5 10:58:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 894358 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A0932215198 for ; Thu, 5 Jun 2025 10:59:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121166; cv=none; b=E48Ei6L3pAuPfSf8jqAq5KTEznaOXJZLdbDTeDj/LRaxkdEoCof86GS2XqQFtyceSbAVWmCUSVmsGEps2ElyVtLUdjqGPjQr0MlKpCse+hjRsHLh+2lX5J4FSYrMg70sdh6xzY1cW6pxFZAgPH8kbixzvBpTV+bdS+rVY+lRB/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121166; c=relaxed/simple; bh=rtlLXi3fELkSRdmIM4pqCx8m0zAThLdH5XWx1eXLj/0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AM7XzCOWBI5S/+aazVp3pY8yIPhtBMRk0szmF6NtEDSY3OMgZ67/EZXJuQZu/fWVR32OUFmbFQJGJmhlG6Xx6v5WtsrPFXW+FVYy9qGKQ8C0Z0U4K6kjrxptRt2hJf6rcwMInps4Mufc6K7kwtJTKfV6Vwwi3YHOkRVx3pdHMKQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id A07A1C4CEEB; Thu, 5 Jun 2025 10:59:25 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , Hans Verkuil Subject: [PATCH 7/9] libdvbv5/dvb-scan: always requeue after dvb_parse_section Date: Thu, 5 Jun 2025 12:58:30 +0200 Message-ID: X-Mailer: git-send-email 2.47.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Even if dvb_parse_section returns non-zero, you still need to requeue the buffer. Otherwise it will effectively be lost. Signed-off-by: Hans Verkuil --- lib/libdvbv5/dvb-scan.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/libdvbv5/dvb-scan.c b/lib/libdvbv5/dvb-scan.c index 3f52d140..afe3a4f0 100644 --- a/lib/libdvbv5/dvb-scan.c +++ b/lib/libdvbv5/dvb-scan.c @@ -412,14 +412,12 @@ int dvb_read_sections(struct dvb_v5_fe_parms *__p, int dmx_fd, ret = dvb_parse_section(parms, sect, buf, buf_length); if (parms->p.stream_ctx) { - /**enqueue the buffer again*/ - if (!ret) { - if (dvb_v5_stream_qbuf(parms->p.stream_ctx, b.index) < 0) { - parms->p.stream_ctx->error = 1; - break; - } else { - parms->p.stream_ctx->buf_flag[b.index] = 1; - } + /* enqueue the buffer again */ + if (dvb_v5_stream_qbuf(parms->p.stream_ctx, b.index) < 0) { + parms->p.stream_ctx->error = 1; + break; + } else { + parms->p.stream_ctx->buf_flag[b.index] = 1; } } } while (!ret); From patchwork Thu Jun 5 10:58:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 894357 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A6FE2E659 for ; Thu, 5 Jun 2025 10:59:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121169; cv=none; b=VBJAcVuw/xLFDD8ENPigEAWYGzzlAawbm0PUEICpYs5OfC8YjnM1Li3OPNs3Ll7qnzvcqx9XCKmITGsllFUg/OwATcDuyMHgrZcpz3GOv0keA8VPIq4Q8hufStIP7bjcP9XMw62jS6FlEKB8kS8AjU+YZpkxz69VjTERCyfUMEA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749121169; c=relaxed/simple; bh=DrYFOKCLyejdi5Ds3f+Js3rOYPN5Pfm9pGAZiITRCq4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CWPeSsMyuXCDw+v+OgPUzWUNnHUR3eEG142jHqWUikicHlbOsndMH9UUQn7wl1YupmPuZj9GOoBXFivEbbpsjfVh2j3jcIfJW6w3rKRfGjuZ27n74bBESsVOWW5MX/f9xVXgLApGn2rs8hKKSRMvT8Ly8ajnnXXYl9PqX64MfWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 520D3C4CEEF; Thu, 5 Jun 2025 10:59:28 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab , Hans Verkuil Subject: [PATCH 9/9] test-media: add initial vidtv streaming test Date: Thu, 5 Jun 2025 12:58:32 +0200 Message-ID: X-Mailer: git-send-email 2.47.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a test to check that streaming I/O works for vidtv. It would be nice if we could also compare the TS data, but this contains timestamps, so it is always different each time you run it. It would be nice if vidtv would have a module option to enforce fixed timestamps. Signed-off-by: Hans Verkuil --- contrib/test/test-media | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/contrib/test/test-media b/contrib/test/test-media index 80315dba..a1d8a10c 100755 --- a/contrib/test/test-media +++ b/contrib/test/test-media @@ -21,6 +21,7 @@ reunbind_time=9 rmmod_time=1 modprobe_time=3 kobj_rel=0 +dvb_mmap=0 v4l2_ctl=v4l2-ctl v4l2_compliance=v4l2-compliance compliance_args= @@ -37,6 +38,9 @@ if [ -f /proc/config.gz ]; then if cat /proc/config.gz | gunzip |grep -q CONFIG_DEBUG_KOBJECT_RELEASE=y ; then kobj_rel=1 fi + if cat /proc/config.gz | gunzip |grep -q CONFIG_DVB_MMAP=y ; then + dvb_mmap=1 + fi elif [ -f .config ]; then if grep -q CONFIG_DEBUG_KOBJECT_RELEASE=y .config ; then kobj_rel=1 @@ -886,6 +890,14 @@ if [ $vidtv -eq 1 ]; then rmmod dvb_vidtv_bridge dvb_vidtv_tuner dvb_vidtv_demod 2&>/dev/null exit 0 fi + + if [ $setup -eq 0 ]; then + tmpdir=`mktemp -d` + else + tmpdir=/tmp/vidtv-test + rm -rf $tmpdir + mkdir $tmpdir + fi fi if [ $vidtv -eq 1 -a $setup -eq 0 ]; then @@ -895,6 +907,44 @@ if [ $vidtv -eq 1 -a $setup -eq 0 ]; then date stdbuf -oL $v4l2_compliance -m platform:vidtv 2>&1 | tee -a $tmp + echo + echo vidtv scan tests | tee /dev/kmsg + echo + date + cat >$tmpdir/vidtv-channel.conf <