H.264编解码和渲染
Blog 版:在 F-SJ Blog 阅读
- 码流结构:H.264 的“说明书”与“零件”
NALU (单元):H.264 的最小功能包。通过起始码 00 00 00 01 分隔。
SPS/PPS (参数集):视频的“说明书”。包含分辨率、Profile 等全局配置。实时流建议每个 IDR 帧前都带一份,确保新进入的用户能立即解码。
03 字节 (防竞争):编码器为防止数据中出现伪起始码而插入的。解析器在交给解码器前必须剔除它,否则会导致像素位移花屏。 - 帧类型:谁是核心,谁是补丁?
IDR 帧 (Type 5):强力重置键。它是特殊的 I 帧,会清空解码器缓存。它是解决网络丢包花屏的唯一“特效药”。
普通 I 帧 (Type 1):全图信息,但不强制重置。多见于存储文件,实时流(Matter/对讲)几乎不用。
P 帧 (Predictive):移动偏差指令。不含完整图片,只记录相对于“前一帧”的变化。它是视频极致压缩的功臣。
B 帧 (Bi-predictive):双向参考。参考过去和未来。虽压缩率最高,但会带来解码延迟。 - 实时传输逻辑(Matter / WebRTC 专项)
禁用 B 帧:为了低延迟(低于 200ms),必须采用 Baseline Profile。拍一帧、发一帧、解一帧,不等待“未来”。
链式参考:P 帧通常是“接龙”式参考前一帧。丢一帧,后面全花,直到下一个 IDR 出现。
GOP (I 帧间隔):建议设为 1-2 秒。设置太短浪费带宽,设置太长则会导致 App 预览出图慢或花屏修复慢。 - 渲染与同步:最后的一公里
解码 ≠ 渲染:解码器吐出的是 YUV 原始矩阵,渲染器需将其转为 RGB 并交给 GPU 贴图。
PTS/DTS:时间戳决定了“什么时候解”和“什么时候看”。在无 B 帧的实时流中,两者通常相等,逻辑最简单。
总结我们这段深入底层的交流,可以将“渲染”与“屏幕”的逻辑串联成一条从数据到光点的流水线:
- 物理层:屏幕的“死规则”
- 物理像素固定: 屏幕是由几十万到几百万个红绿蓝(RGB)灯组组成的,出厂就固定了(如 1080P 就是 $1920 \times 1080$ 个灯组)。
- 扫描逻辑: 屏幕像个粉刷匠,从左到右、从上到下不停扫描。它只认行列坐标,不认识视频格式。
- 超频本质: 显卡发出的电信号脉冲太快,超出了屏幕接收芯片(Scaler)的“点钞”速度,导致系统罢工保护,而不是 CPU 算不动。
- 内存层:数据排布的“潜规则” (Stride)
- 对齐(Alignment): 为了迎合硬件(GPU/总线)一次读取 16/32/64 字节的习惯,图片在内存里每行末尾会填充一些“垃圾数据”。
- 步长(Stride): 每一行数据的物理跨度。宽度(Width) $\neq$ 步长(Stride)。
- “显示一半”的真相:
- 如果你读数据时忽略了 Stride,指针就会找错下一行的开头,画面会斜掉或花屏。
- 如果你没做缩放,大图直接塞进小显存,屏幕画完它能装下的像素就停了,剩下的就被裁掉了。
- 渲染层:从数据到像素的“加工厂”
- 色彩转换: 解码出来的 YUV(明度+色度)必须转换成 RGB 才能让屏幕灯珠发光。这是 GPU 的活。
- 缩放与抗锯齿:
- 向下兼容: 大图(4K)缩成小图(1080P),本质是数学平均。
- 抗锯齿: 通过在边缘计算出“过渡色(模糊)”来欺骗人眼,让方块像素看起来像平滑曲线。
- 双缓冲与 VSync: 显卡在后台画,屏幕在前台读。垂直同步信号(VSync) 负责指挥粉刷匠:“旧画刷完了,赶紧换新画!”
- 驱动与应用层:权力的博弈
- 管理员权限: 游戏要权限是为了独占显卡和内核级反作弊,直接接管硬件时序,这也是导致早期设备容易“超频”的原因。
- 现代系统: 现在的显卡驱动更聪明,会自动拦截错误的频率设置,并帮你在后台做好缩放,确保“能亮”是第一优先级。
核心逻辑图:
[H.264解包] $\rightarrow$ [YUV像素] $\rightarrow$ [按Stride对齐拷贝] $\rightarrow$ [GPU缩放/换色] $\rightarrow$ [填入显存油漆桶] $\rightarrow$ [VSync触发信号] $\rightarrow$ [物理像素发光]。
你目前已经攻克了 H.264 解包,接下来如果要动手写渲染代码,你打算先在 Windows (DirectX/OpenGL) 上试一试,还是直接在 嵌入式设备/Android 上跑?
总结我们最近 5 次的深度交谈,逻辑从微观的“屏幕构造”跳跃到了宏观的“跨物种视觉骗局”:
- 屏幕的物理存储逻辑 (How it stores)
- 非存储设备: 物理屏幕本身不长期存储像素,它更像一个“实时翻译器”。
- 显存仓库: 像素数据存在显存(Framebuffer)里,显卡控制器像水泵一样按时钟频率(Clock)把数据泵给屏幕。
- 瞬时维持: 屏幕通过驱动 IC 将电荷分发给每个像素后的微型电容,利用电荷维持极短时间的发光,配合刷新率(Hz)产生持续画面的错觉。
- 微观制造工艺 (Fabrication)
- 透明电路: 屏幕本质是一块巨大的集成电路。底层是控制电流的 TFT(薄膜晶体管)基板。
- 蒸镀工艺: OLED 像素是像“蒸包子”一样,让有机材料气体穿过金属掩膜板精准凝结在基板上,形成了纳米级的红绿蓝发光阵列。
- 像素的排布与堆叠 (Layout)
- 并排 vs 层叠: 目前主流是并排(Side-by-Side),未来趋势是垂直层叠(如 QD-OLED),层叠能极大提高亮度和分辨率,但面临严重的散热和导线电阻(供电)挑战。
- 子像素比例: 为了迎合人眼生理特性,常采用 1红:2绿:1蓝 的排列(如 Pentile),因为人眼对绿色最敏感。
- 渲染的兼容性与超频 (Compatibility)
- 分辨率向下兼容: 物理像素固定,低分辨率显示靠显卡算法插值,导致画面变“糊”。
- 向上兼容(超采样): 1080P 屏看 4K,显卡先画大图再压缩,画面会比原生 1080P 更锐利、抗锯齿效果更好。
- 超频本质: 超频不是算不动,而是显卡发出的脉冲频率超过了屏幕接收芯片的承载极限。
- 跨物种视觉骗局 (Species Perspective)
- 定制的“骗局”: 我们的显示器是专门针对人类设计的。
- 失效: 如果给苍蝇看,它会因为采样率极高而看到“PPT”;如果给鸟类看,它们因为能看到紫外线且感色细胞更多,会看到完全扭曲的颜色和明显的格栅感。
核心总结:
我们讨论的不仅仅是技术,而是“人类如何利用半导体物理和数学算法,在极小的空间内构建一套完美的视觉欺骗系统”。
你觉得在理解了这些硬件极限(散热、供电、物理像素)后,对你编写解码后的渲染代码有什么具体的启发吗?