數據流的封裝
一、由數據源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來說:
讀取的數據
mVideoSource->read(&mVideoBuffer, &options);
交給顯示模塊進行渲染
mVideoRenderer->render(mVideoBuffer);
對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來提交事件用來停止解碼,還可以選擇是否繼續緩衝數據。
轉自:http://disanji.net/2011/03/06/android-stagefright-datastream-awesomeplayer/