| .. SPDX-License-Identifier: GPL-2.0 |
| |
| ================================ |
| vidtv: Virtual Digital TV driver |
| ================================ |
| |
| Author: Daniel W. S. Almeida <dwlsalmeida@gmail.com>, June 2020. |
| |
| Background |
| ---------- |
| |
| Vidtv is a virtual DVB driver that aims to serve as a reference for driver |
| writers by serving as a template. It also validates the existing media DVB |
| APIs, thus helping userspace application writers. |
| |
| Currently, it consists of: |
| |
| - A fake tuner driver, which will report a bad signal quality if the chosen |
| frequency is too far away from a table of valid frequencies for a |
| particular delivery system. |
| |
| - A fake demod driver, which will constantly poll the fake signal quality |
| returned by the tuner, simulating a device that can lose/reacquire a lock |
| on the signal depending on the CNR levels. |
| |
| - A fake bridge driver, which is the module responsible for modprobing the |
| fake tuner and demod modules and implementing the demux logic. This module |
| takes parameters at initialization that will dictate how the simulation |
| behaves. |
| |
| - Code reponsible for encoding a valid MPEG Transport Stream, which is then |
| passed to the bridge driver. This fake stream contains some hardcoded content. |
| For now, we have a single, audio-only channel containing a single MPEG |
| Elementary Stream, which in turn contains a SMPTE 302m encoded sine-wave. |
| Note that this particular encoder was chosen because it is the easiest |
| way to encode PCM audio data in a MPEG Transport Stream. |
| |
| Building vidtv |
| -------------- |
| vidtv is a test driver and thus is **not** enabled by default when |
| compiling the kernel. |
| |
| In order to enable compilation of vidtv: |
| |
| - Enable **DVB_TEST_DRIVERS**, then |
| - Enable **DVB_VIDTV** |
| |
| When compiled as a module, expect the following .ko files: |
| |
| - dvb_vidtv_tuner.ko |
| |
| - dvb_vidtv_demod.ko |
| |
| - dvb_vidtv_bridge.ko |
| |
| Running vidtv |
| ------------- |
| When compiled as a module, run:: |
| |
| modprobe vidtv |
| |
| That's it! The bridge driver will initialize the tuner and demod drivers as |
| part of its own initialization. |
| |
| By default, it will accept the following frequencies: |
| |
| - 474 MHz for DVB-T/T2/C; |
| - 11,362 GHz for DVB-S/S2. |
| |
| For satellite systems, the driver simulates an universal extended |
| LNBf, with frequencies at Ku-Band, ranging from 10.7 GHz to 12.75 GHz. |
| |
| You can optionally define some command-line arguments to vidtv. |
| |
| Command-line arguments to vidtv |
| ------------------------------- |
| Below is a list of all arguments that can be supplied to vidtv: |
| |
| drop_tslock_prob_on_low_snr |
| Probability of losing the TS lock if the signal quality is bad. |
| This probability be used by the fake demodulator driver to |
| eventually return a status of 0 when the signal quality is not |
| good. |
| |
| recover_tslock_prob_on_good_snr: |
| Probability recovering the TS lock when the signal improves. This |
| probability be used by the fake demodulator driver to eventually |
| return a status of 0x1f when/if the signal quality improves. |
| |
| mock_power_up_delay_msec |
| Simulate a power up delay. Default: 0. |
| |
| mock_tune_delay_msec |
| Simulate a tune delay. Default 0. |
| |
| vidtv_valid_dvb_t_freqs |
| Valid DVB-T frequencies to simulate, in Hz. |
| |
| vidtv_valid_dvb_c_freqs |
| Valid DVB-C frequencies to simulate, in Hz. |
| |
| vidtv_valid_dvb_s_freqs |
| Valid DVB-S/S2 frequencies to simulate at Ku-Band, in kHz. |
| |
| max_frequency_shift_hz, |
| Maximum shift in HZ allowed when tuning in a channel. |
| |
| si_period_msec |
| How often to send SI packets. Default: 40ms. |
| |
| pcr_period_msec |
| How often to send PCR packets. Default: 40ms. |
| |
| mux_rate_kbytes_sec |
| Attempt to maintain this bit rate by inserting TS null packets, if |
| necessary. Default: 4096. |
| |
| pcr_pid, |
| PCR PID for all channels. Default: 0x200. |
| |
| mux_buf_sz_pkts, |
| Size for the mux buffer in multiples of 188 bytes. |
| |
| vidtv internal structure |
| ------------------------ |
| The kernel modules are split in the following way: |
| |
| vidtv_tuner.[ch] |
| Implements a fake tuner DVB driver. |
| |
| vidtv_demod.[ch] |
| Implements a fake demodulator DVB driver. |
| |
| vidtv_bridge.[ch] |
| Implements a bridge driver. |
| |
| The MPEG related code is split in the following way: |
| |
| vidtv_ts.[ch] |
| Code to work with MPEG TS packets, such as TS headers, adaptation |
| fields, PCR packets and NULL packets. |
| |
| vidtv_psi.[ch] |
| This is the PSI generator. PSI packets contain general information |
| about a MPEG Transport Stream. A PSI generator is needed so |
| userspace apps can retrieve information about the Transport Stream |
| and eventually tune into a (dummy) channel. |
| |
| Because the generator is implemented in a separate file, it can be |
| reused elsewhere in the media subsystem. |
| |
| Currently vidtv supports working with 5 PSI tables: PAT, PMT, |
| SDT, NIT and EIT. |
| |
| The specification for PAT and PMT can be found in *ISO 13818-1: |
| Systems*, while the specification for the SDT, NIT, EIT can be found in *ETSI |
| EN 300 468: Specification for Service Information (SI) in DVB |
| systems*. |
| |
| It isn't strictly necessary, but using a real TS file helps when |
| debugging PSI tables. Vidtv currently tries to replicate the PSI |
| structure found in this file: `TS1Globo.ts |
| <https://tsduck.io/streams/brazil-isdb-tb/TS1globo.ts>`_. |
| |
| A good way to visualize the structure of streams is by using |
| `DVBInspector <https://sourceforge.net/projects/dvbinspector/>`_. |
| |
| vidtv_pes.[ch] |
| Implements the PES logic to convert encoder data into MPEG TS |
| packets. These can then be fed into a TS multiplexer and eventually |
| into userspace. |
| |
| vidtv_encoder.h |
| An interface for vidtv encoders. New encoders can be added to this |
| driver by implementing the calls in this file. |
| |
| vidtv_s302m.[ch] |
| Implements a S302M encoder to make it possible to insert PCM audio |
| data in the generated MPEG Transport Stream. The relevant |
| specification is available online as *SMPTE 302M-2007: Television - |
| Mapping of AES3 Data into MPEG-2 Transport Stream*. |
| |
| |
| The resulting MPEG Elementary Stream is conveyed in a private |
| stream with a S302M registration descriptor attached. |
| |
| This shall enable passing an audio signal into userspace so it can |
| be decoded and played by media software. The corresponding decoder |
| in ffmpeg is located in 'libavcodec/s302m.c' and is experimental. |
| |
| vidtv_channel.[ch] |
| Implements a 'channel' abstraction. |
| |
| When vidtv boots, it will create some hardcoded channels: |
| |
| #. Their services will be concatenated to populate the SDT. |
| |
| #. Their programs will be concatenated to populate the PAT |
| |
| #. Their events will be concatenated to populate the EIT |
| |
| #. For each program in the PAT, a PMT section will be created |
| |
| #. The PMT section for a channel will be assigned its streams. |
| |
| #. Every stream will have its corresponding encoder polled in a |
| loop to produce TS packets. |
| These packets may be interleaved by the muxer and then delivered |
| to the bridge. |
| |
| vidtv_mux.[ch] |
| Implements a MPEG TS mux, loosely based on the ffmpeg |
| implementation in "libavcodec/mpegtsenc.c" |
| |
| The muxer runs a loop which is responsible for: |
| |
| #. Keeping track of the amount of time elapsed since the last |
| iteration. |
| |
| #. Polling encoders in order to fetch 'elapsed_time' worth of data. |
| |
| #. Inserting PSI and/or PCR packets, if needed. |
| |
| #. Padding the resulting stream with NULL packets if |
| necessary in order to maintain the chosen bit rate. |
| |
| #. Delivering the resulting TS packets to the bridge |
| driver so it can pass them to the demux. |
| |
| Testing vidtv with v4l-utils |
| ---------------------------- |
| |
| Using the tools in v4l-utils is a great way to test and inspect the output of |
| vidtv. It is hosted here: `v4l-utils Documentation |
| <https://linuxtv.org/wiki/index.php/V4l-utils>`_. |
| |
| From its webpage:: |
| |
| The v4l-utils are a series of packages for handling media devices. |
| |
| It is hosted at http://git.linuxtv.org/v4l-utils.git, and packaged |
| on most distributions. |
| |
| It provides a series of libraries and utilities to be used to |
| control several aspect of the media boards. |
| |
| |
| Start by installing v4l-utils and then modprobing vidtv:: |
| |
| modprobe dvb_vidtv_bridge |
| |
| If the driver is OK, it should load and its probing code will run. This will |
| pull in the tuner and demod drivers. |
| |
| Using dvb-fe-tool |
| ~~~~~~~~~~~~~~~~~ |
| |
| The first step to check whether the demod loaded successfully is to run:: |
| |
| $ dvb-fe-tool |
| Device Dummy demod for DVB-T/T2/C/S/S2 (/dev/dvb/adapter0/frontend0) capabilities: |
| CAN_FEC_1_2 |
| CAN_FEC_2_3 |
| CAN_FEC_3_4 |
| CAN_FEC_4_5 |
| CAN_FEC_5_6 |
| CAN_FEC_6_7 |
| CAN_FEC_7_8 |
| CAN_FEC_8_9 |
| CAN_FEC_AUTO |
| CAN_GUARD_INTERVAL_AUTO |
| CAN_HIERARCHY_AUTO |
| CAN_INVERSION_AUTO |
| CAN_QAM_16 |
| CAN_QAM_32 |
| CAN_QAM_64 |
| CAN_QAM_128 |
| CAN_QAM_256 |
| CAN_QAM_AUTO |
| CAN_QPSK |
| CAN_TRANSMISSION_MODE_AUTO |
| DVB API Version 5.11, Current v5 delivery system: DVBC/ANNEX_A |
| Supported delivery systems: |
| DVBT |
| DVBT2 |
| [DVBC/ANNEX_A] |
| DVBS |
| DVBS2 |
| Frequency range for the current standard: |
| From: 51.0 MHz |
| To: 2.15 GHz |
| Step: 62.5 kHz |
| Tolerance: 29.5 MHz |
| Symbol rate ranges for the current standard: |
| From: 1.00 MBauds |
| To: 45.0 MBauds |
| |
| This should return what is currently set up at the demod struct, i.e.:: |
| |
| static const struct dvb_frontend_ops vidtv_demod_ops = { |
| .delsys = { |
| SYS_DVBT, |
| SYS_DVBT2, |
| SYS_DVBC_ANNEX_A, |
| SYS_DVBS, |
| SYS_DVBS2, |
| }, |
| |
| .info = { |
| .name = "Dummy demod for DVB-T/T2/C/S/S2", |
| .frequency_min_hz = 51 * MHz, |
| .frequency_max_hz = 2150 * MHz, |
| .frequency_stepsize_hz = 62500, |
| .frequency_tolerance_hz = 29500 * kHz, |
| .symbol_rate_min = 1000000, |
| .symbol_rate_max = 45000000, |
| |
| .caps = FE_CAN_FEC_1_2 | |
| FE_CAN_FEC_2_3 | |
| FE_CAN_FEC_3_4 | |
| FE_CAN_FEC_4_5 | |
| FE_CAN_FEC_5_6 | |
| FE_CAN_FEC_6_7 | |
| FE_CAN_FEC_7_8 | |
| FE_CAN_FEC_8_9 | |
| FE_CAN_QAM_16 | |
| FE_CAN_QAM_64 | |
| FE_CAN_QAM_32 | |
| FE_CAN_QAM_128 | |
| FE_CAN_QAM_256 | |
| FE_CAN_QAM_AUTO | |
| FE_CAN_QPSK | |
| FE_CAN_FEC_AUTO | |
| FE_CAN_INVERSION_AUTO | |
| FE_CAN_TRANSMISSION_MODE_AUTO | |
| FE_CAN_GUARD_INTERVAL_AUTO | |
| FE_CAN_HIERARCHY_AUTO, |
| } |
| |
| .... |
| |
| For more information on dvb-fe-tools check its online documentation here: |
| `dvb-fe-tool Documentation |
| <https://www.linuxtv.org/wiki/index.php/Dvb-fe-tool>`_. |
| |
| Using dvb-scan |
| ~~~~~~~~~~~~~~ |
| |
| In order to tune into a channel and read the PSI tables, we can use dvb-scan. |
| |
| For this, one should provide a configuration file known as a 'scan file', |
| here's an example:: |
| |
| [Channel] |
| FREQUENCY = 474000000 |
| MODULATION = QAM/AUTO |
| SYMBOL_RATE = 6940000 |
| INNER_FEC = AUTO |
| DELIVERY_SYSTEM = DVBC/ANNEX_A |
| |
| .. note:: |
| The parameters depend on the video standard you're testing. |
| |
| .. note:: |
| Vidtv is a fake driver and does not validate much of the information |
| in the scan file. Just specifying 'FREQUENCY' and 'DELIVERY_SYSTEM' |
| should be enough for DVB-T/DVB-T2. For DVB-S/DVB-C however, you |
| should also provide 'SYMBOL_RATE'. |
| |
| You can browse scan tables online here: `dvb-scan-tables |
| <https://git.linuxtv.org/dtv-scan-tables.git>`_. |
| |
| Assuming this channel is named 'channel.conf', you can then run:: |
| |
| $ dvbv5-scan channel.conf |
| dvbv5-scan ~/vidtv.conf |
| ERROR command BANDWIDTH_HZ (5) not found during retrieve |
| Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet). |
| Scanning frequency #1 330000000 |
| (0x00) Signal= -68.00dBm |
| Scanning frequency #2 474000000 |
| Lock (0x1f) Signal= -34.45dBm C/N= 33.74dB UCB= 0 |
| Service Beethoven, provider LinuxTV.org: digital television |
| |
| For more information on dvb-scan, check its documentation online here: |
| `dvb-scan Documentation <https://www.linuxtv.org/wiki/index.php/Dvbscan>`_. |
| |
| Using dvb-zap |
| ~~~~~~~~~~~~~ |
| |
| dvbv5-zap is a command line tool that can be used to record MPEG-TS to disk. The |
| typical use is to tune into a channel and put it into record mode. The example |
| below - which is taken from the documentation - illustrates that\ [1]_:: |
| |
| $ dvbv5-zap -c dvb_channel.conf "beethoven" -o music.ts -P -t 10 |
| using demux 'dvb0.demux0' |
| reading channels from file 'dvb_channel.conf' |
| tuning to 474000000 Hz |
| pass all PID's to TS |
| dvb_set_pesfilter 8192 |
| dvb_dev_set_bufsize: buffer set to 6160384 |
| Lock (0x1f) Quality= Good Signal= -34.66dBm C/N= 33.41dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 |
| Lock (0x1f) Quality= Good Signal= -34.57dBm C/N= 33.46dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 |
| Record to file 'music.ts' started |
| received 24587768 bytes (2401 Kbytes/sec) |
| Lock (0x1f) Quality= Good Signal= -34.42dBm C/N= 33.89dB UCB= 0 postBER= 0 preBER= 2.44x10^-3 PER= 0 |
| |
| .. [1] In this example, it records 10 seconds with all program ID's stored |
| at the music.ts file. |
| |
| |
| The channel can be watched by playing the contents of the stream with some |
| player that recognizes the MPEG-TS format, such as ``mplayer`` or ``vlc``. |
| |
| By playing the contents of the stream one can visually inspect the workings of |
| vidtv, e.g., to play a recorded TS file with:: |
| |
| $ mplayer music.ts |
| |
| or, alternatively, running this command on one terminal:: |
| |
| $ dvbv5-zap -c dvb_channel.conf "beethoven" -P -r & |
| |
| And, on a second terminal, playing the contents from DVR interface with:: |
| |
| $ mplayer /dev/dvb/adapter0/dvr0 |
| |
| For more information on dvb-zap check its online documentation here: |
| `dvb-zap Documentation |
| <https://www.linuxtv.org/wiki/index.php/Dvbv5-zap>`_. |
| See also: `zap <https://www.linuxtv.org/wiki/index.php/Zap>`_. |
| |
| |
| What can still be improved in vidtv |
| ----------------------------------- |
| |
| Add *debugfs* integration |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Although frontend drivers provide DVBv5 statistics via the .read_status |
| call, a nice addition would be to make additional statistics available to |
| userspace via debugfs, which is a simple-to-use, RAM-based filesystem |
| specifically designed for debug purposes. |
| |
| The logic for this would be implemented on a separate file so as not to |
| pollute the frontend driver. These statistics are driver-specific and can |
| be useful during tests. |
| |
| The Siano driver is one example of a driver using |
| debugfs to convey driver-specific statistics to userspace and it can be |
| used as a reference. |
| |
| This should be further enabled and disabled via a Kconfig |
| option for convenience. |
| |
| Add a way to test video |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Currently, vidtv can only encode PCM audio. It would be great to implement |
| a barebones version of MPEG-2 video encoding so we can also test video. The |
| first place to look into is *ISO 13818-2: Information technology — Generic |
| coding of moving pictures and associated audio information — Part 2: Video*, |
| which covers the encoding of compressed video in MPEG Transport Streams. |
| |
| This might optionally use the Video4Linux2 Test Pattern Generator, v4l2-tpg, |
| which resides at:: |
| |
| drivers/media/common/v4l2-tpg/ |
| |
| |
| Add white noise simulation |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The vidtv tuner already has code to identify whether the chosen frequency |
| is too far away from a table of valid frequencies. For now, this means that |
| the demodulator can eventually lose the lock on the signal, since the tuner will |
| report a bad signal quality. |
| |
| A nice addition is to simulate some noise when the signal quality is bad by: |
| |
| - Randomly dropping some TS packets. This will trigger a continuity error if the |
| continuity counter is updated but the packet is not passed on to the demux. |
| |
| - Updating the error statistics accordingly (e.g. BER, etc). |
| |
| - Simulating some noise in the encoded data. |
| |
| Functions and structs used within vidtv |
| --------------------------------------- |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_bridge.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_channel.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_demod.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_encoder.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_mux.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_pes.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_psi.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_s302m.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_ts.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.h |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_common.c |
| |
| .. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.c |