返回介绍

3.3 Prepare

发布于 2024-12-23 21:17:30 字数 2878 浏览 0 评论 0 收藏 0

通过之前的经验我们可以很快的知道 prepare 应该对应的是 AwesomePlayer 中的 prepare:

status_t AwesomePlayer::prepare() {
  ...
  return prepare_l();

}

status_t AwesomePlayer::prepare_l() {
  ...
  status_t err = prepareAsync_l();
  ...
  return mPrepareResult;
}

status_t AwesomePlayer::prepareAsync_l() {
  if (mFlags & PREPARING) {
    return UNKNOWN_ERROR;  // async prepare already pending
  }
  if (!mQueueStarted) {
    mQueue.start();
    mQueueStarted = true;
  }
  modifyFlags(PREPARING, SET);
  mAsyncPrepareEvent = new AwesomeEvent(
      this, &AwesomePlayer::onPrepareAsyncEvent);
  mQueue.postEvent(mAsyncPrepareEvent);
  return OK;
}

mQueue 是 TimedEventQueue ,TimedEventQueue 和 Handler 很相似,使用 pthread 和 队列来管理消息。在这里通过异步方式回调 onPrepareAsyncEvent 方法:

void AwesomePlayer::onPrepareAsyncEvent() {
  Mutex::Autolock autoLock(mLock);
  beginPrepareAsync_l();
}
void AwesomePlayer::beginPrepareAsync_l() {
	// 取消 prepare
  if (mFlags & PREPARE_CANCELLED) {
    ALOGI("prepare was cancelled before doing anything");
    abortPrepare(UNKNOWN_ERROR);
    return;
  }
	// 网络媒体
  if (mUri.size() > 0) {
    status_t err = finishSetDataSource_l();
    if (err != OK) {
      abortPrepare(err);
      return;
    }
  }
	// 是否包含视频
  if (mVideoTrack != NULL && mVideoSource == NULL) {
  	// 初始化视频解码器
    status_t err = initVideoDecoder();
    if (err != OK) {
      abortPrepare(err);
      return;
    }
  }
	// 是否包含音频
  if (mAudioTrack != NULL && mAudioSource == NULL) {
  	// 初始化音频解码器
    status_t err = initAudioDecoder();
    if (err != OK) {
      abortPrepare(err);
      return;
    }
  }
  modifyFlags(PREPARING_CONNECTED, SET);
	// 不同的播放源类型
  if (isStreamingHTTP()) {
  	// 网络流媒体
    postBufferingEvent_l();
  } else {
  	// 本地媒体
    finishAsyncPrepare_l();
  }
}

void AwesomePlayer::finishAsyncPrepare_l() {
  if (mIsAsyncPrepare) {
    if (mVideoSource == NULL) {
      notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
    } else {
      notifyVideoSize_l();
    }
    notifyListener_l(MEDIA_PREPARED);
  }
  // 设置 player 的状态
  mPrepareResult = OK;
  modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
  modifyFlags(PREPARED, SET);
  mAsyncPrepareEvent = NULL;
  // 同步线程之间的状态
  mPreparedCondition.broadcast();
	// mAudioTearDown 默认为 false,当暂停的时候通过回调方法将其改为 true
  if (mAudioTearDown) {
    if (mPrepareResult == OK) {
      if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
        seekTo_l(mAudioTearDownPosition);
      }
      if (mAudioTearDownWasPlaying) {
        modifyFlags(CACHE_UNDERRUN, CLEAR);
        play_l();
      }
    }
    mAudioTearDown = false;
  }
}

经过一番设置后,prepare 的过程也算是完成了。这一部分主要是对 player 的状态进行设置,通过消息机制让让调用端也知道这边的 player 状态。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文