Audio播放流程(二)---NuPlayer流程之setDataSource

在这里插入图片描述
先看看setDataSource从客户端传递到服务端的过程

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)  
{  
    status_t err = UNKNOWN_ERROR;  
    const sp<IMediaPlayerService>& service(getMediaPlayerService());  
    if (service != 0) {  
        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));  
        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||  
            (NO_ERROR != player->setDataSource(fd, offset, length))) {  
            player.clear();  
        }  
        err = attachNewPlayer(player);  
    }  
    return err;  
}  

getMediaPlayerService()为一个典型的Binder机制向ServiceManager获取服务的方法,service->create(this, mAudioSessionId),先看create方法在IMediaPlayerService.cpp中的实现:

virtual sp<IMediaPlayer> create(  
        const sp<IMediaPlayerClient>& client, int audioSessionId) {  
    Parcel data, reply;  
    data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());  
    data.writeStrongBinder(client->asBinder());  
    data.writeInt32(audioSessionId);  
  
    remote()->transact(CREATE, data, &reply);  
    return interface_cast<IMediaPlayer>(reply.readStrongBinder());  
}  

这里只是Binder客户端的实现,其最终实现会在MediaPlayerService.cpp中由服务端MediaPlayerService来实现。

sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
        audio_session_t 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());

    ALOGE("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;
}

综合上面两点,spplayer(service->create(this, mAudioSessionId));中player实际上是一个Client类型对象的proxy。其具体实现都在Client中实现。
player->setDataSource(fd, offset, length)就可以直接到MediaPlayerService.cpp中的Client类中来看其具体实现了。

status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
	...
	//根据文件类型选择用于播放的播放器类型
    player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                               fd,
                                                               offset,
                                                               length);
    sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    if (p == NULL) {
        return NO_INIT;
    }

    // now set data source
    setDataSource_post(p, p->setDataSource(fd, offset, length));
    return mStatus;
}

上面需要留意的是getPlayerType这个方法是根据文件的类型从MediaPlayerFactory(多媒体的播放器仓库中) 选择合适的播放器来进行音频的播放,看下这个枚举类型如下:

enum player_type {
    STAGEFRIGHT_PLAYER = 3,
    NU_PLAYER = 4,
    // Test players are available only in the 'test' and 'eng' builds.
    // The shared library with the test player is passed passed as an
    // argument to the 'test:' url in the setDataSource call.
    TEST_PLAYER = 5,
    DASH_PLAYER = 6,
};

里面有4种类型,当前我们MP3播放,系统选择的是NU_PLAYER(至于为什么选择它不在本篇文章的分析的范围内,也是为了流程的清晰性)

之后分析setDataSource_pre的过程

sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
        player_type playerType)
{
    ALOGE("player type = %d", playerType);

    // create the right type of player
    sp<MediaPlayerBase> p = createPlayer(playerType);
    if (p == NULL) {
        return p;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.extractor"));
    if (binder == NULL) {
        ALOGE("Unable to connect to media extractor service");
        return NULL;
    }

    mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
    binder->linkToDeath(mExtractorDeathListener);

    binder = sm->getService(String16("media.codec"));
    if (binder == NULL) {
        ALOGE("Unable to connect to media codec service");
        return NULL;
    }

    mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
    binder->linkToDeath(mCodecDeathListener);

    if (!p->hardwareOutput()) {
        Mutex::Autolock l(mLock);
        mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
                mPid, mAudioAttributes);
        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
    }

    return p;
}

如下是创建的NuPlayer的播放器

sp p = createPlayer(playerType);

这里的setDataSource会走到NuPlayer的setDataSourceAsync方法中,原因如下:

MediaPlayerService::MediaPlayerService()
{
	...
	MediaPlayerFactory::registerBuiltinFactories();
}
void MediaPlayerFactory::registerBuiltinFactories() {

    MediaPlayerFactory::IFactory* pCustomFactory = NULL;
    Mutex::Autolock lock_(&sLock);

    if (sInitComplete)
        return;

    registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
    registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
    AVMediaServiceUtils::get()->getDashPlayerFactory(pCustomFactory, DASH_PLAYER);
    if(pCustomFactory != NULL) {
        ALOGV("Registering DASH_PLAYER");
        registerFactory_l(pCustomFactory, DASH_PLAYER);
    }

    sInitComplete = true;
}
....
virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
	ALOGV(" create NuPlayer");
	return new NuPlayerDriver(pid);
}
...
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
    ALOGV("setDataSource(%p) file(%d)", this, fd);
    Mutex::Autolock autoLock(mLock);
    ...
    mPlayer->setDataSourceAsync(fd, offset, length);
	...
}

最后DataSource会在NuPlayer中完成设定

frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.h

void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);

    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);

    sp<GenericSource> source =
            new GenericSource(notify, mUIDValid, mUID);

    status_t err = source->setDataSource(fd, offset, length);

    if (err != OK) {
        ALOGE("Failed to set data source!");
        source = NULL;
    }

    msg->setObject("source", source);
    msg->post();
}
...
status_t NuPlayer::GenericSource::setDataSource(
        int fd, int64_t offset, int64_t length) {
    resetDataSource();

    mFd = dup(fd);
    mOffset = offset;
    mLength = length;

    // delay data source creation to prepareAsync() to avoid blocking
    // the calling thread in setDataSource for any significant time.
    return OK;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值