具有多个 PPS 和 SPS 的 H264

Posted

技术标签:

【中文标题】具有多个 PPS 和 SPS 的 H264【英文标题】:H264 with multiple PPS and SPS 【发布时间】:2014-01-08 01:20:10 【问题描述】:

我有一张卡,可以在每个 I 帧之前按顺序生成带有 SPS(序列参数集)和 PPS(图片参数集)的 H264 流。我看到大多数 H264 流在第一个 I 帧处包含 PPS 和 SPS。

这是推荐的吗?解码器/复用器通常支持多个 PPS 和 SRS 吗?

【问题讨论】:

【参考方案1】:

H.264 有多种流格式。一种变体称为“附件 B”。

(AUD)(SPS)(PPS)(I-Slice)(PPS)(P-Slice)(PPS)(P-Slice) ... (AUD)(SPS)(PPS)(I-Slice) .

通常您会在每个 I 帧之前看到 SPS/PPS,在其他切片之前看到 PPS。

大多数解码器/复用器都对“附件 B”和 SPS/PPS 的重复感到满意。

如果您更改格式和 SPS/PPS 中游,大多数解码器/复用器将不会做任何有意义的事情。

大多数解码器/复用器将第一个 SPS/PPS 解析为设置过程的一部分,并忽略后续 SPS。

一些解码器/复用器更喜欢没有 (AUD)、起始码和 SPS/PPS 的 H.264。 然后,作为设置解码器/复用器的一部分,您必须在带外输入 SPS/PPS。

【讨论】:

MP4 格式可以与 in-mdat SPS 和 PPS 一起使用,但我见过的几乎每个文件都将 SPS 和 PPS 放在 stsd.avc1.avcC 下的轨道描述中,然后仅 mdat包含样本数据。在流的中间更改 SPS 和 PPS 是可能发生的最简单的古怪事情。我很确定单个流可能具有基于不同 SPS 和 PPS 的各种样本。考虑字段 slice_header.pic_parameter_set_id 和 picture_parameter_set.seq_parameter_set_id 。我怀疑截至 2013 年大多数解码器都不支持此功能。【参考方案2】:

没有 SPS 和 PPS 就无法解码 IDR 帧或 I-slice。对于像 mp4 这样的容器,SPS 和 PPS 存储在文件头中的视频数据之外。播放时解析 mp4,使用 SPS/PPS 配置一次 AVC 解码器,然后可以从任意 IDR/I-slice 开始播放视频。

还有第二种情况,实时视频。对于实时视频,没有文件头,因为没有文件。那么当电视调谐到一个频道时,它从哪里获得 SPS/PPS?因为电视是广播的,这意味着电视无法请求 SPS/PPS,它在流中重复。

因此,当您开始对视频进行编码时,您的编码器并不知道您打算如何处理该视频。现在,如果额外的 SPS/PPS 出现在 mp4 中,解码器会忽略它们,但如果你正在流式传输到电视,没有它们,流永远不会播放。所以大部分默认都是重复 SPS/PPS 以防万一。

【讨论】:

【参考方案3】:

我知道 matroska(mkv) 规范,所以这里 SPS 和 PPS 仅作为编解码器私有数据部分存储一次。因此它们不会在每个 i 帧或 IDR 帧中重复。

如果您的 h264 流的每个 i 帧/IDR 帧都有 SPS/PPS,那么 matroska muxer 将仅在编解码器私有数据中存储 1 个副本。

因此,在存储基于用例的容器格式时,建议仅使用 SPS/PPS 的一份副本,但基于广播和流式传输的容器格式建议在每个 iFrame/IDR 帧之前发送 SPS/PPS,或者在当时 h264 流中的任何编解码器更改时发送 SPS/PPS

【讨论】:

虽然 mkv 确实存储“私有编解码器数据”,即 H264 的 SPS 和 PPS,但没有什么能阻止您将这些数据包写入流。 VLC 和 ffplay 等播放器在看到流中的 SPS/PPS 时会更改编解码器设置。 同意,Matroska Demuxer 会将这些 SPS/PPS + 编码数据仅视为编码数据并将它们提供给解码器,所有 h264 解码器都可以对其进行解码。但是,如果它不是流用例或编解码器正在更改其设置,我认为这样做没有任何好处

以上是关于具有多个 PPS 和 SPS 的 H264的主要内容,如果未能解决你的问题,请参考以下文章

H264参数SPS(序列参数集)和PPS(图像参数集)说明

H264码流中NALU sps pps IDR帧的理解

h264原始的nal打包格式怎么获取pps,sps等消息

FFmpeg解封装h264 ---- 提取SPS PPS

sps和pps的简单理解记录

H.264---SPS和PPS