Linux IVTV 驱动完全指南:CX23415/CX23416 MPEG 编解码卡的 V4L2 设备与固件详解
Linux IVTV 驱动完全指南CX23415/CX23416 MPEG 编解码卡的 V4L2 设备与固件详解【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读本篇文章基于 Linux 内核仓库GitHub_Trending/li/linux中的 Documentation/admin-guide/media/ivtv.rst 官方文档系统讲解 ivtv 驱动——一个面向 Conexant原 iCompressionCX23415/CX23416 MPEG 编解码芯片的视频采集卡 V4L2 设备驱动。读者将掌握 ivtv 驱动支持的硬件能力、完整的 V4L2 设备节点体系编码/解码/原始音视频/VBI/收音机、固件加载要求以及通过内核模块参数配置多卡设备编号等实战技巧并结合 drivers/media/pci/ivtv/ 目录下的内核源码理解其底层实现。ivtv 驱动是什么ivtv 是 Linux 内核中一个基于 V4L2Video for Linux 2框架的设备驱动服务于基于Conexant CX23415/CX23416以及 iCompression iTVC15MPEG 编解码芯片的视频采集卡CX23415同时支持 MPEG 硬件编码与解码CX23416仅支持 MPEG 硬件编码。目前内核驱动中唯一具备完整解码能力MPEG2 硬件解码播放的典型卡片是Hauppauge PVR-350CX23415 方案。ivtv 驱动由 Hans Verkuilhverkuilkernel.org维护其设计初衷是为这类卡片提供一份洁净室clean room实现的 Linux 开源驱动。从驱动源码 drivers/media/pci/ivtv/ivtv-driver.c 可以看到其 PCI 设备匹配表static const struct pci_device_id ivtv_pci_tbl[] { { PCI_VDEVICE(ICOMP, PCI_DEVICE_ID_IVTV15) }, { PCI_VDEVICE(ICOMP, PCI_DEVICE_ID_IVTV16) }, { } };驱动通过 PCI vendor/device IDICOMP厂商PCI_DEVICE_ID_IVTV15/16芯片型号识别 iTVC15 与 CX23416 两类器件对应完整的板卡列表可参考 Documentation/admin-guide/media/ivtv-cardlist.rst。核心特性ivtv 驱动提供的主要能力包括硬件 MPEG2 采集通过电视调谐器tuner或 S-Video/Composite 复合视频输入、音频线路输入line-in硬件实时压缩广播视频与声音为 MPEG2 流FM 收音机硬件采集在硬件支持的情况下可对 FM 广播进行 MPEG2 采集画面为黑帧电视制式支持NTSC、PAL、SECAM并支持立体声伴音支持SAPSecondary Audio Program第二音频节目与双语广播bilingual transmissionsVBI垂直消隐期支持原始 VBIraw VBI支持闭路字幕closed captions与图文电视teletext采集切片 VBIsliced VBI支持闭路字幕与图文电视并能将其插入采集到的 MPEG 流中由ivtv_vbi_setup等函数在 drivers/media/pci/ivtv/ivtv-streams.c 中完成编码参数配置原始 YUV 与 PCM 输入支持未压缩的 YUV 视频与 PCM 音频采集。CX23415PVR-350专属特性硬件 MPEG2 解码播放向解码设备写入 MPEG2 流即可在视频输出口显示OSDOn Screen Display屏幕菜单式显示支持图形叠加到视频信号之上Framebuffer 帧缓冲允许 X 应用程序直接显示在视频设备上对应ivtvfb.c中的 framebuffer 驱动原始 YUV 输出。驱动固件要求重要前置条件ivtv 驱动依赖编码器固件才能工作。官方文档明确要求使用编码器固件 v2.06.039文件大小 376836 字节。这一数值与内核源码中的定义完全一致drivers/media/pci/ivtv/ivtv-firmware.c/* Encoder/decoder firmware sizes */ #define IVTV_FW_ENC_SIZE (376836) #define IVTV_FW_DEC_SIZE (256*1024)固件文件需放入系统的 hotplug 固件目录如/lib/firmware。驱动通过request_firmware()加载固件见load_fw_direct()drivers/media/pci/ivtv/ivtv-firmware.c并且会校验文件大小——若加载的文件大小与预期不符历史上有 udev 竞态导致加载错误文件的问题驱动会重试最多 3 次若最终仍失败则报错Unable to open firmware ... (must be 376836 bytes) Did you put the firmware in the hotplug firmware directory?解码固件大小固定为 256 KB另有一个 MPEG 初始化文件v4l-cx2341x-init.mpg152 KB用于解码器初始化。使用限制该驱动是面向 MPEG 输入流的专用驱动普通电视应用如直接抓取裸帧的 xawtv 类程序无法正常工作需要能处理 MPEG 输入的应用例如mplayer、xine、MythTV等遇到问题可先查阅文档给出的 Ubuntu 社区 IVTV 安装排障页面见原文档与 Documentation/admin-guide/media/ 下的相关文档。设备节点体系ivtv 驱动最多支持12 块板卡同时工作。每块卡按功能注册多个 V4L2 设备节点其设备号基址如下来自 Documentation/admin-guide/media/ivtv.rstcrw-rw---- 1 root video 81, 0 Jun 19 22:22 /dev/video0 crw-rw---- 1 root video 81, 16 Jun 19 22:22 /dev/video16 crw-rw---- 1 root video 81, 24 Jun 19 22:22 /dev/video24 crw-rw---- 1 root video 81, 32 Jun 19 22:22 /dev/video32 crw-rw---- 1 root video 81, 48 Jun 19 22:22 /dev/video48 crw-rw---- 1 root video 81, 64 Jun 19 22:22 /dev/radio0 crw-rw---- 1 root video 81, 224 Jun 19 22:22 /dev/vbi0 crw-rw---- 1 root video 81, 228 Jun 19 22:22 /dev/vbi8 crw-rw---- 1 root video 81, 232 Jun 19 22:22 /dev/vbi16这些设备号偏移在源码中有精确的宏定义drivers/media/pci/ivtv/ivtv-streams.c#define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ #define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ #define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ #define IVTV_V4L2_DEC_YUV_OFFSET 48 /* offset from 0 to register decoder yuv v4l2 minors on */ #define IVTV_V4L2_DEC_VBI_OFFSET 8 /* offset from 0 to register decoder vbi input v4l2 minors on */ #define IVTV_V4L2_DEC_VOUT_OFFSET 16 /* offset from 0 to register vbi output v4l2 minors on */基础设备编号规则每增加一块卡设备号整体 1/dev/video0→ 第一块卡的编码采集设备/dev/video1→ 第二块卡的编码采集设备/dev/video2→ 第三块卡的编码采集设备简单规则卡编号 基础设备号。例如第一块卡若缺少解码器没有 video16第二块卡仍然从 video17 开始编号。如果系统先检测到了其他采集卡如 WinTV PCI则必须通过模块参数ivtv_first_minor告诉 ivtv 从 1或 2……开始计数避免设备号混乱。源码中的注册逻辑验证了这一点drivers/media/pci/ivtv/ivtv-streams.cint num_offset ivtv_stream_info[type].num_offset; int num itv-instance ivtv_first_minor num_offset;各设备节点详解/dev/video0 —— 编码采集设备MPEG 流只读设备从中读取可得到MPEG1/2 Program Stream经典用法cat /dev/video0 my.mpg (需要按 Ctrl-C 退出)对应源码中IVTV_ENC_STREAM_TYPE_MPG流类型DMA 方向为DMA_FROM_DEVICEV4L2 能力为V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITEdrivers/media/pci/ivtv/ivtv-streams.c。/dev/video16 —— 解码输出设备MPEG 播放只写设备仅当存在 MPEG 解码器CX23415时出现向该设备写入 MPEG2 流后视频出现在所选的视频输出接口音频输出到 line-out/audio out典型用法cat my.mpg /dev/video16/dev/video24 —— 原始音频采集设备PCM只读设备读取得到当前选中调谐器或音频 line-in 的原始 PCM 立体声数据有符号 16 位小端、48000 Hz、立体声仅采集音频注意没有对应的原始音频输出设备解码器固件不支持官方文档指出该设备未来应由 ALSA 设备取代驱动中同时提供了 ALSA 接口模块见 drivers/media/pci/ivtv/ivtv-alsa-pcm.c。/dev/video32 —— 原始视频采集设备YUV只读设备读取得到当前视频输入的原始 YUV 数据格式为16×16 线性分块的 NV12即V4L2_PIX_FMT_NV12_16L16注意YUV 与 PCM 流之间不同步因此用途受限。/dev/video48 —— 原始视频显示设备YUV 输出只写设备仅当存在 MPEG 解码器CX23415时出现将 YUV 流写入卡的解码器用于显示。/dev/radio0 —— 收音机调谐设备不可读也不可写用于启用收音机调谐器并设置频率调谐后用/dev/video24读取原始 PCM 流或用/dev/video0获取带黑画面的 MPEG2 流是否出现取决于卡片是否带收音机调谐器。源码中该流类型IVTV_ENC_STREAM_TYPE_RAD的 V4L2 能力为V4L2_CAP_RADIO | V4L2_CAP_TUNERDMA 方式为DMA_NONEdrivers/media/pci/ivtv/ivtv-streams.c其存在性由 ivtv-streams.c 中的V4L2_CAP_RADIO能力检查决定。/dev/vbi0 —— VBI 采集设备只读设备采集垂直消隐期Vertical Blank Interval期间发送的原始或切片视频数据这些数据用于编码**图文电视Teletext、闭路字幕CC、VPS、宽屏信令WSS、电子节目指南EPG**等服务。/dev/vbi8 —— 处理后的 VBI 反馈设备只读设备仅当存在 MPEG 解码器CX23415时出现嵌入在 MPEG 流中的切片 VBI 数据会在此设备上复现——即在/dev/video16播放录像的同时可从/dev/vbi8读取内嵌的 VBI 数据。/dev/vbi16 —— VBI 显示设备只写设备仅当存在 MPEG 解码器CX23415时出现用于将切片 VBI 数据发送到 video-out 接口。无视频输出能力卡片的设备差异不带视频输出能力的卡片即非 PVR-350 类缺少vbi8、vbi16、video16、video48设备也不支持/dev/fbxframebuffer 设备OSD 帧缓冲。内核模块参数模块加载配置ivtv 通过内核模块参数提供板卡配置能力全部定义于 drivers/media/pci/ivtv/ivtv-driver.c。以下为核心参数参数类型说明ivtv_first_minorint第一块卡分配的设备节点号。若系统已有其他 V4L2 卡如 WinTV PCI被先检测到用于错开设备号。取值范围 0 ~IVTV_MAX_CARDS-1ivtv-driver.ccardtypeint 数组卡片类型覆盖仅在自动检测失败时使用。如1WinTV PVR 250、2WinTV PVR 350、3WinTV PVR-150/PVR-500、4AVerMedia M179等完整列表见 ivtv-driver.ctunerint 数组调谐器类型选择取值参考 tuner.h默认 -1自动radioint 数组启用/禁用收音机仅自动检测失败时使用0 禁用1 启用i2c_clock_periodint 数组I2C 时钟周期覆盖默认 -1pal/secam/ntscstring电视制式字符串覆盖默认分别为---、--、-tunertypeint调谐器类型强制指定newi2cint使用新的 I2C 实现新旧 I2C 切换debug/fw_debugint驱动调试开关fw_debug需CONFIG_VIDEO_ADV_DEBUGivtv_pci_latencyintPCI 延迟参数ivtv_yuv_mode/ivtv_yuv_thresholdintYUV 处理模式与阈值enc_mpg_buffers/enc_yuv_buffers/enc_vbi_buffers/enc_pcm_buffersint编码各流的 DMA 缓冲区数量dec_mpg_buffers/dec_yuv_buffers/dec_vbi_buffersint解码各流的 DMA 缓冲区数量典型加载示例例如已有 1 块其他采集卡PVR-350 从 video1 开始编号modprobe ivtv ivtv_first_minor1多卡场景下各数组参数按卡顺序一一对应modprobe ivtv cardtype2,1 tuner0,-1 radio1,0说明模块参数可通过modprobe命令行、/etc/modprobe.d/*.conf或运行时sysfs接口设置具体取决于发行版的内核模块管理方式。从源码理解驱动架构ivtv 驱动的核心代码位于 drivers/media/pci/ivtv/主要模块职责如下ivtv-driver.cPCI 探测、模块参数定义、实例管理最多 12 块卡IVTV_MAX_CARDSivtv-streams.c各 V4L2 流的注册、设备号计算、DMA/缓冲管理ivtv-firmware.c编码器/解码器固件加载与校验、版本检查ivtv-mailbox.c与 CX2341x 固件通信的 mailbox 协议ivtv-irq.c中断处理驱动 DMA 完成事件ivtv-vbi.c原始/切片 VBI 处理与 MPEG 流内嵌ivtv-yuv.c原始 YUV 采集NV12 16L16 格式与 YUV 显示ivtvfb.cPVR-350 的 framebuffer/dev/fbx与 OSD 支持ivtv-alsa-main.c / ivtv-alsa-pcm.cALSA 音频接口ivtv-cards.c板卡描述与 GPIO 控制。各流类型ivtv_stream_info[]完整映射了文档描述的设备能力ivtv-streams.c流类型名称V4L2 类型偏移DMAMPG编码encoder MPGVIDEO0FROM_DEVICEYUV编码encoder YUVVIDEO32FROM_DEVICEVBI编码encoder VBIVBI0FROM_DEVICEPCM编码encoder PCMVIDEO24FROM_DEVICERADencoder radioRADIO0NONEMPG解码decoder MPGVIDEO16TO_DEVICEVBI解码decoder VBIVBI8NONEVOUTdecoder VOUTVBI16NONEYUV解码decoder YUVVIDEO48TO_DEVICE可以看到video0/video16/video24/video32/video48的设备号正是各流类型num_offset的体现而 radio 与 vbi 设备则按 VFL 类型VFL_TYPE_RADIO/VFL_TYPE_VBI注册到对应主设备号空间81,64 与 81,224 系列与文档中给出的ls -l输出完全对应。常见问题与排查要点固件未安装或版本不符驱动会因文件大小校验失败而报错退出。请确认编码器固件为 v2.06.039、大小 376836 字节并放置于 hotplug 固件目录设备号错乱系统中有其他采集卡被先检测到时务必使用ivtv_first_minor参数错开编号遵循卡编号 基础设备号的简单规则普通电视应用无法工作请改用支持 MPEG 输入的应用mplayer、xine、MythTV缺少部分设备节点非 PVR-350 卡片没有vbi8/vbi16/video16/video48与 framebuffer这是正常的硬件能力差异收音机设备不存在说明卡片未配备收音机调谐器。总结ivtv 驱动是 Linux 内核中针对 CX23415/CX23416 MPEG 编解码卡的成熟 V4L2 驱动其设备节点设计围绕编码采集 → MPEG 流 → 解码播放的完整链路展开并通过固件校验、模块参数、多卡编号规则等机制保证可操作性。结合 Documentation/admin-guide/media/ivtv.rst 与 drivers/media/pci/ivtv/ 源码开发者可以清晰地理解从硬件寄存器、固件 mailbox 通信到用户态/dev/video*设备节点的完整软件栈为排障、二次开发或移植提供扎实依据。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考