Exoplayer(4)-Exoplayer启动和轮询流程

Exoplayer启动过程

ExoplayerImpl.prepare() →
ExoPlayerImplInternal.prepare() ->
ExoPlayerImplInternal.prepareInternal() ->
ExoPlayerImplInternal.doSomeWork()

ExoplayerImpl

public void prepare() {
    //如果非STATE_IDLE 状态直接返回   
    if (playbackInfo.playbackState != Player.STATE_IDLE) {
      return;
    }
 
    //调用ExoPlayerImplInternal.prepare()
    internalPlayer.prepare();
  }

ExoPlayerImplInternal

public void prepare() {
    //发送MSG_PREPARE 消息
    handler.obtainMessage(MSG_PREPARE).sendToTarget();
}
 
public boolean handleMessage(Message msg) {
  switch (msg.what) {
        case MSG_PREPARE:
          prepareInternal();
}
 
private void prepareInternal() {
    //设置播放器状态 Player.STATE_BUFFERING
    setState(playbackInfo.timeline.isEmpty() ? Player.STATE_ENDED : Player.STATE_BUFFERING);
    //发送MSG_DO_SOME_WORK消息
    handler.sendEmptyMessage(MSG_DO_SOME_WORK);
}
 
public boolean handleMessage(Message msg) {
   switch (msg.what) {
        case MSG_DO_SOME_WORK:
          doSomeWork();
}

doSomeWork()

/*
 *  doSomeWork()的核心逻辑,
 *  1. 每隔ACTIVE_INTERVAL_MS, 检测和打开数据流,
 *  2. 开启渲染器渲染
 *  3. 检测和校验播放条件设置播放状态
 */
 
private void doSomeWork() throws ExoPlaybackException, IOException {
    //移除MSG_DO_SOME_WORK 消息
    handler.removeMessages(MSG_DO_SOME_WORK);
 
    //查询媒和打开MediaSourceList中保存到媒体数据源,
    updatePeriods();
   
    /* 尝试获取在updatePeriods()中打开的数据源, playingPeriodHolder 可以理解为打开的数据源
     * 如果获取播放中的数据源为空,ACTIVE_INTERVAL_MS间隔后重新尝试调用 doSomeWork()
     * 同时返回,不再执行后续逻辑
     */
    MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
    if (playingPeriodHolder == null) {
      scheduleNextWork(operationStartTimeMs, ACTIVE_INTERVAL_MS);
      return;
    }
 
    //更新播放进度
    updatePlaybackPositions();
 
    boolean renderersEnded = true;
    boolean renderersAllowPlayback = true;
    if (playingPeriodHolder.prepared) {
      //当前渲染器开渲染时间
      long rendererPositionElapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
 
      for (int i = 0; i < renderers.length; i++) {
        Renderer renderer = renderers[i];
        if (!isRendererEnabled(renderer)) {
          //如果当前渲染器不支持渲染,跳过循环 (例如纯播放音频过程中,视频Renderer不可用)
          continue;
        }
         
        //开启渲染器
        renderer.render(rendererPositionUs, rendererPositionElapsedRealtimeUs);
        //渲染是否结束
        renderersEnded = renderersEnded && renderer.isEnded();
        //是否预加载数据
        boolean isReadingAhead = playingPeriodHolder.sampleStreams[i] != renderer.getStream();
        //是否等待下一个视频播放
        boolean isWaitingForNextStream = !isReadingAhead && renderer.hasReadStreamToEnd();
        //是否允许播放
        boolean allowsPlayback =
            isReadingAhead || isWaitingForNextStream || renderer.isReady() || renderer.isEnded();
        //允许渲染,
        renderersAllowPlayback = renderersAllowPlayback && allowsPlayback;
        if (!allowsPlayback) {
          //不允许渲染,抛出异常 
          renderer.maybeThrowStreamError();
        }
      }
    } else {
      //如果打开的数据源没准备好,抛出异常
      playingPeriodHolder.mediaPeriod.maybeThrowPrepareError();
    }
 
    long playingPeriodDurationUs = playingPeriodHolder.info.durationUs;
    boolean finishedRendering =
        renderersEnded
            && playingPeriodHolder.prepared
            && (playingPeriodDurationUs == C.TIME_UNSET
                || playingPeriodDurationUs <= playbackInfo.positionUs);
     
    if (finishedRendering && playingPeriodHolder.info.isFinal) {
      /* 如果是视频序列的最后一个视频正在结束渲染, 设置播放器为STATE_ENDED 状态,
       * 关闭所有的渲染器
       */
      setState(Player.STATE_ENDED);
      stopRenderers();
    } else if (playbackInfo.playbackState == Player.STATE_BUFFERING
        && shouldTransitionToReadyState(renderersAllowPlayback)) {
      //如果缓存状态,并且要切换到渲染, 设置播放器状态为STATE_READY
      setState(Player.STATE_READY);
      if (shouldPlayWhenReady()) {
        //开启渲染
        startRenderers();
      }
    } else if (playbackInfo.playbackState == Player.STATE_READY
        && !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
      // STATE_READY状态下,如果不允许渲染,切换播放器状态为缓冲态STATE_BUFFERING
      isRebuffering = shouldPlayWhenReady();
      setState(Player.STATE_BUFFERING);
      stopRenderers();
    }
 
    
 
    boolean isPlaying = shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY;
    boolean sleepingForOffload = offloadSchedulingEnabled && requestForRendererSleep && isPlaying;
    if (playbackInfo.sleepingForOffload != sleepingForOffload) {
      playbackInfo = playbackInfo.copyWithSleepingForOffload(sleepingForOffload);
    }
    requestForRendererSleep = false;
 
    if (sleepingForOffload || playbackInfo.playbackState == Player.STATE_ENDED) {
      //离线睡眠或者播放结束,直接返回
      return;
    } else if (isPlaying || playbackInfo.playbackState == Player.STATE_BUFFERING) {
      //播放中或者缓存中,间隔 ACTIVE_INTERVAL_MS时间调用doSomeWork
      scheduleNextWork(operationStartTimeMs, ACTIVE_INTERVAL_MS);
    } else if (playbackInfo.playbackState == Player.STATE_READY && enabledRendererCount != 0) {
      //已经准备好,但是还没开始播放,间隔 ACTIVE_INTERVAL_MS时间调用doSomeWork 
      scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS);
    }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值