`

Android多媒体播放器源码解析(stagefright框架)

 
阅读更多

一、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();

}

分享到:
评论

相关推荐

    android2.3源码解读—stagefright框架

    Stagefright框架在Android多媒体架构中扮演着核心角色,它包括多个模块,如解码器、媒体提取器、数据源等,为视频和音频播放提供了高效且灵活的解决方案。这一框架的存在形式是共享库libstagefright.so,其中的...

    android 视频软硬编解码实现方案

    提供的代码片段展示了在Android系统中,如何通过Stagefright框架的接口获取OMX组件,并通过这些组件执行视频编解码等操作。具体实现涉及到了MediaPlayerService、OMXClient、OMXMaster等多个类的交互,以及对OpenMax...

    安卓Android源码——RockPlayer源码.zip

    2. **媒体数据解析**:Android的Stagefright框架提供了解析多媒体文件的服务,RockPlayer通过继承或扩展Stagefright的相关类,如`MediaExtractor`,来解析视频流中的音视频数据。这部分源码会展示如何处理不同封装...

    android中的opencore介绍

    在源码层面,分析OpenCore和Stagefright的实现可以帮助开发者理解Android多媒体处理的底层机制,优化自定义播放器或者进行系统级的调试。此外,对于开发涉及音视频处理的工具或应用,理解这两个框架的工作原理至关...

    Mstar 安卓播放器

    首先,多媒体框架概述部分介绍了多媒体播放的架构,这一架构主要由三层组成:上层的Java API、JNI层(Java Native Interface),以及底层的多媒体引擎(如stagefright)和编解码器接口(如OpenMAX)。Java API和JNI...

    Android代码-Androidroot源码利用CVE-2013-6282漏洞.zip

    CVE-2013-6282是Android系统在2013年发现的一个关键漏洞,它涉及到了Android的Stagefright多媒体框架。这个漏洞允许恶意攻击者通过MMS( Multimedia Messaging Service)消息发送特制的多媒体文件,从而在用户不知情...

    老罗android之旅源代码

    此外,还有用于图形渲染的Skia库和多媒体处理的Stagefright框架。学习这些库的源代码,有助于开发者优化性能、修复潜在问题或者实现自定义功能。 4. **系统服务**:Android提供了丰富的系统服务,如电源管理、网络...

    RockPlayer源码_Android.rar

    - Android的多媒体框架基于OpenCore和Stagefright,RockPlayer在此基础上进行优化,提供了更高效的媒体处理能力。 - 源码中的关键组件包括MediaExtractor(负责解析媒体流)、MediaCodec(硬件加速编码/解码)和...

    wds源码Android

    5. **Multimedia Streaming**: 实现无线投屏需要处理音视频流的编码、解码和传输,涉及多媒体框架如Stagefright。 6. **Protocol Handling**: WDS需要实现特定的无线投屏协议,如Miracast,这涉及协议解析、编码和...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part1

    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 实现...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part3

    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 实现...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part2

    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 实现...

Global site tag (gtag.js) - Google Analytics