返回介绍

3.4 start

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

Java 代码这边的 start 方法对应的是 StagefrightPlayer 中的 start,其中又调用了 player 的 play 方法

status_t StagefrightPlayer::start() {
  ALOGV("start");
  return mPlayer->play();
}

对应的是 AwesomePlayer 中的 play 方法:

status_t AwesomePlayer::play() {
  ATRACE_CALL();
  Mutex::Autolock autoLock(mLock);
  modifyFlags(CACHE_UNDERRUN, CLEAR);
  return play_l();
}
status_t AwesomePlayer::play_l() {
  modifyFlags(SEEK_PREVIEW, CLEAR);
	// 如果正在播放,则什么也不做
  if (mFlags & PLAYING) {
    return OK;
  }
  mMediaRenderingStartGeneration = ++mStartGeneration;
  // 如果没有之前没有调用 prepare,这里会帮你调用一次,顺便我还做了个实验,create 之后 直接 start 是可以播放的,并没有报错什么的。
  if (!(mFlags & PREPARED)) {
    status_t err = prepare_l();
    if (err != OK) {
      return err;
    }
  }
  modifyFlags(PLAYING, SET);
  modifyFlags(FIRST_FRAME, SET);
  if (mDecryptHandle != NULL) {
    int64_t position;
    getPosition(&position);
    mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
        Playback::START, position / 1000);
  }
  if (mAudioSource != NULL) {
    if (mAudioPlayer == NULL) {
      createAudioPlayer_l();
    }
    CHECK(!(mFlags & AUDIO_RUNNING));
    if (mVideoSource == NULL) {
      // We don't want to post an error notification at this point,
      // the error returned from MediaPlayer::start() will suffice.
      status_t err = startAudioPlayer_l(false /* sendErrorNotification */);
      // 是否可以硬解音频
      if ((err != OK) && mOffloadAudio) {
        ALOGI("play_l() cannot create offload output, fallback to sw decode");
        int64_t curTimeUs;
        getPosition(&curTimeUs);
        delete mAudioPlayer;
        mAudioPlayer = NULL;
        // if the player was started it will take care of stopping the source when destroyed
        if (!(mFlags & AUDIOPLAYER_STARTED)) {
          mAudioSource->stop();
        }
        modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR);
        mOffloadAudio = false;
        mAudioSource = mOmxSource;
        if (mAudioSource != NULL) {
          err = mAudioSource->start();
          if (err != OK) {
            mAudioSource.clear();
          } else {
            mSeekNotificationSent = true;
            if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
              seekTo_l(curTimeUs);
            }
            createAudioPlayer_l();
            // 播放音频
            err = startAudioPlayer_l(false);
          }
        }
      }
      if (err != OK) {
        delete mAudioPlayer;
        mAudioPlayer = NULL;
        modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
        if (mDecryptHandle != NULL) {
          mDrmManagerClient->setPlaybackStatus(mDecryptHandle, Playback::STOP, 0);
        }
        return err;
      }
    }
  }
  // timesource 用于视音频同步,通常来说是根据 audio 中的 timesource 为基准,
  // 这里判断下是否有音频时间和音频播放器,如果没有,则采用系统的时间
  if (mTimeSource == NULL && mAudioPlayer == NULL) {
    mTimeSource = &mSystemTimeSource;
  }
  // 播放视频
  if (mVideoSource != NULL) {
    // Kick off video playback
    postVideoEvent_l();
    if (mAudioSource != NULL && mVideoSource != NULL) {
      postVideoLagEvent_l();
    }
  }
  // 流的结尾
  if (mFlags & AT_EOS) {
    // Legacy behaviour, if a stream finishes playing and then
    // is started again, we play from the start...
    seekTo_l(0);
  }
  uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
    | IMediaPlayerService::kBatteryDataTrackDecoder;
  if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
    params |= IMediaPlayerService::kBatteryDataTrackAudio;
  }
  if (mVideoSource != NULL) {
    params |= IMediaPlayerService::kBatteryDataTrackVideo;
  }
  addBatteryData(params);
  if (isStreamingHTTP()) {
    postBufferingEvent_l();
  }
  return OK;
}

视频的播放是通过不断的 postVideoEvent_l 来实现画面的播放,postVideoEvent_l 会向队列中 post 一个 videoEvent,这个 event 最终又会触发 AwesomePlayer::onVideoEvent 的方法, onVideoEvent 方法中又会调用 postVideoEvent_l,形成循环,最终实现视频的播放。startAudioPlayer_l 最终会调用到 AudioPlayer 播放音频。

播放的过程到这里就结束了,接下来暂停和结束的部分就相对简单了。

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

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

发布评论

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