Android-StageFright之資料流的封裝和AwesomePlayer流程
http://disanji.net/2011/03/06/android-stagefright-datastream-awesomeplayer/
資料流的封裝
一、
由資料來源DataSource生成MediaExtractor。
通過MediaExtractor::Create(dataSource)來實現。Create方法通過兩步來生成相應的MediaExtractor:
1、通過dataSource->sniff來探測資料型別
2、生成相應的Extractor:
if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
|| !strcasecmp(mime, "audio/mp4")) {
return new MPEG4Extractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
return new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
return new AMRExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) {
return new WAVExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
return new OggExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
return new MatroskaExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
return new MPEG2TSExtractor(source);
二、
接下來,通過以下程式碼把音視訊軌道分離:
if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
setVideoSource(extractor->getTrack(i));
haveVideo = true;
} else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
setAudioSource(extractor->getTrack(i));
haveAudio = true;
生成mVideoTrack和mAudioTrack兩個MediaSource。
三、
到目前為止我們得到的這兩個MediaSource只具有parser功能,沒有decode功能。還需要對這兩個MediaSource做進一步的包裝:
mVideoSource = OMXCodec::Create(
mClient.interface(), mVideoTrack->getFormat(),
false, // createEncoder
mVideoTrack,
NULL, flags);
mAudioSource = OMXCodec::Create(
mClient.interface(), mAudioTrack->getFormat(),
false, // createEncoder
mAudioTrack);
這回又獲取了兩個MediaSource。它們具有parse和decode功能。當呼叫MediaSource.start()方法後,它的內部就會開始從資料來源獲取資料並解析,等到緩衝區滿後便停止。在AwesomePlayer裡就可以呼叫MediaSource的read方法讀取解碼後的資料。
對於mVideoSource來說:
讀取的資料。
1 |
|
交給顯示模組進行渲染。
1 |
|
對mAudioSource來說:
用mAudioPlayer對mAudioSource進行封裝,然後由mAudioPlayer負責讀取資料和播放控制。
AwesomePlayer流程
URI,FD
|
DataSource
|
MediaExtractor
|
mVideoTrack mAudioTrack//音視訊資料流
|
mVideoSource mAudioSource//音視訊解碼器
| |
mVideoBuffer mAudioPlayer
上面示意了資料由源到最終解碼後的流程。
1、設定DataSource,資料來源可以兩種URI和FD。URI可以http://,rtsp://等。FD是一個本地檔案描述符,能過FD,可以找到對應的檔案。
2、由DataSource生成MediaExtractor。通過sp extractor = MediaExtractor::Create(dataSource);來實現。 MediaExtractor::Create(dataSource)會根據不同的資料內容建立不同的資料讀取物件。
3、通過呼叫setVideoSource由MediaExtractor分解生成音訊資料流(mAudioTrack)和視訊資料流(mVideoTrack)。
4、 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來提交事件用來停止解碼,還可以選擇是否繼續緩衝資料。
相關文章
- struts的資料封裝部分封裝
- 節流防抖封裝封裝
- 防抖和節流及對應的React Hooks封裝ReactHook封裝
- Struts2的資料封裝封裝
- WireShark資料包分析資料封裝封裝
- fetch資料請求的封裝封裝
- 非同步的 SQL 資料庫封裝非同步SQL資料庫封裝
- 如何封裝資料庫操作封裝資料庫
- 資料流圖 和 資料字典
- 基於透明fragment的長流程封裝技巧Fragment封裝
- JSONObject應用Json字串和Object物件之間的轉換,Map封裝資料思路JSONObject字串物件封裝
- 前端封裝成json資料和json陣列的方法前端封裝JSON陣列
- PHP 技巧 - 封裝基本的資料型別PHP封裝資料型別
- JdbcUtil和JdbcTemplate的封裝JDBC封裝
- 網路通訊1:位元組流的封裝封裝
- iOS資料上報模組封裝方案iOS封裝
- axios 請求資料封裝iOS封裝
- DiffUtil之我的封裝思路封裝
- 海量資料遷移之資料抽取流程
- iOS之WKWebView封裝iOSWebView封裝
- .NET Core MongoDB資料倉儲和工作單元模式封裝MongoDB模式封裝
- 關於資料庫操作的封裝程式碼資料庫封裝
- SqlSugar 多資料來源的簡單封裝SqlSugar封裝
- modbustcp封裝使用獲取裝置資料示例TCP封裝
- 字串與資料流之間的轉換字串
- nodejs + express + mssql 封裝資料操作NodeJSExpressSQL封裝
- 方法返回資料統一封裝封裝
- 清除快取資料--工具類封裝快取封裝
- 海量資料遷移之資料載入流程
- 架構之:資料流架構架構
- 039.CI4框架CodeIgniter,封裝Model模型繫結資料庫的封裝框架封裝模型資料庫
- ERP流暢之美:重要的是流程(轉)
- iOS資料庫離線快取思路和網路層封裝iOS資料庫快取封裝
- 封裝和多型封裝多型
- 封裝和繼承封裝繼承
- .NET之生成資料庫全流程資料庫
- JS物件之封裝(二)JS物件封裝
- 使用封裝資源的物件封裝物件