Android 12(S) MultiMedia Learning(四)MediaPlayerService
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的主要代码位置:
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的更多相关文章
- Android 12(S) 图形显示系统 - 解读Gralloc架构及GraphicBuffer创建/传递/释放(十四)
必读: Android 12(S) 图形显示系统 - 开篇 一.前言 在前面的文章中,已经出现过 GraphicBuffer 的身影,GraphicBuffer 是Android图形显示系统中的一个重 ...
- Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)
1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...
- Android系列之Fragment(四)----ListFragment的使用
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 转--Android按钮单击事件的四种常用写法总结
这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的 ...
- Android开发_Android数据的四种存储方式
Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File.由于Android系统中,数据基本都是私有的的,都是存放 ...
- Android图表库MPAndroidChart(十四)——在ListView种使用相同的图表
Android图表库MPAndroidChart(十四)--在ListView种使用相同的图表 各位好久不见,最近挺忙的,所有博客更新的比较少,这里今天说个比较简单的图表,那就是在ListView中使 ...
- Android群英传笔记——第四章:ListView使用技巧
Android群英传笔记--第四章:ListView使用技巧 最近也是比较迷茫,但是有一点点还是要坚持的,就是学习了,最近离职了,今天也是继续温习第四章ListView,也拖了其实也挺久的了,list ...
- Android 12(S) 图形显示系统 - createSurface的流程(五)
题外话 刚刚开始着笔写作这篇文章时,正好看电视在采访一位92岁的考古学家,在他的日记中有这样一句话,写在这里与君共勉"不要等待幸运的降临,要去努力的掌握知识".如此朴实的一句话,此 ...
- Android 12(S) 图形显示系统 - BufferQueue的工作流程(八)
题外话 最近总有一个感觉:在不断学习中,越发的感觉自己的无知,自己是不是要从"愚昧之巅"掉到"绝望之谷"了,哈哈哈 邓宁-克鲁格效应 一.前言 前面的文章中已经 ...
- Android 12(S) 图形显示系统 - Surface 一点补充知识(十二)
必读: Android 12(S) 图形显示系统 - 开篇 一.前言 因为个人工作主要是Android多媒体播放的内容,在工作中查看源码或设计程序经常会遇到调用API: static inline i ...
随机推荐
- 基于ArkUI开发框架,图片马赛克处理的实现
原文:https://mp.weixin.qq.com/s/60HDKcBFV7GTjZpzeHtjeg,点击链接查看更多技术内容. 关于马赛克 马赛克是一种使用较为广泛的图片处理方式, ...
- B端架构升级之路
一.背景 随着B端业务快速发展,系统愈趋复杂.我们发起了B端架构升级专项,基于B端业务的特点,从研发规范建设.B端架构基建.系统架构升级和落地保障等多方面提升了B端的架构水平. 二.升级思路 架构是一 ...
- react native 使用typescript
前言 TypeScript作为JavaScript的一个富类型扩展语言,深受代码风格严谨的前端开发者欢迎.但在react-native下,因为packager的配置困难,使用TypeScript一直是 ...
- MySQL 分析查询与来源机器
当前分析针对版本:MariaDB 10.5 线上出现报错:can't create more than max_prepared_stmt_count statements.造成这个错误的直接原因就是 ...
- c#程序员必学清单
必读书目:1. "Effective C#: 50 Specific Ways to Improve Your C#" by Bill Wagner2. "CLR via ...
- 力扣242(java)-有效的字母异位词(简单)
题目: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词. 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词. 示例 1: 输入: s ...
- 阿里云基于全新 RocketMQ 5.0 内核的落地实践
简介: 本篇文章的核心就消息架构以及产品能力的云原生化,介绍了阿里云是如何基于全新的 RocketMQ 5.0 内核做出自己的判断和演进,以及如何适配越来越多的企业客户在技术和能力方面的诉求. 前言 ...
- PolarDB-X 高可用存储服务: 基于 X-Paxos 一致性协议
简介: 摘自刘永平(慕少)阿里云 PolarDB-X 技术专家在PolarDB-X | 新品发布会中的讲解内容. 了解更多PolarDB-X 内容:https://developer.aliyun.c ...
- [FAQ] swagger-php 支持 Authorization Bearer token 校验的用法
@OA\SecurityScheme 可以是 Controller 层面也可以是 Action 层面. 类型 type="apiKey". in="header" ...
- 5.prometheus监控--监控nginx
1.监控程序环境准备 mkdir /data/docker-compose -p cd /data/docker-compose cat > docker-compose.yaml <&l ...