MPEGTS-HLS 分析一帧数据包(H264)

分析一个TS文件的第一帧(SRS支持HLS协议产生的TS文件)


1. PAT(忽略)


2. PMT(忽略)


3. PES Packet(一帧数据)

通常一帧数据,就是一个PES包(一帧数据 = 一个PES Packet)。一个PES包一般可拆分为多个TS包(也有可能只拆分为一个TS包,即PES包长度小于188个字节)。
通常情况下,PES包由多个TS包组成。
如果PES包长度大于188个字节,那么将会被拆分成多个TS包:
PES Packet = TS Packet 1 + TS Packet 2 + TS Packet 3 + ... + TS Packet N

否则,如果PES包长度小于188个字节,则只能拆分成一个TS包:
PES Packet = TS Packet

分析的这一帧数据(也就是这一个PES包),一共有119756个字节,637个TS包(119756 / 188 = 637)。
下面会分析:
TS Packet 1(第一个TS包)
TS Packet 2 ~ TS Packet 636(第2~第636个TS包)
TS Packet 637(最后一个TS包)


4. TS Packet

首先,TS包的结构如图所示:

TS包结构

4.1 TS Packet 1(第一个TS包)

a. 第一个TS包的二进制数据如下所示:

47 41 01 30 07 10 00 07 24 00 7E 00 00 00 01 E0
00 00 80 C0 0A 31 00 39 EE 05 11 00 39 90 81 00
00 00 01 09 F0 00 00 01 06 00 07 80 D8 31 80 87
0D C0 01 07 00 00 18 00 00 03 00 04 80 00 00 00A
01 27 64 00 28 AC 2B 60 3C 01 13 F2 E0 22 00 00
03 00 02 00 00 03 00 3D C0 80 00 64 30 00 00 64
19 37 BD F0 76 87 0C B8 00 00 00 01 28 EE 3C B0
00 00 01 25 88 80 0E 3F D5 2E 71 35 C8 A5 E1 CE
F4 89 B3 F2 CA D2 65 75 33 63 B1 BA B6 33 B0 7B
80 A8 26 D0 77 01 FF 9A CB 85 C7 D1 DC A8 22 E9
BE 10 89 F9 CF 1A BA 6D 12 3D 19 0C 77 33 1B 7C
03 9B 3D F1 FF 02 AB C6 73 8A DB 51

b. 第一个TS包的二进制数据分析如下所示:
第一个TS包
c. 第一个TS包 = TS Header + TS Header AdaptationField + PES Header + PES Optional Header + NALU AUD + NALU(SEI) + NALU(SPS) + NALU(PPS) + NALU (IDR Frame)

TS Header(TS头): 47 41 01 30
TS Header AdaptationField(TS Header自适应字段):07 10 00 07 24 00 7E 00
PES Header(PES头):00 00 01 E0 00 00
PES Optional Header(PES可选头):80 C0 0A 31 00 39 EE 05 11 00 39 90 81
NALU AUD:00 00 00 01 09 F0

SEI/SPS/PPS/IDR Frame 类型判断,取 00 00 01 后的第一位跟0x1f进行与运算。

NALU(SEI):00 00 01 | 06 00 07 80 D8 31 80 87 0D C0 01 07 00 00 18 00 00 03 00 04 80 00
06 & 0x1f = 6

NALU(SPS):00 00 01 | 27 64 00 28 AC 2B 60 3C 01 13 F2 E0 22 00 00 03 00 02 00 00 03 00 3D C0 80 00 64 30 00 00 64 19 37 BD F0 76 87 0C B8 00
27 & 0x1f = 7

NALU(PPS):00 00 01 | 28 EE 3C B0
28 & 0x1f = 8

NALU(IDR Frame):00 00 01 | 25 88 80 0E 3F D5 2E 71 35 C8 A5 E1 CE F4 89 B3 F2 CA D2 65 75 33 63 B1 BA B6 33 B0 7B 80 A8 26 D0 77 01 FF 9A CB 85 C7 D1 DC A8 22 E9 BE 10 89 F9 CF 1A BA 6D 12 3D 19 0C 77 33 1B 7C 03 9B 3D F1 FF 02 AB C6 73 8A DB 5
25 & 0x1f = 5

d. 下面对每一部分都详细分析:
1. TS Header : 47 41 01 30

SyncByte(8 bits) : 0x47 
TransportErrorIndicator(1 bit) : 0
PayloadUnitStartIndicator(1 bit) : 1
TransportPriority(1 bit) : 0
Pid(13 bits) : 257
TransportScramblingControl(2 bits) : 0
AdaptionFieldControl(2 bits) : 3
ContinuityCounter(4 bits) : 0

2. TS Header AdaptationField :07 10 00 07 24 00 7E 00
TS Header AdaptationField 前两个字节 :07 10

AdaptationFieldLength(8 bits) : 7
DiscontinuityIndicator(1 bit) : 0
RandomAccessIndicator(1 bit) : 0
ElementaryStreamPriorityIndicator(1 bit) : 0
PCRFlag(1 bit) : 1
OPCRFlag(1 bit) : 0
SplicingPointFlag(1 bit) : 0
TrasportPrivateDataFlag(1 bit) : 0
AdaptationFieldExtensionFlag(1 bit) : 0

TS Header AdaptationField 后六个字节 : 00 07 24 00 7E 00

PCR :00 07 24 00 7E 00 转为10进制 = 30668783104
PCR_base :30668783104 >> 15 = 935936
PCR_ext :30668783104 & 0x1ff = 0
PCR_base 转成秒 :935936 / 90000 = 10.39928888888889
PCR = PCR_base * 300 + PCR_ext = 935936 * 300 + 0 = 280780800
  1. MPEG2-TS规定的系统时钟频率为27MHz.PTS就是以系统时钟的300分频为单位的计数值(规定的除以300,参考ISO-13818-1)
  2. PTS转换成秒: 1/(27MHZ/300) = 1 / 90000
    P C R ( i ) = P C R B a s e ( i ) ∗ 300 + P C R E x t ( i ) PCR(i) = PCR Base(i) * 300 + PCR Ext(i) PCR(i)=PCRBase(i)300+PCRExt(i)
if PCR_flag == 1 
{
	program_clock_reference_base // 33 bits
	Reserved // 6 bits
	program_clock_reference_extension // 9 bits
}

ProgramClockReferenceBase(33 bits) : 935936
Reserved(6 bits) : 0x3f
ProgramClockReferenceExtension(9 bits) : 0

3. PES Header :00 00 01 E0 00 00
多个TS包打包成一个PES包,那么第一个TS包,应该包含PES Header。

PacketStartCodePrefix(24 bits) : 00 00 01
StreamID(8 bits) : 0xE0(视频是0xE0,音频是0xC0)
PesPacketLength(16 bits) : 00 00(长度不确定,需要自己计算)

4. PES Optional Header :80 C0 0A 31 00 39 EE 05 11 00 39 90 81
PES Optional Header 前三个字节 :80 C0 0A

ConstTen(2 bits) : 2
PesScramblingControl(2 bits) : 0
PesPriority(1 bit) : 0
DataAlignmentIndicator(1 bit) : 0
Copyrigh(1 bit)t : 0
OriginalOrCopy(1 bit) : 0
PtsDtsFlags(2 bits) : 3
EscrFlag(1 bit) : 0
EsRateFlag(1 bit) : 0
DsmTrickModeFlag(1 bit): 0
AdditionalCopyInfoFlag(1 bit) : 0
PesCRCFlag(1 bit) : 0
PesExtensionFlag(1 bit) : 0
PesHeaderDataLength(8 bits) : 10(0x0A)

PES Optional Header 剩下的字节 :31 00 39 EE 05 11 00 39 90 81

if (PtsDtsFlag == '10') // PTS
0x0010 + PTS[30...32] + marker__bit + PTS[29...15] + marker__bit + PTS[14...0] + marker__bit

if (PtsDtsFlag == '11')  // PTS,DTS
0x0011 + PTS[30...32] + marker__bit + PTS[29...15] + marker__bit + PTS[14...0] + marker__bit
0x0001 + DTS[30...32] + marker__bit + DTS[29...15] + marker__bit + DTS[14...0] + marker__bit

PTS :31 00 39 EE 05,10进制表示:210457193989
DTS :11 00 39 90 81,10进制表示 :73018216577

PTS转换:
PTS[30...32] -> ((210457193989>> 33) & 0x7) << 30 == 0
PTS[30...32] -> ((210457193989>> 17) & 0x7fff) << 15 == 917504
PTS[30...32] -> ((210457193989>> 1) & 0x7fff) == 30466

DTS转换:
DTS[30...32] -> ((73018216577>> 33) & 0x7) << 30 == 0
DTS[30...32] -> ((73018216577>> 17) & 0x7fff) << 15 == 917504
DTS[30...32] -> ((73018216577>> 1) & 0x7fff) == 18496

Parse PTS : 947970(917504 + 30466) / 90000 == 10.533
Parse DTS : 936000(917504 + 18496) / 90000 == 10.4

PTS(33 bits) : 947970
DTS(33 bits) : 936000

5. NALU AUD :00 00 00 01 09 F0
在每一帧的视频帧被打包到pes的时候,其开头一定要加上 00 00 00 01 09 F0 这个NALU AUD。
在下面的Apple FAQ 第10个问题描述的很清楚了:

If AAC audio is used, it must have ADTS headers.
H.264 video access units must use Access Unit Delimiter NALs, and must be in unique PES packets

https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html

6. NALU(SEI) :06 00 07 80 D8 31 80 87 0D C0 01 07 00 00 18 00 00 03 00 04 80 0

Supplementary Enhancement Information (SEI)

7. NALU(SPS) :27 64 00 28 AC 2B 60 3C 01 13 F2 E0 22 00 00 03 00 02 00 00 03 00 3D C0 80 00 64 30 00 00 64 19 37 BD F0 76 87 0C B8 00

Sequence Parameter Set (SPS)

8. NALU(PPS) :28 EE 3C B0

Picture Parameter Set (PPS)

9. NALU(IDR Frame) :25 88 80 0E 3F D5 2E 71 35 C8 A5 E1 CE F4 89 B3 F2 CA D2 65 75 33 63 B1 BA B6 33 B0 7B 80 A8 26 D0 77 01 FF 9A CB 85 C7 D1 DC A8 22 E9 BE 10 89 F9 CF 1A BA 6D 12 3D 19 0C 77 33 1B 7C 03 9B 3D F1 FF 02 AB C6 73 8A DB 51

Instantaneous Decoding Refresh :即时解码刷新。
IDR 和 I Frame的区别 :第一个I帧被称为IDR帧,IDR帧是I帧的一个子集。
I P B Frame : Frame -> Slice -> Macroblock -> YUV Data。宏块是编码处理的基本单元。
Slice种的三种编码模式 :I_Slice、P_Slice、B_Slice,因此 根据Slice来区分 IDR,I,P,B帧

4.1 TS Packet 2 ~ TS Packet 636(第二个TS包~倒数第二个TS包)

第2个~第636个TS包,固定的格式如下 :
TS Packet = TS Header(4 bytes) + TS Payload(184 bytes)
唯一变化的就是TS Header中的字段ContinuityCounter,从0~15循环变化。

4.2 TS Packet 637(最后一个TS包)

a. 最后一个TS包的二进制数据如下所示:

47 01 01 3C 5D 00 FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF EC 7D 15 CE DB 2D 99 EB 31 07 65 B0 19 8B
CA 75 B0 40 02 C0 B4 DE BD B6 B3 A7 E5 50 DA 75
20 72 75 AB 87 84 59 B9 73 56 15 B8 6B 6C 7E 6C
2E 66 28 5D 82 77 8B E9 94 49 DC CC 80 B0 D1 F3
09 36 2C 29 6E E3 12 1A 69 90 40 F1 F9 BF FE 7E
BF 99 C1 D2 7B C8 2B 51 EC 1C 33 60

b. 最后一个TS包的二进制数据分析如下所示:
最后一个TS包
c. 最后一个TS包 = TS Header + TS Header AdaptationField + 填充字段 + TS Payload

1. TS Header : 47 01 01 3C

SyncByte(8 bits) : 0x47 
TransportErrorIndicator(1 bit) : 0
PayloadUnitStartIndicator(1 bit) : 0
TransportPriority(1 bit) : 0
Pid(13 bits) : 257
TransportScramblingControl(2 bits) : 0
AdaptionFieldControl(2 bits) : 3
ContinuityCounter(4 bits) : 12

2. TS Header AdaptationField :5D 00

AdaptationFieldLength(8 bits) : 93(0x5D)
DiscontinuityIndicator(1 bit) : 0
RandomAccessIndicator(1 bit) : 0
ElementaryStreamPriorityIndicator(1 bit) : 0
PCRFlag(1 bit) : 0
OPCRFlag(1 bit) : 0
SplicingPointFlag(1 bit) : 0
TrasportPrivateDataFlag(1 bit) : 0
AdaptationFieldExtensionFlag(1 bit) : 0

3. 填充字段 :0xFF
这个TS包一共填充93个0xFF。

4. TS Payload :剩下的字节


最后分享一个自己写的购物网站, 女性假发, 大家可以给自己女朋友买, 当然也可以自己cosplay用.(手机端为主, 电脑端比较少更新. 可以直接搜索: githair, 跟github很像): https://www.githair.com

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值