Android 13(T) - Media框架(3)- mediaserver

上一节我们了解到android_media_MediaPlayer.cpp中封装的是MediaPlayer native实现,这一节我们就来了解它的内部实现。

1、MediaPlayer

MediaPlayer native代码位于frameworks/av/media/libmedia/mediaplayer.cpp

先来看MediaPlayer的声明,它继承于BnMediaPlayerClient,包含一个IMediaPlayer成员以及一个notify方法。

cpp 复制代码
class MediaPlayer : public BnMediaPlayerClient,
                    public virtual IMediaDeathNotifier
{
	sp<IMediaPlayer>            mPlayer;
	void            notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
}
  • mPlayer是通过mediaserver获取到的;
  • notify用于底层向上callback;
  • 继承于BnMediaPlayerClient是因为MediaPlayer对象会通过binder传递给IMediaPlayer,从而实现callback功能,从IMediaPlayerClient.h中可以看到binder接口只有一个notify;

callback用的比较多方法的是声明一个ICallback对象,里面存储有上层对象,将这个ICallback通过binder传递到底层,而不是将上层对象直接传递下去,这里的用法比较少见,可以学习一下~

接下来看如何获取IMediaPlayer对象的:

cpp 复制代码
status_t MediaPlayer::setDataSource(
        const sp<IMediaHTTPService> &httpService,
        const char *url, const KeyedVector<String8, String8> *headers)
{
    status_t err = BAD_VALUE;
    if (url != NULL) {
    	// 获取MediaPlayerService
        const sp<IMediaPlayerService> service(getMediaPlayerService());
        if (service != 0) {
        	// create player
            sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));
            // call setDataSource
            player->setDataSource(httpService, url, headers);
            // save player
            err = attachNewPlayer(player);
        }
    }
    return err;
}
  1. 先获取media.player服务;
  2. 调用服务的create方法创建本地IMediaPlayer对象,并将自身作为参数传递,返回IMediaPlayer的远程代理;
  3. 调用IMediaPlayersetDataSource方法;
  4. IMediaPlayer对象存储到mPlayer

IMediaPlayer的销毁流程如下:

cpp 复制代码
void MediaPlayer::disconnect()
{
    sp<IMediaPlayer> p;
    {
        Mutex::Autolock _l(mLock);
        p = mPlayer;
        mPlayer.clear();
    }

    if (p != 0) {
        p->disconnect();
    }
}
  1. 调用IMediaPlayer的disconnect方法
  2. 离开disconnect函数作用域,IMediaPlayer自动销毁

MediaPlayer::disconnect中会先加锁,接着将mPlayer赋给一个新的局部变量p,然后释放掉mPlayer的内容。为什么要这么做?我猜想是为了缩短锁占用的时间。

最后来看callback方法notify,这个方法可以透过binder来跨进程调用,所以最后一个自定义的数据类型是Parcel。底层调用notify后,mediaplayer native会根据事件类型判断是否再将事件上抛。

cpp 复制代码
void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
    ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
    bool send = true;
    ....
    sp<MediaPlayerListener> listener = mListener;
	...
    if ((listener != 0) && send) {
        Mutex::Autolock _l(mNotifyLock);
        listener->notify(msg, ext1, ext2, obj);
    }
}

2、MediaServer

上一节我们了解了MediaPlayer native封装的是一个IMediaPlayer对象,这个对象是由mediaserver这个binder service创建的,这一节我们就来了解mediaserver

mediaserver服务的启动代码位于frameworks/av/media/mediaserver/main_mediaserver.cpp

cpp 复制代码
int main(int argc __unused, char **argv __unused)
{
	......
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
	......
}

mediaserver其实提供有两个服务,一个是MediaPlayerService(media.player),另一个是资源管理服务ResourceManagerService(media.resource_manager),这里我们仅了解MediaPlayerService。


3、MediaPlayerService

相关推荐
H1001 小时前
重构(二)
android·重构
拓端研究室1 小时前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil2 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744642 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.2 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao2 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee3 小时前
PHP伪协议总结
android·开发语言·php
mmsx9 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人12 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌13 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习