Apple产品系列中,使用HLS实现直播,HLS可以简单理解为HTTP+M3U8+TS。
一、问题引出
最近遇到一个问题,MP4文件转成TS后,在Apple上播放会有帧错乱现象(前后帧显示时来回跳),但在Windows下的播放器如VLC显示都没有问题。
二、初探
小武同学根据十几年的经验判断,第一感觉认为是DTS或PTS错乱导致,但通过分析后发现DTS和PTS显示正常。
I,B,P帧的时间戳都没有问题。
问题可能出在哪里了呢?伟大的架构师LiuQi同学使用FFMPEG把无法正常播放的TS流文件重新打包了一下(不做转码),发现播放变得正常了。好吧,开始比较两个TS文件的区别(b-1.ts为原始文件,c-1.ts为FFMPEG转封装后的文件)。
先用StreamAnalyzer看一下吧:
SPS和PPS完全一样。
再使用ElecardEye看一下:
Gop结构,Slice信息,也都没有问题。
搞了两天,不管是TS层面,PES信息,还是ES信息上都没有看出有什么区别,见了鬼了!
三、深入分析
看来得用最后的手段了,二进制比较。但从哪个层面比较呢?由内到外吧,先把ES内容剥出来比较一下。
照妖镜一出,小鬼无藏身之处,图中红色部分为原文件中多出的内容。
分析一下吧,00 00 00 01 09 E0,这是NAL_AUD吗(Access Unit Delimiter),访问单元分隔符,表示一个帧数据的结束,只是多一个结束就会导致显示错乱吗?试着把原文中多出的部分删除掉,显示果然正常了。
还是不解,为什么VLC显示没有问题呢?看一下FFMPEG中解码H.264的代码吧:
在FFMPEG的解码过程中,遇到NAL_AUD直接跳过,查找下一个NAL去了,如果连续两个就跳两次,所以不会有问题;但在Apple的播放器中,如QuickTime,会严格把每帧数据和帧分隔符进行配对。
四、总结
在上文中之所以出现了两个NAL_AUD,是因为进行MP4转TS时,代码中没有判断帧后是否已经有了NAL_AUD,而是直接在每帧后面添加了一个,对于要求严格的播放器来讲,就出问题,看来代码要严谨,来不得半点马马虎虎啊!
转载http://write.blog.csdn.net/postedit