Android MediaPlayer 架構UML圖

來源:互聯網
上載者:User

標籤:stagefright   openmax   awesomeplayer   audioplayer   mediaplayerservice   

Android開發交流群:50342056目的

本文用一個UML類圖,講解mp3檔案播放的架構流程。內容以下幾個方面:

1.UML類圖

2.stagefrightPlayer是如何建立的;

3.mp3檔案的解析和解碼的簡單介紹

4.播放mp3檔案過程中,生產者和消費者的關係;

5.openmax和stagefright架構的訊息機制

UML類圖


stagefrightPlayer是如何建立的

對照著UML圖,看下StagefrightPlayer建立的過程。

故事的開始是Java層的MediaPlayer調用了setDataSource這個函數(參數為一個path),導致native對應的MediaPlayer 通過Binder通訊機制在MediaPlayerService中開闢了一個“戶口”,即建立Client對象,這個對象是個匿名的Binder。這個“戶口”在native MediaPlayer中表現為一個IMediaPlayer的介面。

上述過程代碼如下:

路徑:frameworks/av/media/libmedia/MediaPlayer.cpp:setDataSource            sp<IMediaPlayer> player(service->create(this, mAudioSessionId));            if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||                (NO_ERROR != player->setDataSource(url, headers))) {                player.clear();            }            err = attachNewPlayer(player);

建立了IMediaPlayer對象之後,就調用其setDataSource方法。經過Binder的通訊機制一番的轉換之後,調用流程來到MediaPlayerService.cpp中:

代碼路徑:frameworks/av/media/libmediaplayerservice/MediaPlayerService

status_t MediaPlayerService::Client::setDataSource(        const char *url, const KeyedVector<String8, String8> *headers){    ALOGV("setDataSource(%s)", url);    if (url == NULL)        return UNKNOWN_ERROR;    if ((strncmp(url, "http://", 7) == 0) ||        (strncmp(url, "https://", 8) == 0) ||        (strncmp(url, "rtsp://", 7) == 0)) {        if (!checkPermission("android.permission.INTERNET")) {            return PERMISSION_DENIED;        }    }    if (strncmp(url, "content://", 10) == 0) {        // get a filedescriptor for the content Uri and        // pass it to the setDataSource(fd) method        String16 url16(url);        int fd = android::openContentProviderFile(url16);        if (fd < 0)        {            ALOGE("Couldn't open fd for %s", url);            return UNKNOWN_ERROR;        }        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus        close(fd);        return mStatus;    } else {        <span style="color:#FF0000;">player_type playerType = MediaPlayerFactory::getPlayerType(this, url);</span>        <span style="color:#FF0000;">sp<MediaPlayerBase> p = setDataSource_pre(playerType);</span>        if (p == NULL) {            return NO_INIT;        }        setDataSource_post(p,<span style="color:#FF0000;"> p->setDataSource(url, headers)</span>);        return mStatus;    }}
上面大段的代碼和分析流程沒有關係,skim it。要建立一個合適的播放器,就要分析檔案的格式,根據檔案的格式來匹配一個合適的播放器。這個工作交給了MediaPlayerFactory。在其中註冊了許多的工廠用於生產一個合適的播放器。基本原理就是讀取歌曲檔案的開頭一段位元組,根據相關的container來解析歌曲的格式,做的粗糙一點的話就直接根據尾碼名來判斷了。這其中的實現取決於廠商或者組件供應商了。

不管怎麼樣,我們現在假設MediaPlayerFactory根據路徑得到了一個合適的播放器,它的基類是MediaPlayerBase。android中預設的是StagefrightPlayer,繼承了MediaPlayerBase。於是StagefrightPlayer在工廠中被生產出來了。然後調用其setDataSource。

其實StagefrightPlayer只是一個空殼,真正的工作是AwesomePlayer去做,這個對象在StagefrightPlayer建構函式中產生。看到這裡的時候一定要記得看看UML類圖。看看他們兩個之間的關係。於是這個path最終就儲存到了AwesomePlayer內部。

mp3檔案的解析和解碼的簡單介紹

Java層的MediaPlayer設定完路徑之後,還要調用prepare。調用流程和上面設定路徑一樣:MediaPlayer->Client->StagefrightPlayer->AwesomePlayer,略過不表。AwesomePlayer的prepare做了兩件事情。給AwesomePlayer的事件隊列發送一條Event,然後等待這個事件的處理完成。

事件的處理在onPrepareAsyncEvent()函數中完成。做了以下工作:

1.建立一個原始Audio Track流。從這個流中讀取壓縮資料;對應於圖中的mAudioTrack。

2.建立一個讀取pcm資料的流。對應於圖中的mAudioSource。

mAudioTrack實際指向一個Mp3Source,而mAudioSource指向一個OMXCodec。Mp3Source提供Mp3未經處理資料供OMXCodec解碼,然後把解碼完成之後的資料傳遞給AudioPlayer。OMXCodec的解碼工作實際上是由具體的解碼組件完成。一個OMXCodec對應一個Omx中的node instance,node instance操作解碼組件。而node instance提供calback接受組件的訊息。

圖中藍色部分表示讀取原始mp3檔案流程;綠色表示組件的callback 傳遞流程;

播放mp3檔案過程中,生產者和消費者的關係

播放過程中存在兩組生產者和消費者。

第一組:未經處理資料的生產者,Mp3Source;未經處理資料消費者OMXCodec;

第二組:pcm資料的提供者OMXCodec和pcm資料的消費者AudioPlayer。

其中AudioPlayer其實是一個中間橋樑,真正的pcm資料的消費者是AudioTrack。它不斷的通過callback機制來從AudioPlayer中讀取pcm資料。

openmax和stagefright架構的訊息機制

這一部分有兩條主線:

1.OMXCodec如何操作組件;

2.組件的訊息如何傳遞到StagefrightPlayer。

首先說第一條:OMXCodec的建構函式會調用omx的介面建立一個OMXNodeInstance執行個體,通過OMXNodeInstance執行個體來操作組件;在建立OMXNodeInstance的同時會傳遞給OMXNodeInstance一個觀察者OMXCodecObserver。一旦OMXNodeInstance接收到來自組件的訊息,就會通過這個觀察者把訊息傳遞給OMXCodec。

在解碼過程中如果OMXCodec發生了錯誤,AudioPlayer會檢測到read錯誤,會把相關的資訊通過AwesomePlayer傳遞到StagefrightPlayer中去。進而通知到native的MediaPlayer。最後透過jni會post給java的MediaPlayer。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.