前言
相關(guān)文章:
使用VideoToolbox硬編碼H.264
使用VideoToolbox硬解碼H.264
使用AudioToolbox編碼AAC
使用AudioToolbox播放AAC
HLS點播實現(xiàn)(H.264和AAC碼流)
HLS推流的實現(xiàn)(iOS和OS X系統(tǒng))
iOS在線音頻流播放
Audio Unit播放PCM文件
Audio Unit錄音(播放伴奏+耳返)
Audio Unit播放aac/m4a/mp3等文件
Audio Unit和ExtendedAudioFile播放音頻
AUGraph結(jié)合RemoteI/O Unit與Mixer Unit
上面的文章介紹了音視頻信息的加載和解析禽笑,在另外的《OpenGLES文集》也詳細介紹了OpenGL如何繪制圖像王凑。
這次結(jié)合Audio Unit和OpenGL ES机久,分別加載多媒體文件的音頻和視頻信息并播放礼预。
正文
整體思路
demo包括三大部分泞遗,分別是資源加載袱箱、音頻播放熬的、視頻播放点寥。
- 資源加載:是用
AVURLAsset
加載資源文件咕村,再創(chuàng)建資源讀取器AVAssetReader
场钉,然后附加音頻讀取接口mReaderAudioTrackOutput
和視頻讀取接口mReaderVideoTrackOutput
到資源讀取器。 - 音頻播放 :從音頻讀取接口
mReaderAudioTrackOutput
加載音頻信息得到CMSampleBuffer
懈涛,用方法CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer
把音頻數(shù)據(jù)轉(zhuǎn)成AudioBufferList
格式逛万,再采用AudioUnit播放; - 視頻播放:從視頻讀取接口
mReaderVideoTrackOutput
加載視頻信息得到CMSampleBuffer
批钠,用方法CMSampleBufferGetImageBuffer
把視頻數(shù)據(jù)轉(zhuǎn)成CVPixelBufferRef
格式宇植,再用OpenGL ES繪制圖像;
具體解析
1埋心、資源加載
資源加載用的是AVFoundation
提供的方法指郁,先加載音視頻的軌道信息。
然后初始化好音視頻的格式信息outputSettings
拷呆,outputSettings
是AVAssetReaderTrackOutput
初始化的必要條件之一闲坎。
注意音軌和聲道的區(qū)別,比如說在ktv唱歌的時候茬斧,通常伴奏是一個音軌腰懂,錄到的人聲是一個音軌,最后播放的時候進行混合项秉。而聲道我們常用聲道數(shù)的概念绣溜,指的是聲音播放時的揚聲器數(shù)量。
音軌=AudioTrack
聲道=AudioChannel
2娄蔼、音頻播放
音頻播放功能用的是Audio Unit涮毫,其中的RemoteIO Unit只能接受PCM數(shù)據(jù)瞬欧,故而要求讀取出來的音頻信息必須是PCM格式的,并且設(shè)置給Audio Unit的格式需要與outputSettings
一致罢防。
3艘虎、視頻播放
視頻播放其實就是圖像信息的繪制,從資源我們可以讀取到圖像信息咒吐,再把圖像傳給已經(jīng)封裝好的LYOpenGLView類野建,就可以繪制圖像。圖像信息占用內(nèi)存較為明顯恬叹,需要注意內(nèi)存的回收候生。
遇到的問題
1、確定Audio Unit音頻格式
嘗試加載資源文件的音頻格式并設(shè)置給Audio Unit绽昼,但因為Audio Unit無法接受資源文件的格式(大多數(shù)文件的音頻文件格式為AAC)唯鸭。
解決方案是直接設(shè)置讀取的音頻格式信息為PCM,并且手動初始化ASBD硅确,保證兩端的格式一致目溉。
如下,是資源文件的音頻讀取格式和手動初始化的格式:
NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary];
[outputSettings setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
[outputSettings setObject:@(16) forKey:AVLinearPCMBitDepthKey];
[outputSettings setObject:@(NO) forKey:AVLinearPCMIsBigEndianKey];
[outputSettings setObject:@(NO) forKey:AVLinearPCMIsFloatKey];
[outputSettings setObject:@(YES) forKey:AVLinearPCMIsNonInterleaved];
[outputSettings setObject:@(44100.0) forKey:AVSampleRateKey];
[outputSettings setObject:@(1) forKey:AVNumberOfChannelsKey];
AudioStreamBasicDescription inputFormat;
inputFormat.mSampleRate = 44100;
inputFormat.mFormatID = kAudioFormatLinearPCM;
inputFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved;
inputFormat.mFramesPerPacket = 1;
inputFormat.mChannelsPerFrame = 1;
inputFormat.mBytesPerPacket = 2;
inputFormat.mBytesPerFrame = 2;
inputFormat.mBitsPerChannel = 16;
self.fileFormat = inputFormat;
2菱农、音視頻同步
demo中存在兩個變量self.mAudioTimeStamp
和self.mVideoTimeStamp
缭付,分別表示音頻播放和視頻播放的時間戳。
其中音頻播放進度由Audio Unit驅(qū)動循未,視頻播放進度由CADisplayLink驅(qū)動陷猫,為了保證視頻進度不超過音頻進度,添加了if (self.mVideoTimeStamp < self.mAudioTimeStamp)
的判斷的妖。
但在模擬器運行的時候绣檬,視頻的解析比音頻解析的速度小很多,造成較為明顯的不同步嫂粟。
在真機運行的時候娇未,這種現(xiàn)象有明顯的改進。
目前還沒找到較好的同步方式赋元,如果有知道請指教忘蟹。
總結(jié)
本文沒有擴展更多的音頻和視頻知識,通過結(jié)合三個部分知識搁凸,組成基本的音視頻播放流程媚值。
由于時間原因,所做的技術(shù)預(yù)研無法盡善盡美护糖,代碼沒有很好的打磨褥芒。
demo更多是實踐某些想法,如果代碼存在問題,懇請指出锰扶,幫助你我他少踩一些坑献酗。