iOS自定義任意解析度的Camera(包含example code)
說在前面
如果不想看文章,可以直接翻到最後,我已經把程式碼上傳到gist上,但這樣你會失去一個理解程式碼的機會。
概述
該文章會涉及到的概念包括:
AVCaptureDeviceInput
,AVCaptureVideoDataOutput
,AVCaptureVideoPreviewLayer
,AVCaptureSession
,AVAssetWriterInput
,
AVAssetWriter
,AVCaptureAudioDataOutputSampleBufferDelegate
,
AVCaptureVideoDataOutputSampleBufferDelegate
以上技術概念都屬於AVFundation下
實現以下功能:顯示自定義比例的相機並且將相機拍攝的資料以視訊的方式儲存到本地。
基本概念
在開始之前,我先對上面的涉及到的每個概念做一個簡單說明,便於對後面程式碼的理解
AVCaptureDeviceInput 包含videoInput,audioInput,分別獲取音視訊裝置,這裡videoInput還要區分front camera和back camera ,可以定義三個AVCaptureDeviceInput,分別是current camera(front/back),一個front camera,一個back camera。切換camera時,只要給current camera賦不同的camera即可。
AVCaotureVideoPreviewLayer 用來顯示camera的影象的layer,通過設定它的frame和videoGravity屬性,就可以實現顯示不同尺寸的畫面了。
AVCaptureVideoDataOutput 與DeviceInput相對應,要宣告兩個output,分別是video output和audio output,其中可以通過設定video output的AVCaptureConnection控制攝像頭是否是映象顯示,攝像頭方向,auto focus等資料,該output的效果直接顯示在previewLayer上。
AVCaptureSession AVCaptureSession的是起到一個bridge的作用,它建立起AVCaptureDeiviceInput和AVCaptureDeviceOutput之間的關係,這裡需要注意,session同時只能有一種output,該部落格中的方案是建立AVCaptureVideoDataOutput,也就是每一幀圖片都有一個buffer的幀回撥,還有一種output是AVCaptureFileOutputRecordingDelegate,這種回撥是直接把buffer寫到檔案中,拿不到幀回撥資料,也不能自定義幀大小。只能使用系統提供的幾種幀比例。
AVAssetWriterInput 需要分別定義一個audio和video的writer,之前說道的device intput,device output都是顯示上的設定,這裡主要涉及的是寫檔案,video asset writer設定的解析度要與previewLayer的解析度保持一致,否則會出現顯示和儲存的畫質不一致情況。
AVAssetWriter AVAssetWriter繫結audio,video writer,指定寫檔案路徑,控制開始和結束。
圖解
一圖勝千言,可以對照上面的基本概念一起看。
圖中可以看到整個流程分為三大塊:session,previewlayer,asswriter,preview layer初始化的時候會傳參一個session,session通過output delegate和asswriter建立聯絡,asswiter通過捕捉回撥幀資料,寫視訊檔案。
真正實現的時候,還會涉及到很多引數配置,配置的先後順序也是要注意的點,詳細過程還要看程式碼。
程式碼分析
這裡只對宣告的所有屬性做一個簡單的註解,其他模組的程式碼可以在文章底部自行下載檢視。
//preview Layer依附的View,外部傳進來的變數
@property (nonatomic ,strong) UIView *attachView;
@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer;
//用於DeviceOutput
@property (nonatomic ,strong) dispatch_queue_t recoredingQuene;
//AssetWriter配置項
@property (nonatomic ,strong) NSDictionary *audioSetting;
@property (nonatomic ,strong) NSDictionary *videoSetting;
//AsstWriter
@property (nonatomic ,strong) AVAssetWriterInput *audioWriterInput;
@property (nonatomic ,strong) AVAssetWriterInput *videoWriterInput;
@property (nonatomic ,strong) AVAssetWriter *assetWriter;
//video file的儲存路徑
@property (nonatomic ,strong) NSURL *recordingURL;
//Output
@property (nonatomic ,strong) AVCaptureVideoDataOutput *videoOutput;
@property (nonatomic ,strong) AVCaptureVideoDataOutput *audioOutput;
//session
@property (nonatomic ,strong) AVCaptureSession *session;
//Input Device
@property (nonatomic ,strong) AVCaptureDeviceInput *currentCameraInput;
@property (nonatomic ,strong) AVCaptureDeviceInput *frontCamera;
@property (nonatomic ,strong) AVCaptureDeviceInput *backCamera;
@property (nonatomic ,strong) AVCaptureDeviceInput *audioMic;
//閃光燈
@property (nonatomic ,strong) AVCaptureDevice *flashLight;
//控制錄製的變數
@property (nonatomic ,assign) BOOL isRecording;
@property (nonatomic, assign) BOOL isRecordingSessionStarted;
程式碼
如需交流,請掃面下方二維碼(新增時備註:csdn)