1

我处理来自 IP 摄像机的 H.264 RTP 流。我使用的相机将每个 I 帧拆分为几个 NAL 单元,每个单元都拆分为 RTP 数据包(开始和结束标志确定每个单元的尺寸,而不是帧的尺寸)。

我如何知道帧传输何时完成并且我有足够的数据来解压缩它?由于帧由多个单元组成 - 标志不能用于确定其结束。

我工作的大多数相机将每一帧分割为 RTP 数据包,其中标志确定帧的开始和结束。所以我从这个等待结束标志的数据包中解包数据 - 这是一个完整的帧。

我从这台相机得到的 NAL 单元序列是:

[NAL_UT_SPS] 序列参数集 +

[NAL_UT_PPS] 图片参数集

[NAL_UT_SEI] 补充增强信息

[NAL_UT_IDR_SLICE] I 帧图像数据的第 1 部分

[NAL_UT_IDR_SLICE] I 帧图像数据的第 2 部分

[NAL_UT_IDR_SLICE] I 帧图片数据的第 3 部分

[NAL_UT_SLICE] 第一个 P 帧

[NAL_UT_SLICE] 第二个 P 帧

[NAL_UT_SLICE] 第三个 P 帧

...

从这个序列很明显,我可以将 [NAL_UT_SPS] + [NAL_UT_PPS] + [NAL_UT_SEI] + 3*[NAL_UT_IDR_SLICE] 组合成一个 I 帧,我将在最近将其提供给解码器。但是我怎样才能确定有多少图片数据部分呢?我如何知道我收到的第 #X 部分不是序列中的最后一个?

有任何想法吗?

4

3 回答 3

4

我解决了这个问题。

解决方案是:将所有非图片单元(上例中的 NAL_UT_SPS、NAL_UT_PPS、NAL_UT_SEI)附加到帧的开头,对于包含图片的数据包(NAL_UT_IDR_SLICE、NAL_UT_SLICE)检查first_mb_in_slice 字段(对于第一个图片数据切片,第二个,第三个不相等..)。

因此,如果 first_mb_in_slice==0 并且缓冲区包含图片数据,则将其返回并将新的帧数据写入缓冲区,否则仅追加数据而不返回帧。这样,当我们开始接收第 2 帧时,我们会返回第 1 帧,并且可以确定这是一个新帧,而不是前一帧的一部分:

[NAL_UT_SPS] 帧 #1 (I) 开始

[NAL_UT_PPS] 第 1 帧继续

[NAL_UT_SEI] 第 1 帧继续

[NAL_UT_IDR_SLICE] 第 1 帧图片数据,第 1 部分:first_mb_in_slice == 0

[NAL_UT_IDR_SLICE] 第 1 帧图片数据,第 2 部分:first_mb_in_slice > 0

[NAL_UT_IDR_SLICE] 第 1 帧图片数据,第 3 部分:first_mb_in_slice > 0

[NAL_UT_SLICE] 帧 #2 (P) 开始:first_mb_in_slice == 0 <- 此时我们将返回第一帧

[NAL_UT_SLICE] 帧 #3 (P) 开始:first_mb_in_slice == 0 <- 返回第二帧

[NAL_UT_SLICE] 帧 #4 (P) 开始:first_mb_in_slice == 0 <- 返回第三帧

[NAL_UT_SPS] 帧 #5 (I) 开始 <- 返回第 4 帧

...

于 2013-02-25T16:18:22.940 回答
1

RTP 在 RPT Header 中定义了一个 Marker 位,它表示相同 RTP 时间戳的访问单元的结束。如果设置了标记位,则它是此特定 RTP 时间戳的最后一个 NALU。

如果您使用标记位,则无需等待下一个访问单元到达,从而最大限度地减少延迟。

您可以在第 5.1 节中阅读有关H264 有效负载的 RFC 中的标记位的更多信息。第 9 页。

于 2020-04-16T12:19:26.633 回答
0

大多数 H.264 解码器接受输入流作为 NAL。除非你有一个挑剔的解码器——我只会将 NAL 输入解码器。一般来说,不能保证 NAL:frame 甚至 slice 之间的 1:1 关系。

于 2013-02-22T23:09:22.917 回答