• Audio笔记之MediaPlayerService:setDataSource


    //下面是一个典型的播放序列:
    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等类型的音乐

  • 相关阅读:
    在App_Data中创建数据库获取连接串简便方法!
    ObjectDataSource配合存储过程(采用数据集)的使用(删除可以解决,但是编辑出错好像它的方法也无法解决
    金鹰dreamweaver视频教程下载地址
    ASP.NET里创建Microsoft Word文档
    net3:Calendar控件的使用
    vs2005做的留言本——天轰川下载
    Wiley出版 SQL Server 2005宝典
    ADO:防止更新的数据含有单引号而出错
    用 Bitcron 搭博客:你只管写作,它负责呈现
    如何去掉Myeclipse对JS等文件的验证
  • 原文地址:https://www.cnblogs.com/shakin/p/4578857.html
Copyright © 2020-2023  润新知