Android的Camera架構介紹[有圖]

來源:互聯網
上載者:User

【Android 開發人員】

第一部分 Camera概述

Android的Camera包含取景器(viewfinder)和拍攝照片的功能。目前Android發布版的Camera程式雖然功能比較簡單,但是其程式的架構分成用戶端和伺服器兩個部分,它們建立在Android的進程間通訊Binder的結構上。
以開源的Android為例,Camera的代碼主要在以下的目錄中:
Camera的JAVA程式的路徑:
packages/apps/Camera/src/com/android/camera/

在其中Camera.java是主要實現的檔案

Camera的JAVA本地調用部分(JNI):
frameworks/base/core/jni/android_hardware_Camera.cpp
這部分內容編譯成為目標是libandroid_runtime.so。

主要的標頭檔在以下的目錄中:
frameworks/base/include/ui/

Camera底層庫在以下的目錄中:
frameworks/base/libs/ui/
這部分的內容被編譯成庫libui.so。

Camera服務部分:
frameworks/base/camera/libcameraservice/
這部分內容被編譯成庫libcameraservice.so。

為了實現一個具體功能的Camera,在最底層還需要一個硬體相關的Camera庫(例如通過調用video for linux驅動程式和Jpeg編碼程式實現)。這個庫將被Camera的服務庫libcameraservice.so調用。

第二部分 Camera的介面與架構

2.1 Camera的整體架構圖
Camera的各個庫之間的結構可以用的表示:


在 Camera系統的各個庫中,libui.so位於核心的位置,它對上層的提供的介面主要是Camera類,類 libandroid_runtime.so通過調用Camera類提供對JAVA的介面,並且實現了android.hardware.camera 類。 libcameraservice.so是Camera的伺服器程式,它通過繼承libui.so的類實現伺服器的功能,並且與libui.so中的另外一部分內容則通過進程間通訊(即Binder機制)的方式進行通訊。

libandroid_runtime.so和libui.so兩個庫是公用的,其中除了Camera還有其他方面的功能。
Camera部分的標頭檔在frameworks/base/include/ui/目錄中,這個目錄是和libmedia.so庫源檔案的目錄frameworks/base/libs/ui/相對應的。
Camera主要的標頭檔有以下幾個:
■ICameraClient.h
■Camera.h
■ICamera.h
■ICameraService.h
■CameraHardwareInterface.h

在這些標頭檔Camera.h提供了對上層的介面,而其他的幾個標頭檔都是提供一些介面類(即包含了純虛函數的類),這些介面類必須被實作類別繼承才能夠使用。
整個Camera在啟動並執行時候,可以大致上分成Client和Server兩個部分,它們分別在兩個進程中運行,它們之間使用Binder機制實現進程間通訊。這樣在用戶端調用介面,功能則在伺服器中實現,但是在用戶端中調用就好像直接調用伺服器中的功能,進程間通訊的部分對上層程式不可見.

從架構結構上來看,ICameraService.h、ICameraClient.h和ICamera.h三個類定義了MeidaPlayer的介面和架構,ICameraService.cpp和Camera.cpp兩個檔案用於Camera架構的實現,Camera的具體功能在下層調用硬體相關的介面來實現。

從Camera的整體結構上,類Camera是整個系統核心,ICamera類提供了Camera主要功能的介面,在用戶端方面調用,CameraService是Camera服務,它通過調用實際的Camera硬體介面來實現功能。事實上,圖中紅色虛線框的部分都是Camera程式的架構部分,它主要利用了Android的系統的Binder機制來完成通訊。藍色的部分通過調用Camera硬體相關的介面完成具體的Camera服務功能,其它的部分是為上層的JAVA程式提供JNI介面。在整體結構上,左邊可以視為一個用戶端,右邊是一個可以視為伺服器,二者通過Android的
Binder來實現進程間的通訊。

2.2 標頭檔ICameraClient.h
ICameraClient.h用於描述一個Camera用戶端的介面,定義如下所示:
class ICameraClient: public IInterface
{
public:
DECLARE_META_INTERFACE(CameraClient);
virtual void shutterCallback() = 0;
virtual void rawCallback(const sp& picture) = 0;
virtual void jpegCallback(const sp& picture) = 0;
virtual void frameCallback(const sp& frame) = 0;
virtual void errorCallback(status_t error) = 0;
virtual void autoFocusCallback(bool focused) = 0;
};
class BnCameraClient: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
2.3 標頭檔Camera.h

Camera.h是Camera對外的介面標頭檔,它被實現Camera JNI的檔案android_hardware_Camera.cpp所調用。Camera.h最主要是定義了一個Camera類:

class Camera : public BnCameraClient, public IBinder::DeathRecipient
{
public:
static sp connect();
~Camera();
void disconnect();
status_t getStatus() { return mStatus; }
status_t setPreviewDisplay(const sp& surface);
status_t startPreview();
void stopPreview();
status_t autoFocus();
status_t takePicture();
status_t setParameters(const String8& params);
String8 getParameters() const;
void setShutterCallback(shutter_callback cb, void *cookie);
void setRawCallback(frame_callback cb, void *cookie);
void setJpegCallback(frame_callback cb, void *cookie);
void setFrameCallback(frame_callback cb, void *cookie);
void setErrorCallback(error_callback cb, void *cookie);
void setAutoFocusCallback(autofocus_callback cb, void *cookie);
// ICameraClient interface
virtual void shutterCallback();
virtual void rawCallback(const sp& picture);
virtual void jpegCallback(const sp& picture);
virtual void frameCallback(const sp& frame);
virtual void errorCallback(status_t error);
virtual void autoFocusCallback(bool focused);
//……
}
從介面中可以看出Camera類剛好實現了一個Camera的基本操作,例如播放(startPreview)、停止(stopPreview)、暫停(takePicture)等。在Camera類中connect()是一個靜態函數,它用於得到一個Camera的執行個體。在這個類中,具有設定回呼函數的幾個函數:setShutterCallback、setRawCallback和setJpegCallback等,這幾個函數是為了提供給上層使用,上層利用這幾個設定回呼函數,這些回呼函數在相應的回呼函數中調用,例如使用setShutterCallback設定的回呼函數指標被shutterCallback所調用。
在定義中,Camera類雙繼承了BnCameraClient和IBinder:DeathRecipient,BnCameraClient 繼承了BnInterface,這是為基於Android的基礎類Binder機制實現在進程通訊而構建的。事實上,根據BnInterface類模版的定義Interface類相當於雙繼承了ICameraClient和BBinder。這是Android一種常用的定義方式。
Camera類繼承了DeathNotifier類之後,這樣當這個類作為IBinder使用的時候,當這個Binder即將Died的時候被調用其中的binderDied函數。繼承這個類基本上實現了一個回呼函數的功能。

2.4 標頭檔ICamera.h
ICamera.h描述的內容是一個實現Camera功能的介面,其定義如下所示

class ICamera: public IInterface
{
public:
DECLARE_META_INTERFACE(Camera);
virtual void disconnect() = 0;
virtual status_t setPreviewDisplay(const sp& surface) = 0;
virtual void setHasFrameCallback(bool installed) = 0;
virtual status_t startPreview() = 0;
virtual void stopPreview() = 0;
virtual status_t autoFocus() = 0;
virtual status_t takePicture() = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual String8 getParameters() const = 0;
};
class BnCamera: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在Camera類中,主要定義Camera的功能介面,這個類必須被繼承才能夠使用。值得注意的是,這些介面和Camera類的介面有些類似,但是它們並沒有直接的關係。事實上,在Camera類的各種實現中,一般都會通過調用ICamera類的實作類別來完成。

 

2.5 標頭檔ICameraService .h
ICameraService.h用於描述一個Camera的服務,定義方式如下所示:
class ICameraService : public IInterface
{
public:
    DECLARE_META_INTERFACE(CameraService);
    virtual sp     connect(const sp& cameraClient) = 0;
};
class BnCameraService: public BnInterface
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

    由於具有純虛函數, ICameraService 以及BnCameraService必須被繼承實現才能夠使用,在ICameraService 只定義了一個connect()介面,它的傳回值的類型是sp,這個ICamera 是提供實現功能的介面。注意,ICameraService只有串連函數connect(),沒有斷開函數,斷開的功能由ICamera介面來提供。

2.6 標頭檔CameraHardwareInterface.h
CameraHardwareInterface.h定義的是一個Camera底層的介面,這個類的實現者是最終實現Camera的。
CameraHardwareInterface 定以Camera硬體的介面,如下所示:
class CameraHardwareInterface : public virtual RefBase {
public:
virtual ~CameraHardwareInterface() { }
virtual sp getPreviewHeap() const = 0;
virtual status_t startPreview(preview_callback cb, void* user) = 0;
virtual void stopPreview() = 0;
virtual status_t autoFocus(autofocus_callback,void* user) = 0;
virtual status_t takePicture(shutter_callback,raw_callback,jpeg_callback,void* user) = 0;
virtual status_t cancelPicture(bool cancel_shutter,bool cancel_raw,bool cancel_jpeg) = 0;
virtual status_t setParameters(const CameraParameters& params) = 0;
virtual CameraParameters getParameters() const = 0;
virtual void release() = 0;
virtual status_t dump(int fd, const Vector& args) const = 0;
};

使用C語言的方式匯出符號:
extern "C" sp openCameraHardware();

在程式的其他地方,使用openCameraHardware()就可以得到一個 CameraHardwareInterface,然後調用 CameraHardwareInterface的介面完成Camera的功能。

第三部分 Camera的主要實現分析

3.1 JAVA程式部分
   在packages/apps/Camera/src/com/android/camera/
目錄的Camera.java檔案中,包含了對Camera的調用
在Camera.java中包含對包的引用:
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;

    在這裡定義的Camera類繼承了活動Activity類,在它的內部,包含了一個 android.hardware.Camera
public class Camera extends Activity implements View.OnClickListener, SurfaceHolder.Callback {
         android.hardware.Camera mCameraDevice;
}

對Camera功能的一些調用如下所示:
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
mCameraDevice.startPreview();
mCameraDevice.stopPreview();

startPreview、stopPreview 和takePicture等介面就是通過JAVA本地調用(JNI)來實現的。

frameworks/base/core/java/android/hardware/目錄中的Camera.java檔案提供了一個JAVA類:Camera。
public class Camera {
}
public void setParameters(Parameters params) {
Log.e(TAG, "setParameters()");
//params.dump();
native_setParameters(params.flatten());
}

    在這個類當中,大部分代碼使用JNI調用下層得到,例如:

    再者,例如以下代碼:
    public final void setPreviewDisplay(SurfaceHolder holder) {
        setPreviewDisplay(holder.getSurface());
    }
    private native final void setPreviewDisplay(Surface surface);

    兩個setPreviewDisplay參數不同,後一個是本地方法,參數為Surface類型,前一個通過調用後一個實現,但自己的參數以SurfaceHolder為類型。

3.2 Camera的JAVA本地調用部分
    Camera的JAVA本地調用(JNI)部分在frameworks/base/core/jni/目錄的android_hardware_Camera.cpp中的檔案中實現。
    android_hardware_Camera.cpp之中定義了一個JNINativeMethod(JAVA本地調用方法)類型的數組gMethods,如下所示:
static JNINativeMethod camMethods[] = {
{"native_setup","(Ljava/lang/Object;)V",(void*)android_hardware_Camera_native_setup },
  {"native_release","()V",(void*)android_hardware_Camera_release },
  {"setPreviewDisplay","(Landroid/view/Surface;)V",(void *)android_hardware_Camera_setPreviewDisplay },
  {"startPreview","()V",(void *)android_hardware_Camera_startPreview },
  {"stopPreview", "()V", (void *)android_hardware_Camera_stopPreview },
  {"setHasPreviewCallback","(Z)V",(void *)android_hardware_Camera_setHasPreviewCallback },
  {"native_autoFocus","()V",(void *)android_hardware_Camera_autoFocus },
  {"native_takePicture", "()V", (void *)android_hardware_Camera_takePicture },
  {"native_setParameters","(Ljava/lang/String;)V",(void *)android_hardware_Camera_setParameters },
  {"native_getParameters", "()Ljava/lang/String;",(void*)android_hardware_Camera_getParameters }
};

    JNINativeMethod的第一個成員是一個字串,表示了JAVA本地調用方法的名稱,這個名稱是在JAVA程式中調用的名稱;第二個成員也是一個字串,表示JAVA本地調用方法的參數和傳回值;第三個成員是JAVA本地調用方法對應的C語言函數。
    register_android_hardware_Camera 函數將gMethods註冊為的類"android/media/Camera",其主要的實現如下所示。
int register_android_hardware_Camera(JNIEnv *env)
{
    // Register native functions
    return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",
                                              camMethods, NELEM(camMethods));
}

    "android/hardware/Camera"對應JAVA的類android.hardware.Camera。

3.3 Camera本地庫libui.so
frameworks/base/libs/ui/中的Camera.cpp檔案用於實現Camera.h提供的介面,其中一個重要的片段如下所示

  • const sp& Camera::getCameraService()
  • {
  • Mutex::Autolock _l(mLock);
  • if (mCameraService.get() == 0) {
  • sp sm = defaultServiceManager();
  • sp binder;
  • do {
  • binder = sm->getService(String16("media.camera"));
  • if (binder != 0)
  • break;
  • LOGW("CameraService not published, waiting...");
  • usleep(500000); // 0.5 s
  • } while(true);
  • if (mDeathNotifier == NULL) {
  • mDeathNotifier = new DeathNotifier();
  • }
  • binder->linkToDeath(mDeathNotifier);
  • mCameraService = interface_cast(binder);
  • }
  • LOGE_IF(mCameraService==0, "no CameraService!?");
  • return mCameraService;
  • }

其中最重要的一點是binder = sm->getService(String16("media.camera"));;這個調用用來得到一個名稱為"media.camera" 的服務,這個調用傳回值的類型為IBinder,根據實現將其轉換成類型ICameraService使用。
一個函數 connect的實現 如下所示:

  • sp Camera::connect()
  • {
  • sp c = new Camera();
  • const sp& cs = getCameraService();
  • if (cs != 0) {
  • c->mCamera = cs->connect(c);
  • }
  • if (c->mCamera != 0) {
  • c->mCamera->asBinder()->linkToDeath(c);
  • c->mStatus = NO_ERROR;
  • }
  • return c;
  • }

connect通過調用getCameraService得到一個 ICameraService,再通過 ICameraService的cs->connect(c)得到一個 ICamera類型的指標。 調用connect將得到一個 Camera的指標,正常情況下Camera的成員 mCamera已經初始化完成。
一個具體的函數startPreview 如下所示:

  • status_t Camera::startPreview()
  • {
  • return mCamera->startPreview();
  • }


這些操作可以直接對 mCamera來進行,它是ICamera類型的指標。
其他一些函數的實現也與setDataSource類似。
libmedia.so中的其他一些檔案與標頭檔的名稱相同,它們是:
frameworks/base/libs/ui/ICameraClient.cpp
frameworks/base/libs/ui/ICamera.cpp
frameworks/base/libs/ui/ICameraService.cpp
在此處,BnCameraClient和BnCameraService類雖然實現了onTransact()函數,但是由於還有純虛函數沒有實現,因此這個類都是不能執行個體化的。
ICameraClient.cpp中的BnCameraClient在別的地方也沒有實現;而ICameraService.cpp中的BnCameraService類在別的地方被繼承並實現,繼承者實現了Camera服務的具體功能

3.4 Camera服務libcameraservice.so

frameworks/base/camera/libcameraservice/ 用於實現一個Camera的服務,這個服務是繼承ICameraService的具體實現。
在這裡的Android.mk檔案中,使用宏USE_CAMERA_STUB決定是否使用真的Camera,如果宏為真,則使用 CameraHardwareStub.cpp和FakeCamera.cpp構造一個假的Camera,如果為假則使用 CameraService.cpp構造一個實際上的Camera服務。
CameraService.cpp是繼承BnCameraService 的實現,在這個類的內部又定義了類Client,CameraService::Client繼承了BnCamera。在運作的過程中 CameraService::connect()函數用於得到一個CameraService::Client,在使用過程中,主要是通過調用這個類的介面來實現完成Camera的功能,由於CameraService::Client本身繼承了BnCamera類,而BnCamera類是繼承了 ICamera,因此這個類是可以被當成ICamera來使用的。
CameraService和CameraService::Client兩個類的結果如下所示:

  • class CameraService : public BnCameraService
  • {
  • class Client : public BnCamera {};
  • wpmClient;
  • }


在CameraService中的一個靜態函數instantiate()用於初始化一個Camera服務,寒暑如下所示:

  • void CameraService::instantiate() {
  • defaultServiceManager()->addService(
  • String16("media.camera"), new CameraService());
  • }


事實上,CameraService::instantiate()這個函數註冊了一個名稱為"media.camera"的服務,這個服務和Camera.cpp中調用的名稱相對應。
Camera整個運作機制是:在Camera.cpp中可以調用ICameraService的介面,這時實際上調用的是 BpCameraService,而BpCameraService又通過Binder機制和BnCameraService實現兩個進程的通訊。而 BpCameraService的實現就是這裡的CameraService。因此,Camera.cpp雖然是在另外一個進程中運行,但是調用 ICameraService的介面就像直接調用一樣,從connect()中可以得到一個ICamera類型的指標,真箇指標的實現實際上是
CameraService::Client。
而這些Camera功能的具體實現,就是CameraService::Client所實現的了,其建構函式如下所示:

  • CameraService::Client::Client(const sp& cameraService,
  • const sp& cameraClient) :
  • mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)
  • {
  • mHardware = openCameraHardware();
  • mHasFrameCallback = false;
  • }


建構函式中,調用openCameraHardware()得到一個CameraHardwareInterface類型的指標,並作為其成員mHardware。以後對實際的Camera的操作都通過對這個指標進行。這是一個簡單的直接調用關係。
事實上,真正的Camera功能己通過實現CameraHardwareInterface類來完成。在這個庫當中 CameraHardwareStub.h和CameraHardwareStub.cpp兩個檔案定義了一個樁模組的介面,在沒有Camera硬體的情況下使用,例如在模擬器的情況下使用的檔案就是CameraHardwareStub.cpp和它依賴的檔案FakeCamera.cpp。
CameraHardwareStub類的結構如下所示:

  • class CameraHardwareStub : public CameraHardwareInterface {
  • class PreviewThread : public Thread {
  • };
  • };

在類CameraHardwareStub當中,包含一個線程類PreviewThread,這個線程用於處理 PreView,即負責重新整理取景器的內容。實際的Camera硬體介面通常可以通過對v4l2 捕獲驅動的調用來實現,同時還需要一個JPEG編碼程式將從驅動中取出的資料編碼成JPEG檔案。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.