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 ...
随机推荐
- HDD杭州站•ArkUI让开发更灵活
原文:https://mp.weixin.qq.com/s/cX48CPs61daKOC2J5znyJw,点击链接查看更多技术内容. 7月15日的HUAWEI Developer Day(简称HDD) ...
- Spring Cloud 核心组件之Spring Cloud Zuul:API网关服务
Spring Cloud Zuul:API网关服务 SpringCloud学习教程 SpringCloud API网关 Spring Cloud Zuul 是Spring Cloud Netflix ...
- 【5】Spring IoC介绍
有部分 Java 开发者对 IoC(Inversion Of Control)和 DI(Dependency Injection)的概念有些混淆,认为二者是对等的. IoC 其实有两种方式,一种就是 ...
- 重新整理 mysql 基础篇—————表锁和全局锁[六]
前言 锁从大的方面可以分为: 1.全局锁 2.表锁 3.行锁 正文 全局锁 全局锁就是对整个数据加上读锁. 在mysql 中,加入全局锁的命令就是: Flush tables with read lo ...
- mysql 重新整理——性能下降的原因[四]
前言 什么是性能下降? 其实就是代码运行的环境变了,那么环境变化是什么? 比如cpu上升了,内存满了.有或者表中数量增加了,量变了. 其实这些是dba干的,但是呢,我们也需要去了解下,并且优化我们的c ...
- 巧用API网关构建大型应用体系架构
简介: 近期阿里云重磅发布了BizWorks一体化的云原生应用的开发和运营平台,内置阿里巴巴业务中台构建的最佳技术实践.它已经将API网关作为关键组件融入其中,并且基于API网关为用户提供能力开放平台 ...
- 深度解析数据湖存储方案Lakehouse架构
简介:从数据仓库.数据湖的优劣势,湖仓一体架构的应用和优势等多方面深度解析Lakehouse架构. 作者:张泊 Databricks 软件工程师 Lakehouse由lake和house两个词组 ...
- DataWorks功能实践速览 05——循环与遍历
简介: DataWorks功能实践系列,帮助您解析业务实现过程中的痛点,提高业务功能使用效率!通过往期的介绍,您已经了解到在DataWorks上进行任务运行的最关键的几个知识点,其中上期参数透传中为 ...
- [ML] 通过llama.cpp与羊驼聊天的网页界面- 详解 Serge 的启动使用
Serge 虽然能够让我们在笔记本上跑起来 7B模型, 但实际运行非常消耗CPU,对话生成响应非常非常慢. 1. 官方指导是使用如下命令直接运行: $ docker run -d -v weigh ...
- [Linux] 启动管理: 运行级别
Link:https://www.cnblogs.com/farwish/p/14983932.html