在以前的视频项目中,用到了几种商业版的H.264解码器。虽然性能稳定,支持DXVA或CUDA,在高清视频播放效果上不错,但是存在一个共同的缺陷-存在帧间延迟。经过我的测算,大概有3帧的缓冲延迟。当帧率在20fps以上时,所带来的延迟小于150毫秒,还不算明显。但是在低帧率的情况下,延迟显得非常大。
为了解决这个问题,拟将source和decoder写成一个filter,避免filter间传输可能导致的帧间缓冲延迟,这样就不得不研究开源的H.264 decoder软件。这段时间,一直埋头研究ffmpeg中的h.264 decoder源码。对于新手来说,还是挺有挑战性的,因为视频播放框架基于directShow,必须在VC环境下开发,而ffmpeg源码却采用VC不支持的C99标准,ffmpeg的API库无法直接编译使用。
我的工作计划,可以划分为三个阶段:第一阶段是从网上下载了ffmpeg工程组成员hust_xcl从ffmpeg中剥离的H.264解码器包,可以完全基于VC编译和运行。通过它验证了采用ffmpeg的H.264 decoder,以紧耦合方式调用播放,没有帧间延迟。虽然解决了稳定性,但是视频质量稍差,并且性能低,在我的双核N卡机子上解码D1只能达到110fps。经过分析,觉得是源码版本过于陈旧,而且不支持CPU加速指令。其间,还试验了hax264和ffdshow-tryout中的VC工程源码,视频质量有所改善,但是性能方面改善有限,解码D1提高到130fps。
在第二阶段中,采用ffmpeg-0.5版,在mingw环境下采用gcc编译,然后调用VC链接,生成可被VC所使用的动态库。之所以这样做,是因为ffmpeg所带的CPU汇编优化指令,VC无法支持。gcc编译器生成的文件明显要比VC大,通过ffmpeg默认编译生成的libavcodec.dll文件居然有11M之多。只好在configure中增加许多限制选项,找到一种合适的选项组合:
./configure --disable-static --enable-shared --enable-memalign-hack --disable-debug --disable-network --disable-vhook --disable-muxers --disable-mpegaudio-hp --disable-ffserver --disable-ffplay --disable-filters --disable-devices --disable-protocols --disable-demuxers --disable-muxers --disable-encoders --disable-decoders --disable-parsers --disable-bsfs --enable-decoder=h264
通过以上方式所生成的libavcodec.dll减小到1.6MB,性能方面也显著提高,在SSE3指令加速下,解码D1达到210fps,比第一阶段提高了60%。
虽然第二阶段提高了不少,但与商业版解码器相比,还是有明显差距的。coreavc在同样环境下,软解可以达到300fps,在GT8600显卡支持下的CUDA运行模式更是高达360fps。第三阶段还正在实施中,基于当前的ffmpeg-mt源码进行,CPU加速指令不仅可以升级到SSE4.2,而且支持多核处理,性能将会更上一个台阶。
开源的东东虽然鼓捣起来经常走弯路,缺乏稳定可预测的开发环境,但是深入下去有时会有意想不到的成就感。