测试发现一首歌曲无法seek,每次拖动到任意位置,都弹回到最开始处然后播放。
1:首先确定seek到的时间有没有传递到底层去,因为是本地纯音频播放,所以直接到AudioPlayer中加个log看看
status_t AudioPlayer::seekTo(int64_t time_us) {
}
通过打log,seek的时间正常传递了过来,并且更新了蓝色部分的两个值。
2:然后就分析buffer的读取了,buffer的读取是在fillBuffer里面循环读取的,当然做了seek操作和没有seek操作会有一点区别:
size_t AudioPlayer::fillBuffer(void *data, size_t size) {
}
如果发生seek的话,options会携带要seek到的位置,加seek的模式传递到mSource的read函数中,我们知道每一种流都会对应一种流,我们这里的音频文件的mime是video/m4a格式的,其选择的解析器是MPEG4Extractor以及流是MPEG4Source,看其read部分的部分代码:
通过分析这段代码问题找到了
seek的情况处理如下:
1:取出options里面的seekTimeUs和mode;
2:根据seekTimeUs找到对应的sample的sampleIndex,打log发现这块是没有问题的,index找对了;
3:通过sampleIndex找syncSampleIndex,打log发现,这块有问题,syncSampleIndex每次都是0;
4:将syncSampleIndex赋给mCurrentSampleIndex;
5:通过mCurrentSampleIndex得到对应的sample的size,offset等信息
由于syncSampleIndex获取每次都是0,mCurrentSampleIndex也就是0,也就是第一帧,所以每次都是从0开始播放,至于为什么是零,在SampleTable中打log发现,这首歌曲关键帧列表是空的,也就是没有关键帧。对于avc格式的音视频资源来说,播放都要从附近的关键帧开始播放,没有关键帧就乱套了。
对于视频流,会分配很多关键帧;
对于音频流,默认所有的帧都是关键帧。
解决方法
加判断,对于这种没有关键帧的audio,特殊处理,略。
以前还分析过,由于码率不对,导致无法seek的情况,正常高品质MP3文件对应的码率是320,但是由于编码导致的问题,文件中读取出来的码率却是32,导致通过码率计算出来的时间戳都不对,导致seek失败。