在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

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

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

    一、Media FrameWork背景

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

    二、Media Framework“路線圖”

    我們可以看到用紅色框框圈起來(lái)的地方。一個(gè)是app應(yīng)用Gallery(也可以為第三方player);另外一個(gè)是Media Framework。對(duì),沒(méi)錯(cuò),講了這么多,我們的主角“Media Framework”登場(chǎng)了。讓我們來(lái)看看它的廬山真面目, 如圖所示:

    接下來(lái),給大家簡(jiǎn)單介紹下它。看的順序是 (腫么都覺(jué)得是在打表情符號(hào):-D)

    2.1 代理端

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

    2.2 服務(wù)端

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

    2.2.1 Source

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

    2.2.2 Decoder

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

    2.2.3 Renderer

    這里是用來(lái)做Display的,里面涉及到A/V同步的問(wèn)題。

    2.2.4 Foundation

    這個(gè)部分是基礎(chǔ)類。在后面的分析當(dāng)中,我們會(huì)知道在NuPlayer中會(huì)啟動(dòng)相當(dāng)多的線程,這些線程如何異步/同步的通信,需要依靠AMessage/ALooper/AHandler來(lái)支持

    之后, 通過(guò)接口類IOMX來(lái)通過(guò)Binder進(jìn)程間通信,遠(yuǎn)程調(diào)用具體的decoder來(lái)實(shí)現(xiàn)解碼。

    2.3 OMX端

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

    2.4 Kernel端

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

    三、media播放的流程

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

    其中IMediaPlayer.h 定義了binder通信相關(guān)的接口。 定義了:

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

    IMediaPlayer.cpp 是binder通信接口的實(shí)現(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;}

    服務(wù)端在MediaPlayerService中。在MediaPlayerService.h中如下定義:

    class Client : public BnMediaPlayer 在MediaPlayerService.cpp中,create函數(shù)創(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;}

    再來(lái)看一下MediaPlayer這個(gè)類的定義:

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

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

    這個(gè)binder通信服務(wù)為誰(shuí)提供呢?在回來(lái)看一下MediaPlayerServer中的create函數(shù):

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

    客戶端就在這里。這個(gè)binder通信的實(shí)質(zhì)是一個(gè)消息回調(diào)函數(shù)。framework的media框架式一個(gè)雙向binder通信框架。

    以seek接口為例分析一下:

    在mediaplayer.cpp 中調(diào)用seek 接口:

    MediaPlayer (seek)->IMediaPlayer.cpp(bpMediaPlayer.cpp )->IMediaPlayer.cpp(bnMediaPlayer.cpp ) 在這里其實(shí)已經(jīng)達(dá)到了MediaPlayerServer中的client類。當(dāng)?shù)讓拥膍edia 完成seek 以后會(huì)拋出來(lái)一消息,這個(gè)消息通過(guò) const sp& client 通知給MediaPlayer。

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

    四、Media FrameWork源碼分析

    首先,針對(duì)android.media.MediaPlayer進(jìn)行分析。

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

    我們查看

    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在這里實(shí)例化了一個(gè)變量mp:MediaPlayer。

    并且為其設(shè)置了一個(gè)listener:JNIMediaPlayerListener

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

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

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

    原來(lái)他也是對(duì)Bind Native的一個(gè)封裝,而他本身提供了很多方法用于訪問(wèn),包括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;}

    原來(lái)這里又調(diào)用了mPlayer:sp

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

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

    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;};

    為了弄清楚,在什么地方產(chǎn)生的mPlayer,我轉(zhuǎn)而分析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);

    原來(lái)在這個(gè)地方會(huì)創(chuàng)建你sp對(duì)象。

    五、文末

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

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

    相關(guān)推薦

    • 短視頻策劃內(nèi)容的3個(gè)要點(diǎn)(短視頻策劃內(nèi)容怎么做)

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

      2022年11月27日
    • 存儲(chǔ)過(guò)程語(yǔ)法(sql server存儲(chǔ)過(guò)程語(yǔ)法)

      今天小編給各位分享存儲(chǔ)過(guò)程語(yǔ)法的知識(shí),其中也會(huì)對(duì)sql server存儲(chǔ)過(guò)程語(yǔ)法進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問(wèn)題,別忘了關(guān)注本站,現(xiàn)在開(kāi)始吧! oracle存儲(chǔ)過(guò)程基本語(yǔ)法…

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

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

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

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

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

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

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

      夢(mèng)晨 Pine 發(fā)自 凹非寺 量子位 | 公眾號(hào) QbitAI 每一個(gè)真正會(huì)寫(xiě)代碼的人,請(qǐng)?jiān)谙挛?點(diǎn)到總部10層報(bào)到。 每一個(gè)真正會(huì)寫(xiě)代碼的人,請(qǐng)?jiān)谙挛?點(diǎn)到總部10層報(bào)到。 馬斯…

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

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

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

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

      2022年11月18日
    • 英特爾NUC迷你主機(jī)僅需749元 搭載賽揚(yáng)J4005處理器

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

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

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

      2022年11月13日

    聯(lián)系我們

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