由于同時(shí)涉及播放文件和記錄文件兩種功能,因此OpenCORE中的文件格式處理有兩種類型。一種是解析器(Parser),用于解析文件;另一種是組合器(Composer),用于記錄文件。
在媒體文件的播放過(guò)程中,一個(gè)視頻文件會(huì)包含音頻流和視頻流的組合,如在一個(gè)MP4文件中,可能包含了AMR或AAC的音頻壓縮流,以及H263、MPEG 4或者H264 AVC的視頻壓縮流。這些流文件被封裝在一個(gè)包文件中,媒體播放器首先要做的就是將這些流文件從包文件中解析出來(lái),然后根據(jù)文件類型的不同調(diào)用不同的解碼器進(jìn)行解碼,后將解碼后的元數(shù)據(jù)流輸送到相應(yīng)的硬件設(shè)備進(jìn)行播放。
在媒體文件的記錄過(guò)程中,涉及視頻、音頻、圖像的捕獲功能。如在錄像過(guò)程中,首先需要從硬件設(shè)備分別獲得視頻元數(shù)據(jù)流和音頻元數(shù)據(jù)流,然后根據(jù)相關(guān)的配置信息,將元數(shù)據(jù)流壓縮成相應(yīng)格式的壓縮流,并寫(xiě)入文件中,終組合成相應(yīng)的包文件。
需要說(shuō)明的是,目前中、高端的移動(dòng)終端上都配備了專門(mén)用于多媒體加速的DSP,相關(guān)的音頻、視頻編解碼工作都會(huì)在專用DSP上進(jìn)行。OpenCORE關(guān)于文件格式解析的內(nèi)容位于external\opencore\fileformats和external\opencore\protocols\sdp\parser目錄下。
下面分別以MP3和MPEG-4為例來(lái)分析解析器、組合器的實(shí)現(xiàn)。
1.解析器
在Android中,目前內(nèi)置了AVI、MPEG-4、WAV、MP3、AMR、AAC等格式的解析器。下面以MP3為例介紹解析器的實(shí)現(xiàn),相關(guān)的文件包括imp3ff.cpp、mp3fileio.cpp、mp3parser.cpp、mp3utils.cpp等。具體實(shí)現(xiàn)位于external\opencore\fileformats\ mp3\parser目錄下。
在Android中,MP3解析器節(jié)點(diǎn)的注冊(cè)是在PVMERegistryPopulator::RegisterAllNodes()方法中完成的。
為了進(jìn)行MP3文件的播放,需要將MP3的數(shù)據(jù)源添加到播放引擎中,在添加數(shù)據(jù)源的過(guò)程中會(huì)進(jìn)行文件解析。MP3播放時(shí)進(jìn)行文件解析的過(guò)程如下圖所示。

MP3播放時(shí)的文件解析過(guò)程
流程說(shuō)明:
在客戶端通過(guò)PlayerDriver添加數(shù)據(jù)源的過(guò)程中,PVPlayerEngine引擎會(huì)向一個(gè)線程安全的事件隊(duì)列iThreadSafeQueue中添加PVP_ENGINE_COMMAND_ADD_ DATA_SOURCE命令。當(dāng)PVPlayerEngine引擎收到該命令后,調(diào)用DoAddDataSource()方法進(jìn)行數(shù)據(jù)源的添加。
根據(jù)傳過(guò)來(lái)的命令I(lǐng)D,PVPlayerEngine引擎獲得當(dāng)前的PVPlayerDataSource對(duì)象,然后調(diào)用PVPlayerDataSource::GetDataSourceFormatType()方法查看當(dāng)前的文件格式。如果文件格式未知,就需要根據(jù)傳遞的命令I(lǐng)D和命令上下文調(diào)用DoQuerySourceFormatType()方法進(jìn)行文件格式的解析了。
在DoQuerySourceFormatType()方法中,會(huì)經(jīng)過(guò)一系列的操作獲得一個(gè)PVMFCPMPluginAccessInterfaceFactory對(duì)象,然后根據(jù)該對(duì)象調(diào)用PVPlayer RecognizerRegistry:: QueryFormatType()方法打開(kāi)識(shí)別器(Recognizer)的會(huì)話并進(jìn)行識(shí)別。
PVMFRecognizerRegistry對(duì)象通過(guò)調(diào)用PVMFRecognizerRegistryImpl::Recognize()方法,向自身發(fā)送一個(gè)PVMFRECREG_COMMAND_RECOGNIZE命令,將工作交給PVMF RecognizerRegistryImpl::DoRecognize()方法進(jìn)行接下來(lái)的處理。
在PVMFRecognizerRegistryImpl::DoRecognize()方法中,首先會(huì)通過(guò)CheckFor DataAvailability()方法驗(yàn)證數(shù)據(jù)的有效性,然后通過(guò)RunRecognitionPass()方法調(diào)用解析器插件。直到這時(shí),PVMP3FFRecognizerPlugin才有了用武之地。
在PVMP3FFRecognizerPlugin::Recognize()方法中,會(huì)首先通過(guò)OSCL_NEW()方法創(chuàng)建一個(gè)IMpeg3File對(duì)象。然后調(diào)用IMpeg3File::IsMp3File()方法判斷該文件是不是MP3文件。
在IMpeg3File::IsMp3File()方法中,會(huì)通過(guò)OSCL_NEW()方法創(chuàng)建一個(gè)MP3Parser對(duì)象,然后在MP3Utils和MP3FileIO的配合下,通過(guò)MP3Parser::GetMP3Header()嘗試獲得MP3的頭文件。如果成功,再通過(guò)MP3Parser::DecodeMP3Header()來(lái)解析該頭文件,通過(guò)同樣成功,則確認(rèn)該文件就是MP3文件了。
在完成了文件的解析后,即開(kāi)始解碼工作,關(guān)于MP3的解碼工作請(qǐng)參考6.2.3節(jié)MP3的解碼過(guò)程。
2.組合器
在Android中,目前內(nèi)置了MPEG-4等格式的組合器,組合器的實(shí)現(xiàn)要比解析器復(fù)雜的多。下面以MPEG-4為例介紹組合器的實(shí)現(xiàn),相關(guān)的文件位于external\了opencore\fileformats\mp4\composer目錄下。下圖所示為MP4記錄時(shí)的文件解析過(guò)程。

MP4記錄時(shí)的文件解析過(guò)程
流程說(shuō)明:
在進(jìn)行MP4記錄時(shí),客戶端會(huì)通過(guò)PVMediaRecorder::setOutputFormat()方法向記錄引擎PVAuthorEngine發(fā)送AUTHOR_SET_OUTPUT_FORMAT消息,設(shè)置輸出文件的格式。
在AuthorDriver的監(jiān)聽(tīng)線程收到AUTHOR_SET_OUTPUT_FORMAT消息后,會(huì)調(diào)用handleSetOutputFormat()方法進(jìn)行輸出格式MIME類型的設(shè)置。然后調(diào)用PVAuthorEngine引擎的SelectComposer()方法進(jìn)行組合器的選擇。
PVAuthorEngine引擎首先向自身發(fā)送PVAE_CMD_SELECT_COMPOSER消息到事件隊(duì)列中,一旦收到該消息,即調(diào)用DoSelectComposer()方法,根據(jù)消息攜帶的MIME類型獲得相應(yīng)的UUID,然后調(diào)用PVAuthorEngineNodeFactoryUtility::CreateComposer()方法創(chuàng)建組合器。接下來(lái)系統(tǒng)根據(jù)UUID判定是否創(chuàng)建MP4文件,如果是,則調(diào)用PVMp4FFComposerNodeFactory::CreateMp4FFComposer()方法創(chuàng)建MP4的組合器。
當(dāng)開(kāi)始媒體記錄時(shí),MP4組合器會(huì)被調(diào)用DoStart()方法,在該方法中,組合器會(huì)創(chuàng)建MP4文件,設(shè)置記錄模式、緩沖等,然后設(shè)置時(shí)間戳、版本號(hào)、標(biāo)題、作者、版權(quán)、備注等信息,后調(diào)用PVA_FF_IMpeg4File::prepareToEncode()方法開(kāi)始編碼工作。
需要說(shuō)明的是,AuthorDriver為記錄引擎和上層應(yīng)用的接口,PlayerDriver為播放引擎與上層應(yīng)用的接口。