一、android多媒体播放的调用步骤:
a)android中定义一个MediaPlayer类
b)在MediaPlayer中使用JNI技术调用的是android_media_MediaPlayer.cpp(media\jni,在这个类中对标准的JNI函数名称进行的转换)
c)以下涉及的都是C++,android_media_MediaPlayer中调用的是mediaplayer.cpp(media\libmedia,涉及的库libmedia.so)中的函数
d)然后调用MediaPlayerService.cpp(media\libmediaplayerservice)中的函数
e)之后开始选择是使用OpenCore还是Stagefright(2.3中使用的是Stagefright),因此接下来调用的是StagefrightPlayer.cpp(media\libmediaplayerservice)中的相关函数
f)接下去就到了最关键的一个类AwesomePlayer.cpp(media\libstagefright),在这个类里面我们要对read进的buffer进行一些相应的处理,然后再render渲染到surface(这边涉及的库可能是libStagefright.so)
二、以setDataSource()来分析android多媒体播放过程:
a)MediaPlayer类有setDataSource方法,查看源码,它最后调用的是一个native函数(JNI标准),publicnativevoidsetDataSource(Stringpath),这个函数在android_media_MediaPlayer.cpp中实现
b)android_media_MediaPlayer.cpp中
android_media_MediaPlayer_setDataSourceAndHeaders(
JNIEnv*env,jobjectthiz,jstringpath,jobjectheaders)
{
sp<MediaPlayer>mp=getMediaPlayer(env,thiz);
。。。
status_topStatus=mp->setDataSource(String8(pathStr),headers?&headersVector:NULL);
。。。
}
其中mp是一个MediaPlayer的实例对象,pathStr是视频路径,之后会进入到 mediaplayer.cpp中的 setDataSource()函数
c)Mediaplayer.cpp中
status_tMediaPlayer::setDataSource(
constchar*url,constKeyedVector<String8,String8>*headers)
{
LOGV("setDataSource(%s)",url);
status_terr=BAD_VALUE;
if(url!=NULL){
constsp<IMediaPlayerService>&service(getMediaPlayerService());
if(service!=0){
sp<IMediaPlayer>player(
service->create(getpid(),this,url,headers,mAudioSessionId));
err=setDataSource(player);
}
}
returnerr;
}
这里会调用service的create()函数
d)在MediaPlayerService.cpp中
sp<IMediaPlayer>MediaPlayerService::create(
pid_tpid,constsp<IMediaPlayerClient>&client,constchar*url,
constKeyedVector<String8,String8>*headers,intaudioSessionId)
{
int32_tconnId=android_atomic_inc(&mNextConnId);
sp<Client>c=newClient(this,pid,connId,client,audioSessionId);
LOGV("Createnewclient(%d)frompid%d,url=%s,connId=%d,audioSessionId=%d",
connId,pid,url,connId,audioSessionId);
if(NO_ERROR!=c->setDataSource(url,headers))
{
c.clear();
returnc;
}
wp<Client>w=c;
Mutex::Autolocklock(mLock);
mClients.add(w);
returnc;
}
其中调用了Client类的setDataSource()函数,这个Client比较难找,其实它 是在MediaPlayerService.h中定义的,在java中叫内部类,C++中忘了,查看 Client类中的setDataSource()函数的代码
status_tMediaPlayerService::Client::setDataSource(
constchar*url,constKeyedVector<String8,String8>*headers)
{
LOGV("setDataSource(%s)",url);
if(url==NULL)
returnUNKNOWN_ERROR;
if(strncmp(url,"content://",10)==0){
//getafiledescriptorforthecontentUriand
//passittothesetDataSource(fd)method
String16url16(url);
intfd=android::openContentProviderFile(url16);
if(fd<0)
{
LOGE("Couldn'topenfdfor%s",url);
returnUNKNOWN_ERROR;
}
setDataSource(fd,0,0x7fffffffffLL);//thissetsmStatus
close(fd);
returnmStatus;
}else{
player_typeplayerType=getPlayerType(url);
LOGV("playertype=%d",playerType);
//createtherighttypeofplayer
sp<MediaPlayerBase>p=createPlayer(playerType);
if(p==NULL)returnNO_INIT;
if(!p->hardwareOutput()){
mAudioOutput=newAudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
//nowsetdatasource
LOGV("setDataSource");
mStatus=p->setDataSource(url,headers);
if(mStatus==NO_ERROR){
mPlayer=p;
}else{
LOGE("error:%d",mStatus);
}
returnmStatus;
}
}
其中定义了一个MediaPlayerBase类的实例对象p,并且接下去调用了p的 setDataSource()函数,我们先看看createPlayer()这个函数的源码
staticsp<MediaPlayerBase>createPlayer(player_typeplayerType,void*cookie,
notify_callback_fnotifyFunc)
{
sp<MediaPlayerBase>p;
switch(playerType){
#ifndefNO_OPENCORE
casePV_PLAYER:
LOGV("createPVPlayer");
p=newPVPlayer();
break;
#endif
caseSONIVOX_PLAYER:
LOGV("createMidiFile");
p=newMidiFile();
break;
caseSTAGEFRIGHT_PLAYER:
LOGV("createStagefrightPlayer");
p=newStagefrightPlayer;
break;
caseTEST_PLAYER:
LOGV("CreateTestPlayerstub");
p=newTestPlayerStub();
break;
}
if(p!=NULL){
if(p->initCheck()==NO_ERROR){
p->setNotifyCallback(cookie,notifyFunc);
}else{
p.clear();
}
}
if(p==NULL){
LOGE("Failedtocreateplayerobject");
}
returnp;
}
值得注意的是红色部分,这边就到了StagefrightPlayer.cpp,上面说到定义了一 个MediaPlayerBase类的实例对象p,并且接下去调用了p的 setDataSource() 函数,那么我们就理所当然地去找MediaPlayerBase类了,但是找了很久没找到, 现在知道了,上面红色部分将new出来的StagefrightPlayer对象赋给了P,那么 P调 用的setDataSource()事实上是StagefrightPlayer这个类中的
setDataSource()这个函数
e)在StagefrightPlayer.cpp中
status_tStagefrightPlayer::setDataSource(
constchar*url,constKeyedVector<String8,String8>*headers){
LOGI("setDataSource('%s')",url);
returnmPlayer->setDataSource(url,headers);
}
其中,直接调用mPlayer->setDataSource(url,headers),那么这个mPlayer是什么 呢?在上一个步骤中的newStagefrightPlayer中其实已经赋值了,源码如下
StagefrightPlayer::StagefrightPlayer()
:mPlayer(newAwesomePlayer){
LOGV("StagefrightPlayer");
mPlayer->setListener(this);
}
从红色部分可以看出mPlayer是一个AwesomePlayer类的实例对象,那么这个 setDataSource()函数自然就到这个类中去找了
f)在AwesomePlayer.cpp中
voidAwesomePlayer::onVideoEvent(){
。。。。。。
for(;;){
。。。。。。
status_terr=mVideoSource->read(&mVideoBuffer,&options);
options.clearSeekTo();
。。。。。。
}
。。。。。。
if(mVideoRenderer!=NULL){
mVideoRenderer->render(mVideoBuffer);
}
。。。。。。
}
第一行红色字表示将帧数据读入mVideoBuffer,第二行红色字体是将这些帧数据渲染到画布中。我们需要修改的就是这个部分,不往下分析了。
三、以start()来分析android多媒体播放过程
a)首先查看MediaPlayer.java这个类的源码
publicvoidstart()throwsIllegalStateException{
stayAwake(true);
_start();
}
之后调用的是_start()这个native函数(JNI标准),即privatenativevoid_start()throwsIllegalStateException这个函数在android_media_MediaPlayer.cpp中实现
b)在Android_media_MediaPlayer.cpp中
staticvoid
android_media_MediaPlayer_start(JNIEnv*env,jobjectthiz)
{
LOGV("start");
sp<MediaPlayer>mp=getMediaPlayer(env,thiz);
if(mp==NULL){
jniThrowException(env,"java/lang/IllegalStateException",NULL);
return;
}
process_media_player_call(env,thiz,mp->start(),NULL,NULL);
}
我们看红色部分的代码,最终调用的是mp->start(),这个mp其实是MediaPlayer的一个对象,那么我们就去MediaPlayer.cpp中查看源码
c)在MediaPlayer.cpp中
status_tMediaPlayer::start()
{
。。。。。。
mCurrentState=MEDIA_PLAYER_STARTED;
status_tret=mPlayer->start();
if(ret!=NO_ERROR){
mCurrentState=MEDIA_PLAYER_STATE_ERROR;
}else{
。。。。。。
}
这时候调用了mPlayer的start()这个函数,查看MediaPlayer.h中,可以发现sp<IMediaPlayer>mPlayer,那么再去IMediaPlayer.cpp中去看看
d)在IMediaPlayer.cpp中
status_tstart()
{
Parceldata,reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
remote()->transact(START,data,&reply);
returnreply.readInt32();
}
分享到:
相关推荐
Stagefright框架在Android多媒体架构中扮演着核心角色,它包括多个模块,如解码器、媒体提取器、数据源等,为视频和音频播放提供了高效且灵活的解决方案。这一框架的存在形式是共享库libstagefright.so,其中的...
提供的代码片段展示了在Android系统中,如何通过Stagefright框架的接口获取OMX组件,并通过这些组件执行视频编解码等操作。具体实现涉及到了MediaPlayerService、OMXClient、OMXMaster等多个类的交互,以及对OpenMax...
2. **媒体数据解析**:Android的Stagefright框架提供了解析多媒体文件的服务,RockPlayer通过继承或扩展Stagefright的相关类,如`MediaExtractor`,来解析视频流中的音视频数据。这部分源码会展示如何处理不同封装...
在源码层面,分析OpenCore和Stagefright的实现可以帮助开发者理解Android多媒体处理的底层机制,优化自定义播放器或者进行系统级的调试。此外,对于开发涉及音视频处理的工具或应用,理解这两个框架的工作原理至关...
首先,多媒体框架概述部分介绍了多媒体播放的架构,这一架构主要由三层组成:上层的Java API、JNI层(Java Native Interface),以及底层的多媒体引擎(如stagefright)和编解码器接口(如OpenMAX)。Java API和JNI...
CVE-2013-6282是Android系统在2013年发现的一个关键漏洞,它涉及到了Android的Stagefright多媒体框架。这个漏洞允许恶意攻击者通过MMS( Multimedia Messaging Service)消息发送特制的多媒体文件,从而在用户不知情...
此外,还有用于图形渲染的Skia库和多媒体处理的Stagefright框架。学习这些库的源代码,有助于开发者优化性能、修复潜在问题或者实现自定义功能。 4. **系统服务**:Android提供了丰富的系统服务,如电源管理、网络...
- Android的多媒体框架基于OpenCore和Stagefright,RockPlayer在此基础上进行优化,提供了更高效的媒体处理能力。 - 源码中的关键组件包括MediaExtractor(负责解析媒体流)、MediaCodec(硬件加速编码/解码)和...
5. **Multimedia Streaming**: 实现无线投屏需要处理音视频流的编码、解码和传输,涉及多媒体框架如Stagefright。 6. **Protocol Handling**: WDS需要实现特定的无线投屏协议,如Miracast,这涉及协议解析、编码和...
14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现...
14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现...
14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现...