PVPlayer的实现方式
关于opencore下多媒体播放,在mediaserver进程里面仅仅有一行代码:
MediaPlayerService::instantiate();
这行代码的作用是初始化一个MediaPlayerService类的实例,并接把他增加到系统的serveceManager中。
MediaPlayerService的详细实如今目录frameworks/base/media/libmediaplayerservice中。
在涉及到要播放一个详细的媒体文件时,调用的函数是:
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
{
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(this, pid, connId, client);
LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
if (NO_ERROR != c->setDataSource(url))
{
c.clear();
return c;
}
wp<Client> w = c;
Mutex::Autolock lock(mLock);
mClients.add(w);
return c;
}
这个new 了一个Client 而且函数将它返回为sp<IMediaPlayer>。
Client对象什么在文件MediaPlayerService.h中,而且是private类,说明它仅仅被MediaPlayerService对象使用。Client对象继承自BnMediaPlayer,而BnMediaPlaye又继承自BnInterface<IMediaPlayer>,看来是用来响应binder的IPC的函数。
而IMediaPlayer又是何许东东。
IMediaPlayer.cpp在目录frameworks/base/media/中,而IMediaPlayer.h 在目录frameworks/base/include/media中。IMediaPlayer.h中声明了一个IMediaPlayer的类,而它的函数又都是virtual,一看就是用来申明接口的。
MediaPlayerService::create函数调用以后,立即调用Client:setDataSource,事实上如今MediaPlayerService.cpp中,
status_t MediaPlayerService::Client::setDataSource(const char *url)
{
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)
{
LOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
return mStatus;
} else {
player_type playerType = getPlayerType(url); //通过url来取得playertype,比如对于midi,就用SONIVOX_PLAYER,mp3,mp4等就用PVPLAYER
LOGV("player type = %d", playerType);
// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType); //依据不同的playertype来创建不同的player实例
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput();
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
// now set data source
LOGV(" setDataSource");
mStatus = p->setDataSource(url);
if (mStatus == NO_ERROR) {
mPlayer = p;
} else {
LOGE(" error: %d", mStatus);
}
return mStatus;
}
}
注意这行代码:sp<MediaPlayerBase> p = createPlayer(playerType);
他的作用是依据不同的playerType来创建player实例,我们这里主要关注PVPlayer。说了这么多,最终到达opencore那一层了。有时候会认为android这种设计实在太复杂了,调用起来太麻烦,直接实现一个IMediaPlayer的类不就完了吗。可是细致一样,androide的这种设计方式事实上有它在扩展性和可维护性上才这样做的。说究竟就是一句话,减少模块间的耦合性。
涉及到详细的操作,都是通过实现一个接口类来实现,这样详细的实例在创建的时候就能够通过工厂模式来简单的进行扩展。比如上面所提到的createPlayer(playerType)这个函数,当你须要加入自己的特殊格式的播放器的时候,就不用来改它本来的代码,而仅仅用在createPlayer(playerType)的实现以下几行代码:
case XXX_PLAYER:
LOGV(" create XXXFile");
p = new XXXPlayer();
break;
很方便,而这样的扩展性和是由接口和实现的分离带来的,createPlayer 返回的是sp<MediaPlayerBase>类,而去看这个类的代码,发现这个类都是由virtual函数组成的,当你要实现详细实现时候,你能够继承它,然后写好这些virtual函数的实现。
扯远了。设计模式的厉害,可能须要我花整个的职业生涯来体会。
废话不多说,让我们来看PVPlayer的实现,我刚才说过,PVPlayer才是opencore真正的内容。
PVPlayer的申明在frameworks/base/include/media/PVPlayer.h中,而实如今external/opencore/android/playerdriver.cpp。
为什么要这样做?我不懂,我推測还是为了实现和接口的分离,仅仅只是这次的分离就仅仅能简单的通过把头文件和实现文件放到不同目录下来实现。
OK,那么让我们来看看PVPlayer是干嘛的。
PVPlayer继承自MediaPlayerInterface,而MediaPlayerInterface是Opencore对媒体播放的抽象接口的声明类。
那么我们去看看PVPlayer的各个接口的实现吧。PVPlayer的非常多借口都是通过向它的成员mPlayerDriver发送命令来实现,而mPlayerDriver通过调用mPVPlayer的sendEvent函数来告诉PVPlayer,命令是否运行成功了。PlayerDriver是PVPlayer的一个内部成员,它是PVPlayer的命令运行者。
sendEvent的实现例如以下:
void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
MediaPlayerBase::sendEvent的实现例如以下:
virtual void sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
mNotify是MediaPlayerBase的一个成员变量,它是一个函数指针,原型例如以下:
typedef void (*notify_callback_f)(void* cookie, int msg, int ext1, int ext2);
这个成员变量在调用createPlayer的时候就调用setNotifyCallback来赋值的。
所以,能够看到,底层的事件会一层一层的往上调用,直至返回给用户层。
这里涉及到2个设计模式:
命令模式和观察者模式。
这两个模式都是设计模式中的基本模式之中的一个,功能强大,逻辑清晰。详细的内容不是本文的重点,在此略过。
PVPlayer的实现方式的更多相关文章
- 通过adb方式给安卓手机截图的cmd批处理文件
@echo off rem 通过adb方式截图rem 需要安装adb ,一般安装了android sdk 默认带了adb ,路径为sdk目录的android-sdk\platform-toolsr ...
- VisualVM通过jstatd方式远程监控远程主机
配置好权限文件 [root@test bin]# cd $JAVA_HOME/bin [root@test bin]# vim jstatd.all.policy grant codebase &qu ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- C#高性能TCP服务的多种实现方式
哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣,为了吸引眼球所以标题中一定要突出,其实我更喜欢的标题是<猴赛雷,C#编写TCP服务的花样姿势!>. 本篇文章的主 ...
- C# 中参数验证方式的演变
一般在写方法的时候,第一步就是进行参数验证,这也体现了编码者的细心和缜密,但是在很多时候这个过程很枯燥和乏味,比如在拿到一个API设计文档的时候,通常会规定类型参数是否允许为空,如果是字符可能有长度限 ...
- nodejs之get/post请求的几种方式
最近一段时间在学习前端向服务器发送数据和请求数据,下面总结了一下向服务器发送请求用get和post的几种不同请求方式: 1.用form表单的方法:(1)get方法 前端代码: <form act ...
- CSS 选择器及各样式引用方式
Css :层叠样式表 (Cascading Style Sheets),定义了如何显示HTML元素. 目录 1. 选择器的分类:介绍ID.class.元素名称.符合.层次.伪类.属性选择器. 2. 样 ...
随机推荐
- 经验交流List
6月10日:登录功能的实现 第1组,郑超,90 第5组,张琳,90 ----------------------------- 6月11日上午:登录优化 第7组,张朋,90 6月11日下午:查询操作实 ...
- Android 程式开发:(廿二)服务 —— 22.1 自定义服务
服务,就是跑在后台的“程序”,不需要和用户进行交互.举个例子,当使用一款应用的时候,可能同时想在后台播放一些音乐.在这种情况下,后来播放音乐的代码不需要和用户进行交互,所以,它就可能被当成一个服务.当 ...
- MongoDB---性能优化---(1)
MONGODB数据架构 升级解决.计划 发现问题 应用server用户数的突然涌入,创建server反应慢 检查server,我发现,每次反应非常慢,至30ops 检查过程 .发现数据库查询缓 ...
- 公钥password学中的素数以及对称加密
password学.一向被人们觉得门槛非常高,特别高端...这也是实际,可是这决不意味着普通人无法了解它的精髓.对于喜欢画圆的人来讲,即便是理解了password技术背后的哪怕一点理论,也是激 ...
- Java学习——何为JNDI
曾记得在做机房收费系统的时候就接触到了API,由于它的功能非常强大,可是自己对它却不怎么了解.所以当时是又爱又怕.现在,一路走来才明确,事实上它就是一组接口.仅仅要我们去了解它就会发现.它事实上也没想 ...
- ASP.NET - 编写让别人能读懂的代码
http://www.cnblogs.com/richieyang/p/4840614.html
- HDU 3397 Sequence operation(线段树)
HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...
- 控件编写:增强 TMEMO (一)(增加对WM_HSCROLL消息的处理)
相信没有什么人对 MEMO 陌生了吧.尽管其组件的功能不错.但是,对它进行一些功能的改进,可以更好的使用. 有的时候,我们想要知道,当前的坐标是什么?甚至,想要在 滚动条滚动时触发一些事件. 但,TM ...
- 解决SVG跨浏览器兼容性问题
Raphael JS:SVG/VML+JS实现跨浏览器的矢量图形实现方案 http://blog.csdn.net/tiewen/article/details/8535748 SVG那些小事儿 ht ...
- GCC中初始化函数是怎样被处理的?
本文译至: http://gcc.gnu.org/onlinedocs/gccint/Initialization.html 如我们所知,在GCC通过给代码追加__attribute__((const ...