版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Android NuPlayer要點(diǎn)詳解1、AHandler機(jī)制首先介紹NuPlayer中無處不在的AHandler機(jī)制 frameworks/av/include/media/stagefright/foundation/ frameworks/av/media/libstagefright/foundation/ AHandler是Android native層實(shí)現(xiàn)的一個(gè)異步消息機(jī)制,在這個(gè)機(jī)制中所有的處理都是異步的,將變量封裝到一個(gè)消息AMessage結(jié)構(gòu)體中,然后放到隊(duì)列中去,后臺專門有一個(gè)線程會從這個(gè)隊(duì)列中取出消息然后執(zhí)行,執(zhí)行函數(shù)就是onMessageReceived。Ahandl
2、er機(jī)制包括以下幾個(gè)類AMessage消息類,用于構(gòu)造消息,通過post方法投遞出去給ALooperstatus_t AMessage:post(int64_t delayUs) sp<ALooper> looper = mLmote(); if (looper = NULL) ALOGW("failed to post message as target looper for handler %d is gone.", mTarget); return -ENOENT; looper->post(this, delayUs); retu
3、rn OK;void AMessage:deliver() sp<AHandler> handler = mHmote(); if (handler = NULL) ALOGW("failed to deliver message as target handler %d is gone.", mTarget); return; handler->deliverMessage(this); /see AHandlerdeliverMessage,前面通過looper post最后就是調(diào)用這里的deliever送到handler手里AHa
4、ndler 消息處理類,一般當(dāng)做父類,繼承該類的子類需要實(shí)現(xiàn)onMessageReceived方法void AHandler:deliverMessage(const sp<AMessage> &msg) onMessageReceived(msg); mMessageCounter+;.ALooper 與Ahander一一對應(yīng),負(fù)責(zé)存儲消息并分發(fā)Ahandler的消息,與AMessage一對多關(guān)系/ posts a message on this looper with the given timeoutvoid ALooper:post(const sp<AMes
5、sage> &msg, int64_t delayUs) Mutex:Autolock autoLock(mLock); int64_t whenUs; if (delayUs > 0) whenUs = GetNowUs() + delayUs; else whenUs = GetNowUs(); List<Event>:iterator it = mEventQueue.begin(); while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) +it; Event event
6、; event.mWhenUs = whenUs; event.mMessage = msg; if (it = mEventQueue.begin() mQueueChangedCondition.signal(); mEventQueue.insert(it, event);-status_t ALooper:start( bool runOnCallingThread, bool canCallJava, int32_t priority) if (runOnCallingThread) Mutex:Autolock autoLock(mLock); if (mThread != NUL
7、L | mRunningLocally) return INVALID_OPERATION; mRunningLocally = true; do while (loop(); return OK; Mutex:Autolock autoLock(mLock); if (mThread != NULL | mRunningLocally) return INVALID_OPERATION; mThread = new LooperThread(this, canCallJava); status_t err = mThread->run( mName.empty() ? "AL
8、ooper" : mName.c_str(), priority); if (err != OK) mThread.clear(); return err;bool ALooper:loop() Event event; Mutex:Autolock autoLock(mLock); if (mThread = NULL && !mRunningLocally) return false; if (mEventQueue.empty() mQueueChangedCondition.wait(mLock); return true; int64_t whenUs =
9、(*mEventQueue.begin().mWhenUs; int64_t nowUs = GetNowUs(); if (whenUs > nowUs) int64_t delayUs = whenUs - nowUs; mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll); return true; event = *mEventQueue.begin(); mEventQueue.erase(mEventQueue.begin(); event.mMessage->deliver();/see AHandl
10、er.deliverMessage. return true;LooperThread 此線程調(diào)用ALooper的loop方法來分發(fā)消息 virtual status_t readyToRun() mThreadId = androidGetThreadId(); return Thread:readyToRun(); virtual bool threadLoop() return mLooper->loop();ALooperRoaster 與Handler是一對多的關(guān)系, 管理Looper和Handler一一對應(yīng)關(guān)系,負(fù)責(zé)釋放stale handlerALooper:handler
11、_id ALooperRoster:registerHandler( const sp<ALooper> looper, const sp<AHandler> &handler) Mutex:Autolock autoLock(mLock); if (handler->id() != 0) CHECK(!"A handler must only be registered once."); return INVALID_OPERATION; HandlerInfo info; info.mLooper = looper; info.mH
12、andler = handler; ALooper:handler_id handlerID = mNextHandlerID+;/一對一 mHandlers.add(handlerID, info);/一對多 handler->setID(handlerID, looper); return handlerID;void ALooperRoster:unregisterHandler(ALooper:handler_id handlerID) Mutex:Autolock autoLock(mLock); ssize_t index = mHandlers.indexOfKey(han
13、dlerID); if (index < 0) return; const HandlerInfo &info = mHandlers.valueAt(index); sp<AHandler> handler = info.mHmote(); if (handler != NULL) handler->setID(0, NULL); mHandlers.removeItemsAt(index);void ALooperRoster:unregisterStaleHandlers() Vector<sp<ALooper> &g
14、t; activeLoopers; Mutex:Autolock autoLock(mLock); for (size_t i = mHandlers.size(); i > 0;) i-; const HandlerInfo &info = mHandlers.valueAt(i); sp<ALooper> looper = info.mLmote(); if (looper = NULL) ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i); mHandlers
15、.removeItemsAt(i); else / At this point 'looper' might be the only sp<> keeping / the object alive. To prevent it from going out of scope / and having ALooper call this method again recursively / and then deadlocking because of the Autolock above, add / it to a Vector which will go out
16、 of scope after the lock / has been released. activeLoopers.add(looper); 異步消息機(jī)制的創(chuàng)建sp<ALooper> mLooper = new ALooper; /創(chuàng)建一個(gè)Alooper實(shí)例sp<AHandlerReflector> mHandler = new AHandlerReflector /創(chuàng)建一個(gè)Ahandler實(shí)例mLooper->setName(“xxxxx”); /設(shè)置looper名字mLooper->start(false, true, PRIORITY_XXX);
17、/根據(jù)參數(shù)創(chuàng)建并啟動 looper threadmLooper->regiserHandler(mHandler); /register handler 會調(diào)用AHandler的setID方法將looper設(shè)置到Handler里去Post消息sp<AMessage> msg = new AMessage(kWhatSayGoodbye, mHandler); /在AMessage的構(gòu)造方法里獲取Ahandler對應(yīng)的Looper并保存msg->post(); / 調(diào)用looper的post方法Message Post的調(diào)用過程Message:postALooper:po
18、stmEventQueue.insertmQueueChangedCondition.signal() /如果之前沒有event,通知looper threadALooper:loop()if (mEventQueue.empty() /如果消息隊(duì)列為空,則等待mQueueChangedCondition.wait(mLock);return true;event = *mEventQueue.begin();event.mMessage->deliver();AHandler:deliverMessageAHandlerReflector: onMessageReceived具體的實(shí)現(xiàn)
19、NuPlayer下面就進(jìn)入我們的正題,NuPlayer frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver NuPlayerDriver是對NuPlayer的封裝,繼承MediaPlayerInterface接口。通過NuPlayer來實(shí)現(xiàn)播放的功能??催@部分代碼的方法就是先看NuPlayerDriver里面干了啥,轉(zhuǎn)頭就去找NuPlayer里面的實(shí)現(xiàn),一般都要再去NuPlayer的onMessageReceive中看消息的響應(yīng),最后回到NuPlayerDriver的各種notify中看流程的周轉(zhuǎn),下面附上一張播放
20、器狀態(tài)機(jī)流轉(zhuǎn)圖NuPlayerDriver:NuPlayerDriver(pid_t pid) : mState(STATE_IDLE), /對應(yīng)播放器狀態(tài)機(jī)的初始化狀態(tài) mIsAsyncPrepare(false), mAsyncResult(UNKNOWN_ERROR), mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mSeekInProgress(false), mLooper(new ALooper), mPlayerFlags(0), mAtEOS(false), mLooping(false), mA
21、utoLoop(false) ALOGV("NuPlayerDriver(%p)", this); /和前面所述的異步消息創(chuàng)建機(jī)制相符mLooper->setName("NuPlayerDriver Looper"); mLooper->start( false, /* runOnCallingThread */ true, /* canCallJava */ PRIORITY_AUDIO);/mPlayer即NuPlayer,繼承于AHandler mPlayer = AVNuFactory:get()->createNuPlayer
22、(pid); mLooper->registerHandler(mPlayer); mPlayer->setDriver(this);NuPlayerDriver:NuPlayerDriver() ALOGV("NuPlayerDriver(%p)", this); mLooper->stop(); /整個(gè)NuPlayerDriver就是一個(gè)大ALooperAVNuFactory 負(fù)責(zé)關(guān)鍵組件的create,通過它能看到: 1.每一個(gè)NuPlayer對應(yīng)一個(gè)進(jìn)程 2.數(shù)據(jù)流從Source-Decoder-Renderer,中間由AMessages驅(qū)動sp&
23、lt;NuPlayer> AVNuFactory:createNuPlayer(pid_t pid) return new NuPlayer(pid);sp<NuPlayer:DecoderBase> AVNuFactory:createPassThruDecoder( const sp<AMessage> ¬ify, const sp<NuPlayer:Source> &source, const sp<NuPlayer:Renderer> &renderer) return new NuPlayer:Dec
24、oderPassThrough(notify, source, renderer);sp<NuPlayer:DecoderBase> AVNuFactory:createDecoder( const sp<AMessage> ¬ify, const sp<NuPlayer:Source> &source, pid_t pid, const sp<NuPlayer:Renderer> &renderer) return new NuPlayer:Decoder(notify, source, pid, renderer
25、);sp<NuPlayer:Renderer> AVNuFactory:createRenderer( const sp<MediaPlayerBase:AudioSink> &sink, const sp<AMessage> ¬ify, uint32_t flags) return new NuPlayer:Renderer(sink, notify, flags);下面分別分析Source, Decoder, RendererSource以setDataSource為切入點(diǎn)status_t NuPlayerDriver:setDat
26、aSource(const sp<IStreamSource> &source) ALOGV("setDataSource(%p) stream source", this); Mutex:Autolock autoLock(mLock); if (mState != STATE_IDLE) return INVALID_OPERATION; mState = STATE_SET_DATASOURCE_PENDING; mPlayer->setDataSourceAsync(source);/因?yàn)閐river只是NuPlayer的封裝,所以還是要去
27、調(diào)用NuPlayer完成實(shí)際動作 while (mState = STATE_SET_DATASOURCE_PENDING) mCondition.wait(mLock); return mAsyncResult;void NuPlayer:setDataSourceAsync(const sp<IStreamSource> &source) sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); sp<AMessage> notify = new AMessage(kWhatSource
28、Notify, this); msg->setObject("source", new StreamingSource(notify, source); msg->post();/到了NuPlayer中,也不是直接進(jìn)行操作,而是先發(fā)個(gè)消息,驗(yàn)證前面所說的一切都由AMessage驅(qū)動void NuPlayer:onMessageReceived(const sp<AMessage> &msg) switch (msg->what() case kWhatSetDataSource:/實(shí)際的處理在這里 ALOGV("kWhatSe
29、tDataSource"); CHECK(mSource = NULL); status_t err = OK; sp<RefBase> obj; CHECK(msg->findObject("source", &obj); if (obj != NULL) Mutex:Autolock autoLock(mSourceLock); mSource = static_cast<Source *>(obj.get();/賦值給mSource else err = UNKNOWN_ERROR; CHECK(mDriver != N
30、ULL); sp<NuPlayerDriver> driver = mDmote(); if (driver != NULL) driver->notifySetDataSourceCompleted(err);/通知driver設(shè)置完畢 break; .void NuPlayerDriver:notifySetDataSourceCompleted(status_t err) Mutex:Autolock autoLock(mLock); CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING); mAsyncResul
31、t = err; mState = (err = OK) ? STATE_UNPREPARED : STATE_IDLE;/回到driver中,流轉(zhuǎn)播放器狀態(tài)進(jìn)入下一階段 mCondition.broadcast();下面就來看看具體有哪些source,它們都繼承自NuPlayer:Source(NuPlayerSource.h & NuPlayerSource.cpp) 1.HTTP-進(jìn)一步判斷是以下的哪一種:HTTPLiveSource,RTSPSource,GenericSource 2.File-GenericSource 3.StreamSource-StreamingSou
32、rce 4.DataSource-GenericSourceGenericSourcenuplayer/GenericSource.h & GenericSource.cpp幾個(gè)水位static int64_t kLowWaterMarkUs = 2000000ll; / 2secsstatic int64_t kHighWaterMarkUs = 5000000ll; / 5secsstatic int64_t kHighWaterMarkRebufferUs = 15000000ll; / 15secs,這一個(gè)是新增加的水位static const ssize_t kLowWate
33、rMarkBytes = 40000;static const ssize_t kHighWaterMarkBytes = 200000;status_t NuPlayer:GenericSource:initFromDataSource() init extractor;get track info and metadatavoid NuPlayer:GenericSource:prepareAsync() if (mLooper = NULL) mLooper = new ALooper; mLooper->setName("generic"); mLooper-
34、>start(); mLooper->registerHandler(this); sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this); msg->post();status_t NuPlayer:GenericSource:feedMoreTSData() return OK;LiveSessionlibstagefright/httplive/LiveSession.h & cpp/ static/ Bandwidth Switch Mark Defaultsconst int64_t Li
35、veSession:kUpSwitchMarkUs = 15000000ll;const int64_t LiveSession:kDownSwitchMarkUs = 20000000ll;const int64_t LiveSession:kUpSwitchMarginUs = 5000000ll;const int64_t LiveSession:kResumeThresholdUs = 100000ll;/ Buffer Prepare/Ready/Underflow Marksconst int64_t LiveSession:kReadyMarkUs = 5000000ll;con
36、st int64_t LiveSession:kPrepareMarkUs = 1500000ll;const int64_t LiveSession:kUnderflowMarkUs = 1000000ll;與Fetcher,Bandwidth Estimater(和ExoPlayer一樣是滑動窗口平均),switching,Buffering相關(guān)的操作都在這里HTTPLiveSourcenuplayer目錄下enum Flags / Don't log any URLs.不在log中記錄URL kFlagIncognito = 1, ;NuPlayer:HTTPLiveSource
37、:HTTPLiveSource( if (headers) /也搞了一個(gè)header機(jī)制 mExtraHeaders = *headers; ssize_t index = mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"); if (index >= 0) mFlags |= kFlagIncognito; mExtraHeaders.removeItemsAt(index); void NuPlayer:HTTPLiveSource:prepareAsync() if (mLiveLooper = NU
38、LL) mLiveLooper = new ALooper;/一如既往的ALooper mLiveLooper->setName("http live"); mLiveLooper->start(); mLiveLooper->registerHandler(this); sp<AMessage> notify = new AMessage(kWhatSessionNotify, this); mLiveSession = new LiveSession( notify, (mFlags & kFlagIncognito) ? Live
39、Session:kFlagIncognito : 0, mHTTPService); mLiveLooper->registerHandler(mLiveSession); mLiveSession->connectAsync(/HTTPLiveSource包含LiveSession,很多實(shí)際的工作都由LiveSession完成 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);ATSParser frameworks/av/media/libstagefright/mpeg2ts/ATSParse
40、r.cpp 就是一個(gè)TS Parser,雖然也叫Axx,但是沒有消息機(jī)制在里面StreamingSource nuplayer目錄void NuPlayer:StreamingSource:prepareAsync() if (mLooper = NULL) mLooper = new ALooper; mLooper->setName("streaming"); mLooper->start();/何其相似 mLooper->registerHandler(this); notifyVideoSizeChanged(); notifyFlagsChang
41、ed(0); notifyPrepared();StreamingSource中的數(shù)據(jù)由onReadBuffer驅(qū)動,最后的EOS,Discontiunity等都交給ATSParser去處理,ATSParser又最終交給AnotherPacketSource去做真正的處理實(shí)際上,這里提到的三個(gè)Source最后都會用到AnotherPacketSourcevoid NuPlayer:StreamingSource:onReadBuffer() for (int32_t i = 0; i < kNumListenerQueuePackets; +i) char buffer188; sp&l
42、t;AMessage> extra; ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);/實(shí)際用NuPlayerStreamListener完成工作 if (n = 0) ALOGI("input data EOS reached."); mTSParser->signalEOS(ERROR_END_OF_STREAM);/EOS了 setError(ERROR_END_OF_STREAM); break; else if (n = INFO_DISCONTINUIT
43、Y) int32_t type = ATSParser:DISCONTINUITY_TIME; int32_t mask; if (extra != NULL && extra->findInt32( IStreamListener:kKeyDiscontinuityMask, &mask) if (mask = 0) ALOGE("Client specified an illegal discontinuity type."); setError(ERROR_UNSUPPORTED); break; type = mask; mTSPars
44、er->signalDiscontinuity( (ATSParser:DiscontinuityType)type, extra); else if (n < 0) break; else if (buffer0 = 0x00) / XXX legacy if (extra = NULL) extra = new AMessage; uint8_t type = buffer1; if (type & 2) int64_t mediaTimeUs; memcpy(&mediaTimeUs, &buffer2, sizeof(mediaTimeUs); ex
45、tra->setInt64(IStreamListener:kKeyMediaTimeUs, mediaTimeUs); mTSParser->signalDiscontinuity( (type & 1) = 0) ? ATSParser:DISCONTINUITY_TIME : ATSParser:DISCONTINUITY_FORMATCHANGE, extra); else status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer); if (err != OK) ALOGE("TS P
46、arser returned error %d", err); mTSParser->signalEOS(err); setError(err); break; AnotherPacketSourceframeworks/av/media/libstagefright/mpeg2ts 可以類比ExoPlayer中的chunk source,同時(shí)負(fù)責(zé)buffer管理,EOSDiscontinuity的處理等等前面三個(gè)Source最后都會落到AnotherPacketSourcebool AnotherPacketSource:hasBufferAvailable(status_t
47、 *finalResult) Mutex:Autolock autoLock(mLock); *finalResult = OK; if (!mEnabled) return false; if (!mBuffers.empty() /一個(gè)ABuffer List,其實(shí)就是一個(gè)環(huán)形緩沖 return true; *finalResult = mEOSResult; return false;void AnotherPacketSource:queueDiscontinuity( ATSParser:DiscontinuityType type, const sp<AMessage> &extra, bool discard) Mutex:Autolock autoLock(mLock); if (discard) / Leave only discontinuities in the queue. mEOSResult = OK; mLastQueuedTimeUs = 0; mLatestEnqueuedMeta = NULL; if (type = ATSParser:DISCONTINUITY_NONE) return; mDiscontinuitySe
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 廣州中醫(yī)藥大學(xué)《食品微生物學(xué)(雙語)》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣州醫(yī)科大學(xué)《小學(xué)語文教學(xué)設(shè)計(jì)與實(shí)訓(xùn)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025湖北省建筑安全員《A證》考試題庫
- 2025上海建筑安全員-C證考試(專職安全員)題庫附答案
- 【課件】合格的部門經(jīng)理(上)
- 《護(hù)理論文如何投稿》課件
- 環(huán)境與自然經(jīng)濟(jì)學(xué)課件
- 《企業(yè)形象概述》課件
- 單位管理制度展示合集職工管理篇十篇
- 單位管理制度展示大全員工管理十篇
- 2025年遼寧省大連市普通高中學(xué)業(yè)水平合格性考試模擬政治試題(一)
- 2024版戶外廣告牌安裝與維護(hù)服務(wù)合同2篇
- 云南省昆明市五華區(qū)2023-2024學(xué)年九年級上學(xué)期期末數(shù)學(xué)試卷
- 安徽省合肥市第四十中學(xué)2024~2025學(xué)年九年級上學(xué)期化學(xué)期末模擬試題(含答案)
- 安徽省淮北市(2024年-2025年小學(xué)六年級語文)部編版期末考試((上下)學(xué)期)試卷及答案
- 當(dāng)代中國外交(外交學(xué)院)知到智慧樹章節(jié)測試課后答案2024年秋外交學(xué)院
- 大學(xué)生職業(yè)生涯規(guī)劃
- 干燥綜合征的護(hù)理查房
- 2023-2024學(xué)年浙江省杭州市上城區(qū)教科版四年級上冊期末考試科學(xué)試卷
- 期末 (試題) -2024-2025學(xué)年人教PEP版英語五年級上冊
- 《三國志》導(dǎo)讀學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
評論
0/150
提交評論