如何在H264 ES数据中获取PTS

作者&投稿:左丘眨 (若有异议请与网页底部的电邮联系)
如何在h264 es数据中获取pts~

你好
详细的获取教程如下
http://www.360doc.com/content/11/1018/13/1016783_157125784.shtml

xH264的ES原始数据一般是以NAL(Network Abstract Layer)的格式存在。可以直接用于文件存储和网络传输。每一个NALU(Network Abstract Layer Unit)数据,是由数据头+RBSP数据组成。 首先需要将数据流,分割成一个一个独立的NALU数据。 接着获取N...

H264的ES原始数据一般是以NAL(Network Abstract Layer)的格式存在。可以直接用于文件存储和网络传输。每一个NALU(Network Abstract Layer Unit)数据,是由数据头+RBSP数据组成。

首先需要将数据流,分割成一个一个独立的NALU数据。

接着获取NALU的nal_type,i_nal_type的值等于0x7表示这个nalu是个sps数据包。找到并解析这个sps数据包,里面包含有非常重要的帧率信息
time_scale/num_units_in_tick=fps

然后根据nal_type判断slice(H264中的slice类似一个视频帧FRAME的概念)。其中nal_type值小于0x1,或大于0x5,表示这个NALU属于一个slice。
// 检查是否是slice if ( i_nal_type < 1/*NAL_SLICE*/ || i_nal_type > 5/*NAL_SLICE_IDR*/ ) // 找到slice!!!!!

在找到slice的NALU后,可以逐字节将NALU的数据与0x80进行与运算,结果为真表示这个slice(视频帧FRAME)的结束位置。
// 判断是否帧结束 for (uint32_t i = 3; i < nal_length; i++) { if (p_nal[i] & 0x80) { // 找到frame_begin!!!!上一帧frame的结束,下一帧frame的开始 } }

上面的这个代码是摘抄自FFMPEG。他实际作用是判断slice里面的first_mb_in_slice,即第1个宏块在slice中的位置,如果是
一帧开始,这个字段的值肯定是标识第1个宏块。因此,也可以完整解析slice的头部信息,解析出first_mb_in_slice,如果是0(注意:
这是1个哥伦布数值),即这个NALU是一帧的开始。

为什么这里的代码是逐字节判断0x80?我额外写点某大神的名言:程序猿不是十万个为什么,不是维基猿,程序猿是需求猿。如果某程序猿已经着手开始研究如何解析slice头部格式,他很自然的不会有这个疑问。

另外通过nal_type以及silice_type也可以判断出帧结束位置,VLC里面的代码就是这么干。

解析到位于帧结束位置的NALU,就可以判断出每一帧(slice)的开始和结尾。解析slice的slice_type,根据slice_type,可以判断出这个slice的IPB类型。
// 根据slice类型判断帧类型 switch(slice.i_slice_type) { case 2: case 7: case 4: case 9: *p_flags = 0x0002/*BLOCK_FLAG_TYPE_I*/; break; case 0: case 5: case 3: case 8: *p_flags = 0x0004/*BLOCK_FLAG_TYPE_P*/; break; case 1: case 6: *p_flags = 0x0008/*BLOCK_FLAG_TYPE_B*/; break; default: *p_flags = 0; break; }

从现在开始,就有两种办法来计算PTS了。

方法一、根据前后帧的IPB类型,可以得知帧的实际显示顺序,使用前面获取的sps信息中的帧率,以及帧计数frame_count即可计算出PTS。此方法需要做几帧缓存(一般缓存一个group的长度)。

I P B B I P B B I P B ... 帧类型
1 2 3 4 5 6 7 8 9 10 11 ... 第几帧
1 4 2 3 5 8 6 7 9 12 10 ... 帧显示顺序

一个I帧与下一个I帧之间,是一个group。
从上图可见,P类型的帧的显示顺序,是排在后面最后一个B帧之后。
所以要获取第7帧的pts,起码要知道他下一帧的类型,才能得知他的显示顺序。

第8帧的pts=1000(毫秒)*7(帧显示顺序)*帧率

方法二、每一个slice的信息里面,都记录有pic_order_cnt_lsb,当前帧在这个group中的显示顺序。通过这个pic_order_cnt_lsb,可以直接计算出当前帧的PTS。此方法不需要做帧缓存。

计算公式:

pts=1000*(i_frame_counter + pic_order_cnt_lsb)*(time_scale/num_units_in_tick)

i_frame_counter是最近一次I帧位置的帧序,通过I帧计数+当前group中的帧序,得到帧实际显示序列位置,乘上帧率,再乘上1000(毫秒)的base_clock(基本时钟频率),得到PTS。

I P B B I P B B I P B ... 帧类型
1 2 3 4 5 6 7 8 9 10 11 ... 第几帧
1 4 2 3 5 8 6 7 9 12 10 ... 帧显示顺序
0 6 2 4 0 6 2 4 0 6 2 ... pic_order_cnt_lsb

细心一点可以注意到,在上图,slice里面的pic_order_cnt_lsb是以2进行递增。
通常H264里面的sps中记录的帧率,也是实际帧率的2倍time_scale/num_units_in_tick=fps*2

因此,实际的计算公式应该是这样
pts=1000*(i_frame_counter*2+pic_order_cnt_lsb)* (time_scale/num_units_in_tick)
或者是
pts=1000*(i_frame_counter+pic_order_cnt_lsb/2)* (time_scale/num_units_in_tick/2)

所以,第11帧的pts应该是这么计算
1000*(9*2+2)*(time_scale/num_units_in_tick)


广丰县17158913263: h264封装成PS过程中PTS,SCR等怎么计算 -
喻徐跌打: 1:MPEG-2标准文档里有详细解释公式的system_clock_frequency参考值范围,t(i)就是到达时间.时间戳PTS的单位不是ms为单位,而是一个33位数字,单位是90KHz的倍数,因此可以利用这个系数换算成s或ms.具体的PTS解释MPEG-2标准...

广丰县17158913263: 从网络获取的h264码流,aac码流时间戳怎么算 -
喻徐跌打: H264解析slice就可以找到帧,可以从帧信息中获得DTS时间,从sps信息中获得PTS时间 AAC解析frame,根据AAC编码码率信息,可以知道每一个frame的时间增量,获得PTS时间

广丰县17158913263: 如何用C语言取出H.264ES文件里的nal信息 -
喻徐跌打: 读文件,找到nal头,根据nal规则读规定位进行运算!具体的可以参考H264编解码标准!如果不会自己写轮子,可以使用ffmpeg库或者直接使用x264开源库来操作.

广丰县17158913263: 传递H264的时候,RTSP抓包获得的pps sps,怎么解析 -
喻徐跌打: #pragma comment(lib,"crypt32")#include #include #include //+-------------------------------------------------------------------------// convert formatted string to binary// If cchString is 0, then pszString is NULL terminated and// cchString is obtained via strlen() + ...

广丰县17158913263: 如何使用ffmpeg将h264标准码流生成m3u8索引和ts段文件? -
喻徐跌打: 我的思路:1、建立rtsp连接从设备获取标准的h264码流2、组帧并将完整的帧写入帧缓冲区3、线程从帧缓冲区读取一个完整的帧4、对帧进行转码输出ts流5、判断并建立索引文件(索引文件名在与客户段会话的过程确定下来)6、将ts的数据包进行分段并按时(比如10秒)长写入到.ts段文件7、定时对索引文件靠前的ts段信息进行删除更新不知道有没问题,其中转码输出ts流的过程原来没弄过,有弄的话指点下,谢谢!

广丰县17158913263: 汇编语言题目,字符串的合并 -
喻徐跌打: data segment data1 db 'CDE' data2 db 'ABCD' data ends esdata segment data3 db 7 dup(?) esdata ends code segment assume cs:code,ds:data,es:esdata start:mov ax,data ;送段地址 mov ds,ax mov ax,esdata mov es,ax mov si,offset data1 ;...

广丰县17158913263: 在哪个字段有判断I,B,P帧的信息?(MPEG2,H.264) . -
喻徐跌打: MPEG4解析VOL和VOPH.264解析PPSMPEG2跟MPEG4一样,只是头的规定不一样.

广丰县17158913263: RedHat Linux AS 和ES的区别 -
喻徐跌打: Redhat有两大Linux产品系列,其一是免费的FedoraCore系列主要用于桌面版本,提供了较多新特性的支持.另外一个产品系列是收费的Enterprise系列,这个系列分成:AS/ES/WS等分支,...

广丰县17158913263: 如何获取h264一帧有多少个slice -
喻徐跌打: 这其实是一个协议分析过程,每一帧H264数据都是可以通过观察二进制码流分析出来的.根据协议说明,每一帧图像一般在开头有一个单元分隔符NAL,两个单元分隔符之间的数据包就是一帧图像.就是00 00 01 09,这个09就是单元分隔符的标志.不过协议...

广丰县17158913263: 如何从wireshark中获取H264码流 -
喻徐跌打: 没什么关系的.以前H263的rtp包算得还不错,不过H264的时候感觉wireshark的分析就没什么用了. 没什么关系的.以前H263的rtp包算得还不错,不过H264的时候感觉wireshark的分析就没什么用了.

你可能想看的相关专题

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网