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. 通过Jenkins构建CI/CD实现全链路灰度

    简介: 本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 作者:卜比   本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 在发布过程中,为了整体稳定性,我们总是希 ...

  2. KubeVela 正式开源:一个高可扩展的云原生应用平台与核心引擎

    美国西部时间 2020 年 11 月 18 日,在云原生技术"最高盛宴"的 KubeCon 北美峰会 2020 上,CNCF 应用交付领域小组(CNCF SIG App Deliv ...

  3. 如何使用 Kubernetes 监测定位慢调用

    ​简介:本次课程主要分为三大部分,首先将介绍慢调用的危害以及常见的原因:其次介绍慢调用的分析方法以及最佳实践:最后将通过几个案例来去演示一下慢调用的分析过程. 作者:李煌东 大家好,我是阿里云的李煌东 ...

  4. Yurt-Tunnel 详解|如何解决 K8s 在云边协同下的运维监控挑战

    简介: 伴随着 5G.IoT 等技术的快速发展,边缘计算被越来越广泛地应用于电信.媒体.运输.物流.农业.零售等行业和场景中,成为解决这些领域数据传输效率的关键方式.与此同时,边缘计算形态.规模.复杂 ...

  5. 阿里集团业务驱动的升级 —— 聊一聊Dubbo 3.0 的演进思路

    简介: 阿里云在 2020年底提出了"三位一体"理念,目标是希望将"自研技术"."开源项目"."商业产品"形成统一的技术 ...

  6. [Gse] 高效的Golang中文分析库推荐

    优点:用法简单,支持各种语言,基本满足需求. 缺点:默认分词字典文件有 8M 需测试使用速度. 我们可以直接封装一个简单的辅助方法来实现分词功能: // @author cnblogs.com/far ...

  7. [FAQ] docker-compose MySQL8 ERROR: Different lower_case_table_names settings for server

    MySQL8 启动时 lower_case_table_names 的设置和初始值不一致时,会报 ERROR. 在 docker-compose 中,只需要在命令中加入命令选项即可,并配置一个新的 v ...

  8. WPF 关于将 ManipulationDeltaEventArgs 的 Manipulators 属性返回值修改为 ReadOnlyCollection 类型的提议

    这是一个 WPF 框架的 API 变更提议,记录一下博客 讨论的地方是: How about change the type of ManipulationDeltaEventArgs.Manipul ...

  9. dotnet C# 只创建对象不调用构造函数方法

    有时我期望只是创建出对象,但是不要调用对象的构造方法,可以通过使用 FormatterServices 的 GetUninitializedObject 函数来实现只创建对象不调用构造函数方法 这个 ...

  10. vue项目上线前优化(路由懒加载的使用,外部CDN的使用)

    引 当使用vue做完项目后,接下来当然是要进行线上部署了.但是在上线之前还是可以做很多方面优化的,可以让项目上线后的体验更加哦. 若是使用了vue-cli的话,可以从面板界面直观的看到各项数据,控制台 ...