资讯动态

HDMI Data Island Packets深度解析:包结构、TERC4编码与调试实战

发布时间:2026/9/16 8:15:43 来源:尧图企业网站定制
我在上一篇讲TMDS链路的时候其实留了个关键问题没展开HDMI毕竟不是一根只管传画面的线音频、HDR、控制命令都从同一根线里跑它们到底是怎么和视频数据共用一条链路的答案就是DataIsland Packets。它们的载体是行/场消隐区的Data Island Period表面看是“插空传”实际上从包结构到编码都是自成体系的协议。这篇就专门把Data Island Packets的设计动机、字节格式、包类型和排查经验讲透适合正在做HDMI发送/接收、写显示驱动、或者用FPGA自组HDMI链路的同学。读完你至少能回答三类问题一个合法的包长什么样、接收端怎么定位包边界、电视为什么有时候“莫名其妙”不认某个功能。1. 从TMDS的三种工作周期看Data Island的定位1.1 一条HDMI链路上并存的三种数据模式一条TMDS链路有三个数据通道加一个时钟通道每个像素时钟周期每个通道都能传10bit编码数据。但同一条链路上并不是每时每刻都在传像素。DEData Enable信号拉高时是视频数据期三个通道按8bit/通道/时钟正常传像素数据DE拉低之后链路进入消隐区听起来通道应该闲下来了实际上HSync、VSync和一堆控制信号还要在控制周期里传。当源端想传音频样本、元数据或者控制指令时链路会进入第三种状态——Data Island Period。很多做显示驱动的新手会把消隐区当成“空白区”只在里面塞同步信号导致音频和HDR功能怎么调都不出效果根源就是没有意识到Data Island是单独设计的一套工作模式。这三种模式对应的编码深度完全不同视频周期是每通道每时钟8bit控制周期是2bit数据岛周期是4bit。为什么视频期能传一个字节、数据岛期却只传半字节这背后是效率、可靠性和边界识别的三方权衡下一节细讲。1.2 为什么数据岛用4bit编码TERC4与误码可见性Data Island Period里的编码叫TERC4全称TMDS Error Reduction Coding输入4bit、输出10bit。如果直接沿用视频期的8b/10b思路链路的“身份感”会变得模糊——接收端只靠DE区分模式一旦DE电平抖动或者时序裕量不足视频包和数据包就可能互相串扰。如果沿用控制周期的2bit每个时钟又凑不够一个字节传一个包要白白多耗一倍时间效率太低。4bit是一个折中方案一个时钟周期里两个数据通道各传4bit拼在一起刚好是1字节包数据可以一个字节一个字节地往接收端送。而且TERC4的码字表是HDMI规范固定好的16种输入各对应一个10bit输出码这些码字彼此之间留了足够的汉明距离。接收端如果收到码表外的码字就能立刻判断链路出了误码协议分析仪上对应位置会直接标TERC4 error。这种用冗余度换错误可见性的思想和8b/10b里的K码检查很像。很多显卡输出4K60信号在长线上偶尔闪屏抓包看到的就是blanking区里一串TERC4 error而不是视频数据区的错误。所以不要觉得数据岛传的只是“辅助数据”它的信号完整性要求和视频数据完全同级。1.3 Guard Band与Packet Boundary包边界不是靠时间算出来的有了编码还不够接收端还得知道一个包从哪里开始、在哪里结束。HDMI协议在这里设计了两样东西Guard Band保护波段和Packet Boundary包边界字节。每次Data Island Period开始前链路上会先出现一段固定的TERC4码字叫前导Guard Band相当于快递包裹外层的塑封皮。它告诉接收端后面跟着的是包数据不是视频也不是同步信号。包结束位置还有尾随Guard Band标明这段Data Island到此为止。包和包之间则靠Packet Boundary字节衔接每个包发完链路上会插入一个边界字节里面同时编码了当前包的结束状态和后续包的部分信息。这套机制让接收端完全不需要依赖消隐区的具体长度来推算包位置。消隐长度会随分辨率、刷新率和像素时钟变化如果靠时间戳对齐换一个timing就全乱套了。有了Guard Band和Boundary接收端只要在TERC4码流里识别出固定码字就能精确切出每一个包。做FPGA接收端的时候这个识别器就是整个解析逻辑的起点识别错了后面全错。2. Packet的字节结构Header、Body、Boundary逐个拆2.1 4字节的Packet Header类型、计数与保留位每一个Data Island Packet在逻辑上固定由36字节组成4字节的Packet Header加32字节的Packet BodyBody再拆成4个8字节的子包Subpacket。Header的第一个字节叫Packet Type是整个包的“身份证”决定它是什么类型的包。第二个字节通常承载和载荷相关的计数信息有的地方也叫Packet Byte Count用来表示后续某部分子包的有效性。最后两个字节规范上定义为保留位发送端应该填0接收端应该忽略不要依赖它们判断任何业务状态。我在写Linux DRM驱动时见过不少第三方IP核没有把保留位清零直接把寄存器里的旧值发出去。接收端芯片通常不理会但部分严格的HDMI分析仪会把它标成non-compliant。如果你的设备要过认证这种小地方反而是最容易被打回的项别忽略。Packet Type的取值范围是有规律的0x00到0x0B是规范里定义好的固定功能包0x80是InfoFrame家族的总入口。接收端先读Type再决定把后面的Body交给哪个解析模块整个过程有点像网络协议栈里先看端口号、再分发给对应应用。2.2 32字节的Packet Body与四个SubpacketPacket Body的32字节会固定拆成4个8字节的Subpacket这个设计初看有点多余实际是为了让接收端解析逻辑做流水线处理。每收8字节就能先把一部分数据落地不需要等整个Body到齐才动手。不同包对Subpacket的使用方式差异很大。General Control Packet往往只用Subpacket0里的控制位Audio Sample Packet四个子包会装满多声道样本HDR Metadata Packet则在前几个字节放EOTF等核心字段剩余空间填充静态元数据。做分析仪解析的时候四个Subpacket天然对应四个解析状态状态机写起来很规整。这里补充一点Subpacket并不是“必须全用”也不是“必须全不用”。一个包是否使用全部子包要看Packet Type对应的规范定义。有些厂商扩展包只用了Subpacket0剩下的保留字节如果乱填容易让对端误判。稳妥做法是不用到的子包按0填充。2.3 一张表认识所有Packet Type把目前TMDS模式下常见的Data Island Packet Type列成一张表方便你对着分析仪上的数据比对Packet Type包名称用途0x00Null Packet无有效载荷的填充包维持链路同步0x01Audio Clock Regeneration Packet传输CTS/N参数接收端用来恢复音频参考时钟0x02Audio Sample Packet承载PCM或压缩音频样本音频主体0x03General Control Packet控制信号比如AVMUTE、Clear_AVMUTE0x04ACP Packet音频内容保护信息0x05 / 0x06ISRC1 / ISRC2 Packet音源编码识别码0x07One Bit Audio Sample Packet传输DSD单比特音频0x08DST Audio Packet传输DST压缩后的DSD音频0x09High Bitrate Audio Stream PacketDTS-HD MA、Dolby TrueHD等高比特率音频容器0x0AGamut Metadata Packet传输色域辅助元数据0x0BHDR Metadata Packet传输HDR静态元数据包括EOTF、ST 2086等0x80InfoFrame Packet承载AVI、Audio、SPD、VSIF等结构化信息帧如果在HDMI协议分析仪上抓到0x81、0x82这些非规范Type不要急着断定源端发错。特别是HDMI 2.1时代厂商在FRL模式下叠加了不少扩展包先查对端设备支持的HDMI版本再对照规范判断。3. InfoFrame家族显卡给显示器递的“便条”3.1 AVI InfoFrame显示器靠它识画面InfoFrame是这套协议里信息密度最高的一类包它不是一个包而是一族。平时打交道最多的是AVI InfoFrame全称Auxiliary Video InformationPacket Type0x80内部InfoFrame Type0x02。AVI InfoFrame会把当前画面是RGB还是YCbCr、色深是8bit还是10bit、像素是逐行还是隔行、VIC号是多少、量化范围是limited还是full全部交代清楚。显示器拿到这些字段后才能决定切换哪套解码路径和显示模式。VIC字段尤其重要它对应CEA-861标准里定义的视频时序编号电视靠它识别当前是1080p60、4K60还是别的格式。如果AVI里的VIC和实际视频时序对不上有些电视会直接按VIC重新锁相结果就是画面糊、被拉伸或者直接黑屏。我见过一台投影仪输入4K30信号时偶尔显示成“HDMI 1.4兼容模式”后来定位到源端AVI里的VIC写成了161080p60的编号画面只显示中间一块四周全是黑的。调这种问题第一件事就是看AVI包里的VIC、Y、BPC三个字段。3.2 SPD InfoFrame与VSIF设备识别和功能扩展的中转站SPD InfoFrame全称Source Product Descriptor携带的是源设备名称、产品类型、厂商信息。很多电视的“输入源”菜单能显示“Blu-ray Player”或者“Game Console”靠的就是它。SPD包的内容不直接影响画面和声音但做产品化的时候一定要发否则用户看到的信息就是一堆未知设备。更有意思的是VSIFVendor Specific InfoFrame。它允许厂商通过IEEE OUI字段定义自己的扩展内容相当于协议里留的一个万能口袋。HDMI 2.1的ALLM自动低延迟模式、VRR可变刷新率、FRL相关信息以及Dolby Vision、HDR10的动态元数据几乎都塞在VSIF里。看分析仪抓包时VSIF的Length经常变化这是正常的它承载的内容本来就可长可短。这里有个比较容易踩的坑有些电视判断“是不是游戏信号”只看VSIF里的ALLM标志不看别的字段。如果你的设备输出游戏画面但不发ALLM标志电视就不会自动切低延迟模式体感延迟会差不少。反过来如果误发了ALLM标志但设备不支持VRR电视可能会在HDMI论坛认证时判定违例。3.3 InfoFrame的CheckSum一个字节引发的连锁问题InfoFrame自带一字节的Checksum算法非常简单把所有字节Type、Version、Length、Body和Checksum本身按8位累加再对256取模结果必须等于0。写成代码就几行uint8_t compute_checksum(const uint8_t *data, size_t len) { uint8_t sum 0; for (size_t i 0; i len; i) sum data[i]; return (uint8_t)(0x100 - sum); // 补码使累加和模256为0 }实际工程里最常见的丢包原因就是改了InfoFrame的Length字段却忘了重算Checksum。接收端校验失败后通常会把整个包丢弃。症状很隐蔽命令本身没写错版本号也对就因为校验和不对电视完全无视这个包。比如ARC回传功能失效、EDID里的厂商能力读不到都有可能是这条链路上某个InfoFrame被悄悄扔掉了。所以每次更新InfoFrame内容我的习惯是连Version、Length、Checksum一起审核三个字段是一个整体不能只改数据体。尤其是做固件升级的时候新旧固件之间InfoFrame的字节数一旦有变化最容易漏算Checksum。4. 音频与HDR两个最常背锅的数据包4.1 ACR包与CTS/N音频时钟的参考坐标HDMI链路上没有专门的音频时钟线接收端要恢复出和源端一致的音频采样时钟靠的是Audio Clock Regeneration Packet也就是ACR包。ACR包携带两个关键参数CTSCycle Time Stamp和N。接收端利用本地TMDS时钟结合CTS/N的比例关系计算出音频参考频率。只要CTS/N比例正确接收端的锁相环就能稳定恢复出48kHz、44.1kHz这类音频时钟比例错一个数症状非常讨厌音频时好时坏、偶尔爆音或者完全无声。因为表现为“偶发”很多工程师会先怀疑线材、怀疑解码芯片查到最后才发现是ACR包里的N值表少了一项。尤其要提醒一点音频采样率切换的时候ACR包的参数必须跟着切换。比如从48kHz切到44.1kHz很多驱动只更新了Audio Sample PacketACR包还在用旧的N值结果就是播放44.1kHz内容时出现轻微但持续的音调偏移耳朵灵的人立刻能察觉到。4.2 Audio Sample Packet与HBR包36字节里怎么装多声道Audio Sample PacketType0x02是音频真正的主体。它按Subpacket把IEC 60958格式的左右声道样本封进Packet Body16bit、20bit、24bit的打包方式各不相同每个子包能承载特定数量的声道数据。这里容易忽略的是Audio Sample Packet需要和Audio InfoFrame协同工作。Audio InfoFrame里声明了声道数、采样率、编码格式而Audio Sample Packet负责搬运真正的样本数据。如果Audio InfoFrame说8声道但Sample Packet里实际只有2声道的有效样本部分功放会直接报警或者把多余的通道解出噪声。HBR音频走Type0x09的High Bitrate Audio Stream Packet专门对付DTS-HD MA、Dolby TrueHD这种高码率流。接收端先利用Data Island Packet解开容器再把原始音频位流交给音频解码器继续解。这类包对Data Island Period的带宽占用比普通PCM包大如果blanking太短或者带宽规划不合理会出现音频断流。4.3 HDR Metadata Packet与VSIF静态和动态HDR的差别HDR10的静态元数据走的是独立的HDR Metadata PacketType0x0B内容包括EOTF、静态元数据描述符ID、SMPTE ST 2086定义的主基色坐标、白点、最大/最小亮度以及MaxCLL、MaxFALL等参数。接收端拿到这一包之后才有依据切换到PQ曲线把HDR画面的亮部和暗部层次正确映射出来。动态HDR则不太一样。Dolby Vision和HDR10的元数据是逐帧或逐场景变化的没法靠一包静态数据解决于是借助VSIF把动态元数据传过去。所以在评估一台设备HDR支持能力时只看EDID里有没有HDR标志是不够的要看它实际一帧一帧发出了什么静态HDR靠0x0B包动态HDR靠VSIF。调试HDR显示异常时我踩过的坑是AVI与HDR Metadata Packet自相矛盾。比如AVI声明了BT.2020色彩空间但HDR Metadata Packet里的EOTF还写着SDR的0电视拿到的信息自相矛盾最后选择相信AVI结果就是画面发灰、对比度差。记住HDR不是单一包的事情AVI、量化范围、HDR Metadata Packet必须协同一致。5. 实测调试Data Island出问题时怎么定位5.1 抓包第一眼先看什么拿HDMI协议分析仪抓包时第一眼先看Data Island周期的TERC4错误计数和Guard Band识别情况。如果满屏都是TERC4 error说明链路本身就不稳定后面解析出来的任何包内容都不可信先解决物理层问题再说。第二眼看包边界是否连续。一个合法链路里包的排布应该整齐没有截断包每个Packet Boundary都能被正确识别。如果看到某个包只发了Header、Body缺了一半大概率是源端的Data Island时序没做对包内容被消隐区切断了。第三眼才轮到展开InfoFrame逐个字段对照。这里我习惯按“Type - Version - Length - Checksum”顺序看Type错了说明流解析器整体偏了Version错了说明源端和接收端协议代际不匹配Length错了意味Body边界都不可信Checksum错了说明有人在更新包内容时偷懒了。5.2 我实际踩过的三个Data Island坑坑一AVI的VIC写错。当时输出4K60但AVI里的VIC写的是1080p60的编号电视按1080p60去解释4K信号画面只有中间一块。查到最后发现驱动里VIC是写死的宏换了分辨率后没跟着更新。现在我的代码里VIC永远从当前timing结构体推导不做硬编码。坑二ACR包的CTS/N抽风。播放44.1kHz音频时接收端偶发爆音抓包看ACR包确实在发但N值明显不对。后来在显示平台上重新核对了一遍N值表发现旧代码沿用了48kHz的参数表没有覆盖44.1kHz的情况。这类问题纯粹是表驱动不完整数据岛的包虽然没错但包里的参数错了比包格式错了还难排查。坑三HDR包发了一半。示波器看PHY信号完全正常但分析仪显示HDR Metadata Packet截断Checksum也不对。后来定位到是固件升级后HDR Metadata Packet的发送时间和Vsync错位只有上半包落在消隐区下半包冲到了视频区。把发送点固定在Vsync后固定延迟处问题立刻消失。这种时序类问题在FPGA方案里尤其常见。5.3 写驱动和FPGA逻辑时的检查清单基于这几年的调试经验我整理了一张Data Island相关的检查清单每次调HDMI音视频问题都从这几点过一遍DE信号的位置必须严格包裹在blanking内Guard Band区域不能被DE覆盖否则接收端会把前导保护波段当成视频数据或控制周期导致整个Data Island解析失败。Packet Header的Type和保留位按规范填发送端保留位置0别把寄存器旧值直接发出去。InfoFrame的Length、Checksum在每次内容更新后重算Version一起检查三者是整体。音频类包和Audio InfoFrame保持一致通道数、采样率、HBR标志前后呼应。HDR场景下检查AVI的量化范围、色彩空间与HDR Metadata Packet是否互相矛盾。多包重叠时注意带宽blanking太短或像素时钟太高时Data Island Period要排队不能漏发ACR包否则接收端音频时钟会漂。在我自己的流程里抓包永远是第一步不看Data Island的完整包序列就不动驱动代码。HDMI协议里藏坑最多的地方往往不在视频数据期而在这些你看不见的Data Island Packets里希望这篇能让你少走一段弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价