我需要检测 RTP 数据包中的 MPEG4 I-Frame。我知道如何删除 RTP 标头并在其中获取 MPEG4 帧,但我不知道如何识别 I-Frame。
它有特定的签名/标题吗?
好的,所以我想出了 h264 流。
如何检测 I 帧:
我无法弄清楚 MPEG4-ES 流...有什么建议吗?
编辑:H264 IDR
这适用于我的 h264 流 ( fmtp:96 packetization-mode=1; profile-level-id=420029;
)。您只需传递表示通过 RTP 接收的 h264 片段的字节数组。如果要传递整个 RTP,只需更正该RTPHeaderBytes
值以跳过 RTP 标头。我总是得到 I-Frame,因为它是唯一可以分段的帧,请参见此处。我在我的服务器中使用了这段(简化的)代码,它就像一个魅力!!!!如果 I 帧 (IDR) 没有分段,则fragment_type
为 5,因此此代码将返回true
分段而不是分段的 IDR。
public static bool isH264iFrame(byte[] paket)
{
int RTPHeaderBytes = 0;
int fragment_type = paket[RTPHeaderBytes + 0] & 0x1F;
int nal_type = paket[RTPHeaderBytes + 1] & 0x1F;
int start_bit = paket[RTPHeaderBytes + 1] & 0x80;
if (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5)
{
return true;
}
return false;
}
这是 NAL 单元类型的表:
Type Name
0 [unspecified]
1 Coded slice
2 Data Partition A
3 Data Partition B
4 Data Partition C
5 IDR (Instantaneous Decoding Refresh) Picture
6 SEI (Supplemental Enhancement Information)
7 SPS (Sequence Parameter Set)
8 PPS (Picture Parameter Set)
9 Access Unit Delimiter
10 EoS (End of Sequence)
11 EoS (End of Stream)
12 Filter Data
13-23 [extended]
24-31 [unspecified]
编辑 2:MPEG4 I-VOP
我忘了更新这个……感谢 Che 和ISO IEC 14496-2文件,我设法解决了这个问题!Che 很老套,但他的回答并不那么精确......所以简而言之,这里是如何找到 I、P 和 B 帧(I-VOP、P-VOP、B-VOP):
000001B6
(十六进制)开头。所有 MPEG4 帧 (I,P,B) 都是相同的接下来是更多信息,我不打算在这里描述(参见 IEC 文档),但我们只(如 che 所说)需要来自下一个字节的高 2 位(具有 value 的字节之后的下两个位B6
)。这 2 位告诉你 VOP_CODING_TYPE,见下表:
VOP_CODING_TYPE (binary) Coding method
00 intra-coded (I)
01 predictive-coded (P)
10 bidirectionally-predictive-coded (B)
11 sprite (S)
因此,要查找 I 帧,请查找以四个字节开头000001B6
并具有下一个字节的高两位的数据包00
。这将在 MPEG4 流中找到具有简单视频对象类型的 I 帧(不确定高级简单)。
对于任何其他问题,您可以查看提供的文档(ISO IEC 14496-2),关于 MPEG4 您想了解的都有。:)
据我所知,RTP 有效负载中的 MPEG4-ES 流片段通常以 MPEG4 起始码开头,可以是以下之一:
0x000001b0
:visual_object_sequence_start_code(可能是关键帧)0x000001b6
:vop_start_code(关键帧,如果接下来的两位为零)0x000001b3
:group_of_vop_start_code,它包含三个字节,然后是一个可能属于或不属于关键帧的vop_start_code(见上文)0x00000120
: video_object_layer_start_code (可能是关键帧)0x00000100
- 0x0000011f
:video_object_start_code(那些看起来也像关键帧)恐怕您需要解析流以确保:-/
实际上,您对 h264 流是正确的,如果 NAL 值(第一个字节)是0x7C
它意味着 I-Frame 是分段的。没有其他帧(P 和 B)可以被分片,所以如果有packetization-mode=1
,SDP
则表示 I-Frame 是分片的,因此如果您0x7C
作为第一个字节读取,则它是 I-Frame。在此处阅读更多信息:http ://www.rfc-editor.org/rfc/rfc3984.txt 。
这对我有用:
- 找出“有效负载类型”,例如:有效负载类型:DynamicRTP-Type-96 (96)
- 告诉wireshark哪个流是H264:文件->首选项->协议->H264。输入 96 作为有效负载类型。
- 过滤 slice_type:"h264.slice_type eq 7"
对于 H264:
例子:
nal_ref_idc: 3, nal type: 7 (0x07) descripcion: 7 (SPS)<br>
00000000 24 00 00 2B 80 60 22 ED 96 57 3E 68 57 F3 22 B5 $..+.`"í.W>hWó"µ<br>
00000010 67 64 00 1E AD 84 01 0C 20 08 61 00 43 08 02 18 gd..... .a.C...
00000020 40 10 C2 00 84 2B 50 5A 09 34 DC 04 04 04 08 @.Â..+PZ.4Ü....<br>
nal_ref_idc: 3, nal type: 8 (0x08) descripcion: 8 (PPS)<br>
00000000 24 00 00 10 80 60 22 EE 96 57 3E 68 57 F3 22 B5 $....`"î.W>hWó"µ
00000010 68 EE 3C B0 hî<°
FU_A (fragmentation unit A)
nal_ref_idc: 3, nal type: 5 (0x05) descripcion: 5 (IDR (Instantaneous Decoding Refresh) Picture)
00000000 24 00 05 96 80 60 22 F1 96 57 3E 68 57 F3 22 B5 $....`"ñ.W>hWó"µ
00000010 7C 05 A0 AA 2F 81 92 AB CA FE 9E 34 D8 06 AD 74 |. ª/..«Êþ.4Ø.t
...
0x000001b6:vop_start_code(关键帧,如果接下来的两位为零)这是 MPEG-4 的正确方法