亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                Android音視頻開發(fā)-Media FrameWork框架與源碼解析

                Android音視頻開發(fā)-Media FrameWork框架與源碼解析

                一、Media FrameWork背景

                Media Framework (媒體函數庫):此函數庫讓Android 可以播放與錄制許多常見的音頻與視頻文件,支持的文件類型包括MPEG4、H.264、MP3、AAC、AMR、JPG 與PNG 等。 Surface Manager (外觀管理函數庫):管理圖形界面的操作與2D、3D 圖層的顯示。

                二、Media Framework“路線圖”

                我們可以看到用紅色框框圈起來的地方。一個是app應用Gallery(也可以為第三方player);另外一個是Media Framework。對,沒錯,講了這么多,我們的主角“Media Framework”登場了。讓我們來看看它的廬山真面目, 如圖所示:

                接下來,給大家簡單介紹下它??吹捻樞蚴? (腫么都覺得是在打表情符號:-D)

                2.1 代理端

                這一端做的事情只是將下面復雜的邏輯進行封裝(java),然后透過jni調用底下的native層方法來實現(xiàn)具體功能。并且,這些個具體的功能是在服務端實現(xiàn)的,他們分屬不同的進程,通過Binder來通信,最終通過調用服務端的方法實現(xiàn)具體的邏輯處理。(有童鞋問:Binder是個什么東東呢? 小弟有時間會講解的,現(xiàn)在就理解它是一個進程間通信的一種方式就好,求甚解的朋友們可以百度下_)

                2.2 服務端

                這邊的主要任務就是在MediaPlayerFactory中,創(chuàng)建出NuplayerDriver(這個不是底層驅動啦,我們理解為一個抽象出來的NuPlayer的基類就好啦)。 然后Nuplayer中,我們可以看到有三大模塊。

                2.2.1 Source

                這里是為咱們的播放器提供數據源的(解協(xié)議,解封裝在這里)。

                2.2.2 Decoder

                這里是解碼數據的地方(解碼在這里)

                2.2.3 Renderer

                這里是用來做Display的,里面涉及到A/V同步的問題。

                2.2.4 Foundation

                這個部分是基礎類。在后面的分析當中,我們會知道在NuPlayer中會啟動相當多的線程,這些線程如何異步/同步的通信,需要依靠AMessage/ALooper/AHandler來支持

                之后, 通過接口類IOMX來通過Binder進程間通信,遠程調用具體的decoder來實現(xiàn)解碼。

                2.3 OMX端

                這一端就比較靠近底層了,里面會有各種各樣的插件注冊其中。它還鏈接這Codec Driver,這里面就是放的各種具體的解碼器啦。

                2.4 Kernel端

                最后, OMX的具體解碼器在啟動Kernel層的A/V Codec Driver完成解碼操作。

                三、media播放的流程

                在framework中涉及media播放的流程頭文件如下:IMediaPlayer.h mediaplayer.h IMediaPlayerClient.h

                其中IMediaPlayer.h 定義了binder通信相關的接口。 定義了:

                class BnMediaPlayer: public BnInterface{public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);};

                IMediaPlayer.cpp 是binder通信接口的實現(xiàn)。

                class BpMediaPlayer: public BpInterface; status_t BnMediaPlayer::onTransact();

                mediaplayer.h 是定義binder通信的客戶端。在mediaplayer.cpp中如下代碼獲取BpMediaPlayer:

                status_t MediaPlayer::setDataSource( const char *url, const KeyedVector *headers){ LOGV(“setDataSource(%s)”, url); status_t err = BAD_VALUE; if (url != NULL) { const sp& service(getMediaPlayerService()); if (service != 0) { sp player( service->create(getpid(), this, url, headers)); err = setDataSource(player); } } return err;}

                服務端在MediaPlayerService中。在MediaPlayerService.h中如下定義:

                class Client : public BnMediaPlayer 在MediaPlayerService.cpp中,create函數創(chuàng)建了BnMediaPlayer:

                sp MediaPlayerService::create( pid_t pid, const sp& client, const char* url, const KeyedVector *headers){ int32_t connId = android_atomic_inc(&mNextConnId); sp 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, headers)) { c.clear(); return c; } wp w = c; Mutex::Autolock lock(mLock); mClients.add(w); return c;}

                再來看一下MediaPlayer這個類的定義:

                class MediaPlayer : public BnMediaPlayerClient, public virtual IMediaDeathNotifier{} 很奇怪:在binder通信的客戶端又有了一個binder通信的服務端: BnMediaPlayerClient 在IMediaPlayerClient.h 中這個binder通信只有一個接口:

                class IMediaPlayerClient: public IInterface{public: DECLARE_META_INTERFACE(MediaPlayerClient); virtual void notify(int msg, int ext1, int ext2) = 0;};

                這個binder通信服務為誰提供呢?在回來看一下MediaPlayerServer中的create函數:

                sp MediaPlayerService::create( pid_t pid, const sp& client, const char* url, const KeyedVector *headers)

                客戶端就在這里。這個binder通信的實質是一個消息回調函數。framework的media框架式一個雙向binder通信框架。

                以seek接口為例分析一下:

                在mediaplayer.cpp 中調用seek 接口:

                MediaPlayer (seek)->IMediaPlayer.cpp(bpMediaPlayer.cpp )->IMediaPlayer.cpp(bnMediaPlayer.cpp ) 在這里其實已經達到了MediaPlayerServer中的client類。當底層的media 完成seek 以后會拋出來一消息,這個消息通過 const sp& client 通知給MediaPlayer。

                在media相關的頭文件中還有一個MediaPlayerInterface.h 。這個頭文件定義了底層播放器的接口。

                四、Media FrameWork源碼分析

                首先,針對android.media.MediaPlayer進行分析。

                里面有很多native代碼,我們找到native_setup這個jni調用,就可以找到整個框架的入口。

                我們查看

                android_media_MediaPlayer_native_setup@framworks/base/media/jni/android_media_MediaPlayer.cpp

                `static` `void` `android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)“{“ “LOGV(“”native_setup”“);“ “sp mp = “new` `MediaPlayer();“ “if` `(mp == NULL) {“ “jniThrowException(env, “”java/lang/RuntimeException”“, “”Out of memory”“);“ “return“;“ “}` ` “// create new listener and give it to MediaPlayer“ “sp listener = “new` `JNIMediaPlayerListener(env, thiz, weak_this);“ “mp->setListener(listener);` ` “// Stow our new C++ MediaPlayer in an opaque field in the Java object.“ “setMediaPlayer(env, thiz, mp);“}`

                從這里的這段代碼我們可以看到,android在這里實例化了一個變量mp:MediaPlayer。

                并且為其設置了一個listener:JNIMediaPlayerListener

                在后面我們會看到對mp的調用,現(xiàn)在讓我們先看看MediaPlayer是什么東東。

                MediaPlayer@framworks/base/include/media/mediaplayer.h MediaPlayer@framworks/base/media/libmedia/mediaplayer.cpp

                在這里我們終于找到了MediaPlayer:BnMediaPlayerClient:IMediaPlayerClient

                原來他也是對Bind Native的一個封裝,而他本身提供了很多方法用于訪問,包括start等。下面是start的cpp代碼:

                status_t MediaPlayer::start(){ LOGV(“start”); Mutex::Autolock _l(mLock); if (mCurrentState & MEDIA_PLAYER_STARTED) return NO_ERROR; if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { mPlayer->setLooping(mLoop); mPlayer->setVolume(mLeftVolume, mRightVolume); mCurrentState = MEDIA_PLAYER_STARTED; status_t ret = mPlayer->start(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; } else { if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { LOGV(“playback completed immediately following start()”); } } return ret; } LOGE(“start called in state %d”, mCurrentState); return INVALID_OPERATION;}

                原來這里又調用了mPlayer:sp

                從這里我們發(fā)現(xiàn)最終的服務,還是由IMediaPlayer這個東西提供的,而IMediaPlayer@framworks/base/include/media/IMediaPlayer.h

                實際上是如下定義的一個類,它繼承了IInterface@framworks/base/include/binder/IInterface.h這個類(注意雖然名字是Interface,但是它確實是個類!:-))

                class IMediaPlayer: public IInterface{public: DECLARE_META_INTERFACE(MediaPlayer); virtual void disconnect() = 0; virtual status_t setVideoSurface(const sp& surface) = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; virtual status_t stop() = 0; virtual status_t pause() = 0; virtual status_t isPlaying(bool* state) = 0; virtual status_t seekTo(int msec) = 0; virtual status_t getCurrentPosition(int* msec) = 0; virtual status_t getDuration(int* msec) = 0; virtual status_t reset() = 0; virtual status_t setAudioStreamType(int type) = 0; virtual status_t setLooping(int loop) = 0; virtual status_t setVolume(float leftVolume, float rightVolume) = 0; virtual status_t invoke(const Parcel& request, Parcel *reply) = 0; virtual status_t setMetadataFilter(const Parcel& filter) = 0; virtual status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata) = 0;};

                為了弄清楚,在什么地方產生的mPlayer,我轉而分析MediaPlayerService@framworks/base/media/libmediaplayerservice/MediaPlayerService.h

                其中有如下代碼

                virtual sp createMediaRecorder(pid_t pid);void removeMediaRecorderClient(wp client);virtual sp createMetadataRetriever(pid_t pid); // House keeping for media player clientsvirtual sp create(pid_t pid, const sp& client, const char* url);virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length);

                原來在這個地方會創(chuàng)建你sp對象。

                五、文末

                在本篇中,我們知道了Media Framework在整個Android框架中的位置, 也了解了Media Framework自己是個什么樣框架,以及它和各部分的聯(lián)系。 以及他的源碼分析。這也是音視頻學習的重要部分。音視頻進階入門,請私信發(fā)送“核心筆記”或“手冊”,即可獲取音視頻資料!

                鄭重聲明:本文內容及圖片均整理自互聯(lián)網,不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年6月25日 21:22
                下一篇 2022年6月25日 21:22

                相關推薦

                • 短視頻策劃內容的3個要點(短視頻策劃內容怎么做)

                  短視頻在制作時,內容框架非常重要。如果直奔主題,然后結束,聚卓告訴你,這樣的短視頻已經過時了。現(xiàn)在的短視頻需要框架的,但不是任何框架,它需要一種易于理解和消化的框架。而且,現(xiàn)在大多…

                  2022年11月27日
                • 存儲過程語法(sql server存儲過程語法)

                  今天小編給各位分享存儲過程語法的知識,其中也會對sql server存儲過程語法進行解釋,如果能碰巧解決你現(xiàn)在面臨的問題,別忘了關注本站,現(xiàn)在開始吧! oracle存儲過程基本語法…

                  2022年11月26日
                • 成都健康碼打不開顯示接口請求未知異常怎么辦(成都健康碼打不開顯示接口請求未知異常)

                  成都這幾天的疫情也是備受關注,疫情期間各地出行都是需要查看健康碼的,不過今天卻有成都的小伙伴反饋健康碼無法打開的情況。成都健康碼打不開顯示接口請求未知異常怎么辦?由于健康碼無法打開…

                  2022年11月24日
                • 1千克等于多少磅

                  克,此定義在1958年被美國以及其他英聯(lián)邦會員國承認換算回來,一千克等于262磅,一磅等于037千克英國在1963年開始,依據度量衡法案的規(guī);1 磅=16 盎司=04536 千克 …

                  2022年11月24日
                • 神舟戰(zhàn)神S7-DA5NS電腦預售 到手價僅需5399元

                  神舟戰(zhàn)神S7-DA5NS正在京東商城預售搶購,預售到手價僅需5399元。其搭載了全新12代i5-12450H處理器,擁有2.0GHz八核十二線程效能,RTX3050 4G GDDR…

                  2022年11月23日
                • 馬斯克凌晨一點半曬“代碼審查”現(xiàn)場,編排他的段子比瘋狂星期四還多

                  夢晨 Pine 發(fā)自 凹非寺 量子位 | 公眾號 QbitAI 每一個真正會寫代碼的人,請在下午2點到總部10層報到。 每一個真正會寫代碼的人,請在下午2點到總部10層報到。 馬斯…

                  2022年11月21日
                • win11任務管理器在哪(任務管理器怎么打開)

                  在win10電腦中,我們可以在任務管理器里查看系統(tǒng)各項資源使用情況,也可以通過這個地方強行結束卡死的進程。不過很多人不知道如何打開電腦上的任務管理器,下面就和大家講解一下方法吧。 …

                  2022年11月18日
                • 手淘搜索是自然流量嗎(手淘搜索流量怎么提高)

                  作為一個賣家,我們都應該知道,現(xiàn)在店鋪的流量大部分來自移動端,也就是我們說的手機端流量。隨著智能手機的發(fā)展及網速的提升,手機購物已成為常態(tài)。而淘寶也一直嘗試著從一個購物平臺往社交平…

                  2022年11月18日
                • 英特爾NUC迷你主機僅需749元 搭載賽揚J4005處理器

                  作為資深NUC用戶,小編對迷你臺式機可謂是情有獨鐘,畢竟迷你臺式機可以大量的節(jié)省空間?,F(xiàn)在,這款英特爾NUC迷你主機僅需749元。 這款英特爾NUC迷你主機搭載了intel賽揚J4…

                  2022年11月17日
                • 優(yōu)派和aoc顯示器哪個好(優(yōu)派顯示器怎么樣)

                  這兩年便攜式顯示器的崛起并不是一個偶然,對于很多人包括筆者在內,對家庭第二塊顯示器的需求的確是越來越大。一方面單獨買個筆記本在家使用并不劃算,反而是搭配雙屏顯示更符合自己的需求;另…

                  2022年11月13日

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時間:周一至周五,10:30-18:30,節(jié)假日休息