Android Camera API2.0下全新的Camera FW/HAL架構簡述
本文均屬自己閱讀原始碼的點滴總結,轉賬請註明出處謝謝。
歡迎和大家交流。qq:1037701636 email:
Software:系統原始碼Android5.1
前沿:
前面博文大多少總結的是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,好處很明顯是響應的速度會更快一些:
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檔案:
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介面,用於資料的接收。
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<ANativeWindow> 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;
}
在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將每一視訊幀資料回傳:
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的架構簡圖