MediaPlayer源码介绍2

Android2023年8月7日 am8:09发布12个月前更新 3XCN.COM站长
0 0 0
广告也精彩
目录

前言

之前介绍MediaPlayer ,接上文《MediaPlayer JNI层介绍》(看做《MediaPlayer源码介绍1》)介绍到mediaplayer.cpp,这也是一个代理,真正处理的并不是这个。

今天以setDataSource()为例继续分析。

涉及代码

frameworks\av\media\libmedia\mediaplayer.cpp
frameworks\av\media\libmedia\IMediaPlayerService.cpp
frameworks\av\media\libmedia\IMediaDeathNotifier.cpp
frameworks\native\libs\binder\IServiceManager.cpp
frameworks\native\libs\binder\include\binder\IInterface.h
frameworks\native\libs\binder\include\binder/Binder.h
frameworks\av\media\libmedia\IMediaPlayerService.cpp
frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp
frameworks\av\media\libmedia\IMediaPlayerClient.cpp

正文

MediaPlayer源码介绍2

直接进入mediaplayer.cpp的代码

setDataSource

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length){
    status_t err = UNKNOWN_ERROR;
    // getMediaPlayerService()获取的是BpMediaPlayerService
    // BpMediaPlayerService的对象service
    const sp<IMediaPlayerService> service(getMediaPlayerService());
    if (service != 0) {
        //创建BpMediaPlayer对象player,具体看BpMediaPlayerService中create方法
        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
            (NO_ERROR != player->setDataSource(fd, offset, length))) { //BpMediaPlayer->setDataSource();
            player.clear();
        }
        //赋值,mPlayer = plyaer; //BpMediaPlayer在IMediaPlayer.cpp
        err = attachNewPlayer(player);
    }
    return err;
}

由于跟上一篇太久了,我们重新分析一下。

const sp<IMediaPlayerService> service(getMediaPlayerService());

先看getMediaPlayerService(),这个是在IMediaDeathNotifier.cpp中。

getMediaPlayerService()

IMediaDeathNotifier::getMediaPlayerService(){
    Mutex::Autolock _l(sServiceLock);
    //sMediaPlayerService 是BpMediaPlayerService对象。
    if (sMediaPlayerService == 0) {
        //sm是BpServiceManager的对象
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
           //获取media.player服务的binder
            binder = sm->getService(String16("media.player"));
            if (binder != 0) {
                break;
            }
            //binder空,延迟0.5s再获取
            usleep(500000);
        } while (true);
        if (sDeathNotifier == NULL) {
            sDeathNotifier = new DeathNotifier();
        }
        //服务死亡监听
        binder->linkToDeath(sDeathNotifier);
        //通过这里获取BpMediaPlayerService的对象
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    }
    return sMediaPlayerService;
}

getMediaPlayerService()方法是单例模式,也就值创建一次。一般来说,默认进入sMediaPlayerService == 0,因此先创建。

晕,这有一个defaultServiceManager(),这个在IServiceManager.cpp中。

sp<IServiceManager> sm = defaultServiceManager();
defaultServiceManager()
//BpServiceManager,在interface_cast中进行转换的
sp<IServiceManager> defaultServiceManager(){
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
    return gDefaultServiceManager;
}

也是单例模式,通过之前文章(《interface_cast简介》)对interface_cast有一定的了解,那就可以得出 defaultServiceManager()放回的就是BpServiceManager,也就是ServiceManager的代理。

BpMediaPlayerService

上面可通过BpMediaPlayerService获取到media.player的binder。

sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);

又是interface_cast,由此可知sMediaPlayerService就是BpMediaPlayerService对象。

进入BpMediaPlayerService的构造函数,进入IMediaPlayerService.cpp。

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>{
public:
    explicit BpMediaPlayerService(const sp<IBinder>& impl)
        : BpInterface<IMediaPlayerService>(impl)
    {
    }
}

这里进入了父类BpInterface初始化BpInterface<IMediaPlayerService>(impl),这在IInterface.h中定义。

inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}

又进入父类的BpRefBase出货BpRefBase(remote)

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

经过一步一步父类的赋值,可以看出mRemote就是我们上面获取的binder。

PS: mRemote(o.get())这个是C++中构造函数赋值的写法!

小结

通过下面一条语句的操作

const sp<IMediaPlayerService> service(getMediaPlayerService());

我们已经获取了如下信息:

  1. service是BpMediaPlayerService的对象

  2. mRemote是[media.player]服务的的native层的binder对象

我们继续。

create()

sp<IMediaPlayer> player(service->create(this, mAudioSessionId));

上面说了service就是BpMediaPlayerService的对象。

virtual sp<IMediaPlayer> create(
    const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
    Parcel data, reply;
    data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
    data.writeStrongBinder(IInterface::asBinder(client));
    data.writeInt32(audioSessionId);
    //通过remote()的transact()方法
    remote()->transact(CREATE, data, &reply);
    //创建BpMediaPlayer
    return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}

上面执行了两步(1)通过remote()的transact()方法传输CREATE命令(2)创建BpMediaPlayer。

remote()->transact(CREATE, data, &reply);

remote()是谁?这个在Binder.h中定义。

inline  IBinder*        remote()                { return mRemote; }

也就是调用[media.player]服务的的native层的binder对象的transact()。

经过binder通信,最后进入BnMediaPlayerService::onTransact()。(其中细节不太明白,后面明白了再写,多谢)。

BnMediaPlayerService的实现也在IMediaPlayerService.cpp

onTransact
status_t BnMediaPlayerService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    switch (code) {
        case CREATE: {
            CHECK_INTERFACE(IMediaPlayerService, data, reply);
            //client是BpMediaPlayerClient对象
            sp<IMediaPlayerClient> client =
                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
            audio_session_t audioSessionId = (audio_session_t) data.readInt32();
            //MediaPlayerService继承BnMediaPlayerService,所以MediaPlayerService实现了create
           //这里的player是BnMediaPlayer对象,具体看create()中创建的
            sp<IMediaPlayer> player = create(client, audioSessionId);
            //返回asBinder(BpMediaPlayer)
            reply->writeStrongBinder(IInterface::asBinder(player));
            return NO_ERROR;
        } break;
        //略
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

我们看client

//client是BpMediaPlayerClient对象
//data.readStrongBinder()就是的MediaPlayer(继承BnMediaPlayerClient)的binder对象
sp<IMediaPlayerClient> client =
            interface_cast<IMediaPlayerClient>(data.readStrongBinder());

又是interface_cast,老朋友了,获取的client是BpMediaPlayerClient。

需要注意的是BpMediaPlayerClient里面有个notify()

virtual void notify(int msg, int ext1, int ext2, const Parcel *obj){
    Parcel data, reply;
    data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
    data.writeInt32(msg);
    data.writeInt32(ext1);
    data.writeInt32(ext2);
    if (obj && obj->dataSize() > 0) {
        data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
    }
    //remote()是BnMediaPlayerClient的binder
    remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
}

后续会通过notify()进行返回状态通知。

如有错误,请指正,多谢

MediaPlayerService
sp<IMediaPlayer> player = create(client, audioSessionId);

看代码知道,MediaPlayerService继承BnMediaPlayerService的,而且上面create()没有实现,那就找他的子类。(哈哈,负债子还?)

MediaPlayerService在MediaPlayerService.cpp中。

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);
    //创建服务端Bn实现端(BnMediaPlayer)子类Client播放器对象
    //Client 继承 BnMediaPlayer
    sp<Client> c = new Client(
            this, pid, connId, client, audioSessionId,
            IPCThreadState::self()->getCallingUid());
    wp<Client> w = c;
    {
        Mutex::Autolock lock(mLock);
        mClients.add(w);
    }
    return c;
}

创建了Client对象(BnMediaPlayer的子类),后面客户端是通过这个来跟服务端交互的。

player

sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
virtual sp<IMediaPlayer> create(
    //略
    //reply.readStrongBinder()返回的是mClients(BnMediaPlayer子类)的binder
    //创建BpMediaPlayer
    return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}

由上面分析,player就是BpMediaPlayer,继续

if (service != 0) {
    sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
    if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
        //BpMediaPlayer->setDataSource(source)
        (NO_ERROR != player->setDataSource(source))) {
        player.clear();
    }
    err = attachNewPlayer(player);
}
setDataSource

进入IMediaPlayer.cpp

 status_t setDataSource(int fd, int64_t offset, int64_t length) {
     Parcel data, reply;
     data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
     data.writeFileDescriptor(fd);
     data.writeInt64(offset);
     data.writeInt64(length);
    //通过binder,就是BnMediaPlayer的binder
     remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
     return reply.readInt32();
 }

通过binder通信(暂时不关注细节哈),进入了BnMediaPlayer类onTransact(),进入IMediaPlayer.cpp

status_t BnMediaPlayer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
    switch (code) {
        //略
        case SET_DATA_SOURCE_FD: {
            CHECK_INTERFACE(IMediaPlayer, data, reply);
            int fd = data.readFileDescriptor();
            int64_t offset = data.readInt64();
            int64_t length = data.readInt64();
            // MediaPlayerService中的Client继承BnMediaPlayer
            //也就进入MediaPlayerService::Client::setDataSource()
            reply->writeInt32(setDataSource(fd, offset, length));
            return NO_ERROR;
        }
        //略
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

BnMediaPlayer没有实现父类的接口,那就找其子类(父债子还!)。Client是BnMediaPlayer的之类,而且Client的定义在MediaPlayerService.cpp

status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length){
    struct stat sb;
    int ret = fstat(fd, &sb);
    if (ret != 0) {
        return UNKNOWN_ERROR;
    }
    if (offset >= sb.st_size) {
        return UNKNOWN_ERROR;
    }
    if (offset + length > sb.st_size) {
        length = sb.st_size - offset;
    }
    player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                               fd,
                                                               offset,
                                                               length);
    //创建播放器(NuPlayerDriver),这里暂时不深入,下次介绍哈
    sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    if (p == NULL) {
        return NO_INIT;
    }
    return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
}

好绕啊,哈哈,最终执行的是p->setDataSource(fd, offset, length)。

p又是谁?暂停打住哈,后面在分析。

attachNewPlayer
err = attachNewPlayer(player);

获取到了player(BpMediaPlayer的对象),这里进行赋值

status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player){
    status_t err = UNKNOWN_ERROR;
    sp<IMediaPlayer> p;
    {
        Mutex::Autolock _l(mLock);
        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
            return INVALID_OPERATION;
        }
        clear_l();
        //p存在之前的mPlayer
        p = mPlayer;
        //赋值新的player
        mPlayer = player;
        if (player != 0) {
            mCurrentState = MEDIA_PLAYER_INITIALIZED;
            err = NO_ERROR;
        } else {
            ALOGE("Unable to create media player");
        }
    }
    //如果之前的不为null,就通知disconnect()
    if (p != 0) {
        p->disconnect();
    }
    return err;
}

到这里,就获取到了mPlayer,然后可以通过这个mPlayer。

小结

上面只是setDataSource()的分析,但其他的方法都差不多,都是通过mPlayer中的mRemote->onTransact(),经过Binder通信,然后调用服务MediaPlayerService::Client对应的方法中。

BP(binder proxy)和BN(binder native)是通过binder来通信的,Bp端可以通过BinderProxy的transact()方法与Bn端发送请求,而Bn端通过继承Binder类并重写onTransact()接收并处理来自Bp端的请求。 Bn意味着Binder Native端,Bp是Binder Proxy端,Bn端通过onTransact()方法接收来自Bp端的请求的代码,然后把结果写入reply,Bp端再从reply中读取返回值并返回给调用者。

参考文章

  1. interface_cast简介

  2. MediaPlayer java层介绍

  3. Binder系列6—获取服务(getService)

  4. android MediaPlayer架构

 历史上的今天

版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站文章: 部分来源于网络,仅供站长学习和参考,若侵权请留言
广告也精彩

相关文章

广告也精彩

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...

网站升级中

公告

近期网站升级中,可能存在一些bug。欢迎反馈 https://www.91es.com/we.html

本站域名

本站域名 : 91es.com3xcn.com。本站邮箱 : 站长邮箱 i@oorr.cn,通知邮箱we@oorr.cn ,如有更新,请看公告 。