项目中遇到的一个rmvb 播放时的问题,记录一下解决的过程!
1,问题描述
播放器用ffmpeg中rmdec 作为 rmvb的demuxer。FFmpeg的版本为:1.1。
在播放音频编码为 COOK的rmvb文件时,seek之后,前几秒播放的是seek之间的声音。
2,问题分析
起初认为可能是底层decoder或者render在seek后还有缓存的数据,所以让driver engineer进行排查。
但通过对比正常播放与seek后播放时往decoder送的数据,发现两者是不一样的;而且每次从不同的位置seek到同一时间点,传的数据每次也不相同。
因此,排除decoder或render的错误。
接下来要确定到底在哪出了问题,是ffmpeg demuxer本身的问题,还是demuxer后到往decoder送数据之间出了问题?
刚开始认识demuxer出问题的可能性不大,因为ffmpeg相对已经比较成熟啦。为此特意下载一个比较新的版本ffmpeg2.0进行查看。
经过对比,demuxer的改动并不大,唯一比较大的是新添加了一个seek函数,但是这个函数其实还是函数调用utils.c的相关函数,跟没添加之前基本相同,未发现异常。
通过对比seek后,从demuxer读到的数据以及传给decoder的数据,发现两者是一样。
因此,断定demxuer本身出了问题。
天啊,竟然是ffmpeg的问题。这是万万没有想到的,因为ffmpeg也是刚开始用,还没有仔细看过研究过demuxer,所以感到一头雾水。
没有办法,问题还是要要解的,只能硬着头皮看代码喽。
突然一句话,引起我的注意。
if (rm->audio_pkt_cnt) {
// If there are queued audio packet return them first
st = s->streams[rm->audio_stream_num];
res = ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
if(res < 0)
return res;
flags = 0;
}
因此,怀疑可能跟audio_pkt_cnt有关。
此时,想到了上面提到ffmpeg2.0新添加的seek函数,于是又去查看一次。发现seek里,将rm->audio_pkt_cnt赋值为:0.
代码如下:
static int rm_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
{
RMDemuxContext *rm = s->priv_data;
if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0)
return -1;
rm->audio_pkt_cnt = 0;
return 0;
}
因此,基本可以下结论啦,同时修改方法也有啦!有点小激动!!!
第二天到公司一试,果不其然,问题解决啦!
大功告成!