Android系統WMA文件播放功能的設計與實(shí)現
WMA文件開(kāi)始有一個(gè)16 Byte的標識,表示是WMA:30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 62 CE 6C。如果音頻文件的前16個(gè)字符和這16 Byte相符,那么就可以判斷該文件為WMA文件。WMAExtraetor中的SniffWMA函數就是通過(guò)讀取文件前16 Byte來(lái)判斷該文件是不是WMA文件。在SniffWMA函數中,如果判斷前16 Byte和WMA的16個(gè)標識字節相等,就會(huì )把MEDIA_MIMETYPE_AUDIO_WMA給mimeType指針,標志著(zhù)該音頻文件類(lèi)型為WMA格式。MEDIA_MIMETYPE_AUDIO_WMA是在MediaDefs.h文件中定義,在MediaDefs.cpp文件中賦值:

(2)WMA文件的解析。
WMAExtmetor從WMA文件的第31 Byte開(kāi)始取16 Byte,然后依次和file_header、stream_header、data_header、comment_header、exten-ded_content_header對比,如果和file_header相等,則從下個(gè)Byte開(kāi)始依次獲取文件大小、創(chuàng )建時(shí)間、數據包個(gè)數、…數據包大小。然后再從下個(gè)Byte開(kāi)始讀取16 Byte再進(jìn)行對比,如果和extended_content_header相等,則可以從下個(gè)Byte中依次獲取名稱(chēng)、藝術(shù)家、版權、注釋等非音頻信息。然后再接著(zhù)讀取16 Byte進(jìn)行比對,直到和data_eader相等。data_header后就是音頻文件解碼數據,data_header的結束位置就是第一個(gè)數據包在文件中的偏移量。WMAExtractor會(huì )創(chuàng )建一個(gè)MetaData,并把文件頭中獲取的sample_rate、Byte_rate、channels、dura-tion都存入MetaData中。在WMAExtractor的getMetaData函數中,把之前獲取的非音頻信息放入MetaData中,最后返回該MetaData。在WMAEx-tractor的getTrack函數中,創(chuàng )建一個(gè)WMASource,并把WMA數據和MetaData傳給WMASource。
(3)編碼數據的讀取。
獲取未解碼數據是通過(guò)WmASource的read函數讀取的。WMA數據是以數據包為單位的,同文件中的數據包大小相同。每個(gè)數據包中有多幀數據,每個(gè)數據包的起始位置減去第—個(gè)數據包的起始位置再除以包的大小等于一個(gè)整數,這個(gè)整數就是該數據包之前數據包的個(gè)數。每個(gè)數據包的第一個(gè)Byte一般都等于0x82。第二個(gè)Byte以后是該數據包的相關(guān)信息。根據包的相關(guān)數據就可以獲取該包中的未解碼數據。
WMASource的read讀取未解碼數據時(shí),首先會(huì )判斷從WMADecoder傳來(lái)的options是否為空,如果不為空,并可以從options中獲取一個(gè)播放時(shí)間seekTimeUs,就通過(guò)seekTimeUs、總播放時(shí)間和總數據包的個(gè)數算出要播放數據包的起始位置,然后從該起始位置獲取一個(gè)數據包的數據,并從該數據包中獲取有效數據的大小、起始位置、時(shí)間等數據,最后把該有效數據和時(shí)間放在WMADecoder傳來(lái)的Buffer里。
WMASource的Read被調用時(shí),如果傳來(lái)的Options為空或是不能從Options中獲取時(shí)間seekTimeUs,就會(huì )從WMA文件中讀取一個(gè)數據包,根據其中的有效數據的大小、起始位置獲取有效數據,并獲取該數據包中的時(shí)間,然后把該有效數據和時(shí)間放在WMADecoder傳來(lái)的buffer里。第一個(gè)數據包的起始位置就是解析頭文件時(shí)獲取的第一個(gè)數據包的偏移量,所以第一次調用WMASource的read時(shí),就是從這個(gè)偏移量的下個(gè)位置讀取第一個(gè)數據包的。在WMASource中有一個(gè)專(zhuān)門(mén)記錄讀取位置的指針。每次讀取1個(gè)數據包后,該指針就會(huì )指向數據包末尾的下一個(gè)位置,當下一次WMASource的read讀取未解碼數據時(shí),如果不是音樂(lè )定點(diǎn)播放,就會(huì )從該指針所指的位置開(kāi)始讀取數據包。本文引用地址:http://dyxdggzs.com/article/194616.htm
(4)編碼數據的解碼和輸出。
AwesomePlayer通過(guò)OMXCodec中的Create函數創(chuàng )建WMADecoder,所以在OMXCodec中注冊WMADecoder的相關(guān)信息:
在創(chuàng )建WMADecoder時(shí),把之前創(chuàng )建的WMASource傳給WMADecoder。在WMADecoder構造函數中,WMADecoder從WMASource中獲取Metadata,并從Metadata獲取sampleRate、numChannels、duration等。在WMADecoder的start函數中,通過(guò)調用avcodec_open函數,來(lái)分配解碼所需的空間、創(chuàng )建并初始化解碼所需的相關(guān)參數。在WMADecoder析構函數中會(huì )調用WMADecoder的Stop函數。在Stop函數中會(huì )釋放所有相關(guān)空間。
c++相關(guān)文章:c++教程
評論