Android NuPlayer要点详解.docx
- 文档编号:4056981
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:47
- 大小:105.15KB
Android NuPlayer要点详解.docx
《Android NuPlayer要点详解.docx》由会员分享,可在线阅读,更多相关《Android NuPlayer要点详解.docx(47页珍藏版)》请在冰豆网上搜索。
AndroidNuPlayer要点详解
AndroidNuPlayer要点详解
1、AHandler机制
首先介绍NuPlayer中无处不在的AHandler机制
frameworks/av/include/media/stagefright/foundation/
frameworks/av/media/libstagefright/foundation/
AHandler是Androidnative层实现的一个异步消息机制,在这个机制中所有的处理都是异步的,将变量封装到一个消息AMessage结构体中,然后放到队列中去,后台专门有一个线程会从这个队列中取出消息然后执行,执行函数就是onMessageReceived。
Ahandler机制包括以下几个类
AMessage
消息类,用于构造消息,通过post方法投递出去给ALooper
status_tAMessage:
:
post(int64_tdelayUs){
sp
if(looper==NULL){
ALOGW("failedtopostmessageastargetlooperforhandler%disgone.",mTarget);
return-ENOENT;
}
looper->post(this,delayUs);
returnOK;
}
voidAMessage:
:
deliver(){
sp
if(handler==NULL){
ALOGW("failedtodelivermessageastargethandler%disgone.",mTarget);
return;
}
handler->deliverMessage(this);//seeAHandler@deliverMessage,前面通过looperpost最后就是调用这里的deliever送到handler手里
}
AHandler
消息处理类,一般当做父类,继承该类的子类需要实现onMessageReceived方法
voidAHandler:
:
deliverMessage(constsp
onMessageReceived(msg);
mMessageCounter++;
….
}
ALooper
与Ahander一一对应,负责存储消息并分发Ahandler的消息,与AMessage一对多关系
//postsamessageonthislooperwiththegiventimeout
voidALooper:
:
post(constsp
Mutex:
:
AutolockautoLock(mLock);
int64_twhenUs;
if(delayUs>0){
whenUs=GetNowUs()+delayUs;
}else{
whenUs=GetNowUs();
}
List
:
iteratorit=mEventQueue.begin();
while(it!
=mEventQueue.end()&&(*it).mWhenUs<=whenUs){
++it;
}
Eventevent;
event.mWhenUs=whenUs;
event.mMessage=msg;
if(it==mEventQueue.begin()){
mQueueChangedCondition.signal();
}
mEventQueue.insert(it,event);
}
----------------------------------------------------------
status_tALooper:
:
start(
boolrunOnCallingThread,boolcanCallJava,int32_tpriority){
if(runOnCallingThread){
{
Mutex:
:
AutolockautoLock(mLock);
if(mThread!
=NULL||mRunningLocally){
returnINVALID_OPERATION;
}
mRunningLocally=true;
}
do{
}while(loop());
returnOK;
}
Mutex:
:
AutolockautoLock(mLock);
if(mThread!
=NULL||mRunningLocally){
returnINVALID_OPERATION;
}
mThread=newLooperThread(this,canCallJava);
status_terr=mThread->run(
mName.empty()?
"ALooper":
mName.c_str(),priority);
if(err!
=OK){
mThread.clear();
}
returnerr;
}
boolALooper:
:
loop(){
Eventevent;
{
Mutex:
:
AutolockautoLock(mLock);
if(mThread==NULL&&!
mRunningLocally){
returnfalse;
}
if(mEventQueue.empty()){
mQueueChangedCondition.wait(mLock);
returntrue;
}
int64_twhenUs=(*mEventQueue.begin()).mWhenUs;
int64_tnowUs=GetNowUs();
if(whenUs>nowUs){
int64_tdelayUs=whenUs-nowUs;
mQueueChangedCondition.waitRelative(mLock,delayUs*1000ll);
returntrue;
}
event=*mEventQueue.begin();
mEventQueue.erase(mEventQueue.begin());
}
event.mMessage->deliver(); //seeAHandler.deliverMessage
…..
returntrue;
}
LooperThread
此线程调用ALooper的loop方法来分发消息
virtualstatus_treadyToRun(){
mThreadId=androidGetThreadId();
returnThread:
:
readyToRun();
}
virtualboolthreadLoop(){
returnmLooper->loop();
}
ALooperRoaster
与Handler是一对多的关系,管理Looper和Handler一一对应关系,负责释放stalehandler
ALooper:
:
handler_idALooperRoster:
:
registerHandler(
constsp
Mutex:
:
AutolockautoLock(mLock);
if(handler->id()!
=0){
CHECK(!
"Ahandlermustonlyberegisteredonce.");
returnINVALID_OPERATION;
}
HandlerInfoinfo;
info.mLooper=looper;
info.mHandler=handler;
ALooper:
:
handler_idhandlerID=mNextHandlerID++;//一对一
mHandlers.add(handlerID,info);//一对多
handler->setID(handlerID,looper);
returnhandlerID;
}
voidALooperRoster:
:
unregisterHandler(ALooper:
:
handler_idhandlerID){
Mutex:
:
AutolockautoLock(mLock);
ssize_tindex=mHandlers.indexOfKey(handlerID);
if(index<0){
return;
}
constHandlerInfo&info=mHandlers.valueAt(index);
sp
if(handler!
=NULL){
handler->setID(0,NULL);
}
mHandlers.removeItemsAt(index);
}
voidALooperRoster:
:
unregisterStaleHandlers(){
Vector
{
Mutex:
:
AutolockautoLock(mLock);
for(size_ti=mHandlers.size();i>0;){
i--;
constHandlerInfo&info=mHandlers.valueAt(i);
sp
if(looper==NULL){
ALOGV("Unregisteringstalehandler%d",mHandlers.keyAt(i));
mHandlers.removeItemsAt(i);
}else{
//Atthispoint'looper'mightbetheonlysp<>keeping
//theobjectalive.Topreventitfromgoingoutofscope
//andhaving~ALoopercallthismethodagainrecursively
//andthendeadlockingbecauseoftheAutolockabove,add
//ittoaVectorwhichwillgooutofscopeafterthelock
//hasbeenreleased.
activeLoopers.add(looper);
}
}
}
}
异步消息机制的创建
sp
sp
mLooper->setName(“xxxxx”);//设置looper名字
mLooper->start(false,true,PRIORITY_XXX);//根据参数创建并启动looperthread
mLooper->regiserHandler(mHandler);//registerhandler会调用AHandler的setID方法将looper设置到Handler里去
Post消息
sp
msg->post();//调用looper的post方法
MessagePost的调用过程
Message:
:
post
↓
ALooper:
:
post
mEventQueue.insert
mQueueChangedCondition.signal()//如果之前没有event,通知looperthread
↓
ALooper:
:
loop()
if(mEventQueue.empty()){//如果消息队列为空,则等待
mQueueChangedCondition.wait(mLock);
returntrue;
}
event=*mEventQueue.begin();
event.mMessage->deliver();
↓
AHandler:
:
deliverMessage
↓
AHandlerReflector:
:
onMessageReceived
↓
具体的实现
NuPlayer
下面就进入我们的正题,NuPlayer
frameworks/av/media/libmediaplayerservice/nuplayer/
NuPlayerDriver
NuPlayerDriver是对NuPlayer的封装,继承MediaPlayerInterface接口。
通过NuPlayer来实现播放的功能。
看这部分代码的方法就是先看NuPlayerDriver里面干了啥,转头就去找NuPlayer里面的实现,一般都要再去NuPlayer的onMessageReceive中看消息的响应,最后回到NuPlayerDriver的各种notify中看流程的周转,下面附上一张播放器状态机流转图
NuPlayerDriver:
:
NuPlayerDriver(pid_tpid)
:
mState(STATE_IDLE),//对应播放器状态机的初始化状态
mIsAsyncPrepare(false),
mAsyncResult(UNKNOWN_ERROR),
mSetSurfaceInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
mSeekInProgress(false),
mLooper(newALooper),
mPlayerFlags(0),
mAtEOS(false),
mLooping(false),
mAutoLoop(false){
ALOGV("NuPlayerDriver(%p)",this);
//和前面所述的异步消息创建机制相符
mLooper->setName("NuPlayerDriverLooper");
mLooper->start(
false,/*runOnCallingThread*/
true,/*canCallJava*/
PRIORITY_AUDIO);
//mPlayer即NuPlayer,继承于AHandler
mPlayer=AVNuFactory:
:
get()->createNuPlayer(pid);
mLooper->registerHandler(mPlayer);
mPlayer->setDriver(this);
}
NuPlayerDriver:
:
~NuPlayerDriver(){
ALOGV("~NuPlayerDriver(%p)",this);
mLooper->stop();//整个NuPlayerDriver就是一个大ALooper
}
AVNuFactory
负责关键组件的create,通过它能看到:
1.每一个NuPlayer对应一个进程
2.数据流从Source-Decoder-Renderer,中间由AMessages驱动
sp
:
createNuPlayer(pid_tpid){
returnnewNuPlayer(pid);
}
sp : DecoderBase>AVNuFactory: : createPassThruDecoder( constsp constsp : Source>&source, constsp : Renderer>&renderer){ returnnewNuPlayer: : DecoderPassThrough(notify,source,renderer); } sp : DecoderBase>AVNuFactory: : createDecoder( constsp constsp : Source>&source, pid_tpid, constsp : Renderer>&renderer){ returnnewNuPlayer: : Decoder(notify,source,pid,renderer); } sp : Renderer>AVNuFactory: : createRenderer( constsp : AudioSink>&sink, constsp uint32_tflags){ returnnewNuPlayer: : Renderer(sink,notify,flags); } 下面分别分析Source,Decoder,Renderer Source 以setDataSource为切入点 status_tNuPlayerDriver: : setDataSource(constsp ALOGV("setDataSource(%p)streamsource",this); Mutex: : AutolockautoLock(mLock); if(mState! =STATE_IDLE){ returnINVALID_OPERATION; } mState=STATE_SET_DATASOURCE_PENDING; mPlayer->setDataSourceAsync(source);//因为driver只是NuPlayer的封装,所以还是要去调用NuPlayer完成实际动作 while(mState==STATE_SET_DATASOURCE_PENDING){ mCondition.wait(mLock); } returnmAsyncResult; } -------------------------------------- voidNuPlayer: : setDataSourceAsync(constsp sp sp msg->setObject("source",newStreamingSource(notify,source)); msg->post(); //到了NuPlayer中,也不是直接进行操作,而是先发个消息,验证前面所说的一切都由AMessage驱动 } --------------------------------------- voidNuPlayer: : onMessageReceived(constsp switch(msg->what()){ casekWhatSetDataSource: //实际的处理在这里 { ALOGV("kWhatSetDataSource"); CHECK(mSource==NULL); status_terr=OK; sp CHECK(msg->findObject("source",&obj)); if(obj! =NULL){ Mutex: : AutolockautoLock(mSourceLock); mSource=static_cast }else{ err=UNKNOWN_ERROR; } CHECK(mDriver! =NULL); sp if(driver! =NULL){ driver->notifySetDataSourceCompleted(err);//通知driver设置完毕 } break; }...... --------------------------------------- voidNuPlayerDriver: : notifySetDataSourceCompleted(status_terr){ Mutex: : AutolockautoLock(mLock); CHECK_EQ(mState,STATE_SET_DATASOURCE_PENDING); mAsyncResult=err; mState=(err==OK)? STATE_UNPREPARED: STATE_IDLE;//回到driver中,流转播放器状态进入下一阶段 mCondition.broadcast(); } 下面就来看看具体有哪些source,它们都继承自NuPlayer: Source(NuPlayerSource.h&NuPlayerSource.cpp) 1.HTTP-进一步判断是以下的哪一种: HTTPLiveSource,RTSPSource,GenericSource 2.File-GenericSource 3.StreamSource-StreamingSource 4.DataSource-GenericSource GenericSource nuplayer/GenericSource.h&Ge
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android NuPlayer要点详解 NuPlayer 要点 详解