前沿:
前面博文大多少總結的是Camera HAL1到HAL3的系統架構,但這些架構對於Camera APP開發來說依舊還是處於Camera API1.0的標準。而隨着Camera3、HAL3.0等的不斷更新,Google先是在Framework中更改了整個架構從而去匹配Camera API1.0的處理邏輯,隨着時間的推移,Google直接對Camera API進行了全新的升級,去除了原先的Camera.java的相關接口,取而代之的是設計了Camera API2來完全匹配之前設計的Camera3以及HAL3,這樣的好處是整個架構看起來會更簡單。
本文主要簡單的說明一下API2.0下Camera在Framewrok層中的處理邏輯,以及對比之前API1.0下他放棄了什麼,同時增加了什麼?
1. 全新的Camera API2.0
在API2.0中你再也看不得之前的startPreview、takePicture、AutoFocus等標準的操作接口,取而代之的是出現了大量涉及到CaptureRequest/CaptureResult相關的API,Google 在API Level21中即Android5.0版本中開始使用,並deprecate舊的Camera.java相關的接口。
2. AIDL技術在CameraService中的出現
AIDL是Android Java層實現C/S架構的一種方式,在Native Binder機制的幫助下,在Java層直接建立一種進程間通信。在Camera API2.0下可以看到大量的ADIL處理方式在Java層中出現,替代之前API1.0下都需要進入了Native層來完成通信。
對於CameraService而言,無論是哪種架構或者方式,都是應該滿足下面的幾個過程:
(1)CameraService啓動;
(2)一個Client端通過CameraService Proxy連接到CameraService,並獲得一個CameraClient Proxy。後續通過CameraClient Proxy直接和CameraService來交互。
(3)Client要提供Callback實體接口到Service端,即每個Service端的CameraClient都需要一個Callback Proxy來完成數據、消息的Callback。
無論Android怎麼升級,Camera模塊基本都處於這種工作模式下,只是具體的實現方式不同而已。此外,上面所提的到C/S架構基本都是通過Binder IPC來實現的。
傳統的CameraService架構是在API1.0下請求Service在客戶端創建一個Camera,是一種很明顯的C++層的C/S架構,但在API2.0的架構下原先在Client層的Camera直接是交由Java層CameraDevice來維護,通過AIDL的處理方式實現接口ICameraDeviceUser,在Java層維護一個Camera proxy,好處很明顯是響應的速度會更快一些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
interface
ICameraDeviceUser { /** *
Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h */ void
disconnect(); //
ints here are status_t //
non-negative value is the requestId. negative value is status_t int
submitRequest(in CaptureRequest request, boolean
streaming); int
cancelRequest( int
requestId); int
deleteStream( int
streamId); //
non-negative value is the stream ID. negative value is status_t int
createStream( int
width, int
height, int
format, in Surface surface); int
createDefaultRequest( int
templateId, out CameraMetadataNative request); int
getCameraInfo(out CameraMetadataNative info); int
waitUntilIdle(); int
flush(); } |
同樣的我們看到CameraSevice在Android Java層處的ICameraService.AIDL文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
interface
ICameraService { /** *
Keep up-to-date with frameworks/av/include/camera/ICameraService.h */ int
getNumberOfCameras(); //
rest of 'int' return values in this file are actually status_t int
getCameraInfo( int
cameraId, out CameraInfo info); int
connect(ICameraClient client, int
cameraId, String
clientPackageName, int
clientUid, //
Container for an ICamera object out
BinderHolder device); int
connectPro(IProCameraCallbacks callbacks, int
cameraId, String
clientPackageName, int
clientUid, //
Container for an IProCameraUser object out
BinderHolder device); int
connectDevice(ICameraDeviceCallbacks callbacks, int
cameraId, String
clientPackageName, int
clientUid, //
Container for an ICameraDeviceUser object out
BinderHolder device); int
addListener(ICameraServiceListener listener); int
removeListener(ICameraServiceListener listener); int
getCameraCharacteristics( int
cameraId, out CameraMetadataNative info); } |
3.Camera2Client消失,CameraDeviceClient出世
CameraDeviceClient可以說是替代了原先API1.0下升級後的Camera2Client,此外在API2.0下是不允許Camera HAL Module 版本號爲CAMERA_DEVICE_API_VERSION_1_0的,至於選擇使用的是Camera2Device還是Camera3Device來連接HAL3主要通過HAL的CAMERA_DEVICE_API_VERSION來指定。此外HAL中的VERSION必須要在CAMERA_DEVICE_API_VERSION_2_0以上才允許建立CameraDeviceClient。
4. Native消失了的各種Stream創建者
在之前的博文中,一直都在重點強調Camera2Client下出現了各種,目前看來這些只能停留在API1.0的世界裏面了,隨着時間的推移Android版本的升級也許會慢慢的消逝,也就直接告訴我們HAL1.0的CameraHardwareInterface的實現方式將不復存在,當然一切還得取決於廠商的實現方式。
在這裏要重點說明的是在Camera2Client下出現了CallbackProcessor、FrameProcessor、StreamingProcessor等模塊,每個模塊負責處理不同的業務以及相關底層視頻圖像數據的處理與回調,其中對於數據的處理通過建立CPUConsumer與Surface的架構,更多的是以一種Consumer的角度實現對Buffer的queue與dequeue相關的操作,最終實現Camera3Device標準下的處理邏輯。
而在API2中在Framework層中,這些模塊將不再被使用,代替他們的是在Android5.0中的Java層中出現的各種Consumer,類似與Preview模式下的SurfaceFlinger在Java層中的surfaceview,這種模式是通過建立不同類型的Consumer,然後在Native層建立一個BufferQueue,並將這個BufferQueue的IGraphicBufferConsumer用於構建CPUConsumer,將IGraphicBufferProducer通過createStream給CameraDevice增加一個Stream。
當然本質上看起來兩者實現方式的機制是一樣的,都是需要create一個Stream,然後Stream需要對應的ANativeWindow類型的Surface,用於從HAL3中獲取數據,一旦獲取數據後和這個Surface綁定的Consumer就可以通過OnFrameAvailable()來接收處理buffer。下面的接口說明了在API2下對於不同數據處理模塊只需要get一個Surface後通過AIDL實現方式就可以創建一個stream接口,用於數據的接收。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
status_t
CameraDeviceClient::createStream( int
width, int
height, int
format, const
sp<igraphicbufferproducer>& bufferProducer) { ATRACE_CALL(); ALOGV(%s
(w = %d, h = %d, f = 0x%x), __FUNCTION__, width, height, format); status_t
res; if
( (res = checkPid(__FUNCTION__) ) != OK) return
res; Mutex::Autolock
icl(mBinderSerializationLock); if
(bufferProducer == NULL) { ALOGE(%s:
bufferProducer must not be null ,
__FUNCTION__); return
BAD_VALUE; } if
(!mDevice.get()) return
DEAD_OBJECT; //
Don't create multiple streams for the same target surface { ssize_t
index = mStreamMap.indexOfKey(bufferProducer->asBinder()); if
(index != NAME_NOT_FOUND) { ALOGW(%s:
Camera %d: Buffer producer already has a stream for
it (ID
%zd), __FUNCTION__,
mCameraId, index); return
ALREADY_EXISTS; } } ............. int32_t
disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT; int32_t
allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK | GraphicBuffer::USAGE_HW_TEXTURE
| GraphicBuffer::USAGE_HW_COMPOSER; bool
flexibleConsumer = (consumerUsage & disallowedFlags) == 0
&& (consumerUsage
& allowedFlags) != 0 ; sp<ibinder>
binder; sp
anw; if
(bufferProducer != 0 )
{ binder
= bufferProducer->asBinder(); anw
= new
Surface(bufferProducer, useAsync); //創新一個本地的surface,用於Product } //
TODO: remove w,h,f since we are ignoring them .......... res
= mDevice->createStream(anw, width, height, format, &streamId); //創建stream return
res; } </anativewindow></ibinder></igraphicbufferproducer> |
在API2.0下可以看到在Android Java層中提供了不同的Module來處理不同的視頻圖像數據,這個過程是很類似與Camera2Client下的各種Processor模塊的,只是後者是將數據處理打包後再返回到APP中,而前者是直接由Java層的不同模塊來異步的響應並直接處理不同類型數據流的到來,如PREVIEW、RRCORD、STILL_CAPTURE、VIDEO_SNAPSHOT、ZERO_SHUTTER_LAG等不同模式的數據流將由MediaRecoder、SurfaceView、ImageReader等來直接處理,總體來說效率會更佳。
5. FrameProcessorBase依然存在 該類在舊版本中被FrameProcessor用來處理3A相關的信息,主要是Callback每一幀的ExtraResult到APP,也就是3A相關的數據信息。這也是在API1和API2中唯一都需要手動CallBack的模塊,其餘的數據流都是被上述提到的模塊自動處理,其中實現的方式如2小節(3)所描述,其中採用ICameraDeviceCallbacks將每一視頻幀數據回傳:
1
2
3
4
5
6
7
8
9
10
11
|
interface
ICameraDeviceCallbacks { /** *
Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h */ oneway
void
onCameraError( int
errorCode); oneway
void
onCameraIdle(); oneway
void
onCaptureStarted( int
requestId, long
timestamp); oneway
void
onResultReceived( int
requestId, in CameraMetadataNative result); } |
6 小結,整個API2下Camera3的架構簡圖