日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

android?camera框架分析與移植

 昵稱7324690 2012-08-25

android camera框架分析與移植

(2011-08-12 23:47:52)
標(biāo)簽:

雜談

分類: Android

俗話說(shuō):知己知彼,百戰(zhàn)不殆,想要移植camera硬件,需要了解android中camera的框架思想和調(diào)用流程,才能事半功倍。

 

(1)       Android中camera編程思路:

     Camera類介紹:

常用接口,這些接口是camera編程時(shí)作為框架層回調(diào)時(shí)候使用:

 

android <wbr>camera框架分析與移植

常用方法,這些方法作為camera應(yīng)用編程時(shí)使用的API

   android <wbr>camera框架分析與移植

 

在應(yīng)用層的編程上常用流程為:

預(yù)覽: 

    mCamera = Camera.open();

Camera.Parameters p = mCamera.getParameters();

  p.setPreviewSize(w, h);

  mCamera.setParameters(p);
 

SurfaceView  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);

  SurfaceHolder  holder = mSurfaceView.getHolder();

  holder.addCallback(this);

  mCamera.setPreviewDisplay(holder);

  mCamera.startPreview();

 

當(dāng)我們打開攝像頭應(yīng)用的時(shí)候首先是預(yù)覽的功能,預(yù)覽就是將攝像頭拍攝下的景物實(shí)時(shí)的呈現(xiàn)出來(lái),在android應(yīng)用中能夠顯示給用戶交互的類都是繼承自view類,我們需要給camera預(yù)覽顯示時(shí)提供一個(gè)畫布一樣的東西,這里我們使用surfaceview類,為什么不直接使用view類呢?關(guān)于view顯示的框架我將在以后的博文中給大家分析,這里使用surfaceview類作為camera的顯示,可以使camera框架層得到一個(gè)可以控制顯示框架的代理,使用這個(gè)代理可以將camera獲取的幀數(shù)據(jù)發(fā)送到顯示框架去合成顯示,如果我們?cè)O(shè)置了預(yù)覽回調(diào):

android <wbr>camera框架分析與移植

也可以在回調(diào)中將每一幀的數(shù)據(jù)保存起來(lái)形成錄像的功能


拍照:
    mCamera.takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)

拍照本身調(diào)用就需要設(shè)置回調(diào)函數(shù),回調(diào)函數(shù)中可以設(shè)置幾種回調(diào)方式,這幾種都是拍照時(shí)框架層提供給應(yīng)用層數(shù)據(jù),有原始數(shù)據(jù),有jpeg數(shù)據(jù),這幾種都是拍攝下來(lái)的數(shù)據(jù)的不同儲(chǔ)存方式,供我們?cè)趹?yīng)用層處理使用。

 

小結(jié):在應(yīng)用層上我們可以了解到什么?

預(yù)覽和拍照都可以通過(guò)回調(diào)的方式獲取框架層的數(shù)據(jù),當(dāng)然預(yù)覽也可以不需要把框架層的數(shù)據(jù)獲取,直接發(fā)給顯示框架去顯示。

 

(2)       現(xiàn)在我們要開始分析camera類代碼了解調(diào)用細(xì)節(jié):

 

 

Camera.java (frameworks\base\core\java\android\hardware)     

public static Camera open() {

        return new Camera(); //構(gòu)造camera

    }

 

    Camera() {

        mShutterCallback = null;

        mRawImageCallback = null;

        mJpegCallback = null;

        mPreviewCallback = null;

        mPostviewCallback = null;

        mZoomCallback = null;

 

        Looper looper;

        if ((looper = Looper.myLooper()) != null) { //創(chuàng)建Handler,處理本地的通知事件

            mEventHandler = new EventHandler(this, looper);

        } else if ((looper = Looper.getMainLooper()) != null) {

            mEventHandler = new EventHandler(this, looper);

        } else {

            mEventHandler = null;

        }

 

        native_setup(new WeakReference<Camera>(this)); //調(diào)用本地方法,完成初始化

    }

 

    private native final void native_setup(Object camera_this);

   

WeakReference 類的作用:如果想觀察一個(gè)類什么時(shí)候被垃圾回收清除,我們使用WeakReference類來(lái)定義,當(dāng)Camera類的引用為null是,可以通過(guò)WeakReferenceget方法獲取此類的信息,了解此類是否被垃圾回收

 

EventHandler調(diào)用流程;

 

 

android <wbr>camera框架分析與移植

 

 

(1)        private native final void native_setup(Object camera_this);

(2)        private native final void native_setParameters(String params);

(3)        private native final String native_getParameters();

(4)        private native final void setPreviewDisplay(Surface surface);

(5)        public native final void startPreview();

 

camera中我們發(fā)現(xiàn)應(yīng)用層代碼調(diào)用中都調(diào)用了本地(native)方法

 

 

 

android <wbr>camera框架分析與移植



 

 

 

Camera在應(yīng)用層做了重要的兩件是,初始化一個(gè)EventHandler,等待本地消息通知,調(diào)用本地方法進(jìn)入jni層代碼空間,在這里jni的調(diào)用方向有兩種:

1):java調(diào)用C/C++代碼,將用戶功能性的代碼放到jni層處理

2):C/C++代碼調(diào)用java層代碼,將框架層的消息傳遞給應(yīng)用層處理

 

(2) Camera jni層代碼:

android_hardware_Camera.cpp (frameworks\base\core\jni)      

 

int register_android_hardware_Camera(JNIEnv *env)

{

    field fields_to_find[] = {

        { "android/hardware/Camera", "mNativeContext",   "I", &fields.context },

        { "android/view/Surface",    "mSurface",         "I", &fields.surface }

    };

 

 

//初始化fields_t結(jié)構(gòu)體context,surface

    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)        return -1;

 

    jclass clazz = env->FindClass("android/hardware/Camera");

//初始化fields_t結(jié)構(gòu)體post_event

    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",

                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");

    if (fields.post_event == NULL) {

        LOGE("Can't find android/hardware/Camera.postEventFromNative");

        return -1;

    }

 

 

    // Register native functions 注冊(cè)本地函數(shù)列表

    return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",

                                              camMethods, NELEM(camMethods));

}

 

int register_android_hardware_Camera方法是首先調(diào)用的方法,作用是將java層的變量域和方法域存在jni層,jni層調(diào)用java層的成員變量和成員方法都要依賴域:

struct fields_t {

    jfieldID    context;// mNativeContext

    jfieldID    surface;// mSurface

    jmethodID   post_event;// postEventFromNative

};

 

 

AndroidRuntime::registerNativeMethods 方法主要是將本地函數(shù)注冊(cè)給虛擬機(jī),java層可以通過(guò)虛擬機(jī)調(diào)用這些方法

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 },

  { "previewEnabled",

    "()Z",

    (void *)android_hardware_Camera_previewEnabled },

  { "setHasPreviewCallback",

    "(ZZ)V",

    (void *)android_hardware_Camera_setHasPreviewCallback },

  { "addCallbackBuffer",

    "([B)V",

    (void *)android_hardware_Camera_addCallbackBuffer },

  { "native_autoFocus",

    "()V",

    (void *)android_hardware_Camera_autoFocus },

  { "native_cancelAutoFocus",

    "()V",

    (void *)android_hardware_Camera_cancelAutoFocus },

  { "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 },

  { "reconnect",

    "()V",

    (void*)android_hardware_Camera_reconnect },

  { "lock",

    "()V",

    (void*)android_hardware_Camera_lock },

  { "unlock",

    "()V",

    (void*)android_hardware_Camera_unlock },

  { "startSmoothZoom",

    "(I)V",

    (void *)android_hardware_Camera_startSmoothZoom },

  { "stopSmoothZoom",

    "()V",

    (void *)android_hardware_Camera_stopSmoothZoom },

};

 

JNINativeMethod列出java層方法和c/c++層方法的映射表:

 

 

android <wbr>camera框架分析與移植

 

 

1android_hardware_Camera_native_setup方法

 

這個(gè)方法主要作用是建立如圖的聯(lián)系:

 

android <wbr>camera框架分析與移植

 sp<Camera> camera = Camera::connect();//初始化三組proxy/stub聯(lián)系

    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);

    context->incStrong(thiz);

    camera->setListener(context);//初始化mListener

    env->SetIntField(thiz, fields.context, (int)context.get());

 

  

隨后產(chǎn)生server和HAL之間的聯(lián)系:

 

android <wbr>camera框架分析與移植

void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)

{

    LOGV("dataCallback(%d)", msgType);

 

    sp<Client> client = getClientFromCookie(user);

    if (client == 0) {

        return;

    }

 

    sp<ICameraClient> c = client->mCameraClient;

    if (dataPtr == NULL) {

        LOGE("Null data returned in data callback");

        if (c != NULL) {

            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);

            c->dataCallback(msgType, NULL);

        }

        return;

    }

       CAMERA_MSG_SHUTTER

 

    switch (msgType) {

        case CAMERA_MSG_PREVIEW_FRAME:

            client->handlePreviewData(dataPtr);//處理預(yù)覽數(shù)據(jù)函數(shù)

            break;

        case CAMERA_MSG_POSTVIEW_FRAME:

            client->handlePostview(dataPtr);

            break;

        case CAMERA_MSG_RAW_IMAGE: //處理未壓縮照片函數(shù)

            client->handleRawPicture(dataPtr);

            break;

        case CAMERA_MSG_COMPRESSED_IMAGE: //處理壓縮處理的照片函數(shù)

            client->handleCompressedPicture(dataPtr);

            break;

        default:

            if (c != NULL) {

                c->dataCallback(msgType, dataPtr);

            }

            break;

    }

 

#if DEBUG_CLIENT_REFERENCES

    if (client->getStrongCount() == 1) {

        LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");

        client->printRefs();

    }

#endif

}

 

Linux中使用V4L2最為攝像頭驅(qū)動(dòng),V4L2在用戶空間通過(guò)各種ioctl調(diào)用進(jìn)行控制,并且可以使用mmap進(jìn)行內(nèi)存映射

 android <wbr>camera框架分析與移植

 

ioctl函數(shù)命令參數(shù)如下:

 .vidioc_querycap  = vidioc_querycap,  //查詢驅(qū)動(dòng)功能 
 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,  //獲取當(dāng)前驅(qū)動(dòng)支持的視頻格式 
 .vidioc_g_fmt_vid_cap  = vidioc_g_fmt_vid_cap,  //讀取當(dāng)前驅(qū)動(dòng)的頻捕獲格式 
 .vidioc_s_fmt_vid_cap  = vidioc_s_fmt_vid_cap,   //設(shè)置當(dāng)前驅(qū)動(dòng)的頻捕獲格式 
 .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,  //驗(yàn)證當(dāng)前驅(qū)動(dòng)的顯示格式 
 .vidioc_reqbufs   = vidioc_reqbufs,   //分配內(nèi)存 
 .vidioc_querybuf  = vidioc_querybuf,  //把VIDIOC_REQBUFS中分配的數(shù)據(jù)緩存轉(zhuǎn)換成物理地址 
 .vidioc_qbuf   = vidioc_qbuf,  //把數(shù)據(jù)從緩存中讀取出來(lái) 
 .vidioc_dqbuf   = vidioc_dqbuf,   //把數(shù)據(jù)放回緩存隊(duì)列 
 .vidioc_streamon  = vidioc_streamon,  //開始視頻顯示函數(shù) 
 .vidioc_streamoff  = vidioc_streamoff,   //結(jié)束視頻顯示函數(shù) 

 .vidioc_cropcap   = vidioc_cropcap,   //查詢驅(qū)動(dòng)的修剪能力 
 .vidioc_g_crop   = vidioc_g_crop,     //讀取視頻信號(hào)的矩形邊框
 .vidioc_s_crop   = vidioc_s_crop,     //設(shè)置視頻信號(hào)的矩形邊框  .vidioc_querystd  = vidioc_querystd,   //檢查當(dāng)前視頻設(shè)備支持的標(biāo)準(zhǔn),例如PAL或NTSC。 
 .vidioc_default   = vidioc_default,

 

 android <wbr>camera框架分析與移植

 

HAL首先:初始化的時(shí)候進(jìn)行camera基礎(chǔ)參數(shù)的設(shè)置,然后調(diào)用mmap系統(tǒng)調(diào)用將camera驅(qū)動(dòng)層的數(shù)據(jù)隊(duì)列映射到用戶空間,

其次:當(dāng)預(yù)覽方法被調(diào)用的時(shí)候啟動(dòng)預(yù)覽線程,循環(huán)的檢測(cè)隊(duì)列中是否有幀數(shù)據(jù),如果幀數(shù)據(jù)存在,讀取幀數(shù)據(jù),由于讀取的數(shù)據(jù)為YUV格式的數(shù)據(jù),所有要將YUV數(shù)據(jù)轉(zhuǎn)換成RGB的送給顯示框架顯示,也可以將轉(zhuǎn)換過(guò)的數(shù)據(jù)送給視頻編碼模塊,編碼成功后儲(chǔ)存變成錄像的功能,

最后:當(dāng)用戶使用拍照的功能的時(shí)候,拍照線程被調(diào)用(非循環(huán)),檢測(cè)隊(duì)列中的幀數(shù)據(jù),將幀數(shù)據(jù)從隊(duì)列中取出,拍照的數(shù)據(jù)一定需要傳到JAVA層,所有可以將數(shù)據(jù)轉(zhuǎn)換成JPEG格式再上傳,也可以轉(zhuǎn)換成RGB的數(shù)據(jù)上傳給java層

所有上傳的數(shù)據(jù)處理都要經(jīng)過(guò)dataCallback,除非實(shí)現(xiàn)了overlay

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多