Android Multimedia架構總結(九)Stagefright架構之資料處理及到OMXCodec過程

來源:互聯網
上載者:User

標籤:

轉載請把頭部出處連結和尾部二維碼一起轉載,本文出自逆流的魚:http://blog.csdn.net/hejjunlin/article/details/52532085

不知不覺到第九篇了,感覺還有好多好多沒有寫,路漫漫其修遠兮 ,吾將上下而求索,上篇主要介紹了Stagefright架構及AwesomePlayer的資料解析器,最後我們說道,涉及parse及decode部分,將在本篇中介紹,看下今天的Agenda:

  • 兩張圖看資料走向
  • AwesomePlayer中prepare過程
  • AwesomePlayer初始化音視頻解碼器過程
  • Stagefright的Decode過程
  • Stagefright處理資料過程
  • 資料由源到最終解碼後的流程
兩張圖看資料走向

一切從MediaSource中來,一切又從MediaSource中去
Audio:

Video:

AwesomePlayer中prepare過程

首先我們開始看下AwesomePlayer的prepare的執行過程:


以上代碼總結為:prepare程序呼叫了prepareAsync_l函數,在prepareAsync_l中執行new AwesomeEvent,並將AwesomePlayer調用onPrepareAsyncEvent的結果返回AwesomeEvent的構造作為參數。
接著分析AwesomeEvent的過程: 啟動mQueue,作為event handler

上面new AwesomeEvent會執行onPrepareAsyncEvent函數,我們看下該函數的做了什嗎?


以上代碼總結為:會將AV(音視頻)進行分處理,於是有了AwesomePlayer::initVideoDecoder及AwesomePlayer::initAudioDecoder()函數。
本文出自逆流的魚:http://blog.csdn.net/hejjunlin/article/details/52532085

初始化音視頻解碼器過程

我們先看下initVideoDecoder,即初始化視頻解碼器:


接著看下初始化音頻解碼器,看下幾個變數的聲明:

接著看代碼如下:


對上面代碼進行總結:
Stagefright調用AwesomePlayer的prepare後,AwesomePlayer調用自身的prepareAsync進行初始化化音視頻解碼器,這兩個方法裡面都會OMXCodec::Create,接下來看下這個過程。

Stagefright的Decode過程

經過“資料流的封裝”得到的兩個MediaSource,其實是兩個OMXCodec。AwesomePlayer和mAudioPlayer都是從MediaSource中得到資料進行播放。AwesomePlayer得到的是最終需要渲染的原始視頻資料,而mAudioPlayer讀取的是最終需要播放的原始音頻資料。也就是說,從OMXCodec中讀到的資料已經是未經處理資料了。
OMXCodec是怎麼把資料來源經過parse、decode兩步以後轉化成未經處理資料的。從OMXCodec::Create這個構造方法開始,下面看它的代碼:



以上代碼總結為:對應參數分析:

  • IOMX &omx指的是一個OMXNodeInstance對象的執行個體。
  • MetaData &meta這個參數由MediaSource.getFormat擷取得到。這個對象的主要成員就是一個KeyedVector(uint32_t, typed_data) mItems,裡面存放了一些代表MediaSource格式資訊的名值對。
  • bool createEncoder指明這個OMXCodec是編碼還是解碼。
  • MediaSource &source是一個MediaExtractor(資料解析器)。
  • char *matchComponentName指定一種Codec用於產生這個OMXCodec。
    先使用findMatchingCodecs尋找對應的Codec,找到以後為當前IOMX分配節點並註冊事件監聽器:omx->allocateNode(componentName, observer, &node)。最後,把IOMX封裝進一個OMXCodec:

這樣就得到了OMXCodec。

  • AwesomePlayer中得到這個OMXCodec後,接著看initVideoDecoder/initAudioDecoder,這裡看initAudioDecoder方法,是把 mAudioSource = mOmxSource,賦值,接著調用mAudioSource->start()進行初始化。 OMXCodec初始化主要是做兩件事:
    • 向OpenMAX發送開始命令。mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle)
    • 調用allocateBuffers()分配兩個緩衝區,存放在Vector mPortBuffers[2]中,分別用於輸入和輸出。
  • 然後在現個initxxxDecoder方法中會調用(mAudioSource->start()/mVideoSource->start())

觸發MediaSource的子類VideoSource及AudioSource調用start()方法後,它的內部就會開始從資料來源擷取資料並解析,等到緩衝區滿後便停止。在AwesomePlayer裡就可以調用MediaSource的read方法讀取解碼後的資料。

  • 對於mVideoSource來說,讀取的資料:mVideoSource->read(&mVideoBuffer, &options)交給顯示模組進行渲染,mVideoRenderer->render(mVideoBuffer);
  • 對mAudioSource來說,用mAudioPlayer對mAudioSource進行封裝,然後由mAudioPlayer負責讀取資料和播放控制。

  • AwesomePlayer調用OMXCode讀取ES資料,並且進行解碼的處理

  • OMXCodec調用MediaSource的read函數來擷取音視頻的資料
  • OMXCodec調用Android的IOMX介面,其實就是Stagefrightdecode中的 OMX實現

本文出自逆流的魚:http://blog.csdn.net/hejjunlin/article/details/52532085

這個過程就是prepare的過程,重點是解碼把流放到Buffer中
接下來,當java層調用start方法時,通過mediaplayerservice,再傳到StagefrightPlayer中,引用AwesomePlayer,這樣就調到AwesomePlayer的play方法,看代碼:


  • 當AwesomePlayer調用play後,通過mVideoSource->read(&mVideoBuffer, &options)讀取資料。mVideoSource->read(&mVideoBuffer, &options)具體是調用OMXCodec.read來讀取資料。而OMXCodec.read主要分兩步來實現資料的讀取:
  • (1) 通過調用drainInputBuffers()對mPortBuffers[kPortIndexInput]進行填充,這一步完成 parse。由OpenMAX從資料來源把demux後的資料讀取到輸入緩衝區,作為OpenMAX的輸入。
  • (2) 通過fillOutputBuffers()對mPortBuffers[kPortIndexOutput]進行填充,這一步完成 decode。由OpenMAX對輸入緩衝區中的資料進行解碼,然後把解碼後可以顯示的視頻資料輸出到輸出緩衝區。
    AwesomePlayer通過mVideoRenderer->render(mVideoBuffer)對經過parse和decode 處理的資料進行渲染。一個mVideoRenderer其實就是一個封裝了IOMXRenderer的AwesomeRemoteRenderer:

Stagefright處理資料過程
  • Audioplayer為AwesomePlayer的成員,audioplayer通過callback來驅動資料的擷取,awesomeplayer則是通過 videoevent來驅動。二者有個共性,就是資料的擷取都抽象成mSource->read()來完成,且read內部把parse和decode綁在一起。Stagefright AV同步部分,audio完全是callback驅動資料流,注意是video部分在onVideoEvent裡會擷取audio的時間戳記,是傳統的AV時間戳記做同步。

  • AwesomePlayer的Video主要有以下幾個成員:

    • mVideoSource(解碼視頻)
    • mVideoTrack(從多媒體檔案中讀取視頻資料)
    • mVideoRenderer(對解碼好的視頻進行格式轉換,android使用的格式為RGB565)
    • mISurface(重繪圖層)
    • mQueue(event事件隊列)
  • stagefright運行時的Audio流程如下:

    • 首先設定mUri的路徑
    • 啟動mQueue,建立一個線程來運行 threadEntry(命名為TimedEventQueue,這個線程就是event調度器)
    • 開啟mUri所指定的檔案的頭部,則會根據類型選擇不同的分離器(如MPEG4Extractor)
    • 使用 MPEG4Extractor對MP4進行音視頻軌道的分離,並返回MPEG4Source類型的視頻軌道給mVideoTrack
    • 根據 mVideoTrack中的編碼類別型來選擇解碼器,avc的編碼類別型會選擇AVCDecoder,並返回給mVideoSource,並設定mVideoSource中的mSource為mVideoTrack
    • 插入onVideoEvent到Queue中,開始解碼播放
    • 通過mVideoSource對象來讀取解析好的視頻buffer

如果解析好的buffer還沒到AV時間戳記同步的時刻,則延遲到下一輪操作

1、mVideoRenderer為空白,則進行初始化(如果不使用 OMX會將mVideoRenderer設定為AwesomeLocalRenderer)
2、通過mVideoRenderer對象將解析好的視頻buffer轉換成RGB565格式,並發給display模組進行映像繪製
3、將onVideoEvent重新插入event調度器來迴圈

本文出自逆流的魚:http://blog.csdn.net/hejjunlin/article/details/52532085

Stagefright資料由源到最終解碼後的流程

可以對照《Android Multimedia架構總結(八)Stagefright架構之AwesomePlayer及資料解析器》中那個圖,這裡不貼了,

  • 設定DataSource,資料來源可以兩種URI和FD。URI可以http://,rtsp://等。FD是一個本地檔案描述符,能過FD,可以找到對應的檔案。
  • 由DataSource產生MediaExtractor。通過sp extractor = MediaExtractor::Create(dataSource);來實現。 MediaExtractor::Create(dataSource)會根據不同的資料內容建立不同的資料讀取對象。
  • 通過調用setVideoSource由MediaExtractor分解產生音頻資料流(mAudioTrack)和視頻資料流(mVideoTrack)。
  • onPrepareAsyncEvent()如果DataSource是URL的話,根據地址擷取資料,並開始緩衝,直到擷取到mVideoTrack和mAudioTrack。mVideoTrack和mAudioTrack通過調用initVideoDecoder()和initAudioDecoder()來產生 mVideoSource和mAudioSource這兩個音視頻解碼器。然後調用postBufferingEvent_l()提交事件開啟緩衝。
  • 資料緩衝的執行函數是onBufferingUpdate()。緩衝區有足夠的資料可以播放時,調用play_l()開始播放。play_l()中關鍵是調用了postVideoEvent_l(),提交了 mVideoEvent。這個事件執行時會調用函數onVideoEvent()。這個函數通過調用 mVideoSource->read(&mVideoBuffer, &options)進行視頻解碼。音頻解碼通過mAudioPlayer實現。
  • 視頻解碼器解碼後通過mVideoSource->read讀取一幀幀的資料,放到mVideoBuffer中,最後通過 mVideoRenderer->render(mVideoBuffer)把視頻資料發送到顯示模組。當需要暫停或停止時,調用cancelPlayerEvents來提交事件用來停止解碼,還可以選擇是否繼續緩衝資料。

第一時間獲得部落格更新提醒,以及更多android乾貨,源碼分析,歡迎關注我的公眾號,掃一掃下方二維碼或者長按識別二維碼,即可關注。

如果你覺得好,隨手點贊,也是對筆者的肯定,也可以分享此公眾號給你更多的人,原創不易

Android Multimedia架構總結(九)Stagefright架構之資料處理及到OMXCodec過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.