Android音视频开发入门(4)MediaPlayerService

MediaPlayerService是多媒体框架中一个非常重要的服务,从前面的内容我们可以知道在 MediaPlayer的C/S模式中

  • MediaPlayerServiceMediaPlayerService::Client是服务器端。MediaPlayerServier实现了IMediaPlayerService定义的业务逻辑。
    其主要功能是MediaPlyaer::setDataSource输入的url调用 create()创建对应的player。
  • MediaPlayer::Client实现IMediaPlayer定义的业务逻辑,其主要功能包括 start、stop、pause、resume…

1. Client/server通过IPC的通信流程图

Android中的通信很多都是通过Binder机制来完成的,对于MediaPlayer和MediaPlayerService也不例外。
我们来看看下面的C/S Binder通信图:

在这里插入图片描述
从图中可以总结出下面几点:

  • MediaPlayer是客户端也就是 C/S中的 Client层
  • MediaPlayerService和MediaPlayerService::Client是服务端,也就是我们说的 C/S模型中的S层
  • MediaPlayerService实现 IMediaPlayerService 定义的业务逻辑
  • MediaPlayerService::Client 实现 IMediaPlayer定义的业务逻辑
  • 通过Transact()可以向远端的IBinder对象发出调用,通过 onTransact()可以使你自己的远程对象能够响应接收到的调用。

2. 相关联类图

我们知道Binder通信时,需要通过 IBinder接口转化具体的实体对象,那么中间会有很多其它类,下面看看类关系图:
在这里插入图片描述
细品IPC通信图,可以得出下面的结论:

  • BnXXX 和 BpXXX都派生自两个类
    class BpXXX : public IMediaPlayerService, public BpRefBase
    class BnXXX : public IMediaPlayerService, public BBinder
  • BpXXX和BnXXX都派生自 IMediaPlayerService,我们之前说过,IMediaPlayerService使用来定义一些功能的接口的,而派生出两个类,所以它们虽然使用了相同的接口,但是他们有不同的实现方式
    BpXXX中:把对应的binder_transaction_data 打包之后,通过BpRefBase中的 mRemote(BpBinder)发送出去,并等待结果
    BnXXX中:实现对应的业务逻辑,通过调用 BnXXX 派生类中的方法来实现,如 MediaPlayerService::Client
  • IBinder用于进程间通信
    BpRefBase中有一个remote()用来与Binder驱动交互
    Binder是用来从Binder驱动中接收相关请求并进行相关处理的
    BpBinder和BinderDriver进行互通

3. MediaPlayerService产生过程

我们从入口看,入口在 /frameworks/av/media/mediaserver/main_mediaserver.cpp:

int main(int argc __unused, char **argv __unused)
{
    //信号
    signal(SIGPIPE, SIG_IGN);

    //进程赋值处理
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm(defaultServiceManager());
    ALOGI("ServiceManager: %p", sm.get());
    InitializeIcuOrDie();
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

从第一个有意义的函数 defaultServiceManager(),它在/frameworks/native/libs/binder/IServiceManager.cpp:

p<IServiceManager> defaultServiceManager()
{
    //如果存在一个 BpServiceManager就返回它
    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;
}

这种构建模式其实是我们熟悉的 单例模式。每个进程都只需要构建出一个 BpServiceManager代理,
ProcessState::self() -> getContextObject(NULL),接下来看看 getContextObject(),它在 /frameworks/native/libs/binder/ProcessState.cpp中:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);
    //在数组 mHandleToObject里面根据handle索引查找handle_entry结构体
    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        //指向结构体中的binder地址
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            //BpBinder新建一个IBinder BpBinder.create(0)
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

struct handle_entry{
   IBinder* binder;
   RefBase::weakref_type* refs;
}

总结代码
传入的句柄handler的值为0,表示ServiceManager,构建一个BpBinder,所以现在相当于 gDefaultServiceManager = interface_cast(BpBinder.create(0))

接下来看看 interface_cast()是什么:

inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);
}
...
asInteface(){
  ...
  //这里构建了一个新的BoServiceManager对象
  intr = new BpServiceManager(obj)
}

其asInterface最终还是创建出一个 BpServiceManager对象。

所以defaultServiceManager()就是 句柄handle(0)创建一个 BpBinder(0),跟举这个BpBinder创建出一个 BpServiceManager代理。
下面来分析一下BpServiceManager 这个类是什么成分,代码如下:

 class BpServiceManager : public BpInterface<IServiceManager>
    {
        public:
        explicit BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl) {}
    };

这里的 它继承了 BpInterface,它是一个模板类,这里相当于它同时 继承了 BpInterfaceIServiceManager
BpInterface在用到它的构造函数时,就会 去添加服务内部
在 MediaPlayerSrvice.cpp中有一个 instantiate(),通过ServiceManager来添加MediaPlayerService服务:

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

defaultServiceManager() 返回的是刚创建的BpServiceManager,并调用它的 addService()
BpMediaPlayerService作为服务端代理,那么BnMediaPlayerService一定是实现端
MediaPlayerService继承自 BnMediaPlayerService,实现了真正的的业务函数。

4. 添加服务的过程

下面分析一下 BpServiceManager的 addService()

virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated, int dumpsysPriority) {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        //也就是MediaPlayerService
        data.writeStrongBinder(service);
        data.writeInt32(allowIsolated ? 1 : 0);
        data.writeInt32(dumpsysPriority);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }

这里的 remote函数返回的就是 前面创建的 BpBinder(0)对象:

status_t BpBinder::transact(
            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        // Once a binder has died, it will never come back to life.
        if (mAlive) {
            status_t status = IPCThreadState::self()->transact(
                    mHandle, code, data, reply, flags);
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }

        return DEAD_OBJECT;
    }

status_t IPCThreadState::transact(int32_t handle,
                                      uint32_t code, const Parcel& data,
                                      Parcel* reply, uint32_t flags)
    {
        ...
        //发送addTransactionData
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
        ...
        } else {
            //等待响应
            err = waitForResponse(NULL, NULL);
        }
        return err;
    }

 status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
                                                  int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
    {
        //cmd BC_TRANSACTION 应用程序向Binder发送的命令
        binder_transaction_data tr;

        tr.target.handle = handle;
        tr.code = code;
        tr.flags = binderFlags;
        ...
        //把命令和数据一起发送到 Parcel mOut中
        mOut.writeInt32(cmd);
        mOut.write(&tr, sizeof(tr));
        return NO_ERROR;
    }

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
        uint32_t cmd;
        while (1) {
            //和Driver进行沟通后获得结果
            if ((err=talkWithDriver()) < NO_ERROR) break;
            cmd = (uint32_t)mIn.readInt32();
            switch (cmd) {
                case BR_TRANSACTION_COMPLETE:
                    ...
                    break;
            }
        }

        return err;
    }

status_t IPCThreadState::talkWithDriver(bool doReceive) {
        binder_write_read bwr;

        bwr.write_size = outAvail;
        //写入 mOut的数据
        bwr.write_buffer = (uintptr_t) mOut.data();
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t) mIn.data();
        ...
        //把mOut写到Binder中,并读取mIn的数据
        if (ioctl(mProcess -> mDriverFD, BINDER_WRITE_READ, & bwr) >=0)
        err = NO_ERROR;
        ...
        return err;
    }

joinThreadPool、startThreadPool 进入线程循环
talkWithDriver等待客户端Client请求,从Binder读取命令请求进行处理。
到现在为止,MediaPlayerService的服务端已经向总管 ServiceManager注册了

5. 通过BinderDriver和MediaPlayer通信的过程

下面看看客户端是如何获得服务的代理并和服务端通信的。
我们以 MediaPlayer的业务函数解码解析播放一个 网络视频的URL为例。

首先在 MediaPlayer decode(url)时,首先调用了 getMediaPlayerService()
我们来看看这个函数:

  IMediaDeathNotifier::
    getMediaPlayerService() {
        //生成一个BpServiceManager代理对象
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            //获取String16("media.player")的服务对象
            binder = sm -> getService(String16("media.player"));
            if (binder != 0) {
                break;
            }
            usleep(500000); // 0.5 s
        } while (true);
        ...
        sMediaPlayerService = interface_cast < IMediaPlayerService > (binder);
        return sMediaPlayerService;
    }

Client端的MediaPlayer先获取一个 BpServiceManager的代理,然后调用其 getService()向服务总管 ServiceManager查询名叫 String16(“media.player”)的服务,这个getService的方法处于 /frameworks/native/libs/binder/ 的 IServiceManager.cpp:

  class BpServiceManager :public BpInterface<IServiceManager>
    {
        public:
        virtual sp<IBinder > getService(const String16 & name) const
        {
            int n = 0;
            while (uptimeMillis() < timeout) {
                n++;
                //调用checkService函数
                sp<IBinder> svc = checkService(name);
                if (svc != NULL) return svc;
            }
            return NULL;
        }

        virtual sp<IBinder > checkService( const String16 & name) const
        {
            Parcel data, reply;
            //首先调用writeInterfaceToken,然后写入 android.os.IServiceManager
            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor ());
            //写入media.player
            data.writeString16(name);
            //然后通过Binder把data及reply的数据通知出去,在onTransact函数中进行回调
            remote()->transact(CHECK_SERVICE_TRANSACTION, data, & reply);
            return reply.readStrongBinder();
        }
    }

这里首先将请求打包成Parcel格式,然后调用 remote->transact函数,前面我们分析过 BpServiceManager::remote返回的就是 newBpBinder(0),对应的句柄为 ServiceManager。继续在BpBinder中寻找实现代码:

status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
        IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
}

最后调用 IPCThreadState的transact函数,在Android中 ProcessState是哭护短和服务端的公共部分,作为Binder通信的基础,ProcessState是一个singleton类, 每个进程只有一个对象,这个对象负责打开Binder驱动,建立线程池,让其进程里面的所有线程都能通过Binder通信。

与之相关的就是 IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取、写入和请求处理框架。

IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量中:

status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel&data,Parcel*reply, uint32_t flags) {
        status_t err;
        //填充 binder_transaction_data 结构体,写入mOut中
        //这里就是把 "media.player"、"android.os.IServiceManager"等写进去
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
        ..
        //然后等待返回
        waitForResponse(reply);
        return err;
    }
    
status_t IPCThreadState::  waitForResponse(Parcel *reply, status_t *acquireResult) {
        while (1) {
            talkWithDriver())
            //输入mOut,输出mIn
            cmd = mIn.errorCheck();
            switch (cmd) {
                case BR_REPLY: {
                    binder_transaction_data tr;
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply -> ipcSetDataReference(
                                reinterpret_cast <const uint8_t * > (tr.data.ptr.buffer),
                                tr.data_size,
                                reinterpret_cast <const
                        binder_size_t * > (tr.data.ptr.offsets),
                                tr.offsets_size / sizeof(binder_size_t),
                                freeBuffer, this);
                    } else {
                        err = *reinterpret_cast<const status_t * > (tr.data.ptr.buffer);
                        freeBuffer(NULL,
                                reinterpret_cast <const uint8_t * > (tr.data.ptr.buffer),
                                tr.data_size,
                                reinterpret_cast <const
                        binder_size_t * > (tr.data.ptr.offsets),
                                tr.offsets_size / sizeof(binder_size_t), this);
                    }
                }
            }
        }
    }

waitForResponse返回的是一个 readStrongBinder(),进入Parcel的readStrongBinder()中:

  status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, wp<IBinder>* out) {
    const flat_binder_object * flat = in.readObject(false);
        if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
            }
        }
    }

这里的flat->type是BINDER_TYPE_HANDLE,所以调用 ProcessState::getStrongProxyForHandle():

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
        sp<IBinder> result;
        handle_entry* e = lookupHandleLocked(handle);
        if (e != NULL) {
            IBinder* b = e->binder;
            if (b == NULL || !e->refs->attemptIncWeak(this)) {
                b = BpBinder::create(handle);
                e->binder = b;
                if (b) e->refs = b->getWeakRefs();
                result = b;
            } else {
                result.force_set(b);
                e->refs->decWeak(this);
            }
        }
        return result;
    }

这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄。
这个ProcessState根据这个句柄创建了一个 BpBinder,并将其保存了起来。这样下次需要的时候就从ServiceManager请求获取相同的句柄就可以直接返回了。

根据这个返回的BpBinder获得MediaPlayerService的代理:

sMediaPlayerService = interface_cast(binder);

和前面的ServiceManager一样,调用IMediaPlayerService的asInterface宏函数,就可以获得一个代理BpMediaPlayerService对象,它的remote为BpBinder(handle),这个handle就是向服务总管ServiceManager查询到的MediaPlayerService对应的Binder句柄。

最后总结一下:

  • 在实际业务中,如当 MediaPlayer::setDataSource 返回时,会创建一个与 MediaPlayerService::Client对应的BpMediaPlayer,用于获取 MediaPlayerService::Client的各项功能
  • MediaPlayer又是如何找到 MediaPlayerService::Client的呢?
    只有MediaPlayerService向ServiceManager进行了注册才可以,所以MediaPlayer必须先获取 BpMediaPlayerService,然后通过BpMediaService的管理功能创建一个MediaPlayerService::Client
  • 为什么不直接定义一个MediaPlayer,让其向 ServiceManager注册呢?
    MediaPlayerService包含的功能不仅是 Client,还有 AudioOutput、AudioCache、MediaConfigClient等功能。
    MediaPlayerService就是一个 媒体服务的窗口

6. 创建播放器

在MediaPlayer的构造函数中,会预先注册一些播放器的Factory。很多ROM厂商如果要应用自己写的播放器,也需要有一个Factory,这里也是一样的:

MediaPlayerService::MediaPlayerService()
    {
        ALOGV("MediaPlayerService created");
        mNextConnId = 1;
        //注册一些播放器的Factory
        MediaPlayerFactory::registerBuiltinFactories();
    }
    
 void MediaPlayerFactory::registerBuiltinFactories() {
        Mutex::Autolock lock_(&sLock);

        IFactory* factory = new NuPlayerFactory();
        //注册两个 Factory
        if (registerFactory_l(factory, NU_PLAYER) != OK)
            delete factory;
        factory = new TestPlayerFactory();
        if (registerFactory_l(factory, TEST_PLAYER) != OK)
            delete factory;

        sInitComplete = true;
    }

通过 registerFactory_l(factory, NU_PLAYER)会创建一个 NuPlayer
通过registerFactory_l(factory, TEST_PLAYER)会创建一个 TestPlayer
第一个NuPlayer比较重要,我们来看看它的工厂创建方法:

    class NuPlayerFactory : public MediaPlayerFactory::IFactory {
        public: virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                               const char* url,
        float curScore) {
            static const float kOurScore = 0.8;

            
            if (!strncasecmp("http://", url, 7)
                    || !strncasecmp("https://", url, 8)
                    || !strncasecmp("file://", url, 7)) {
                //如果是 http://、https://、file://
                size_t len = strlen(url);
                //后缀是  .m3u8
                if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
                    return kOurScore;
                }

                if (strstr(url,"m3u8")) {
                    return kOurScore;
                }

                //如果是SDP协议
                if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
                    return kOurScore;
                }
            }
            //如果是 RTSP协议
            if (!strncasecmp("rtsp://", url, 7)) {
                return kOurScore;
            }

            return 0.0;
        } 
        ...
        virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
            return new NuPlayerDriver(pid);
        }
    };

最后没有返回一个 NuPlayer,而是创建了NuPlayerDriver,实际上是在NuPlayerDriver的构造函数中,创建了 一个NuPlayer

发布了248 篇原创文章 · 获赞 99 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/rikkatheworld/article/details/102983222