getMediaPlayerService方法获取到的是media.player服务

IMediaDeathNotifier::getMediaPlayerService()
{
// ......
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
binder = sm->getService(String16("media.player"));
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
// ......
return sMediaPlayerService;
}

MediaPlayerService 和 MediaPlayerFactory的主要代码位置:

http://aospxref.com/android-12.0.0_r3/xref/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

http://aospxref.com/android-12.0.0_r3/xref/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

1、服务注册

main_mediaserver 中会调用instantiate方法将media.player服务注册到servicemanager当中

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

注册时会实例化一个MediaPlayerService对象,构造函数中会调用 MediaPlayerFactory::registerBuiltinFactories 来初始化播放器工厂

// MediaPlayerService
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerService created");
mNextConnId = 1; MediaPlayerFactory::registerBuiltinFactories();
} // MediaPlayerFactory
void MediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock); if (sInitComplete)
return; IFactory* factory = new NuPlayerFactory();
if (registerFactory_l(factory, NU_PLAYER) != OK)
delete factory;
factory = new TestPlayerFactory();
if (registerFactory_l(factory, TEST_PLAYER) != OK)
delete factory; sInitComplete = true;
}

2、服务使用

2.1、create

create方法中实例化了一个Client对象,并且把这个对象返回给了native mediaplayer,同时创建的Client对象会被记录到mClient这个列表当中

sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId, const AttributionSourceState& attributionSource)
{
// ......
sp<Client> c = new Client(
this, verifiedAttributionSource, connId, client, audioSessionId);
// ......
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}

 

3、MediaPlayerService::Client

client是MediaPlayerService的一个内部类,继承于BnMediaPlayer,既然是个binder对象,所以可以使用binder service来传递给native mediaplayer。

/**********************************************************
* Native mediaplayer -> MediaPlayerService::Client
* setDataSource 构造函数 setDataSource
* setVideoSurfaceTexture setVideoSurfaceTexture
* prepareAsync setAudioStreamType prepareAsync
* start setLooping setVolume start
**********************************************************/

3.1、构造函数

构造函数主要初始化了成员变量,这里看到第四个参数传来的是native mediaPlayer对象,主要是要调用notify方法,回调上层postEventFromNative函数

MediaPlayerService::Client::Client(
const sp<MediaPlayerService>& service, const AttributionSourceState& attributionSource,
int32_t connId, const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId)
: mAttributionSource(attributionSource)
{
ALOGV("Client(%d) constructor", connId);
mConnId = connId;
mService = service;
mClient = client;
mLoop = false;
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
mRetransmitEndpointValid = false;
mAudioAttributes = NULL;
mListener = new Listener(this); #if CALLBACK_ANTAGONIZER
ALOGD("create Antagonizer");
mAntagonizer = new Antagonizer(mListener);
#endif
}

3.2、setDataSource

这里干了两件事:

a. MediaPlayerFactory::getPlayerType 从MediaPlayerFactory中获取播放器的类型

b. setDataSource_pre 根据类型来创建播放器

c. setDataSource 调用创建的MediaPlayerBase的setDataSource方法

status_t MediaPlayerService::Client::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
if (url == NULL)
return UNKNOWN_ERROR; if ((strncmp(url, "http://", 7) == 0) ||
(strncmp(url, "https://", 8) == 0) ||
(strncmp(url, "rtsp://", 7) == 0)) {
if (!checkPermission("android.permission.INTERNET")) {
return PERMISSION_DENIED;
}
} if (strncmp(url, "content://", 10) == 0) {
// get a filedescriptor for the content Uri and
// pass it to the setDataSource(fd) method String16 url16(url);
int fd = android::openContentProviderFile(url16);
if (fd < 0)
{
ALOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
return mStatus = status;
} else {
player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
} return mStatus =
setDataSource_post(
p, p->setDataSource(httpService, url, headers));
}
}

3.3、setVideoSurfaceTexture

这里做的事情目前还不太了解是做什么用的,但是调用了MediaPlayerBase的setVideoSurfaceTexture方法

status_t MediaPlayerService::Client::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR; sp<IBinder> binder(IInterface::asBinder(bufferProducer));
if (mConnectedWindowBinder == binder) {
return OK;
} sp<ANativeWindow> anw;
if (bufferProducer != NULL) {
anw = new Surface(bufferProducer, true /* controlledByApp */);
status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture"); if (err != OK) {
ALOGE("setVideoSurfaceTexture failed: %d", err);
// Note that we must do the reset before disconnecting from the ANW.
// Otherwise queue/dequeue calls could be made on the disconnected
// ANW, which may result in errors.
reset(); Mutex::Autolock lock(mLock);
disconnectNativeWindow_l(); return err;
}
} // Note that we must set the player's new GraphicBufferProducer before
// disconnecting the old one. Otherwise queue/dequeue calls could be made
// on the disconnected ANW, which may result in errors.
status_t err = p->setVideoSurfaceTexture(bufferProducer); mLock.lock();
disconnectNativeWindow_l(); if (err == OK) {
mConnectedWindow = anw;
mConnectedWindowBinder = binder;
mLock.unlock();
} else {
mLock.unlock();
status_t err = nativeWindowDisconnect(
anw.get(), "disconnectNativeWindow"); if (err != OK) {
ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
strerror(-err), err);
}
} return err;
}

3.4、setAudioStreamType

setAudioStreamType 操作的是AudioOutput对象,暂时不研究audio部分

status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
{
ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
// TODO: for hardware output, call player instead
Mutex::Autolock l(mLock);
if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
return NO_ERROR;
}

3.5、prepareAsync

调用了MediaPlayerBase的prepareAsync方法

status_t MediaPlayerService::Client::prepareAsync()
{
ALOGV("[%d] prepareAsync", mConnId);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
status_t ret = p->prepareAsync();
#if CALLBACK_ANTAGONIZER
ALOGD("start Antagonizer");
if (ret == NO_ERROR) mAntagonizer->start();
#endif
return ret;
}

3.6、start

调用了MediaPlayerBase的start方法

status_t MediaPlayerService::Client::start()
{
ALOGV("[%d] start", mConnId);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
p->setLooping(mLoop);
return p->start();
}

看到这里明白了mediaPlayer的调用顺序

mediaplayer java   -->     JNI    -->    mediaPlayer native     -->     mediaplayerservice (create player)     -->     NuplayerDriver

上层收到MEDIA_PREPARED事件的过程

接下来一节将会学习NuPlayer

Android 12(S) MultiMedia Learning(四)MediaPlayerService的更多相关文章

  1. Android 12(S) 图形显示系统 - 解读Gralloc架构及GraphicBuffer创建/传递/释放(十四)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 在前面的文章中,已经出现过 GraphicBuffer 的身影,GraphicBuffer 是Android图形显示系统中的一个重 ...

  2. Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)

    1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...

  3. Android系列之Fragment(四)----ListFragment的使用

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  4. 转--Android按钮单击事件的四种常用写法总结

    这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下     很多学习Android程序设计的人都会发现每个人对代码的 ...

  5. Android开发_Android数据的四种存储方式

    Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File.由于Android系统中,数据基本都是私有的的,都是存放 ...

  6. Android图表库MPAndroidChart(十四)——在ListView种使用相同的图表

    Android图表库MPAndroidChart(十四)--在ListView种使用相同的图表 各位好久不见,最近挺忙的,所有博客更新的比较少,这里今天说个比较简单的图表,那就是在ListView中使 ...

  7. Android群英传笔记——第四章:ListView使用技巧

    Android群英传笔记--第四章:ListView使用技巧 最近也是比较迷茫,但是有一点点还是要坚持的,就是学习了,最近离职了,今天也是继续温习第四章ListView,也拖了其实也挺久的了,list ...

  8. Android 12(S) 图形显示系统 - createSurface的流程(五)

    题外话 刚刚开始着笔写作这篇文章时,正好看电视在采访一位92岁的考古学家,在他的日记中有这样一句话,写在这里与君共勉"不要等待幸运的降临,要去努力的掌握知识".如此朴实的一句话,此 ...

  9. Android 12(S) 图形显示系统 - BufferQueue的工作流程(八)

    题外话 最近总有一个感觉:在不断学习中,越发的感觉自己的无知,自己是不是要从"愚昧之巅"掉到"绝望之谷"了,哈哈哈 邓宁-克鲁格效应 一.前言 前面的文章中已经 ...

  10. Android 12(S) 图形显示系统 - Surface 一点补充知识(十二)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 因为个人工作主要是Android多媒体播放的内容,在工作中查看源码或设计程序经常会遇到调用API: static inline i ...

随机推荐

  1. docker 应用篇————容器卷[十一]

    前言 简单介绍一下容器卷. 正文 我们发现一个文件,就是什么呢? 就是说因为我们的容器一但删除那么什么都没有了. 那么如何能够不删除呢?那么可以使用容器卷. 比如说系统我们容器内的/usr 使用我们的 ...

  2. 重新整理数据结构与算法(c#)—— 算法套路二分法[二十四]

    前言 前面写过二分法使用的是递归手法,然后该节才有不递归的方式执行. 二分法的时间复杂度为log(2)n.空间复杂度为:1. 正文 代码: static void Main(string[] args ...

  3. 【Windbg Preview】Failed to load data access DLL, 0x80004005

    最近使用Windbg的时候一直在用Preview版本,感觉解析一下就能直接加载起环境来太爽了.不过最近遇到一个dump加载不起来了. 但是最近一次加载却失败了,尝试了很久也不行 Failed to l ...

  4. NG 转发配置

    ng的用途就不用说了,反向代理么,都知道,不过以前一直不太理解怎没配,现在终于理解点了 1.下载ng,如图: 2.先解压,解压后的路径不建议有空格和中文,其次配置环境变量,加到系统path 3.启动n ...

  5. CSS 中 MASK 实现图片遮罩登炫酷效果

    顾名思义,mask 译为遮罩.在 CSS 中,mask 属性允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域. 其实 mask 的出现已经有一段时间了,只是没有特别多 ...

  6. 【pytorch学习】之数据预处理

    2 数据预处理 为了能用深度学习来解决现实世界的问题,我们经常从预处理原始数据开始,而不是从那些准备好的张量格式数据开始.在Python中常用的数据分析工具中,我们通常使用pandas软件包.像庞大的 ...

  7. Spring Cloud Gateway 突发高危漏洞,下一代云原生网关恰逢其时?

    ​简介:Log4j2 的漏洞刚告一段落,Spring 官方在 2022 年 3 月 1 日发布了 Spring Cloud Gateway 的两个 CVE 漏洞:分别为 CVE-2022-22946( ...

  8. Dubbo-go v3.0 正式发布 ——打造国内一流开源 Go 服务框架

    ​简介:Dubbo-go 是常新的,每年都在不断进化.介绍 Dubbo-go 3.0 工作之前,先回顾其过往 6 年的发展历程,以明晰未来的方向. ​ 作者 | 李志信 来源 | 阿里技术公众号 作者 ...

  9. WPF 基础 2D 图形学知识 判断点是否在线段上

    在知道一个使用两个点表示的线段,和另一个点,求另一个点是否在线段上 本文算法属于通用的算法,可以在 WPF 和 UWP 和 Xamarin 等上运行,基本上所有的 .NET 平台都能执行 如下图,如果 ...

  10. fastreport .net打印普通报表

    fastreport .net打印普通报表 前言: .net代码层先不记录在这,后续会单独写一篇博客来记录. 直接在工具上进行功能点的实现 一.效果图 二.功能点 分页 分页小计 金额大写 三.功能点 ...