Metal之实现视频采集与实时渲染
生活随笔
收集整理的這篇文章主要介紹了
Metal之实现视频采集与实时渲染
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、視頻渲染實現思路
① 思路說明
- 通過AVFoundation進行視頻數據的采集,并將采集到的原始數據存儲到CMSampleBufferRef中,即視頻幀數據(視頻幀其實本質也是一張圖片)。
- 通過CoreVideo將CMSampleBufferRef中存儲的圖像數據,轉換為Metal可以直接使用的紋理。
- 將Metal紋理進行渲染,并即刻顯示到屏幕上。
② 思路實現
- 在實際的開發應用中,AVFoundation 提供了一個 layer,即AVCaptureVideoPreviewLayer 預覽層,我們可以使用預覽層直接預覽視頻采集后的即可渲染,用于直接實現上面思路中的第二步和第三步。
- 根據官方文檔之AVCaptureVideoPreviewLayer說明,AVCaptureVideoPreviewLayer 是 CALayer 的子類,用于在輸入設備捕獲視頻時顯示視頻,此預覽圖層與捕獲會話結合使用,主要有以下三步:
- 創建預覽層對象;
- 將預覽層與captureSession鏈接;
- 將預覽層加到view的子layer中。
③ 整體流程
- viewDidLoad函數:初始化Metal和視頻采集的準備工作;
- MTKViewDelegate協議方法:視頻采集數據轉換為紋理;
- AVCaptureVideoDataOutputSampleBufferDelegate協議方法:將采集轉換后的紋理渲染到屏幕上。
二、初始化 Metal 和視頻采集的準備工作
① 整體流程如下:
② setupMetal函數
- 初始化MTKView,用于顯示視頻采集數據轉換后的紋理;
- 創建命令隊列:通過MTKView中的device創建;
- 設置MTKView的讀寫操作 & 創建紋理緩沖區:
- MTKView中的framebufferOnly屬性,默認的幀緩存是只讀的即YES,由于view需要顯示紋理,所以需要該屬性改為可讀寫即NO;
- 通過CVMetalTextureCacheCreate方法創建CoreVideo中的metal紋理緩存區,因為采集的視頻數據是通過CoreVideo轉換為metal紋理的,主要的用于存儲轉換后的metal紋理;
③ setupCaptureSession函數
- 設置AVCaptureSession & 視頻采集的分辨率;
- 創建串行隊列:串行隊列創建的目的在于處理captureSession的交互時,不會影響主隊列,在蘋果官方文檔中有如下圖示,表示captureSession是如何管理設備的輸入 & 輸出,以及與主隊列之間的關系,session管理輸入和輸出圖示如下:
- 關于串行隊列在官方文檔中的描述:
- 實現邏輯如下:
- 設置輸入設備
- 獲取后置攝像頭設備AVCaptureDevice:通過獲取設備數組,循環判斷找到后置攝像頭,將后置攝像頭設備為當前的輸入設備;
- 通過攝像頭設備創建AVCaptureDeviceInput:將AVCaptureDevice 轉換為 AVCaptureDeviceInput,主要是因為 AVCaptureSession 無法直接使用 AVCaptureDevice,所以需要將device轉換為deviceInput;
- 輸入設備添加到captureSession中:在添加之前,需要通過captureSession的canAddInput函數判斷是否可以添加輸入設備,如果可以,則通過session的addInput函數添加輸入設備;
- 設置輸出設備
- 創建AVCaptureVideoDataOutput對象,即輸出設備;
- 設置輸出設備的setAlwaysDiscardsLateVideoFrames屬性(表示視頻幀延時使是否丟棄數據)為NO:
- YES:處理現有幀的調度隊列,在captureOutput:didOutputSampleBuffer:FromConnection:Delegate方法中被阻止時,對象會立即丟棄捕獲的幀;
- NO:在丟棄新幀之前,允許委托有更多的時間處理舊幀,但這樣可能會內存增加
- 設置輸出設備的setVideoSettings屬性(即像素格式),表示每一個像素點顏色保存的格式,且設置的格式是BGRA,而不是YUV,主要是為了避免Shader轉換,如果使用了YUV格式,就需要編寫shader來進行顏色格式轉換;
- 設置輸出設備的視頻捕捉輸出的delegate;
- 將輸出設備添加到captureSession中;
- 輸入與輸出鏈接 & 設置視頻輸出方向:通過AVCaptureConnection鏈接輸入和輸出,并設置connect的視頻輸出方向,即設置videoOrientation屬性;
- 輸入與輸出鏈接 & 設置視頻輸出方向:通過AVCaptureConnection鏈接輸入和輸出,并設置connect的視頻輸出方向,即設置videoOrientation屬性;
- 開始捕捉,即開始視頻采集,也可以通過一個按鈕來控制視頻采集的開始與停止
- startRunning:開啟捕捉
- stopRunning:停止捕捉
三 、AVCaptureVideoDataOutputSampleBufferDelegate協議
① 整體流程
- 在視頻采集的同時,采集到的視頻數據,即視頻幀會自動回調視頻采集回調方法captureOutput:didOutputSampleBuffer:fromConnection:,在該方法中處理采集到的原始視頻數據,將其轉換為metal紋理;
- didOutputSampleBuffer代理方法:主要是獲取視頻的幀數據,將其轉換為metal紋理,函數流程如下:
② 流程分解說明
- 從sampleBuffer中獲取位圖:通過CMSampleBufferGetImageBuffer函數從sampleBuffer形參中獲取視頻像素緩存區對象,即視頻幀數據,平常所說的位圖:
- 獲取捕捉視頻幀的寬高:通過CoreVideo中的CVPixelBufferGetWidth和CVPixelBufferGetHeight函數獲取寬高;
- 將位圖轉換為metal紋理:
- 通過CVMetalTextureRef創建臨時紋理;
- 通過CVMetalTextureCacheCreateTextureFromImage函數創建metal紋理緩沖區,賦值給臨時紋理;
- 判斷臨時紋理是否創建成功,如果臨時紋理創建成功,則繼續往下執行;
- 設置MTKView中的drawableSize屬性,即表示可繪制紋理的大小;
- 通過CVMetalTextureGetTexture函數,獲取紋理緩沖區的metal紋理對象;
- 釋放臨時紋理;
四、MTKViewDelegate協議
① 說明
- 將獲取的metal紋理即刻渲染并顯示到屏幕上,這里是通過MTKViewDelegate協議的drawInMTKView代理方法渲染并顯示。
- drawInMTKView代理方法
MTKView默認的幀速率與屏幕刷新頻率一致,所以每當屏幕刷新時,都會回調 視頻采集方法和視圖渲染方法,以下是視圖渲染方法執行流程:
② 具體步驟
- 判斷紋理是否獲取成功:即紋理不為空,如果紋理為空,則沒必要執行視圖渲染流程;
- 通過commandQueue創建commandBuffer命令緩存區;
- 將MTKView的紋理作為目標渲染紋理,即獲取view中紋理對象
- 設置高斯模糊濾鏡:
- MetalPerformanceShaders是Metal的一個集成庫,有一些濾鏡處理的Metal實現;
- 此時的濾鏡就等價于Metal中的MTLRenderCommandEncoder渲染命令編碼器,類似于GLSL中program;
- 高斯模糊濾鏡在渲染時,會觸發離屏渲染,且其中的sigma值設置的越高,圖像越模糊;
- 將獲取的紋理顯示到屏幕上;
- 將commandBuffer通過commit提交給GPU;
- 清空當前紋理,為下一次紋理數據讀取做準備;
如果不清空,也是可以的,下一次的紋理數據會將上次的數據覆蓋;
五、總結
① 視頻采集流程
- 設置session;
- 創建串行隊列;
- 設置輸入設備;
- 設置輸出設備;
- 輸入與輸出鏈接;
- 設置視頻輸出方向;
- 開始捕捉,即開始視頻采集;
- AVCaptureVideoDataOutputSampleBufferDelegate協議處理采集后的視頻數據;
② 如何判斷采集的數據是音頻還是視頻
- 通過AVCaptureConnection判斷
- 視頻:包含視頻輸入設備 & 視頻輸出設備,通過AVCaptureConnection鏈接起來
- 音頻:包含音頻輸入設備 & 音頻輸出設備,同樣通過AVCaptureConnection鏈接起來
- 如果需要判斷當前采集的輸出是視頻還是音頻,需要將connect對象設置為全局變量,然后在采集回調方法captureOutput:didOutputSampleBuffer:fromConnection:中判斷全局的connection 是否等于代理方法參數中的coneection ,如果相等,就是視頻,反之是音頻;
- 通過AVCaptureOutput判斷
在采集回調方法captureOutput:didOutputSampleBuffer:fromConnection:中判斷output形參的類型,如果是AVCaptureVideoDataOutput 類型則是視頻,反之,是音頻。
總結
以上是生活随笔為你收集整理的Metal之实现视频采集与实时渲染的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据结构与算法】之面试必考的“二分算法
- 下一篇: iOS之深入解析数组遍历的底层原理和性能