Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Camera API2.0下全新的Camera FW/HAL架構簡述

Android Camera API2.0下全新的Camera FW/HAL架構簡述

編輯:關於Android編程

 

前沿:

前面博文大多少總結的是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& 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 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;
}

在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的架構簡圖
/

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved