5步告诉你QQ音乐的完美音质是怎么来的,播放器的秘密都在这里

不久前,团队发现其Android平台App在播放MV视频《凤凰花开的路口》时,会带有如电流声一般的杂音,这影响了用户体验。 研发同学在初步定位时,发现有如下特征:

Android平台杂音问题必现;

iOS、PC平台能正常播放,没有噪音。

然而,各平台都是统一用HLS格式播放,即源头都是一样的。对于该问题,我们的定位思路如下:

梳理视频播放流程;

找到切入点排查。

二、播放流程概览

img

分析播放流程如上图(图中内容从左往右),概括其关键步骤如下:

播放器初始化:

创建读数据线程:read_thread;

创建存放audio解码前数据的队列:audioq;

创建存放audio解码后数据的队列:sampq。

数据读取:

①创建context;

②探测协议类型:avformat_open_input;

③探测媒体类型:avformat_find_stream_info;

④获取音视频流:av_find_best_stream;

⑤打开媒体解码器:stream_component_open;

⑥读取媒体数据,获得AVPacket:av_read_frame(ic, pkt);

⑦音视频数据分别送入audioq中;

重复⑥、⑦步骤到数据完毕。

音频解码:

在audio_thread中对audioq中的数据进行decoder_decode_frame解码;

解码后的帧AVFrame存放到sampq中;

音频播放:

aout_thread_n中,通过调用回调接口sdl_audio_callback,对sampq中的音频帧数据进行解码成PCM数据;

写入PCM数据到buffer数组,并由AudioTrack播放。

三、问题分解与切入

在梳理出播放流程后,标记出找到有可能出错的环节,方便进行“分层定位”(图中黄色标记)

播放下载文件是否有问题;

数据读取是否有问题;

音频解码逻辑是否有问题;

AudioTrack的设置是否有问题;

接下来,根据难易程度,对上述环节逐个验证。

1、播放下载文件是否正常

把Android平台播放的ts文件与各平台的进行比对,发现两者一样,该环节正常。

2、AudioTrack设置是否正常

通过日志检查AudioTrack以下配置参数:

采样率

位深

频道

以上参数设置的值与音频流的相符合,该环节正常。

3、音频解码逻辑是否有问题

验证解码逻辑是否有问题,可以通过对PCM数据进行分析来确认。 对aout_thread_n进行修改,将PCM数据额外输出到本地,并与正常的PCM数据进行对比。

正常PCM数据频谱图:

img

异常PCM数据频谱图:

img

正常PCM数据波形图:

img

异常PCM数据波形图:

img

对比分析可得出:

从频谱图中看出,异常的PCM在人耳十分敏感的频响(1000~8000Hz )区域内的音频数据严重缺失,导致“杂音问题”

从波形图中看出,异常的与正常的无声区和有声区都吻合,若解封装、解码逻辑出现异常,极大几率是呈现无波动(一条直线的形式)情况。因此可以先大胆假设解码、解封装逻辑是符合预期的

若解码逻辑正常,再结合之前已经验证文件下载正常。可以推测是数据读取环节出现异常

4、数据读取是否有问题

通过对数据读取的各步骤增加日志后,发现在av_find_best_stream音频流选择时出现异常: ffmpeg -i 发现,该视频ts分片有2个音频流

img

通过强制分别读取两条音频流数据播放,发现:

第一条正常播放(PCM数据正常)

第二条播放杂音(PCM数据异常)

Android平台选择了第二条进行播放

基于此,也就验证了在第3步中的假设是正确的。

由上分析,可以得出结论:Android平台选择了第二条数据有问题的流进行播放。

四、问题根源:音频流选择 1、选择方式

分析代码,大致如下所列,av_find_best_stream函数选择音频流,该函数会根据2个主要参数进行选择:

各音频流的在探测媒体类型(avformat_find_stream_info)时,额外解码出来的帧数(选择多的)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgfjd.html