- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
3.4 start
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 播放音频。
播放的过程到这里就结束了,接下来暂停和结束的部分就相对简单了。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论