前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MediaPlayer(三)--C++ binder框架

MediaPlayer(三)--C++ binder框架

作者头像
小蚂蚁与大象
发布2020-04-17 17:38:35
1.1K0
发布2020-04-17 17:38:35
举报

结构框架

上一篇文章MediaPlayer--MediaPlayer基本框架没有将C++的mediaplayer binder通讯展开,这篇文章主要展开这一部分。

大概画了下C++ MediaPlayer的uml图,不是很满意,请高手指教

这里面主要的client和service实现类是以下两个文件(Android8.1 路径)

frameworks/av/media/libmedia/mediaplayer.cpp

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

这里面涉及了三对IPC的通讯,即

IMediaPlayerClient

IMediaPlayerService

IMediaPlayer

其中 IMediaPlayerService , IMediaPlayer 的服务端在MediaPlayerService.cpp, 客户端在mediaplayer.cpp。IMediaPlayerClient 的服务端在mediaplayer.cpp, 客户端在MediaPlayerService.cpp, 这是MediaPlayerService回调mediaplayer使用的。 IMediaPlayerService会创建IMediaPlayer的实例

流程

MediaPlayer 同MediaPlayerService通讯 是通过变量 sp<IMediaPlayer> mPlayer, mPlayer赋值是在setDataSource

代码语言:javascript
复制
status_t MediaPlayer::setDataSource(
        const sp<IMediaHTTPService> &httpService,
        const char *url, const KeyedVector<String8, String8> *headers)
{
    ALOGV("setDataSource(%s)", url);
    status_t err = BAD_VALUE;
    if (url != NULL) {
        const sp<IMediaPlayerService> service(getMediaPlayerService());
        if (service != 0) {
            sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
            if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
                (NO_ERROR != player->setDataSource(httpService, url, headers))) {
                player.clear();
            }
            err = attachNewPlayer(player);
        }
    }
    return err;
}

关于创建mPlayer这块主要分3步:

1 const sp<IMediaPlayerService> service(getMediaPlayerService()); 这一步其实是获取了BpMediaPlayerService

2 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); 这一步是通过BpMediaPlayerService 的create方法返回了BpMediaPlayer

3 attachNewPlayer 将player赋值给mPlayer

看一下 1 和 2 的两个函数的实现

代码语言:javascript
复制
/*static*/const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
    ALOGV("getMediaPlayerService");
    Mutex::Autolock _l(sServiceLock);
    if (sMediaPlayerService == 0) {
        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();
        }
        binder->linkToDeath(sDeathNotifier);
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    }
    ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    return sMediaPlayerService;
}

这里简单讲一下

1 sp<IServiceManager> sm = defaultServiceManager(); 获取到ServiceManager

2 sm->getService(String16("media.player")); 通过ServiceManager获取到 MediaPlayerService,MediaPlayerService在android初始化时就向ServiceManager注册了

3 interface_cast<IMediaPlayerService>(binder); 这里实际是new BpMediaPlayerService(binder)

代码语言:javascript
复制
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
    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(CREATE, data, &reply);
        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
    }

create方法做了两件事

1 remote()->transact(CREATE, data, &reply) 通过 IMediaPlayerService binder通讯,将IMediaPlayerClient的IBinder传给了MediaPlayerService, MediaPlayerServcie后面可以通过IMediaPlayerClient 回调MediaPlayer

2 interface_cast<IMediaPlayer>(reply.readStrongBinder()); 上一步binder通讯MeidaPlayer的binder对象, 同过binder是创建了 BpMediaPlayer 实例

Binder可分为实名binder和匿名binder, 实名binder是在ServiceManager注册的servce,可以通过ServiceManager的getService获取,而匿名binder没在ServiceManager中注册,没法通过ServiceManager获取,需要想办法获取service的binder实例才能通讯。对于MediaPlayer的结构,MediaPlayerServcie 属于实名binder, IMediaPlayer 和 IMediaPlayerClient 属于匿名binder。MediaPlayer 通过 MediaPlayerServcie实名binder, 将IMediaPlayerClient binder 传递给MediaPlayerServcie,同时MediaPlayerServcie将IMediaPlayer binder返回MediaPlayer。 这样MediaPlayer 就能通过 IMediaPlayer 调用 MediaPlayerServcie::client接口, MediaPlayerServcie可以通过IMediaPlayerClient调用MediaPlayer接口

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档