框架的使用极大的提高了开发效率,让我们能够有更多的精力去关注系统的整体架构和业务需求,而不需要过多的关注一些具体的实现细节,但任何事情都有两面性,如果某个细节出了问题,由于对具体的实现不了解,那么会给我们解决问题带来不少困扰。
下面借用最近遇到的问题分享一个解决问题的思路,我们的会议系统使用ffmpeg生成的mp4文件在windows下不能正常预览,进一步测试还有如下表现:1、在wmp(系统自带播放器)下播放弹出“无法播放此文件”,而使用vlc播放是正常的;2、使用mp4info打开该文件显示“open failed”;3、使用mp4reader可以正常打开。
通过以上现象大致可以判断,可能是我们生成的mp4文件格式不太正规,而vlc、mp4reader容错性比较好能够兼容它。那么很自然的想到,从网上下载一个正常的mp4文件(使用以上软件都可以正常打开),用mp4reader对比两者的结构看看,但是通过对比,并没有发现明显的不同,而手头也没有类似BeyondCompare的软件去比较两个mp4文件,那么只能转换思路,既然wmp、mp4info打开两个文件的表现不同,那么就从比较简单的mp4info入手,先让同事帮忙找了一下mp4info的源码,没有找到,那么只能直接上调试器了。
因为有“open failed”这个明显的提示,所以难度小一些,经过反复调试,找到了一个关键点,如下图:
再跟踪进去发现处理到这个地方的时候异常了,用mp4info打开两个mp4文件对比发现,有问题的文件,avc1下面缺少avcC,如下图:
这是正常的:
第一次用mp4info看的时候,由于层次太深,忽略了。查询资料(度娘这次还是很给力的,不过要是时间充足可以自己把ffmpeg相关源码看看),可以知道avcC的生成跟ffmpeg编码时候的extradata(h264编码时候就是sps、pps)有关,通过调试会议系统的代码发现:生成mp4的时候,extradata的确是空的,再查询资料得知ffmpeg编码时候增加AV_CODEC_FLAG_GLOBAL_HEADER参数即可填充extradata,修改代码重试,问题解决。
这下前面的现象就都可以解释了:wmp认为缺少了avcC这个重要的东西,打开文件时直接报错了,windows预览用的模块跟wmp使用相同的组件,自然也不能打开;vlc之所以能够播放,是因为它做了容错,因为sps、pps即使头部没有,也可以在I帧前面获取到。
回到开头讲的,之所以解决问题这么麻烦,就是因为我们直接使用ffmpeg生成mp4文件,而对于mp4容器的格式、ffmpeg相关机制并不是很熟悉。所以即使用框架来完成工作,那么最好也要对所用框架有一定研究,一些基础的协议、格式还是要熟悉,这样才能从容应对遇到的问题。
参考资料: