1. 程式人生 > >camera錄影過程一

camera錄影過程一

1 概述

camera 的錄影分為三個過程:
  1. camera模組將從hal層的預覽執行緒中,獲取原始的未壓縮的yvu視屏幀,通過回撥函式傳遞到CameraSource模組
  2. OMXCodec模組將從CameraSource模組的read介面獲取yuv視訊幀拷貝到編碼模組提供的輸入埠的buffer列表中,編碼模組從輸入埠的buffer列表讀取包含yuv的buffer、編碼、然後送回到輸出埠的buffer列表,供OMXCodec模組取回
  3. 從OMXCodec模組的read介面讀取壓縮編碼後的h264幀,通過TS容器寫到輸出檔案控制代碼上,得到TS流的檔案
在這篇文章中,我們將集中討論第一種情況,即CameraSource.read()介面的呼叫過程

2  CameraSource.read過程涉及的類圖結構

camera預覽執行緒CameraHardware::inPreviewThread在獲取到yuv視訊幀後,通過呼叫CameraHardware::frameCallbackNotifier函式,即最終呼叫到 CameraClient::dataCallbackTimestamp函式,將視訊幀buffer通過ICameraClient binder傳送給Camera::dataCallbackTimestamp函式,該函式又通過 ICameraRecordingProxyListener binder將視訊幀對應的Imemory控制代碼轉發到
CameraSource::dataCallbackTimestamp函式。 而在CameraSource::read函式中,會將剛才收到的IMemory控制代碼對應的記憶體如下的處理: *buffer = new MediaBuffer(frame->pointer(), frame->size()); 以上語句中的pointer()函式會將IMemory控制代碼對應的記憶體對映到CameraSource所在的程序C地址空間,從而使CameraSource和CameraClient共享同一個yuv視訊記憶體塊。
需要注意的是:yuv視訊幀,是在CameraClient所在的程序分配的,而CameraClient和camera HAL是屬於同一個程序的。

3 CameraSource.read的呼叫流程


以上Camerasource.read過程,涉及到2次binder呼叫,在資料傳遞的過程中,只是傳遞的共享記憶體對應的控制代碼(Imemory),而不是傳輸實際的yuv記憶體資料,所以效率比較高。在Camerasource.read函式中,通過呼叫的Imemory的pointer函式,來講預覽用的記憶體對映到Camerasource.read所在程序,從而可以直接訪問該塊記憶體。

另外錄影和預覽是同一個CameraHardware::inPreviewThread執行緒,這樣就可以在錄影、預覽、停止錄影等之間無縫的快速切換。

4 總結

camera錄影過程,涉及到模組比較多,有camera模組,編碼模組,omx模組,容器模組,並且涉及大塊資料在各程序之間的共享操作。所以會比較複雜,中間會頻繁使用binder來進行程序的通訊。一個祕訣就是:循著binder的機制來檢視程式的資料流,而binder機制中的Bpxxx(客戶端),Bnxxx(伺服器端),Ixxx(介面),則是跟蹤程式流程的重要線索。

另外binder服務又分為知名服務,和匿名服務,像camera模組,就有個media.camera的知名服務,而meidaRecorder模組則屬於meida.player的知名服務,而更多的則是匿名服務,匿名服務可以通過知名服務或是其他已知的匿名服務來傳遞。

詳細的binder傳遞過程,可以參考binder的驅動相關的文章。