Android ExoPlayer 音画同步代码分析

一、音画同步

音画同步是一项非常重要的工作,但音画同步涉及多种方式,由于场景的需要,每种方式有所区别。音画同步一般都是以Audio Master方式为主,人体对声音的敏感度超过视觉,这也是以音频为主的方式,当然未必一定是固定的方式,根据场景进行定制开发。

二、常见的音同步方式

【1】获取音频的PositionUs ,先Seek视频 ,再Seek音频

这种方式本质上画面和视频都会产生卡顿,之所以两次Seek的原因是视频的GOP不确定性以及关键帧的查找相对音频比较复杂,显然Seek视频反有可能达不到预期,再次Seek音频进行兜底处理。

优点:简单

确定:体验很差

【2】获取音频或者视频的PositionUs

计算时间差值,快的一方WAIT(或pause),时间差之后Resume

优点:难度一般

确定:控制复杂

【3】视频丢帧

这种方式一般是常见的播放器实现方式,以音频控制时间为准。

优点:体验较好

确定:计算复杂

【4】变速同步

以音频时间播放为准,修改视频播放速度

优点:体验较好,视频快时视频减速,视频慢时视频加速

缺点:需要兼容各种播放器状态。

三、ExoPlayer 音画同步

3.1 为什么说ExoPlayer是以音频为准

ExoPlayer重我们知道,其本身是有是时钟的,使用时钟的好处是避免了AudioTrack#getPlayHeadPosition的两个问题,一个是只能增大,不能后退的问题,第二个原因是部分杂牌设备对getPlayHeadPosition的适配不敬人意,存在前后抖动的问题,这对音画同步而言简直就是灾难性的。

在ExoPlayer中com.google.android.exoplayer2.audio.BaseRenderer#getMediaClock方法是空实现,但是在子类重视频依然返回null,只有音频进行了实现

com.google.android.exoplayer2.audio.MediaCodecAudioRenderer#getMediaClock()。

@Override
@Nullable
public MediaClock getMediaClock() {
  return this;
}

这也证明了存在音频Track时以音频为准,当然如果没有音频Track,ExoPlayer中会使用自然时钟StandaloneMediaClock。下面是Render时钟选择,空时钟的视频Render最终被排除掉

public void onRendererEnabled(Renderer renderer) throws ExoPlaybackException {
  @Nullable MediaClock rendererMediaClock = renderer.getMediaClock(); //只有音频的不为空
  if (rendererMediaClock != null && rendererMediaClock != rendererClock) { 
    if (

你可能感兴趣的:(ffmpeg)