//下面是一个典型的播放序列: 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等类型的音乐
时间: 2024-11-05 23:34:38