3.3. 数字电视解复用器 kABI

3.3.1. 数字电视解复用器

内核数字电视解复用器 kABI 定义了一个驱动程序内部接口,用于将底层、硬件特定的驱动程序注册到与硬件无关的解复用层。它仅对数字电视设备驱动程序编写者感兴趣。此 kABI 的头文件名为 demux.h,位于 include/media 中。

应该为系统中的每个解复用器实现解复用器 kABI。它用于选择解复用器的 TS 源并管理解复用器资源。当解复用器客户端通过解复用器 kABI 分配资源时,它会收到指向该资源 kABI 的指针。

每个解复用器都从 DVB 前端或从内存接收其 TS 输入,这是通过此解复用器 kABI 设置的。在具有多个前端的系统中,除非在硬件平台中固定,否则可以使用 kABI 选择其中一个 DVB 前端作为解复用器的 TS 源。

解复用器 kABI 仅控制前端与其与解复用器的连接;用于设置其他前端参数(例如调谐)的 kABI 通过数字电视前端 kABI 定义。

实现抽象接口解复用器的函数应定义为静态或模块私有,并注册到解复用器核心以进行外部访问。不需要实现结构体 dmx_demux 中的每个函数。例如,解复用器接口可能支持节过滤,但不支持 PES 过滤。kABI 客户端应在调用函数之前检查任何函数指针的值:NULL 的值表示该函数不可用。

每当解复用器 API 的函数修改共享数据时,都应解决丢失更新和竞争条件问题的可能性,例如通过使用互斥锁保护部分代码。

请注意,从下半部上下文调用的函数不得休眠。即使是不使用 GFP_ATOMIC 的简单内存分配,如果需要交换,也可能导致内核线程进入休眠状态。例如,Linux 内核从下半部上下文中调用网络设备接口的函数。因此,如果从网络设备代码调用解复用器 kABI 函数,则该函数不得休眠。

3.3.2. 解复用器回调 API

此内核空间 API 包括将过滤后的数据传递给解复用器客户端的回调函数。与其他 DVB kABI 不同,这些函数由客户端提供,并从解复用器代码调用。

此抽象接口的函数指针不像其他解复用器 API 那样打包到结构中,因为回调函数是注册和独立使用的。例如,API 客户端可以提供多个用于接收 TS 数据包的回调函数,而没有用于 PES 数据包或节的回调。

实现回调 API 的函数不需要是可重入的:当解复用器驱动程序调用其中一个函数时,驱动程序不允许在原始调用返回之前再次调用该函数。如果回调是由硬件中断触发的,建议使用 Linux 下半部机制或启动 tasklet,而不是直接从硬件中断调用回调函数。

此机制由 dmx_ts_cb()dmx_section_cb() 回调实现。

3.3.3. 数字电视解复用器设备注册函数和数据结构

enum dmxdev_type

解复用器过滤器类型。

常量

DMXDEV_TYPE_NONE

未设置过滤器。

DMXDEV_TYPE_SEC

节过滤器。

DMXDEV_TYPE_PES

节目基本流 (PES) 过滤器。

enum dmxdev_state

dmxdev 的状态机。

常量

DMXDEV_STATE_FREE

表示过滤器已释放。

DMXDEV_STATE_ALLOCATED

表示过滤器已分配以供使用。

DMXDEV_STATE_SET

表示已设置过滤器参数。

DMXDEV_STATE_GO

表示过滤器正在运行。

DMXDEV_STATE_DONE

表示数据包已被过滤,并且过滤器现在已禁用。仅在 DMX_ONESHOT 时设置。请参阅 dmx_sct_filter_params

DMXDEV_STATE_TIMEDOUT

表示超时条件。

struct dmxdev_feed

数字电视 dmxdev 源

定义:

struct dmxdev_feed {
    u16 pid;
    struct dmx_ts_feed *ts;
    struct list_head next;
};

成员

pid

要过滤的节目 ID

ts

指向 struct dmx_ts_feed 的指针

next

指向下一个源的 struct list_head

struct dmxdev_filter

数字电视 dmxdev 过滤器

定义:

struct dmxdev_filter {
    union {
        struct dmx_section_filter *sec;
    } filter;
    union {
        struct list_head ts;
        struct dmx_section_feed *sec;
    } feed;
    union {
        struct dmx_sct_filter_params sec;
        struct dmx_pes_filter_params pes;
    } params;
    enum dmxdev_type type;
    enum dmxdev_state state;
    struct dmxdev *dev;
    struct dvb_ringbuffer buffer;
    struct dvb_vb2_ctx vb2_ctx;
    struct mutex mutex;
    struct timer_list timer;
    int todo;
    u8 secheader[3];
};

成员

filter

一个描述 dmxdev 过滤器的联合。目前仅用于节过滤器。

filter.sec

一个 struct dmx_section_filter 指针。仅适用于节过滤器。

feed

一个描述 dmxdev 源的联合。根据过滤器类型,它可以是 feed.tsfeed.sec

feed.ts

一个 struct list_head 列表。用于 TS 和 PES 源。

feed.sec

一个 struct dmx_section_feed 指针。仅适用于节源。

params

一个联合体,用于描述 dmxdev 过滤器参数。根据过滤器类型,它可以是 params.secparams.pes

params.sec

一个嵌入的 struct dmx_sct_filter_params 结构体。仅用于 section 过滤器。

params.pes

一个嵌入的 struct dmx_pes_filter_params 结构体。仅用于 PES 过滤器。

type

dmxdev 过滤器的类型,由 enum dmxdev_type 定义。

state

dmxdev 过滤器的状态,由 enum dmxdev_state 定义。

dev

指向 struct dmxdev 的指针。

buffer

一个嵌入的 struct dvb_ringbuffer 缓冲区。

vb2_ctx

VB2 处理程序的控制结构体。

mutex

保护对 struct dmxdev_filter 的访问。

timer

嵌入的 struct timer_list 定时器,用于检查 feed 超时。仅用于 section 过滤器。

todo

secheader 的索引。仅用于 section 过滤器。

secheader

用于解析 section 头的缓冲区缓存。仅用于 section 过滤器。

struct dmxdev

描述一个数字电视解复用设备。

定义:

struct dmxdev {
    struct dvb_device *dvbdev;
    struct dvb_device *dvr_dvbdev;
    struct dmxdev_filter *filter;
    struct dmx_demux *demux;
    int filternum;
    int capabilities;
    unsigned int may_do_mmap:1;
    unsigned int exit:1;
#define DMXDEV_CAP_DUPLEX 1;
    struct dmx_frontend *dvr_orig_fe;
    struct dvb_ringbuffer dvr_buffer;
#define DVR_BUFFER_SIZE (10*188*1024);
    struct dvb_vb2_ctx dvr_vb2_ctx;
    struct mutex mutex;
    spinlock_t lock;
};

成员

dvbdev

指向与解复用设备节点关联的 struct dvb_device 的指针。

dvr_dvbdev

指向与 dvr 设备节点关联的 struct dvb_device 的指针。

filter

指向 struct dmxdev_filter 的指针。

demux

指向 struct dmx_demux 的指针。

filternum

过滤器的数量。

capabilities

解复用器的功能,由 enum dmx_demux_caps 定义。

may_do_mmap

用于指示设备是否可以进行 mmap 的标志。

exit

用于指示解复用器正在被释放的标志。

dvr_orig_fe

指向 struct dmx_frontend 的指针。

dvr_buffer

用于 DVB 输出的嵌入的 struct dvb_ringbuffer

dvr_vb2_ctx

VB2 处理程序的控制结构体。

mutex

保护此结构体的使用。

lock

保护对 dmxdev->filter->data 的访问。

int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap)

初始化一个数字电视解复用器,并注册解复用器和 DVR 设备。

参数

struct dmxdev *dmxdev

指向 struct dmxdev 的指针。

struct dvb_adapter *adap

指向 struct dvb_adapter 的指针。

void dvb_dmxdev_release(struct dmxdev *dmxdev)

释放一个数字电视解复用器并注销它。

参数

struct dmxdev *dmxdev

指向 struct dmxdev 的指针。

3.3.4. 高级数字电视解复用器接口

enum dvb_dmx_filter_type

解复用器 feed 的类型。

常量

DMX_TYPE_TS

feed 处于 TS 模式。

DMX_TYPE_SEC

feed 处于 Section 模式。

enum dvb_dmx_state

解复用器过滤器的状态机。

常量

DMX_STATE_FREE

表示过滤器已释放。

DMX_STATE_ALLOCATED

表示过滤器已分配以供使用。

DMX_STATE_READY

表示过滤器已准备好使用。

DMX_STATE_GO

表示过滤器正在运行。

struct dvb_demux_filter

描述一个 DVB 解复用器 section 过滤器。

定义:

struct dvb_demux_filter {
    struct dmx_section_filter filter;
    u8 maskandmode[DMX_MAX_FILTER_SIZE];
    u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
    bool doneq;
    struct dvb_demux_filter *next;
    struct dvb_demux_feed *feed;
    int index;
    enum dvb_dmx_state state;
    enum dvb_dmx_filter_type type;
};

成员

filter

struct dmx_section_filter 定义的 Section 过滤器。

maskandmode

逻辑 and 位掩码。

maskandnotmode

逻辑 and not 位掩码。

doneq

一个标志,指示过滤器何时准备就绪。

next

指向下一个 section 过滤器的指针。

feed

指向 struct dvb_demux_feed 的指针。

index

使用的解复用器过滤器的索引。

state

enum dvb_dmx_state 描述的过滤器的状态。

type

enum dvb_dmx_filter_type 描述的过滤器类型。

struct dvb_demux_feed

描述一个 DVB 字段

定义:

struct dvb_demux_feed {
    union {
        struct dmx_ts_feed ts;
        struct dmx_section_feed sec;
    } feed;
    union {
        dmx_ts_cb ts;
        dmx_section_cb sec;
    } cb;
    struct dvb_demux *demux;
    void *priv;
    enum dvb_dmx_filter_type type;
    enum dvb_dmx_state state;
    u16 pid;
    ktime_t timeout;
    struct dvb_demux_filter *filter;
    u32 buffer_flags;
    enum ts_filter_type ts_type;
    enum dmx_ts_pes pes_type;
    int cc;
    bool pusi_seen;
    u16 peslen;
    struct list_head list_head;
    unsigned int index;
};

成员

feed

一个联合体,用于描述数字电视 feed。根据 feed 类型,它可以是 feed.tsfeed.sec

feed.ts

一个指向 struct dmx_ts_feed 的指针。仅用于 TS feed。

feed.sec

一个 struct dmx_section_feed 指针。仅适用于节源。

cb

一个联合体,用于描述数字电视回调。根据 feed 类型,它可以是 cb.tscb.sec

cb.ts

一个 dmx_ts_cb() 回调函数指针。仅用于 TS feed。

cb.sec

一个 dmx_section_cb() 回调函数指针。仅用于 section feed。

demux

指向 struct dvb_demux 的指针。

priv

DVB 驱动程序可以选择使用的私有数据。

type

过滤器的类型,由 enum dvb_dmx_filter_type 定义。

state

过滤器的状态,由 enum dvb_dmx_state 定义。

pid

要过滤的 PID。

timeout

feed 超时。

filter

指向 struct dvb_demux_filter 的指针。

buffer_flags

通过 DVB 内存映射 API 报告不连续性用户时使用的缓冲区标志,由 enum dmx_buffer_flags 定义。

ts_type

TS 的类型,由 enum ts_filter_type 定义。

pes_type

PES 的类型,由 enum dmx_ts_pes 定义。

cc

MPEG-TS 数据包连续性计数器

pusi_seen

如果为 true,则表示检测到不连续性。它用于防止从上一节中馈送垃圾数据。

peslen

PES(打包基本流)的长度。

list_head

数字电视解复用器 feed 列表的头部。

index

每个 feed 的唯一索引。可以用作硬件 pid 过滤器索引。

struct dvb_demux

表示一个数字电视解复用器

定义:

struct dvb_demux {
    struct dmx_demux dmx;
    void *priv;
    int filternum;
    int feednum;
    int (*start_feed)(struct dvb_demux_feed *feed);
    int (*stop_feed)(struct dvb_demux_feed *feed);
    int (*write_to_decoder)(struct dvb_demux_feed *feed, const u8 *buf, size_t len);
    u32 (*check_crc32)(struct dvb_demux_feed *feed, const u8 *buf, size_t len);
    void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst, const u8 *src, size_t len);
    int users;
#define MAX_DVB_DEMUX_USERS 10;
    struct dvb_demux_filter *filter;
    struct dvb_demux_feed *feed;
    struct list_head frontend_list;
    struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
    u16 pids[DMX_PES_OTHER];
#define DMX_MAX_PID 0x2000;
    struct list_head feed_list;
    u8 tsbuf[204];
    int tsbufp;
    struct mutex mutex;
    spinlock_t lock;
    uint8_t *cnt_storage;
    ktime_t speed_last_time;
    uint32_t speed_pkts_cnt;
};

成员

dmx

嵌入的 struct dmx_demux,包含解复用器功能和回调。

priv

DVB 驱动程序可以选择使用的私有数据。

filternum

最大 DVB 过滤器数量。

feednum

最大 DVB feed 数量。

start_feed

为了启动 DVB feed 而调用的回调例程。

stop_feed

为了停止 DVB feed 而调用的回调例程。

write_to_decoder

如果馈送是 TS 并且被路由到 A/V 解码器,则在新接收到 TS 数据包时调用的回调例程。仅在 av7110-av.c 中使用。

check_crc32

用于检查 CRC 的回调例程。如果未初始化,则 dvb_demux 将使用内部的例程。

memcopy

用于内存复制接收数据的回调例程。如果未初始化,dvb_demux 将默认使用 memcpy()

users

已打开的 demux 文件描述符的数量计数器。目前,限制为 10 个用户。

filter

指向 struct dvb_demux_filter 的指针。

feed

指向 struct dvb_demux_feed 的指针。

frontend_list

struct list_head,包含 demux 使用的前端。

pesfilter

struct dvb_demux_feed 的数组,其中包含将要过滤的 PES 类型。

pids

已过滤的节目 ID 列表。

feed_list

struct list_head,包含馈送。

tsbuf

内部用于存储 TS 数据包的临时缓冲区。

tsbufp

内部使用的临时缓冲区索引。

mutex

指向 struct mutex 的指针,用于保护馈送设置逻辑。

lock

指向 spinlock_t 的指针,用于保护缓冲区处理。

cnt_storage

用于 TS/TEI 连续性检查的缓冲区。

speed_last_time

用于 TS 速度检查的 ktime_t

speed_pkts_cnt

用于 TS 速度检查的数据包计数。

int dvb_dmx_init(struct dvb_demux *demux)

初始化一个数字电视解复用结构体。

参数

struct dvb_demux *demux

要初始化的 struct dvb_demux

描述

在能够注册数字电视解复用结构体之前,驱动程序应调用此例程。在其典型用法中,在调用它之前,应在驱动程序中初始化一些字段。

一个典型的用例是

dvb->demux.dmx.capabilities =
        DMX_TS_FILTERING | DMX_SECTION_FILTERING |
        DMX_MEMORY_BASED_FILTERING;
dvb->demux.priv       = dvb;
dvb->demux.filternum  = 256;
dvb->demux.feednum    = 256;
dvb->demux.start_feed = driver_start_feed;
dvb->demux.stop_feed  = driver_stop_feed;
ret = dvb_dmx_init(&dvb->demux);
if (ret < 0)
        return ret;
void dvb_dmx_release(struct dvb_demux *demux)

释放数字电视解复用内部缓冲区。

参数

struct dvb_demux *demux

要释放的 struct dvb_demux

描述

DVB 核心在内部在 demux 中分配数据。此例程释放这些数据。请注意,结构体本身不会被释放,因为它可能嵌入在其他结构体中。

void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)

对一个包含多个 188 字节的 MPEG-TS 数据包的缓冲区使用 dvb 软件过滤器。

参数

struct dvb_demux *demux

指向 struct dvb_demux 的指针

const u8 *buf

包含要过滤的数据的缓冲区

size_t count

大小为 188 的 MPEG-TS 数据包的数量。

描述

此例程将丢弃不以 0x47 开头的 DVB 数据包。

如果 DVB 解复用器填充的 MPEG-TS 缓冲区已经对齐,则使用此例程。

注意

buf 的大小应等于 count * 188

void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)

对一个包含多个 188 字节的 MPEG-TS 数据包的缓冲区使用 dvb 软件过滤器。

参数

struct dvb_demux *demux

指向 struct dvb_demux 的指针

const u8 *buf

包含要过滤的数据的缓冲区

size_t count

大小为 188 的 MPEG-TS 数据包的数量。

描述

如果 DVB 数据包不以 0x47 开头,它将查找第一个以 0x47 开头的字节。

如果 DVB 解复用器填充的缓冲区可能不以数据包起始标记 (0x47) 开头,则使用此例程。

注意

buf 的大小应等于 count * 188

void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)

对一个包含多个 204 字节的 MPEG-TS 数据包的缓冲区使用 dvb 软件过滤器。

参数

struct dvb_demux *demux

指向 struct dvb_demux 的指针

const u8 *buf

包含要过滤的数据的缓冲区

size_t count

大小为 204 的 MPEG-TS 数据包的数量。

描述

如果 DVB 数据包不以 0x47 开头,它将查找第一个以 0x47 开头的字节。

如果 DVB 解复用器填充的缓冲区可能不以数据包起始标记 (0x47) 开头,则使用此例程。

注意

buf 的大小应等于 count * 204

void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)

使原始数据可用于用户空间,而不进行过滤

参数

struct dvb_demux *demux

指向 struct dvb_demux 的指针

const u8 *buf

包含数据的缓冲区

size_t count

要传递的数据包的数量。每个数据包的实际大小取决于 dvb_demux->feed->cb.ts 逻辑。

描述

如果驱动程序需要将原始有效负载传递到用户空间,而不经过内核解复用器,则可以使用它。这意味着支持一些不基于 MPEG-TS 的交付系统。

此函数依赖于 dvb_demux->feed->cb.ts 来实际处理缓冲区。

3.3.5. 驱动程序内部底层硬件特定驱动程序解复用接口

enum ts_filter_type

用于 dmx_ts_feed.set() 的过滤器类型位图

常量

TS_PACKET

将 TS 数据包(188 字节)发送到回调(默认)。

TS_PAYLOAD_ONLY

如果设置了 TS_PACKET,则仅将 TS 有效负载(每个数据包 <= 184 字节)发送到回调

TS_DECODER

将流发送到内置解码器(如果存在)。

TS_DEMUX

如果设置了 TS_PACKET,则将 TS 发送到 demux 设备,而不是 dvr 设备

struct dmx_ts_feed

包含 TS 馈送过滤器的结构体

定义:

struct dmx_ts_feed {
    int is_filtering;
    struct dmx_demux *parent;
    void *priv;
    int (*set)(struct dmx_ts_feed *feed,u16 pid,int type,enum dmx_ts_pes pes_type, ktime_t timeout);
    int (*start_filtering)(struct dmx_ts_feed *feed);
    int (*stop_filtering)(struct dmx_ts_feed *feed);
};

成员

is_filtering

当过滤正在进行时设置为非零

parent

指向 struct dmx_demux 的指针

priv

指向 API 客户端私有数据的指针

set

设置 TS 过滤器

start_filtering

开始 TS 过滤

stop_filtering

停止 TS 过滤

描述

TS 馈送通常映射到解复用芯片上的硬件 PID 过滤器。使用此 API,客户端可以设置过滤属性以在特定的 TS 馈送上开始/停止过滤 TS 数据包。

struct dmx_section_filter

描述段过滤器的结构体

定义:

struct dmx_section_filter {
    u8 filter_value[DMX_MAX_FILTER_SIZE];
    u8 filter_mask[DMX_MAX_FILTER_SIZE];
    u8 filter_mode[DMX_MAX_FILTER_SIZE];
    struct dmx_section_feed *parent;
    void *priv;
};

成员

filter_value

包含将由段过滤器匹配的 TS 段头最多 16 个字节(128 位)

filter_mask

包含一个 16 字节(128 位)的过滤器掩码,其中位由 filter_value 指定,该掩码将用于过滤器匹配逻辑。

filter_mode

包含一个 16 字节(128 位)的过滤器模式。

parent

指向 struct dmx_section_feed 的反向指针。

priv

指向 API 客户端私有数据的指针。

描述

filter_mask 控制将 filter_value 的哪些位与 section 头部/有效负载进行比较。在 filter_mask 中二进制值为 1 的位,相应的位会被比较。过滤器只接受所有测试位位置都等于 filter_value 的 section。

struct dmx_section_feed

包含 section feed 过滤器的结构体

定义:

struct dmx_section_feed {
    int is_filtering;
    struct dmx_demux *parent;
    void *priv;
    int check_crc;
    int (*set)(struct dmx_section_feed *feed,u16 pid, int check_crc);
    int (*allocate_filter)(struct dmx_section_feed *feed, struct dmx_section_filter **filter);
    int (*release_filter)(struct dmx_section_feed *feed, struct dmx_section_filter *filter);
    int (*start_filtering)(struct dmx_section_feed *feed);
    int (*stop_filtering)(struct dmx_section_feed *feed);
};

成员

is_filtering

当过滤正在进行时设置为非零

parent

指向 struct dmx_demux 的指针

priv

指向 API 客户端私有数据的指针

check_crc

如果非零,则检查过滤后的 section 的 CRC 值。

set

设置 section 过滤器

allocate_filter

此函数用于在解复用器上分配 section 过滤器。只有在没有在此 section feed 上进行过滤时才应调用它。如果无法分配过滤器,则函数将失败并返回 -ENOSPC。

release_filter

此函数释放先前分配的 section 过滤器的所有资源。在 此 section feed 上进行过滤时,不应调用此函数。调用此函数后,调用者不应尝试取消引用过滤器指针。

start_filtering

开始 section 过滤

stop_filtering

停止 section 过滤

描述

TS 馈送通常映射到解复用芯片上的硬件 PID 过滤器。使用此 API,客户端可以设置过滤属性以在特定的 TS 馈送上开始/停止过滤 TS 数据包。

dmx_ts_cb

Typedef: DVB 解复用器 TS 过滤器回调函数原型

语法

int dmx_ts_cb (const u8 *buffer1, size_t buffer1_length, const u8 *buffer2, size_t buffer2_length, struct dmx_ts_feed *source, u32 *buffer_flags)

参数

const u8 *buffer1

指向过滤后的 TS 数据包开始位置的指针。

size_t buffer1_length

buffer1 中 TS 数据的长度。

const u8 *buffer2

指向过滤后的 TS 数据包尾部的指针,或 NULL。

size_t buffer2_length

buffer2 中 TS 数据的长度。

struct dmx_ts_feed *source

指示哪个 TS feed 是回调的来源。

u32 *buffer_flags

存储缓冲区标志的地址。这些标志用于通过 DVB 内存映射 API 报告不连续性用户,如 enum dmx_buffer_flags 中定义。

描述

此函数回调原型由解复用器 API 的客户端提供,从解复用器代码中调用。仅当使用 dmx_demux 的 start_filtering() 函数启用 TS feed 上的过滤时,才会调用该函数。任何与过滤器设置匹配的 TS 数据包都会被复制到一个循环缓冲区中。过滤后的 TS 数据包使用此回调函数传递给客户端。预期 buffer1buffer2 回调参数指向循环缓冲区内的地址,但也可能存在其他实现。请注意,被调用方不应尝试释放 buffer1buffer2 参数指向的内存。

调用此函数时,buffer1 参数通常指向循环缓冲区中第一个未传递的 TS 数据包的起始位置。buffer2 缓冲区参数通常为 NULL,除非接收到的 TS 数据包已跨越循环缓冲区的最后一个地址并“包裹”到缓冲区的开头。在后一种情况下,buffer1 参数将包含循环缓冲区内的地址,而 buffer2 参数将包含循环缓冲区的第一个地址。此函数传递的字节数(即 buffer1_length + buffer2_length)通常等于 set() 函数中给出的 callback_length 参数的值,但有一个例外:如果在接收 callback_length 字节的 TS 数据之前发生超时,则任何未传递的数据包都会立即通过调用此函数传递给客户端。超时持续时间由 TS Feed API 中的 set() 函数控制。

如果接收到的 TS 数据包出现 TS 级别前向纠错 (FEC) 无法修复的错误,则应设置 TS 数据包头部的 Transport_error_indicator 标志。TS 数据包不应被丢弃,因为该错误可能由更高层协议纠正。如果被调用方在处理回调时速度较慢,则循环缓冲区最终可能会填满。如果发生这种情况,解复用器驱动程序应丢弃缓冲区已满时收到的任何 TS 数据包,并返回 -EOVERFLOW。

可以使用 dmx_ts_feed.**set** 函数选择返回到回调的数据类型。type 参数决定应返回原始 TS 数据包 (TS_PACKET) 还是仅返回有效负载 (TS_PACKET|TS_PAYLOAD_ONLY)。如果另外设置了 TS_DECODER 位,则流也将被发送到硬件 MPEG 解码器。

  • 成功时为 0;

  • 缓冲区溢出时为 -EOVERFLOW。

返回值

dmx_section_cb

Typedef: DVB 解复用器 TS 过滤器回调函数原型

语法

int dmx_section_cb (const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, struct dmx_section_filter *source, u32 *buffer_flags)

参数

const u8 *buffer1

指向过滤后的 section 开始位置的指针,例如在解复用器驱动程序的循环缓冲区内。

size_t buffer1_len

buffer1 中过滤后的 section 数据的长度,包括头部和 CRC。

const u8 *buffer2

指向过滤后的 section 数据尾部的指针,或 NULL。用于处理循环缓冲区的回绕。

size_t buffer2_len

buffer2 中过滤后的 section 数据的长度,包括头部和 CRC。

struct dmx_section_filter *source

指示哪个 section feed 是回调的来源。

u32 *buffer_flags

存储缓冲区标志的地址。这些标志用于通过 DVB 内存映射 API 报告不连续性用户,如 enum dmx_buffer_flags 中定义。

描述

此函数回调原型由解复用器 API 的客户端提供,从解复用器代码中调用。仅当使用函数 dmx_ts_feed.**start_filtering** 启用 section 过滤时,才会调用该函数。当解复用器驱动程序接收到与至少一个 section 过滤器匹配的完整 section 时,会通过此回调函数通知客户端。通常,为每个接收到的 section 调用此函数;但是,也可以使用一个回调传递多个 section,例如,当系统负载较高时。如果在接收 section 时发生错误,则应调用此函数,并在 success 字段中设置相应的错误类型,无论是否有数据要传递。Section Feed 实现应为接收到的 section 维护一个循环缓冲区。但是,如果 Section Feed API 是作为 TS Feed API 的客户端实现的,则不需要这样做,因为 TS Feed 实现会缓冲接收到的数据。可以使用 Section Feed API 中的 dmx_ts_feed.**set** 函数配置循环缓冲区的大小。如果在接收新 section 时循环缓冲区中没有空间,则必须丢弃该 section。如果发生这种情况,则下次回调时 success 参数的值应为 DMX_OVERRUN_ERROR。

enum dmx_frontend_source

用于标识前端的类型

常量

DMX_MEMORY_FE

解复用器的来源是内存。这意味着要过滤的 MPEG-TS 来自用户空间,通过 write() 系统调用。

DMX_FRONTEND_0

解复用器的来源是连接到解复用器的前端。

struct dmx_frontend

列出与解复用器关联的前端的结构体

定义:

struct dmx_frontend {
    struct list_head connectivity_list;
    enum dmx_frontend_source source;
};

成员

connectivity_list

可以连接到特定解复用器的前端列表;

source

前端的类型。

描述

FIXME:此结构体很可能很快会被一些

基于媒体控制器的逻辑取代。

enum dmx_demux_caps

MPEG-2 TS 解复用器功能位图

常量

DMX_TS_FILTERING

如果支持 TS 过滤,则设置此项;

DMX_SECTION_FILTERING

如果支持 section 过滤,则设置此项;

DMX_MEMORY_BASED_FILTERING

如果 write() 可用,则设置此项。

描述

这些标志在 dmx_demux.capabilities 字段中进行“或”运算。

DMX_FE_ENTRY

DMX_FE_ENTRY (列表)

将已注册前端列表中的元素从通用类型 struct list_head 转换为类型 * struct dmx_frontend

参数

列表

struct dmx_frontend 的列表

struct dmx_demux

包含解复用器功能和回调的结构体。

定义:

struct dmx_demux {
    enum dmx_demux_caps capabilities;
    struct dmx_frontend *frontend;
    void *priv;
    int (*open)(struct dmx_demux *demux);
    int (*close)(struct dmx_demux *demux);
    int (*write)(struct dmx_demux *demux, const char __user *buf, size_t count);
    int (*allocate_ts_feed)(struct dmx_demux *demux,struct dmx_ts_feed **feed, dmx_ts_cb callback);
    int (*release_ts_feed)(struct dmx_demux *demux, struct dmx_ts_feed *feed);
    int (*allocate_section_feed)(struct dmx_demux *demux,struct dmx_section_feed **feed, dmx_section_cb callback);
    int (*release_section_feed)(struct dmx_demux *demux, struct dmx_section_feed *feed);
    int (*add_frontend)(struct dmx_demux *demux, struct dmx_frontend *frontend);
    int (*remove_frontend)(struct dmx_demux *demux, struct dmx_frontend *frontend);
    struct list_head *(*get_frontends)(struct dmx_demux *demux);
    int (*connect_frontend)(struct dmx_demux *demux, struct dmx_frontend *frontend);
    int (*disconnect_frontend)(struct dmx_demux *demux);
    int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids);
};

成员

capabilities

功能标志的位字段。

前端

连接到解复用器的前端

priv

指向 API 客户端私有数据的指针

打开

此函数为调用者预留解复用器,并在必要时初始化解复用器。当不再需要解复用器时,应调用 close 函数。允许多个客户端同时访问解复用器。因此,函数实现应在调用 open 时增加解复用器的使用计数,并在调用 close 时减少它。 demux 函数参数包含指向解复用器 API 和实例数据的指针。它返回:成功时返回 0;如果达到最大使用计数,则返回 -EUSERS;参数错误则返回 -EINVAL。

关闭

此函数为调用者预留解复用器,并在必要时初始化解复用器。当不再需要解复用器时,应调用 close 函数。允许多个客户端同时访问解复用器。因此,函数实现应在调用 open 时增加解复用器的使用计数,并在调用 close 时减少它。 demux 函数参数包含指向解复用器 API 和实例数据的指针。它返回:成功时返回 0;如果解复用器未使用(例如,没有用户),则返回 -ENODEV;参数错误则返回 -EINVAL。

写入

此函数为解复用器驱动程序提供一个包含 TS 数据包的内存缓冲区。解复用器驱动程序软件将从内存读取数据包,而不是从 DVB 前端接收 TS 数据包。任何具有活动 TS、PES 或 Section 过滤器的此解复用器的客户端都将通过解复用器回调 API(参见 0)接收过滤后的数据。当缓冲区中的所有数据都被解复用器消耗完毕后,该函数返回。解复用器硬件通常无法从内存读取 TS。如果是这种情况,基于内存的过滤必须完全在软件中实现。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 buf 函数参数包含指向内核空间内存中 TS 数据的指针。 count 函数参数包含 TS 数据的长度。它返回:成功时返回 0;如果互斥锁被中断,则返回 -ERESTARTSYS;如果有信号处理挂起,则返回 -EINTR;如果解复用器被移除,则返回 -ENODEV;参数错误则返回 -EINVAL。

allocate_ts_feed

分配一个新的 TS feed,用于过滤携带特定 PID 的 TS 数据包。 TS feed 通常对应于解复用器芯片上的硬件 PID 过滤器。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 feed 函数参数包含指向 TS feed API 和实例数据的指针。 callback 函数参数包含指向用于传递接收到的 TS 数据包的回调函数的指针。它返回:成功时返回 0;如果互斥锁被中断,则返回 -ERESTARTSYS;如果没有更多可用的 TS feed,则返回 -EBUSY;参数错误则返回 -EINVAL。

release_ts_feed

释放使用 allocate_ts_feed 分配的资源。在调用此函数之前,应停止在 TS feed 上进行的任何过滤操作。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 feed 函数参数包含指向 TS feed API 和实例数据的指针。它返回:成功时返回 0;参数错误则返回 -EINVAL。

allocate_section_feed

分配一个新的 section feed,即用于过滤和接收 section 的解复用器资源。在具有硬件支持 section 过滤的平台上,section feed 直接映射到解复用器硬件。在其他平台上,TS 数据包首先在硬件中进行 PID 过滤,然后在软件中模拟硬件 section 过滤器。调用者获取 dmx_section_feed_t 类型的 API 指针作为输出参数。使用此 API,调用者可以设置过滤参数并开始接收 section。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 feed 函数参数包含指向 TS feed API 和实例数据的指针。 callback 函数参数包含指向用于传递接收到的 TS 数据包的回调函数的指针。它返回:成功时返回 0;如果没有更多可用的 TS feed,则返回 -EBUSY;参数错误则返回 -EINVAL。

release_section_feed

释放使用 allocate_section_feed 分配的资源,包括已分配的过滤器。在调用此函数之前,应停止在 section feed 上进行的任何过滤操作。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 feed 函数参数包含指向 TS feed API 和实例数据的指针。它返回:成功时返回 0;参数错误则返回 -EINVAL。

add_frontend

注册解复用器和前端之间的连接,即表明解复用器可以通过调用 connect_frontend 连接来使用给定的前端作为 TS 源。此函数的客户端必须为前端结构体分配动态或静态内存,并在调用此函数之前初始化其字段。此函数通常在驱动程序初始化期间调用。调用者不得在成功调用 remove_frontend 之前释放前端结构体的内存。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 frontend 函数参数包含指向前端实例数据的指针。它返回:成功时返回 0;参数错误则返回 -EINVAL。

remove_frontend

表明通过调用 add_frontend 注册的给定前端不再可以通过此解复用器连接作为 TS 源。当从系统中移除前端驱动程序或解复用器驱动程序时,应调用此函数。如果前端正在使用中,则该函数将失败并返回 -EBUSY。成功调用此函数后,如果前端结构体是在 add_frontend 操作之前动态分配的,则调用者可以释放其内存。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 frontend 函数参数包含指向前端实例数据的指针。它返回:成功时返回 0;如果未找到前端,则返回 -ENODEV;参数错误则返回 -EINVAL。

get_frontends

提供已为此解复用器注册的前端的 API。通过此调用获得的任何前端都可以用作 connect_frontend 的参数。include 文件 demux.h 包含宏 DMX_FE_ENTRY(),用于将通用类型 struct list_head * 的元素转换为类型 struct dmx_frontend *。调用者不得释放通过此函数调用获得的任何元素的内存。 demux 函数参数包含指向解复用器 API 和实例数据的指针。它返回指向前端接口列表的 struct list_head 指针,如果列表为空,则返回 NULL。

connect_frontend

将前端的 TS 输出连接到解复用器的输入。解复用器只能连接到通过 add_frontend 函数注册到该解复用器的前端。根据硬件平台的功能,可能允许也可能不允许将多个解复用器连接到同一前端。不使用时,应通过调用 disconnect_frontend 释放前端。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 frontend 函数参数包含指向前端实例数据的指针。它返回:成功时返回 0;参数错误则返回 -EINVAL。

disconnect_frontend

断开解复用器和先前通过 connect_frontend 调用连接的前端。 demux 函数参数包含指向解复用器 API 和实例数据的指针。它返回:成功时返回 0;参数错误则返回 -EINVAL。

get_pes_pids

获取 DMX_PES_AUDIO0、DMX_PES_VIDEO0、DMX_PES_TELETEXT0、DMX_PES_SUBTITLE0 和 DMX_PES_PCR0 的 PID。 demux 函数参数包含指向解复用器 API 和实例数据的指针。 pids 函数参数包含一个包含五个 u16 元素的数组,其中将存储 PID。它返回:成功时返回 0;参数错误则返回 -EINVAL。