//下面是一個典型的播放序列: MediaPlayer player=new MediaPlayer() player->setDataSource(url,header); player->prepare(); player->start(); ... //使用MediaPlayerServcie的Client對象設置數據源 status_t MediaPlayer::setDataSource( const char *url, const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); status_t err = BAD_VALUE; if (url != NULL) { //1、獲得MediaPlayerService const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { //2、返回MediaPlayerService的Client對象player,並保存在Service的數組對象中, //后續使用該Client將向MediaPlayer提供服務,因此每個MediaPlayer都對應一個Client sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); //3、選擇正確的播放器,並設置播放器的數據源 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || (NO_ERROR != player->setDataSource(url, headers))) { player.clear(); } //4、保存最新的Client對象,斷開之前Client對象 err = attachNewPlayer(player); } } return err; } 1、獲取MeidaPlayerSercie /*static*/const sp<IMediaPlayerService>& IMediaDeathNotifier::getMediaPlayerService() { ALOGV("getMediaPlayerService"); Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { //獲得BpServiceManager對象 sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } ALOGW("Media player service not published, waiting..."); usleep(500000); // 0.5 s } while (true); if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } //通過Bind獲取BpMediaPlayerService對象 binder->linkToDeath(sDeathNotifier); sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); } ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); return sMediaPlayerService; } 2、構造MediaPlayerService的Client對象 sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client, int audioSessionId) { pid_t pid = IPCThreadState::self()->getCallingPid(); int32_t connId = android_atomic_inc(&mNextConnId); sp<Client> c = new Client( this, pid, connId, client, audioSessionId, IPCThreadState::self()->getCallingUid()); ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid, IPCThreadState::self()->getCallingUid()); wp<Client> w = c; { Mutex::Autolock lock(mLock); mClients.add(w); } return c; } //保存Client端的AudioSessionId等信息 MediaPlayerService::Client::Client( const sp<MediaPlayerService>& service, pid_t pid, int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId, uid_t uid) { ALOGV("Client(%d) constructor", connId); mPid = pid; mConnId = connId; mService = service; mClient = client; mLoop = false; mStatus = NO_INIT; mAudioSessionId = audioSessionId; mUID = uid; mRetransmitEndpointValid = false; #if CALLBACK_ANTAGONIZER ALOGD("create Antagonizer"); mAntagonizer = new Antagonizer(notify, this); #endif } //通過url獲取對應的播放器,然后保存該播放器,並設置播放器的數據源 status_t MediaPlayerService::Client::setDataSource( const char *url, const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); if (url == NULL) return UNKNOWN_ERROR; if ((strncmp(url, "http://", 7) == 0) || (strncmp(url, "https://", 8) == 0) || (strncmp(url, "rtsp://", 7) == 0)) { if (!checkPermission("android.permission.INTERNET")) { return PERMISSION_DENIED; } } if (strncmp(url, "content://", 10) == 0) { // get a filedescriptor for the content Uri and // pass it to the setDataSource(fd) method String16 url16(url); int fd = android::openContentProviderFile(url16); if (fd < 0) { ALOGE("Couldn't open fd for %s", url); return UNKNOWN_ERROR; } setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus close(fd); return mStatus; } else { //通過url獲取對應的播放器 player_type playerType = MediaPlayerFactory::getPlayerType(this, url); sp<MediaPlayerBase> p = setDataSource_pre(playerType); if (p == NULL) { return NO_INIT; } setDataSource_post(p, p->setDataSource(url, headers)); return mStatus; } } //通過播放器工廠的scoreFactory函數判斷該播放器是否合適,選擇播放器類型 #define GET_PLAYER_TYPE_IMPL(a...) \ Mutex::Autolock lock_(&sLock); \ \ player_type ret = STAGEFRIGHT_PLAYER; \ float bestScore = 0.0; \ \ for (size_t i = 0; i < sFactoryMap.size(); ++i) { \ \ IFactory* v = sFactoryMap.valueAt(i); \ float thisScore; \ CHECK(v != NULL); \ thisScore = v->scoreFactory(a, bestScore); \ if (thisScore > bestScore) { \ ret = sFactoryMap.keyAt(i); \ bestScore = thisScore; \ } \ } \ \ if (0.0 == bestScore) { \ ret = getDefaultPlayerType(); \ } \ \ return ret; player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, const char* url) { GET_PLAYER_TYPE_IMPL(client, url); } //這里如果所有播放器都不合適,則選擇默認播放器這里流程是, //從播放器倉庫中選取最佳播放器,通過scoreFactory來確定 player_type MediaPlayerFactory::getDefaultPlayerType() { char value[PROPERTY_VALUE_MAX]; if (property_get("media.stagefright.use-nuplayer", value, NULL) && (!strcmp("1", value) || !strcasecmp("true", value))) { return NU_PLAYER; } return STAGEFRIGHT_PLAYER; }
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( player_type playerType) { ALOGV("player type = %d", playerType); // create the right type of player sp<MediaPlayerBase> p = createPlayer(playerType); if (p == NULL) { return p; } //根據AudioSessionId設置播放器的輸出端 if (!p->hardwareOutput()) { mAudioOutput = new AudioOutput(mAudioSessionId); static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); } return p; } sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType) { // determine if we have the right player type sp<MediaPlayerBase> p = mPlayer; if ((p != NULL) && (p->playerType() != playerType)) { ALOGV("delete player"); p.clear(); } if (p == NULL) { p = MediaPlayerFactory::createPlayer(playerType, this, notify); } if (p != NULL) { p->setUID(mUID); } return p; } //主要是創建播放器 //上面看具體StagefrightPlayerFactory 實現的時候,代碼中實現了createPlayer,此處就是調用的此方法 //因此等價於return (new StagefrightPlayer()) ; void MediaPlayerService::Client::setDataSource_post( const sp<MediaPlayerBase>& p, status_t status) { ALOGV(" setDataSource"); mStatus = status; if (mStatus != OK) { ALOGE(" error: %d", mStatus); return; } // Set the re-transmission endpoint if one was chosen. if (mRetransmitEndpointValid) { mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint); if (mStatus != NO_ERROR) { ALOGE("setRetransmitEndpoint error: %d", mStatus); } } if (mStatus == OK) { mPlayer = p; } } //setDataSource_post(p, p->setDataSource(source)) //設置播放器的數據源,因為實際的視屏播放是由該播放器完成 status_t StagefrightPlayer::setDataSource( const char *url, const KeyedVector<String8, String8> *headers) { return mPlayer->setDataSource(url, headers); } status_t AwesomePlayer::setDataSource( const char *uri, const KeyedVector<String8, String8> *headers) { Mutex::Autolock autoLock(mLock); return setDataSource_l(uri, headers); } status_t AwesomePlayer::setDataSource_l( const char *uri, const KeyedVector<String8, String8> *headers) { reset_l(); mUri = uri; if (headers) { mUriHeaders = *headers; ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); if (index >= 0) { // Browser is in "incognito" mode, suppress logging URLs. // This isn't something that should be passed to the server. mUriHeaders.removeItemsAt(index); modifyFlags(INCOGNITO, SET); } } ALOGI("setDataSource_l(URL suppressed)"); // The actual work will be done during preparation in the call to // ::finishSetDataSource_l to avoid blocking the calling thread in // setDataSource for any significant time. { Mutex::Autolock autoLock(mStatsLock); mStats.mFd = -1; mStats.mURI = mUri; } return OK; } //4、保存新的MediaPlayerService的Client對象,並斷開之前的Client和Service status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player) { status_t err = UNKNOWN_ERROR; sp<IMediaPlayer> p; { // scope for the lock Mutex::Autolock _l(mLock); if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) || (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) { ALOGE("attachNewPlayer called in state %d", mCurrentState); return INVALID_OPERATION; } //重置相關參數 clear_l(); p = mPlayer; mPlayer = player;//更新Client屬性 if (player != 0) { mCurrentState = MEDIA_PLAYER_INITIALIZED; err = NO_ERROR; } else { ALOGE("Unable to create media player"); } } //斷開之前的Client if (p != 0) { p->disconnect(); } return err; } // always call with lock held void MediaPlayer::clear_l() { mCurrentPosition = -1; mSeekPosition = -1; mVideoWidth = mVideoHeight = 0; mRetransmitEndpointValid = false; } void MediaPlayerService::Client::disconnect() { ALOGV("disconnect(%d) from pid %d", mConnId, mPid); // grab local reference and clear main reference to prevent future // access to object sp<MediaPlayerBase> p; { Mutex::Autolock l(mLock); p = mPlayer;//播放器對象,如StagefrightPlayer mClient.clear();//MdediaPlayer對象 } mPlayer.clear(); // clear the notification to prevent callbacks to dead client // and reset the player. We assume the player will serialize // access to itself if necessary. if (p != 0) { p->setNotifyCallback(0, 0); #if CALLBACK_ANTAGONIZER ALOGD("kill Antagonizer"); mAntagonizer->kill(); #endif p->reset();//調用具體播放器的reset函數,如 } disconnectNativeWindow(); IPCThreadState::self()->flushCommands(); } void MediaPlayerService::Client::disconnectNativeWindow() { if (mConnectedWindow != NULL) { status_t err = native_window_api_disconnect(mConnectedWindow.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); } } mConnectedWindow.clear(); } status_t StagefrightPlayer::reset() { ALOGV("reset"); mPlayer->reset(); return OK; } //具體的reset操作,不同的播放器有不同的實現 void AwesomePlayer::reset_l() { mVideoRenderingStarted = false; mActiveAudioTrackIndex = -1; mDisplayWidth = 0; mDisplayHeight = 0; if (mDecryptHandle != NULL) { mDrmManagerClient->setPlaybackStatus(mDecryptHandle, Playback::STOP, 0); mDecryptHandle = NULL; mDrmManagerClient = NULL; } if (mFlags & PLAYING) { uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { params |= IMediaPlayerService::kBatteryDataTrackAudio; } if (mVideoSource != NULL) { params |= IMediaPlayerService::kBatteryDataTrackVideo; } addBatteryData(params); } if (mFlags & PREPARING) { modifyFlags(PREPARE_CANCELLED, SET); if (mConnectingDataSource != NULL) { ALOGI("interrupting the connection process"); mConnectingDataSource->disconnect(); } if (mFlags & PREPARING_CONNECTED) { // We are basically done preparing, we're just buffering // enough data to start playback, we can safely interrupt that. finishAsyncPrepare_l(); } } while (mFlags & PREPARING) { mPreparedCondition.wait(mLock); } cancelPlayerEvents(); mWVMExtractor.clear(); mCachedSource.clear(); mAudioTrack.clear(); mVideoTrack.clear(); mExtractor.clear(); // Shutdown audio first, so that the respone to the reset request // appears to happen instantaneously as far as the user is concerned // If we did this later, audio would continue playing while we // shutdown the video-related resources and the player appear to // not be as responsive to a reset request. if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) && mAudioSource != NULL) { // If we had an audio player, it would have effectively // taken possession of the audio source and stopped it when // _it_ is stopped. Otherwise this is still our responsibility. mAudioSource->stop(); } mAudioSource.clear(); mTimeSource = NULL; delete mAudioPlayer; mAudioPlayer = NULL; if (mTextDriver != NULL) { delete mTextDriver; mTextDriver = NULL; } mVideoRenderer.clear(); if (mVideoSource != NULL) { shutdownVideoDecoder_l(); } mDurationUs = -1; modifyFlags(0, ASSIGN); mExtractorFlags = 0; mTimeSourceDeltaUs = 0; mVideoTimeUs = 0; mSeeking = NO_SEEK; mSeekNotificationSent = true; mSeekTimeUs = 0; mUri.setTo(""); mUriHeaders.clear(); mFileSource.clear(); mBitrate = -1; mLastVideoTimeUs = -1; { Mutex::Autolock autoLock(mStatsLock); mStats.mFd = -1; mStats.mURI = String8(); mStats.mBitrate = -1; mStats.mAudioTrackIndex = -1; mStats.mVideoTrackIndex = -1; mStats.mNumVideoFramesDecoded = 0; mStats.mNumVideoFramesDropped = 0; mStats.mVideoWidth = -1; mStats.mVideoHeight = -1; mStats.mFlags = 0; mStats.mTracks.clear(); } mWatchForAudioSeekComplete = false; mWatchForAudioEOS = false; }
以上調用流程:
MediaPlayer(JAVA層)->MediaPlayer(C層)->Client->MediaPlayService->StagefrightPlayer->AwesomePlayer
最終所有對應具體文件的操作都需要AwesomePlayer落實,如:
prepare
play
pause
總結下幾種播放器的區別
StagefrightPlayer: 默認播放器,本地文件基本都使用其播放
NuPlayerDriver:主要用於播放網絡視頻,http https rtsp等
SonivoxPlayer:用於播放midi等類型的音樂