summaryrefslogtreecommitdiff
path: root/Documentation/driver-api/media/drivers/vidtv.rst
blob: 673bdff919ea47c7d6bc6636624560f0ff8efc59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
.. 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