AVFoundation框架的功能十分強大,同時也充斥着各類類,好比各類session,各類input,各類output。以前並無對整個框架進行過完整梳理,雖然也能東拼西湊的那各類類完成需求,但遇到深度定製的需求以及踩到坑以後,總會比較吃力。最近,在看《learning AV Foundation》這本書,看完後嘗試着梳理了一個總體脈絡,並將理解的知識點整合用Swift重寫了一個demo,包括拍攝+實時濾鏡+實時寫入+自定義導出分辨率等。本篇爲視頻拍攝部分,下一章會更新視頻的組合編輯及音頻混合部分。git
能夠看到,整個流程能夠分爲三部分,分別爲數據採集、數據加工和數據保存。github
數據採集: 數據採集不只限於本文場景中的經過攝像頭和麥克分設備採集,還好比AVAssetReader從AVAsset實例中讀取。不管以什麼方式採集,這一階段的輸出都爲CMSampleBuffer。值得一提的是,攝像頭採集的是yuv格式的壓縮的視頻信號,在輸出時要還原成能夠處理的數字信號,這一配置在AVCaptureVideoDataOutput的videoSettings屬性中。session
數據加工: 數據加工階段能夠基於CMSampleBuffer進行各類處理,包括加濾鏡等,都在這個階段。sampleBuffer會包含一個CVPixelBuffer,它是一個帶有單個視頻幀原始像素數據的Core Video對象,據此咱們能夠進行像素級別的加工。架構
數據保存: 數據保存階段將加工後的媒體資源進行編碼並寫入到容器文件中,好比mp4文件或.mov文件等。此處使用AVAssetWriter,它支持實時寫入。它指望接收到的數據也是CMSampleBuffer格式。同時咱們也能夠傳入其餘數據,經過pixelBufferAdaptor適配成它所指望的數據。好比,本文的demo中傳入了CIImage,能夠先將CIImage渲染成CVPixelBuffer,再進行寫入。框架
以上就是總體脈絡,本文的demo也是基於這個思路封裝的。CaptureManager負責數據採集,經過block回調輸出CMSampleBuffer數據。VideoWriteManager負責數據保存,接收CMSampleBuffer數據,經過block回調生成的文件路徑。CameraViewController做爲二者的調度方,並承擔數據加工工做以及將加工後的數據展現給用戶進行預覽。ide
經過設備採集的核心類是AVCaptureSession,它的輸入是AVCaptureDeviceInput,輸出是AVCaptureOutput,管理從物理設備中獲得的數據流,並按照output的配置輸出指定的文件或數據。AVCaptureOutput是一個抽象基類,若是定製化需求不高,能夠直接使用AVCaptureMovieOut高級類來直接輸出文件。可是若是須要進行底層的數據加工或自定義配置,就須要使用AVCaptureVideoDataout和AVCaptureAudioDataOutput來輸出CMSampleBuffer格式的原始數據。此外,爲了避免阻塞主線程,咱們通常會爲AVCaptureOutput分配專門的串行隊列。性能
濾鏡大多使用GPUImage框架,但這不是本文的核心,所以,demo中僅使用了CoreImage框架來實現濾鏡效果。爲了達到實時濾鏡的效果,須要在每一幀的回調數據中,都對每一幀的圖像數據都應用當前濾鏡的效果,從而用戶能夠在拍攝過程當中不斷切換各類濾鏡。學習
此處在學習《learning AV Foundation》書中的demo時,書中的demo是把原始數據分別傳給用戶預覽界面和寫入類,二者各自處理。但我以爲這樣至關於一樣的加工處理了兩遍,從代碼維護和性能上都不是很可取。由於,此處我是處理完後,把處理完的數據分別傳給預覽界面顯示和寫入類保存。編碼
AVAssetWriter經過多個(音頻、視頻等)AVAssetWriterInput對象配置。AVAssetWriterInput經過mediaType和outputSettings來初始化,咱們能夠在outputSettings中進行視頻比特率、視頻寬高、關鍵幀間隔等細緻的配置,這也是AVAssetWrite相比AVAssetExportSession明顯的優點。AVAssetWriterInput在附加數據後會在最終輸出時生成一個獨立的AVAssetTrack.線程
此處用到了PixelBufferAdaptor來附加CVPixelBuffer類型的數據,它在附加CVPixelBuffer對象的視頻樣本時能提供最優性能。
以上就是AVFoundation Caputure部分的總體思路和脈絡,更多采坑細節如視頻旋轉問題等請參考Demo,內有詳細註釋。