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

相关推荐
DogDaoDao7 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
JohnnyDeng948 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
Android小码家11 小时前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士11 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love12 小时前
MySQL的执行流程
android·数据库·mysql
云起SAAS17 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒18 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌18 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_9151063219 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴1 天前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io