9.2.3. vidtv: 虚拟数字电视驱动程序¶
作者:Daniel W. S. Almeida <dwlsalmeida@gmail.com>,2020 年 6 月。
9.2.3.1. 背景¶
Vidtv 是一个虚拟 DVB 驱动程序,旨在通过充当模板,为驱动程序编写者提供参考。它还验证现有的媒体 DVB API,从而帮助用户空间应用程序编写者。
目前,它由以下部分组成:
一个虚假的调谐器驱动程序,如果所选频率与特定传输系统的有效频率表相差太远,它将报告不良的信号质量。
一个虚假的解调器驱动程序,它会不断轮询调谐器返回的虚假信号质量,模拟一个可以根据 CNR 水平丢失/重新获得信号锁定的设备。
一个虚假的桥接驱动程序,该模块负责 modprobing 虚假的调谐器和解调模块,并实现解复用逻辑。此模块在初始化时接收参数,这些参数将决定模拟的行为方式。
负责编码有效 MPEG 传输流的代码,然后将其传递给桥接驱动程序。这个虚假的流包含一些硬编码内容。目前,我们有一个单一的、仅音频的频道,其中包含一个 MPEG 基本流,该基本流又包含一个 SMPTE 302m 编码的正弦波。请注意,选择此特定编码器是因为它是以 MPEG 传输流编码 PCM 音频数据的最简单方法。
9.2.3.2. 构建 vidtv¶
vidtv 是一个测试驱动程序,因此在编译内核时默认情况下 不 启用。
为了启用 vidtv 的编译
启用 DVB_TEST_DRIVERS,然后
启用 DVB_VIDTV
当编译为模块时,预期会生成以下 .ko 文件
dvb_vidtv_tuner.ko
dvb_vidtv_demod.ko
dvb_vidtv_bridge.ko
9.2.3.3. 运行 vidtv¶
当编译为模块时,运行
modprobe vidtv
就是这样!桥接驱动程序将在其自身初始化过程中初始化调谐器和解调器驱动程序。
默认情况下,它将接受以下频率
DVB-T/T2/C 的 474 MHz;
DVB-S/S2 的 11,362 GHz。
对于卫星系统,该驱动程序模拟一个通用的扩展 LNBf,其频率在 Ku 波段,范围从 10.7 GHz 到 12.75 GHz。
您可以选择性地为 vidtv 定义一些命令行参数。
9.2.3.4. vidtv 的命令行参数¶
下面是可以提供给 vidtv 的所有参数的列表
- drop_tslock_prob_on_low_snr
如果信号质量差,则丢失 TS 锁定的概率。虚假解调器驱动程序可以使用此概率来最终在信号质量不佳时返回 0 状态。
- recover_tslock_prob_on_good_snr
当信号改善时恢复 TS 锁定的概率。虚假解调器驱动程序可以使用此概率来最终在信号质量改善时/如果信号质量改善时返回 0x1f 状态。
- mock_power_up_delay_msec
模拟上电延迟。默认值:0。
- mock_tune_delay_msec
模拟调谐延迟。默认值:0。
- vidtv_valid_dvb_t_freqs
要模拟的有效 DVB-T 频率,单位为 Hz。
- vidtv_valid_dvb_c_freqs
要模拟的有效 DVB-C 频率,单位为 Hz。
- vidtv_valid_dvb_s_freqs
要在 Ku 波段模拟的有效 DVB-S/S2 频率,单位为 kHz。
- max_frequency_shift_hz,
调谐频道时允许的最大 HZ 偏移量。
- si_period_msec
发送 SI 数据包的频率。默认值:40ms。
- pcr_period_msec
发送 PCR 数据包的频率。默认值:40ms。
- mux_rate_kbytes_sec
如果需要,尝试通过插入 TS 空数据包来保持此比特率。默认值:4096。
- pcr_pid,
所有频道的 PCR PID。默认值:0x200。
- mux_buf_sz_pkts,
复用缓冲区的大小,以 188 字节的倍数表示。
9.2.3.5. vidtv 内部结构¶
内核模块按以下方式拆分
- vidtv_tuner.[ch]
实现一个虚假的调谐器 DVB 驱动程序。
- vidtv_demod.[ch]
实现一个虚假的解调器 DVB 驱动程序。
- vidtv_bridge.[ch]
实现一个桥接驱动程序。
MPEG 相关代码按以下方式拆分
- vidtv_ts.[ch]
用于处理 MPEG TS 数据包的代码,例如 TS 标头、适配字段、PCR 数据包和 NULL 数据包。
- vidtv_psi.[ch]
这是 PSI 生成器。PSI 数据包包含有关 MPEG 传输流的常规信息。需要 PSI 生成器,以便用户空间应用程序可以检索有关传输流的信息,并最终调谐到(虚拟)频道。
由于生成器是在单独的文件中实现的,因此可以在媒体子系统的其他地方重用它。
目前,vidtv 支持使用 5 个 PSI 表:PAT、PMT、SDT、NIT 和 EIT。
PAT 和 PMT 的规范可以在 ISO 13818-1: Systems 中找到,而 SDT、NIT、EIT 的规范可以在 ETSI EN 300 468: Specification for Service Information (SI) in DVB systems 中找到。
严格来说这不是必需的,但在调试 PSI 表时使用真实的 TS 文件会有所帮助。Vidtv 目前尝试复制在此文件中找到的 PSI 结构:TS1Globo.ts。
可视化流结构的好方法是使用 DVBInspector。
- vidtv_pes.[ch]
实现 PES 逻辑,将编码器数据转换为 MPEG TS 数据包。然后,可以将这些数据包馈送到 TS 复用器,并最终馈送到用户空间。
- vidtv_encoder.h
vidtv 编码器的接口。可以通过在此文件中实现调用来将新编码器添加到此驱动程序中。
- vidtv_s302m.[ch]
实现 S302M 编码器,以便可以将 PCM 音频数据插入生成的 MPEG 传输流中。相关的规范可在线获取,名称为 SMPTE 302M-2007: Television - Mapping of AES3 Data into MPEG-2 Transport Stream。
生成的 MPEG 基本流在附加了 S302M 注册描述符的私有流中传递。
这应能够将音频信号传递到用户空间,以便可以通过媒体软件对其进行解码和播放。ffmpeg 中相应的解码器位于“libavcodec/s302m.c”中,并且是实验性的。
- vidtv_channel.[ch]
实现一个“频道”抽象。
当 vidtv 启动时,它将创建一些硬编码的频道
它们的服务将被连接起来以填充 SDT。
它们的节目将被连接起来以填充 PAT
它们的事件将被连接起来以填充 EIT
对于 PAT 中的每个节目,将创建一个 PMT 部分
频道的 PMT 部分将分配其流。
每个流都将在循环中轮询其对应的编码器,以生成 TS 数据包。这些数据包可以由复用器交织,然后传递到桥接器。
- vidtv_mux.[ch]
实现一个 MPEG TS 复用器,它松散地基于“libavcodec/mpegtsenc.c”中的 ffmpeg 实现
复用器运行一个循环,该循环负责
记录自上次迭代以来经过的时间量。
轮询编码器以获取 ‘elapsed_time’ 值得的数据。
如果需要,插入 PSI 和/或 PCR 数据包。
如果需要,用 NULL 数据包填充结果流,以维持选择的比特率。
将生成的 TS 数据包传递给桥接驱动程序,以便将其传递给解复用器。
9.2.3.6. 使用 v4l-utils 测试 vidtv¶
使用 v4l-utils 中的工具是测试和检查 vidtv 输出的好方法。它托管在这里:v4l-utils 文档。
从其网页
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.
首先安装 v4l-utils,然后加载 vidtv 模块
modprobe dvb_vidtv_bridge
如果驱动程序正常,它应该加载并且其探测代码将运行。这将拉入调谐器和解调驱动程序。
9.2.3.6.1. 使用 dvb-fe-tool¶
检查解调器是否成功加载的第一步是运行
$ 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
这应该返回当前在解调器结构中设置的内容,即
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,
}
....
有关 dvb-fe-tools 的更多信息,请在此处查看其在线文档:dvb-fe-tool 文档。
9.2.3.6.2. 使用 dvb-scan¶
为了调谐到一个频道并读取 PSI 表,我们可以使用 dvb-scan。
为此,应提供一个名为“扫描文件”的配置文件,这是一个示例
[Channel]
FREQUENCY = 474000000
MODULATION = QAM/AUTO
SYMBOL_RATE = 6940000
INNER_FEC = AUTO
DELIVERY_SYSTEM = DVBC/ANNEX_A
注意
参数取决于您正在测试的视频标准。
注意
Vidtv 是一个伪驱动程序,并且不会验证扫描文件中的太多信息。对于 DVB-T/DVB-T2,仅指定“FREQUENCY”和“DELIVERY_SYSTEM”应该足够了。但是,对于 DVB-S/DVB-C,您还应该提供“SYMBOL_RATE”。
您可以在此处在线浏览扫描表:dvb-scan-tables。
假设此频道名为“channel.conf”,则可以运行
$ 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
有关 dvb-scan 的更多信息,请在此处查看其在线文档:dvb-scan 文档。
9.2.3.6.3. 使用 dvb-zap¶
dvbv5-zap 是一个命令行工具,可用于将 MPEG-TS 记录到磁盘。典型的用法是调谐到一个频道并将其置于记录模式。下面的示例(摘自文档)说明了这一点[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
可以通过使用一些识别 MPEG-TS 格式的播放器(例如 mplayer
或 vlc
)播放流的内容来观看频道。
通过播放流的内容,可以直观地检查 vidtv 的工作原理,例如,使用以下命令播放记录的 TS 文件
$ mplayer music.ts
或者,在某个终端上运行此命令
$ dvbv5-zap -c dvb_channel.conf "beethoven" -P -r &
并且,在第二个终端上,使用以下命令从 DVR 接口播放内容
$ mplayer /dev/dvb/adapter0/dvr0
有关 dvb-zap 的更多信息,请在此处查看其在线文档:dvb-zap 文档。另请参阅:zap。
9.2.3.7. vidtv 中仍可改进的内容¶
9.2.3.7.1. 添加 debugfs 集成¶
虽然前端驱动程序通过 .read_status 调用提供 DVBv5 统计信息,但一个不错的补充是通过 debugfs 向用户空间提供其他统计信息,debugfs 是一个易于使用的、基于 RAM 的文件系统,专门为调试目的而设计。
此逻辑将在单独的文件中实现,以免污染前端驱动程序。这些统计信息是特定于驱动程序的,并且在测试期间可能很有用。
Siano 驱动程序是使用 debugfs 向用户空间传递特定于驱动程序的统计信息的一个示例,可以将其用作参考。
为了方便起见,应通过 Kconfig 选项进一步启用和禁用此功能。
9.2.3.7.2. 添加测试视频的方法¶
目前,vidtv 只能编码 PCM 音频。如果能够实现 MPEG-2 视频编码的精简版本,以便我们也可以测试视频,那就太好了。首先要研究的是ISO 13818-2:信息技术 — 移动图像和相关音频信息的通用编码 — 第 2 部分:视频,它涵盖了 MPEG 传输流中压缩视频的编码。
这可能会选择使用 Video4Linux2 测试模式生成器 v4l2-tpg,它位于
drivers/media/common/v4l2-tpg/
9.2.3.7.3. 添加白噪声模拟¶
vidtv 调谐器已经具有用于识别所选频率是否与有效频率表相距太远的代码。目前,这意味着解调器最终可能会失去对信号的锁定,因为调谐器会报告信号质量不佳。
一个不错的补充是在信号质量不佳时通过以下方式模拟一些噪声
随机丢弃一些 TS 数据包。如果更新了连续性计数器,但没有将数据包传递给解复用器,则这将触发连续性错误。
相应地更新错误统计信息(例如 BER 等)。
在编码数据中模拟一些噪声。
9.2.3.8. vidtv 中使用的函数和结构¶
-
struct vidtv_dvb¶
Vidtv 桥接状态
定义:
struct vidtv_dvb {
struct platform_device *pdev;
struct dvb_frontend *fe[NUM_FE];
struct dvb_adapter adapter;
struct dvb_demux demux;
struct dmxdev dmx_dev;
struct dmx_frontend dmx_fe[NUM_FE];
struct i2c_adapter i2c_adapter;
struct i2c_client *i2c_client_demod[NUM_FE];
struct i2c_client *i2c_client_tuner[NUM_FE];
u32 nfeeds;
struct mutex feed_lock;
bool streaming;
struct vidtv_mux *mux;
#ifdef CONFIG_MEDIA_CONTROLLER_DVB;
struct media_device mdev;
#endif ;
};
成员
pdev
平台设备。在探测桥接时获取。
fe
前端。在探测解调器模块时获取。
adapter
表示 DTV 适配器。请参阅“dvb_register_adapter”。
demux
dvb_dmx_swfilter_packets()
调用使用的解复用器。dmx_dev
表示解复用器设备。
dmx_fe
与解复用器关联的前端。
i2c_adapter
与桥接驱动程序关联的 i2c_adapter。
i2c_client_demod
与解调器模块关联的 i2c_clients。
i2c_client_tuner
与调谐器模块关联的 i2c_clients。
nfeeds
活动的馈送数量。
feed_lock
保护对启动/停止流逻辑/数据的访问。
streaming
我们现在是否正在流式传输。
mux
负责将 MPEG TS 数据包传递到桥接的抽象。
mdev
用于媒体控制器支持的 media_device 结构。
-
struct vidtv_channel¶
“频道”抽象
定义:
struct vidtv_channel {
char *name;
u16 transport_stream_id;
struct vidtv_psi_table_sdt_service *service;
u16 program_num;
struct vidtv_psi_table_pat_program *program;
struct vidtv_psi_table_pmt_stream *streams;
struct vidtv_encoder *encoders;
struct vidtv_psi_table_eit_event *events;
struct vidtv_channel *next;
};
成员
name
频道名称
transport_stream_id
用于识别 TS 的数字,随意选择。
service
一个单个服务。将连接到 SDT。
program_num
PAT、PMT 和 SDT 之间的链接。
program
一个单个程序,其中一个或多个流与之关联。将连接到 PAT。
streams
用于填充“程序”的 PMT 部分的流循环
encoders
编码器循环。每个流必须有一个编码器。
events
可选事件信息。这将馈送到 EIT。
next
可选地链接此频道。
描述
当 vidtv 启动时,它将创建一些硬编码的频道。它们的服务将被连接起来以填充 SDT。它们的程序将被连接起来以填充 PAT 对于 PAT 中的每个程序,将创建一个 PMT 部分频道的 PMT 部分将分配其流。将轮询每个流的相应编码器以生成 TS 数据包这些数据包可能会被 mux 交错,然后传递到桥接
参数
struct vidtv_mux *m
包含频道的 mux。
参数
struct vidtv_mux *m
将频道存储到的 mux。
-
struct vidtv_demod_cnr_to_qual_s¶
将 CNR 值映射到给定的调制和 fec_inner 组合
定义:
struct vidtv_demod_cnr_to_qual_s {
u32 modulation;
u32 fec;
u32 cnr_ok;
u32 cnr_good;
};
成员
modulation
fec
请参阅枚举 fe_fec_rate
cnr_ok
信噪比阈值,用于判断信号是否正常。低于该阈值,可能会失去同步。
cnr_good
信噪比阈值,用于判断信号是否强。
描述
此结构体匹配给定调制方式和 fec_inner 组合的“good”和“ok” CNR 值。如果信号质量不太好,我们可能会模拟一些噪声。
这些值取自 libdvbv5。
-
struct vidtv_demod_config¶
用于初始化解调器的配置
定义:
struct vidtv_demod_config {
u8 drop_tslock_prob_on_low_snr;
u8 recover_tslock_prob_on_good_snr;
};
成员
drop_tslock_prob_on_low_snr
由于低信噪比而导致丢失锁定的概率
recover_tslock_prob_on_good_snr
当信号改善时恢复的概率
描述
用于初始化解调器模块的配置,通常由桥接驱动程序填充。对于 vidtv,这在探测解调器模块之前由 vidtv_bridge 填充。
-
struct vidtv_demod_state¶
解调器状态
定义:
struct vidtv_demod_state {
struct dvb_frontend frontend;
struct vidtv_demod_config config;
enum fe_status status;
u16 tuner_cnr;
};
成员
前端
由解调器分配的前端结构。
配置
用于初始化解调器的配置。
状态
解调器状态。
tuner_cnr
信号载波的当前信噪比
-
struct vidtv_encoder¶
一个通用的编码器类型。
定义:
struct vidtv_encoder {
enum vidtv_encoder_id id;
char *name;
u8 *encoder_buf;
u32 encoder_buf_sz;
u32 encoder_buf_offset;
u64 sample_count;
struct vidtv_access_unit *access_units;
void *src_buf;
u32 src_buf_sz;
u32 src_buf_offset;
bool is_video_encoder;
void *ctx;
__be16 stream_id;
__be16 es_pid;
void *(*encode)(struct vidtv_encoder *e);
u32 (*clear)(struct vidtv_encoder *e);
struct vidtv_encoder *sync;
u32 sampling_rate_hz;
void (*last_sample_cb)(u32 sample_no);
void (*destroy)(struct vidtv_encoder *e);
struct vidtv_encoder *next;
};
成员
id
以便在需要时可以转换为具体的实现。
name
通常与流名称相同。
encoder_buf
用于访问单元的编码器内部缓冲区。
encoder_buf_sz
编码器缓冲区大小,以字节为单位
encoder_buf_offset
我们在编码器缓冲区中的字节位置。
sample_count
我们总共编码了多少个样本。
access_units
编码器有效负载单元,用于时钟参考
src_buf
要编码的原始数据的来源,如果为空,编码器可能会设置默认值。
src_buf_sz
src_buf 的大小。
src_buf_offset
我们在源缓冲区中的位置。
is_video_encoder
是否为视频编码器(与音频相对)
ctx
特定于编码器的状态。
stream_id
示例:音频流 (0xc0-0xdf),视频流 (0xe0-0xef)。
es_pid
用于此编码器中基本流的 TS PID。
encode
为给定的时间量准备足够的 AU。
clear
清除编码器输出。
sync
尝试与此编码器同步。
sampling_rate_hz
使用的采样率(或帧率,如果为视频)。
last_sample_cb
当编码器数据耗尽时调用。这样源可以以零碎的方式读取数据,而不是必须一次性提供所有数据。
destroy
销毁此编码器,释放已分配的资源。
next
链中的下一个
-
struct vidtv_mux_timing¶
与计时相关的信息
定义:
struct vidtv_mux_timing {
u64 start_jiffies;
u64 current_jiffies;
u64 past_jiffies;
u64 clk;
u64 pcr_period_usecs;
u64 si_period_usecs;
};
成员
start_jiffies
当我们启动复用线程时“jiffies”的值。
current_jiffies
当前迭代的“jiffies”值。
past_jiffies
过去迭代的“jiffies”值。
clk
我们将从中驱动 PCR 的 27Mhz 时钟。在每次迭代中按比例更新。
pcr_period_usecs
我们应该发送 PCR 数据包的频率。
si_period_usecs
我们应该发送 PSI 数据包的频率。
描述
这用于决定何时应发送 PCR 或 PSI 数据包。这也将为时钟提供存储空间,该时钟用于计算 PCR 的值。
-
struct vidtv_mux_si¶
存储 PSI 上下文。
定义:
struct vidtv_mux_si {
struct vidtv_psi_table_pat *pat;
struct vidtv_psi_table_pmt **pmt_secs;
struct vidtv_psi_table_sdt *sdt;
struct vidtv_psi_table_nit *nit;
struct vidtv_psi_table_eit *eit;
};
成员
pat
复用器正在使用的 PAT。
pmt_secs
复用器正在使用的 PMT 段。PAT 中的每个程序一个。
sdt
复用器正在使用的 SDT。
nit
复用器正在使用的 NIT。
eit
复用器正在使用的 EIT。
描述
这用于存储复用器正在使用的 PAT、PMT 段和 SDT。
复用器通过查看 vidtv_channel 中的硬编码通道来获取这些,然后定期为它们发送 TS 数据包>
-
struct vidtv_mux_pid_ctx¶
存储给定 TS PID 的上下文。
定义:
struct vidtv_mux_pid_ctx {
u16 pid;
u8 cc;
struct hlist_node h;
};
成员
pid
TS PID。
cc
此 PID 的连续性计数器。它在每个 TS 数据包上递增,并在 0xf0 处回绕。如果解码器注意到此计数器突然跳跃,这将触发不连续状态。
h
这嵌入在哈希表中,映射 pid -> vidtv_mux_pid_ctx
-
struct vidtv_mux¶
一个大致基于 libavcodec/mpegtsenc.c 的复用器抽象
定义:
struct vidtv_mux {
struct dvb_frontend *fe;
struct device *dev;
struct vidtv_mux_timing timing;
u32 mux_rate_kbytes_sec;
unsigned long pid_ctx[1 << ((3) - 1)];
void (*on_new_packets_available_cb)(void *priv, u8 *buf, u32 npackets);
u8 *mux_buf;
u32 mux_buf_sz;
u32 mux_buf_offset;
struct vidtv_channel *channels;
struct vidtv_mux_si si;
u64 num_streamed_pcr;
u64 num_streamed_si;
struct work_struct mpeg_thread;
bool streaming;
u16 pcr_pid;
u16 transport_stream_id;
u16 network_id;
char *network_name;
void *priv;
};
成员
fe
由复用器分配的前端结构。
dev
指向
struct device
的指针。timing
跟踪与计时相关的信息。
mux_rate_kbytes_sec
TS 的比特率,以 kbytes 为单位。
pid_ctx
一个哈希表,用于跟踪每个 PID 的元数据。
on_new_packets_available_cb
一个回调,用于通知新的 TS 数据包已准备就绪。
mux_buf
指向此复用器缓冲区的指针。TS 数据包存储在那里,然后传递给桥接驱动程序。
mux_buf_sz
“mux_buf”的大小。
mux_buf_offset
“mux_buf”中的当前偏移量。
channels
与此复用器关联的通道。
si
跟踪 PSI 上下文。
num_streamed_pcr
已流式传输的 PCR 数据包数。
num_streamed_si
已流式传输的 PSI 数据包数。
mpeg_thread
负责复用器循环的线程。
streaming
“mpeg_thread”是否正在运行。
pcr_pid
用于 PSI 数据包的 TS PID。所有通道将共享相同的 PCR。
transport_stream_id
传输流 ID
network_id
网络 ID
network_name
网络名称
priv
私有数据。
-
struct vidtv_mux_init_args¶
用于初始化复用器的参数。
定义:
struct vidtv_mux_init_args {
u32 mux_rate_kbytes_sec;
void (*on_new_packets_available_cb)(void *priv, u8 *buf, u32 npackets);
u32 mux_buf_sz;
u64 pcr_period_usecs;
u64 si_period_usecs;
u16 pcr_pid;
u16 transport_stream_id;
struct vidtv_channel *channels;
u16 network_id;
char *network_name;
void *priv;
};
成员
mux_rate_kbytes_sec
TS 的比特率,以 kbytes 为单位。
on_new_packets_available_cb
一个回调,用于通知新的 TS 数据包已准备就绪。
mux_buf_sz
“mux_buf”的大小。
pcr_period_usecs
我们应该发送 PCR 数据包的频率。
si_period_usecs
我们应该发送 PSI 数据包的频率。
pcr_pid
用于 PSI 数据包的 TS PID。所有通道将共享相同的 PCR。
transport_stream_id
传输流 ID
channels
要使用的可选通道列表
network_id
网络 ID
network_name
网络名称
priv
私有数据。
-
struct pes_header_write_args¶
用于写入 PES 标头的参数。
定义:
struct pes_header_write_args {
void *dest_buf;
u32 dest_offset;
u32 dest_buf_sz;
u32 encoder_id;
bool send_pts;
u64 pts;
bool send_dts;
u64 dts;
u16 stream_id;
u32 n_pes_h_s_bytes;
u32 access_unit_len;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
在 dest_buffer 中开始写入的位置。
dest_buf_sz
dest_buffer 的大小
encoder_id
编码器 ID(请参阅 vidtv_encoder.h)
send_pts
我们应该发送 PTS 吗?
pts
要发送的 PTS 值。
send_dts
我们应该发送 DTS 吗?
dts
要发送的 DTS 值。
stream_id
要使用的流 ID。示例:音频流 (0xc0-0xdf),视频流 (0xe0-0xef)。
n_pes_h_s_bytes
填充字节。如果需要,编码器可能会使用,解码器会丢弃。
access_unit_len
一个访问单元的大小(包括它可能需要的任何标头)
-
struct pes_ts_header_write_args¶
用于写入 TS 标头的参数。
定义:
struct pes_ts_header_write_args {
void *dest_buf;
u32 dest_offset;
u32 dest_buf_sz;
u16 pid;
u8 *continuity_counter;
bool wrote_pes_header;
u32 n_stuffing_bytes;
u64 pcr;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
在 dest_buffer 中开始写入的位置。
dest_buf_sz
dest_buffer 的大小
pid
用于 TS 数据包的 PID。
continuity_counter
在每个新的 TS 数据包上递增。
wrote_pes_header
指示 PES 标头已写入的标志
n_stuffing_bytes
填充字节。如果需要,编码器可能会使用,解码器会丢弃。
pcr
由 27Mhz 时钟驱动的计数器。
-
struct pes_write_args¶
数据包化器的参数。
定义:
struct pes_write_args {
void *dest_buf;
void *from;
u32 access_unit_len;
u32 dest_offset;
u32 dest_buf_sz;
u16 pid;
u32 encoder_id;
u8 *continuity_counter;
u16 stream_id;
bool send_pts;
u64 pts;
bool send_dts;
u64 dts;
u32 n_pes_h_s_bytes;
u64 pcr;
};
成员
dest_buf
要写入的缓冲区。
from
指向包含一个访问单元的编码器缓冲区的指针。
access_unit_len
一个访问单元的大小(包括它可能需要的任何标头)
dest_offset
在 dest_buffer 中开始写入的位置。
dest_buf_sz
dest_buffer 的大小
pid
用于 TS 数据包的 PID。
encoder_id
编码器 ID(请参阅 vidtv_encoder.h)
continuity_counter
在每个新的 TS 数据包上递增。
stream_id
要使用的流 ID。示例:音频流 (0xc0-0xdf),视频流 (0xe0-0xef)。
send_pts
我们应该发送 PTS 吗?
pts
要发送的 PTS 值。
send_dts
我们应该发送 DTS 吗?
dts
要发送的 DTS 值。
n_pes_h_s_bytes
填充字节。如果需要,编码器可能会使用,解码器会丢弃。
pcr
由 27Mhz 时钟驱动的计数器。
-
u32 vidtv_pes_write_into(struct pes_write_args *args)¶
将 PES 数据包作为 MPEG-TS 数据包写入缓冲区。
参数
struct pes_write_args *args
写入时要使用的参数
描述
此函数将来自编码器的访问单元的 ES 数据转换为 MPEG TS 数据包。它首先使用 PES 标头封装它,然后将其拆分为 TS 数据包。
然后将数据写入由“args.buf”指向的缓冲区
返回
写入缓冲区的字节数。这通常不等于访问单元的大小,因为我们需要 PES 标头、TS 标头和填充字节(如果有)的空间。
-
struct psi_write_args¶
PSI 数据包化器的参数。
定义:
struct psi_write_args {
void *dest_buf;
void *from;
size_t len;
u32 dest_offset;
u16 pid;
bool new_psi_section;
u8 *continuity_counter;
bool is_crc;
u32 dest_buf_sz;
u32 *crc;
};
成员
dest_buf
要写入的缓冲区。
from
要复制的 PSI 数据。
len
要写入多少。
dest_offset
在 dest_buffer 中开始写入的位置。
pid
TS 数据包 ID。
new_psi_section
在开始表段时设置。
continuity_counter
在每个新数据包上递增。
is_crc
在末尾写入 CRC 时设置。
dest_buf_sz
dest_buffer 的大小
crc
用于存储此块的 crc 的指针
-
struct desc_write_args¶
为了写入描述符而使用的参数。
定义:
struct desc_write_args {
void *dest_buf;
u32 dest_offset;
struct vidtv_psi_desc *desc;
u16 pid;
u8 *continuity_counter;
u32 dest_buf_sz;
u32 *crc;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
在 dest_buffer 中开始写入的位置。
desc
指向描述符的指针
pid
TS 数据包 ID。
continuity_counter
在每个新数据包上递增。
dest_buf_sz
dest_buffer 的大小
crc
用于存储此块的 crc 的指针
-
struct crc32_write_args¶
为了在 PSI 表的末尾写入 CRC 而使用的参数。
定义:
struct crc32_write_args {
void *dest_buf;
u32 dest_offset;
__be32 crc;
u16 pid;
u8 *continuity_counter;
u32 dest_buf_sz;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
在 dest_buffer 中开始写入的位置。
crc
要写入的 CRC 值
pid
TS 数据包 ID。
continuity_counter
在每个新数据包上递增。
dest_buf_sz
dest_buffer 的大小
-
struct header_write_args¶
用于写入通用表头的参数,按顺序排列
定义:
struct header_write_args {
void *dest_buf;
u32 dest_offset;
struct vidtv_psi_table_header *h;
u16 pid;
u8 *continuity_counter;
u32 dest_buf_sz;
u32 *crc;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
在 dest_buffer 中开始写入的位置。
h
指向表头的指针。
pid
TS 数据包 ID。
continuity_counter
在每个新数据包上递增。
dest_buf_sz
dest_buffer 的大小
crc
用于存储此块的 crc 的指针
-
void vidtv_psi_sdt_service_assign(struct vidtv_psi_table_sdt *sdt, struct vidtv_psi_table_sdt_service *service)¶
将服务循环分配给SDT。
参数
struct vidtv_psi_table_sdt *sdt
要分配到的SDT。
struct vidtv_psi_table_sdt_service *service
服务循环(一个或多个服务)
描述
这将释放表中之前的服务循环。这会将服务循环的所有权分配给表,即当调用其销毁函数时,该表将释放此服务循环。
-
void vidtv_psi_desc_assign(struct vidtv_psi_desc **to, struct vidtv_psi_desc *desc)¶
在某个点分配描述符循环
参数
struct vidtv_psi_desc **to
将此描述符循环分配到哪里
struct vidtv_psi_desc *desc
将被分配的描述符循环。
描述
这将释放'to'中的循环(如果存在)。
-
void vidtv_pmt_desc_assign(struct vidtv_psi_table_pmt *pmt, struct vidtv_psi_desc **to, struct vidtv_psi_desc *desc)¶
在PMT部分中的某个点分配描述符循环。
参数
struct vidtv_psi_table_pmt *pmt
将包含描述符循环的PMT部分
struct vidtv_psi_desc **to
将此描述符循环分配到PMT中的位置
struct vidtv_psi_desc *desc
将被分配的描述符循环。
描述
这将释放'to'中的循环(如果存在)。这会将循环的所有权分配给表,即当调用其销毁函数时,该表将释放此循环。
-
void vidtv_sdt_desc_assign(struct vidtv_psi_table_sdt *sdt, struct vidtv_psi_desc **to, struct vidtv_psi_desc *desc)¶
在SDT的某个点分配描述符循环。
参数
struct vidtv_psi_table_sdt *sdt
将包含描述符循环的SDT
struct vidtv_psi_desc **to
将此描述符循环分配到PMT中的位置
struct vidtv_psi_desc *desc
将被分配的描述符循环。
描述
这将释放'to'中的循环(如果存在)。这会将循环的所有权分配给表,即当调用其销毁函数时,该表将释放此循环。
-
void vidtv_psi_pat_program_assign(struct vidtv_psi_table_pat *pat, struct vidtv_psi_table_pat_program *p)¶
将程序循环分配给PAT。
参数
struct vidtv_psi_table_pat *pat
要分配到的PAT。
struct vidtv_psi_table_pat_program *p
程序循环(一个或多个程序)
描述
这将释放表中之前的程序循环。这会将程序循环的所有权分配给表,即当调用其销毁函数时,该表将释放此程序循环。
-
void vidtv_psi_pmt_stream_assign(struct vidtv_psi_table_pmt *pmt, struct vidtv_psi_table_pmt_stream *s)¶
将流循环分配给PAT。
参数
struct vidtv_psi_table_pmt *pmt
要分配到的PMT。
struct vidtv_psi_table_pmt_stream *s
流循环(一个或多个流)
描述
这将释放表中之前的流循环。这会将流循环的所有权分配给表,即当调用其销毁函数时,该表将释放此流循环。
-
struct vidtv_psi_table_pmt **vidtv_psi_pmt_create_sec_for_each_pat_entry(struct vidtv_psi_table_pat *pat, u16 pcr_pid)¶
为PAT中找到的每个程序创建一个PMT部分
参数
struct vidtv_psi_table_pat *pat
要查找程序的PAT。
u16 pcr_pid
此PMT部分中描述的程序要使用的PCR的包ID
-
u16 vidtv_psi_pmt_get_pid(struct vidtv_psi_table_pmt *section, struct vidtv_psi_table_pat *pat)¶
获取PMT部分的TS PID。
参数
struct vidtv_psi_table_pmt *section
我们要检索其PID的PMT部分。
struct vidtv_psi_table_pat *pat
要查找的PAT表。
返回
“section”的TS PID
-
void vidtv_psi_pat_table_update_sec_len(struct vidtv_psi_table_pat *pat)¶
重新计算并更新PAT节的长度。
参数
struct vidtv_psi_table_pat *pat
要更新其长度的PAT。
描述
这将遍历表并累积其组件的长度,然后将其用于替换“section_length”字段。
如果section_length > MAX_SECTION_LEN,则操作失败。
-
void vidtv_psi_pmt_table_update_sec_len(struct vidtv_psi_table_pmt *pmt)¶
重新计算并更新PMT节的长度。
参数
struct vidtv_psi_table_pmt *pmt
要更新其长度的PMT。
描述
这将遍历表并累积其组件的长度,然后将其用于替换“section_length”字段。
如果section_length > MAX_SECTION_LEN,则操作失败。
-
void vidtv_psi_sdt_table_update_sec_len(struct vidtv_psi_table_sdt *sdt)¶
重新计算并更新SDT节的长度。
参数
struct vidtv_psi_table_sdt *sdt
要更新其长度的SDT。
描述
这将遍历表并累积其组件的长度,然后将其用于替换“section_length”字段。
如果section_length > MAX_SECTION_LEN,则操作失败。
-
struct vidtv_psi_pat_write_args¶
用于写入PAT表的参数
定义:
struct vidtv_psi_pat_write_args {
char *buf;
u32 offset;
struct vidtv_psi_table_pat *pat;
u32 buf_sz;
u8 *continuity_counter;
};
成员
buf
目标缓冲区。
offset
目标缓冲区中的偏移量。
pat
指向PAT的指针。
buf_sz
目标缓冲区的大小。
continuity_counter
指向CC的指针。在每个新数据包上递增。
-
u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args *args)¶
将 PAT 作为 MPEG-TS 数据包写入缓冲区。
参数
struct vidtv_psi_pat_write_args *args
描述
此函数将 PAT 表的 MPEG TS 数据包写入缓冲区。调用代码通常会通过调用其初始化函数来生成 PAT,因此负责释放它。
返回
写入缓冲区的字节数。这不等于 PAT 的大小,因为在 TS 封装期间需要更多空间用于 TS 标头。
-
struct vidtv_psi_sdt_write_args¶
用于写入 SDT 表的参数
定义:
struct vidtv_psi_sdt_write_args {
char *buf;
u32 offset;
struct vidtv_psi_table_sdt *sdt;
u32 buf_sz;
u8 *continuity_counter;
};
成员
buf
目标缓冲区。
offset
目标缓冲区中的偏移量。
sdt
指向 SDT 的指针。
buf_sz
目标缓冲区的大小。
continuity_counter
指向CC的指针。在每个新数据包上递增。
-
u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args *args)¶
将 SDT 作为 MPEG-TS 数据包写入缓冲区。
参数
struct vidtv_psi_sdt_write_args *args
描述
此函数将 SDT 表的 MPEG TS 数据包写入缓冲区。调用代码通常会通过调用其初始化函数来生成 SDT,因此负责释放它。
返回
写入缓冲区的字节数。这不等于 SDT 的大小,因为在 TS 封装期间需要更多空间用于 TS 标头。
-
struct vidtv_psi_pmt_write_args¶
用于写入 PMT 段的参数
定义:
struct vidtv_psi_pmt_write_args {
char *buf;
u32 offset;
struct vidtv_psi_table_pmt *pmt;
u16 pid;
u32 buf_sz;
u8 *continuity_counter;
u16 pcr_pid;
};
成员
buf
目标缓冲区。
offset
目标缓冲区中的偏移量。
pmt
指向 PMT 的指针。
pid
节目 ID
buf_sz
目标缓冲区的大小。
continuity_counter
指向CC的指针。在每个新数据包上递增。
pcr_pid
用于 PSI 数据包的 TS PID。所有通道将共享相同的 PCR。
-
u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args)¶
将 PMT 作为 MPEG-TS 数据包写入缓冲区。
参数
struct vidtv_psi_pmt_write_args *args
描述
此函数将 PMT 段的 MPEG TS 数据包写入缓冲区。调用代码通常会通过调用其初始化函数来生成 PMT 段,因此负责释放它。
返回
写入缓冲区的字节数。这不等于 PMT 段的大小,因为在 TS 封装期间需要更多空间用于 TS 标头。
-
struct vidtv_psi_table_pmt *vidtv_psi_find_pmt_sec(struct vidtv_psi_table_pmt **pmt_sections, u16 nsections, u16 program_num)¶
查找 ‘program_num’ 的 PMT 段
参数
struct vidtv_psi_table_pmt **pmt_sections
要查找的段。
u16 nsections
段的数量。
u16 program_num
来自 PAT 的指向 PMT 段的 'program_num'。
返回
指向 PMT 的指针(如果找到),否则为 NULL。
-
struct vidtv_psi_table_transport¶
NIT 和/或其他表的 TS 循环中的一个条目。参见 ETSI 300 468 第 5.2.1 节
定义:
struct vidtv_psi_table_transport {
__be16 transport_id;
__be16 network_id;
__be16 bitfield;
struct vidtv_psi_desc *descriptor;
struct vidtv_psi_table_transport *next;
};
成员
transport_id
正在描述的 TS ID
network_id
包含 TS ID 的 network_id
位域
包含描述符循环长度
描述符
描述符循环
next
指向下一个条目的指针
-
struct vidtv_psi_table_nit¶
网络信息表 (NIT)。参见 ETSI 300 468 第 5.2.1 节
定义:
struct vidtv_psi_table_nit {
struct vidtv_psi_table_header header;
__be16 bitfield;
struct vidtv_psi_desc *descriptor;
__be16 bitfield2;
struct vidtv_psi_table_transport *transport;
};
成员
标头
PSI 表标头
位域
包含网络描述符长度
描述符
描述网络的描述符循环
位域2
包含传输流循环长度
传输
传输流循环
-
struct vidtv_psi_nit_write_args¶
用于写入 NIT 段的参数
定义:
struct vidtv_psi_nit_write_args {
char *buf;
u32 offset;
struct vidtv_psi_table_nit *nit;
u32 buf_sz;
u8 *continuity_counter;
};
成员
buf
目标缓冲区。
offset
目标缓冲区中的偏移量。
nit
指向 NIT 的指针
buf_sz
目标缓冲区的大小。
continuity_counter
指向CC的指针。在每个新数据包上递增。
-
u32 vidtv_psi_nit_write_into(struct vidtv_psi_nit_write_args *args)¶
将 NIT 作为 MPEG-TS 数据包写入缓冲区。
参数
struct vidtv_psi_nit_write_args *args
描述
此函数将 NIT 表的 MPEG TS 数据包写入缓冲区。调用代码通常会通过调用其初始化函数来生成 NIT,因此负责释放它。
返回
写入缓冲区的字节数。这不等于 NIT 的大小,因为在 TS 封装期间需要更多空间用于 TS 标头。
-
struct vidtv_psi_eit_write_args¶
用于写入 EIT 段的参数
定义:
struct vidtv_psi_eit_write_args {
char *buf;
u32 offset;
struct vidtv_psi_table_eit *eit;
u32 buf_sz;
u8 *continuity_counter;
};
成员
buf
目标缓冲区。
offset
目标缓冲区中的偏移量。
eit
指向 EIT 的指针
buf_sz
目标缓冲区的大小。
continuity_counter
指向CC的指针。在每个新数据包上递增。
-
u32 vidtv_psi_eit_write_into(struct vidtv_psi_eit_write_args *args)¶
将 EIT 作为 MPEG-TS 数据包写入缓冲区。
参数
struct vidtv_psi_eit_write_args *args
描述
此函数将 EIT 表的 MPEG TS 数据包写入缓冲区。调用代码通常会通过调用其初始化函数来生成 EIT,因此负责释放它。
返回
写入缓冲区的字节数。这不等于 EIT 的大小,因为在 TS 封装期间需要更多空间用于 TS 标头。
-
void vidtv_psi_eit_table_update_sec_len(struct vidtv_psi_table_eit *eit)¶
重新计算并更新 EIT 段长度。
参数
struct vidtv_psi_table_eit *eit
要更新长度的 EIT。
描述
这将遍历表并累积其组件的长度,然后将其用于替换“section_length”字段。
如果 section_length > EIT_MAX_SECTION_LEN,则操作失败。
-
void vidtv_psi_eit_event_assign(struct vidtv_psi_table_eit *eit, struct vidtv_psi_table_eit_event *e)¶
将事件循环分配给 EIT。
参数
struct vidtv_psi_table_eit *eit
要分配到的 EIT。
struct vidtv_psi_table_eit_event *e
事件循环
描述
这将释放表中以前的事件循环。这会将流循环的所有权分配给表,即,当调用其销毁函数时,该表将释放此流循环。
-
struct vidtv_s302m_ctx¶
s302m 编码器上下文。
定义:
struct vidtv_s302m_ctx {
struct vidtv_encoder *enc;
u32 frame_index;
u32 au_count;
int last_duration;
unsigned int note_offset;
enum musical_notes last_tone;
};
成员
enc
指向包含的编码器结构的指针。
frame_index
块中的当前帧
au_count
到目前为止编码的访问单元总数
last_duration
当前播放的音调的持续时间
note_offset
音乐音调数组中的位置
last_tone
当前播放的音调
-
struct vidtv_s302m_encoder_init_args¶
s302m 编码器的参数。
定义:
struct vidtv_s302m_encoder_init_args {
char *name;
void *src_buf;
u32 src_buf_sz;
u16 es_pid;
struct vidtv_encoder *sync;
void (*last_sample_cb)(u32 sample_no);
struct vidtv_encoder *head;
};
成员
name
用于标识此特定实例的名称
src_buf
源缓冲区,如果此项为 NULL,编码器将默认为正弦波。
src_buf_sz
源缓冲区的大小。
es_pid
要使用的 MPEG 基本流 PID。
sync
尝试将音频与此视频编码器同步(如果不是 NULL)。
last_sample_cb
当编码器用完数据时调用的回调。
head
添加到此链
-
struct pcr_write_args¶
pcr_write_into 函数的参数。
定义:
struct pcr_write_args {
void *dest_buf;
u32 dest_offset;
u16 pid;
u32 buf_sz;
u8 *continuity_counter;
u64 pcr;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
缓冲区中的字节偏移量。
pid
PCR 数据包的 TS PID。
buf_sz
缓冲区的字节大小。
continuity_counter
TS continuity_counter。
pcr
来自系统时钟的采样。
-
struct null_packet_write_args¶
null_write_into 函数的参数
定义:
struct null_packet_write_args {
void *dest_buf;
u32 dest_offset;
u32 buf_sz;
u8 *continuity_counter;
};
成员
dest_buf
要写入的缓冲区。
dest_offset
缓冲区中的字节偏移量。
buf_sz
缓冲区的字节大小。
continuity_counter
TS continuity_counter。
-
u32 vidtv_ts_null_write_into(struct null_packet_write_args args)¶
将 TS 空包写入缓冲区。
参数
struct null_packet_write_args args
写入时使用的参数。
描述
此函数将一个空包写入缓冲区。通常用于填充 TS 流。
返回
写入缓冲区的字节数。
-
u32 vidtv_ts_pcr_write_into(struct pcr_write_args args)¶
将 PCR 包写入缓冲区。
参数
struct pcr_write_args args
写入时使用的参数。
描述
此函数将 PCR 包写入缓冲区。用于同步编码器和解码器之间的时钟。
返回
写入缓冲区的字节数。
-
struct vidtv_tuner_config¶
用于初始化调谐器的配置。
定义:
struct vidtv_tuner_config {
struct dvb_frontend *fe;
u32 mock_power_up_delay_msec;
u32 mock_tune_delay_msec;
u32 vidtv_valid_dvb_t_freqs[NUM_VALID_TUNER_FREQS];
u32 vidtv_valid_dvb_c_freqs[NUM_VALID_TUNER_FREQS];
u32 vidtv_valid_dvb_s_freqs[NUM_VALID_TUNER_FREQS];
u8 max_frequency_shift_hz;
};
成员
fe
指向由 vidtv_demod 分配的 dvb_frontend 结构的指针。
mock_power_up_delay_msec
模拟上电延迟。
mock_tune_delay_msec
模拟调谐延迟。
vidtv_valid_dvb_t_freqs
要模拟的有效 DVB-T 频率。
vidtv_valid_dvb_c_freqs
要模拟的有效 DVB-C 频率。
vidtv_valid_dvb_s_freqs
要模拟的有效 DVB-S 频率。
max_frequency_shift_hz
调谐频道时允许的最大频率偏移量 (以赫兹为单位)
描述
用于初始化调谐器模块的配置,通常由桥接驱动程序填充。对于 vidtv,此配置在探测调谐器模块之前由 vidtv_bridge 填充。
-
u32 vidtv_memcpy(void *to, size_t to_offset, size_t to_size, const void *from, size_t len)¶
MPEG-TS 生成器使用的包装例程,以避免超出输出缓冲区。
参数
void *to
将复制 MPEG-TS 包的起始元素。
size_t to_offset
要填充的 to 缓冲区的起始位置。
size_t to_size
to 缓冲区的大小。
const void *from
要复制的缓冲区的起始元素。
size_t len
要从 from 缓冲区复制到 to**+ **to_offset 缓冲区的元素数量。
注意
真实的数字电视解调驱动程序不应有 memcpy 包装器。我们在这里使用它,因为在内核空间中模拟 MPEG-TS 生成需要一些额外的注意。
返回
返回写入的字节数
-
u32 vidtv_memset(void *to, size_t to_offset, size_t to_size, const int c, size_t len)¶
MPEG-TS 生成器使用的包装例程,以避免超出输出缓冲区。
参数
void *to
要设置的起始元素
size_t to_offset
要填充的 to 缓冲区的起始位置。
size_t to_size
to 缓冲区的大小。
const int c
将内存设置为的值。
size_t len
要从 from 缓冲区复制到 to**+ **to_offset 缓冲区的元素数量。
注意
真实的数字电视解调驱动程序不应有 memset 包装器。我们在这里使用它,因为在内核空间中模拟 MPEG-TS 生成需要一些额外的注意。
返回
返回写入的字节数
-
struct vidtv_tuner_hardware_state¶
模拟调谐器硬件状态
定义:
struct vidtv_tuner_hardware_state {
bool asleep;
u32 lock_status;
u32 if_frequency;
u32 tuned_frequency;
u32 bandwidth;
};
成员
asleep
调谐器是否处于睡眠状态,即是否调用了 _sleep() 或 _suspend()。
lock_status
调谐器是否已成功锁定到请求的频率。
if_frequency
调谐器的中频。为了模拟而硬编码。
tuned_frequency
实际调谐频率。
bandwidth
实际带宽。
描述
此结构旨在模拟调谐器硬件的状态,就像我们有物理调谐器硬件一样。
-
struct vidtv_tuner_dev¶
调谐器结构
定义:
struct vidtv_tuner_dev {
struct dvb_frontend *fe;
struct vidtv_tuner_hardware_state hw_state;
struct vidtv_tuner_config config;
};
成员
fe
指向由 vidtv_demod 分配的 dvb_frontend 结构的指针
hw_state
一个结构,用于模拟调谐器的硬件状态,就像我们有物理调谐器硬件一样。
配置
用于启动调谐器模块的配置,通常由桥接驱动程序填充。对于 vidtv,此配置在探测调谐器模块之前由 vidtv_bridge 填充。