[原]编程手记2008.08.26

很多时候,探索的结果仅仅是验证某些做法不可行。

播放器中有个步骤是将每帧YUV420的解码数据拷贝到一个输出缓冲区中,然后转换成RGB32、缩放、AlphaBlend、显示。为了优化性能,考虑将那个帧拷贝的步骤去掉,让解码器直接将解码图像写入输出缓冲。

ffmpeg的avcodec_decode_video()在解码时传入一个AVFrame的指针,解码数据存在AVFrame->data[]里。AVFrame由用户调用avcodec_alloc_frame()分配内存,使用完后调用av_free()释放。但是AVFrame->data[]的存储空间既非由avcodec_alloc_frame()分配,也不由用户分配,而是在avcodec_decode_video()解码时分配。

去掉帧拷贝的自然想法就是将输出缓冲的类型设为AVFrame类型。按照这个思路用avcodec_alloc_frame()分配了几个AVFrame,循环利用,每次取队尾的AVFrame送给avcodec_decode_video()。但解码图像播放出来总是不正常,更有些序列播放时呈现出严重抖动的效果,观察发现大约是帧的次序有误(观看几秒钟脑袋就会呈现出晕车的症状,这会还晕着呢)。确认程序逻辑没有错误后,依然半天没找到原因。最后无奈,将所有AVFrame->data[]指向的存储地址打印出来观察,特别是观察了循环一周之后的地址才发现,AVFrame->data[]指向的存储在每次avcodec_decode_video()都会变,而AVFrame->data[]指向的存储在AVFrame未被av_free()释放前就会被重新利用覆盖。。。汗啊。。。ffmpeg咋不按规则出牌呢。。。怀疑是ffmpeg的bug,因为好像是依次顺序偏移了一帧。只好将这个想法放弃,svn revert。。。,昨天半个下午加上今天一个上午的时间都白忙活了。。。


下午将yuv2rgb转换中的计算改为了查表,但效率没升反降了。可能是因为原本就要吸收写显存的时间,而查表又要访问内存。。。还是把计算与写显存掺和更合适吧。。。因此又是svn revert。。。


下午还发现了一个问题。开始是发现播放http链接时cpu占用明显比rtsp链接小一大截。折腾了一个多钟头,终于发现不是播放http链接的cpu占用少,而是http时的播放速率慢了约1/3。由于cpu的约一半占用时间与显示有关,显示速率慢了,cpu占用自然就降了。其实,当时观察到avcodec.dll和swplayer.exe的cpu占用率下降都成比例就该想到这点了,不过也确实有些难以想到。追根溯源,发现是音频播放速度慢而造成的,因为视频是根据音频的播放速度同步的。播放http链接与rtsp链接的不同:http时,无论是压缩数据还是解码数据的缓冲区很快就会满,而rtsp时,压缩数据和解码数据的缓冲区几乎都不会满(音频解码数据的缓冲区也较大)。简单观察貌似也与此有关,但原因还未找到。。。

真奇怪,这个问题这么多天第一次真正的注意到,之前只是模糊的感觉有些序列播起来好像速度有些慢,以为是buf不足的问题,没想到竟是在buf更充足的情况下产生的。。。


总结:今天没什么进展,大部分时间都是在做无用功了,发现了一个问题还未能解决。不过跟据经验在这样的几天之后总会发现又迈进了一大步。。。
原文地址:https://www.cnblogs.com/techsunny/p/1277286.html