Android系統(tǒng)--Camera API 1

Camera1分析

1.相關(guān)概念介紹

camera 1相關(guān)內(nèi)容 作用
camera.java 進(jìn)行初始化設(shè)置以及調(diào)用jni實(shí)現(xiàn)功能
android_hardware_Camera.cpp 調(diào)用native層代碼獲得底層camera硬件的訪問(wèn)入口

camera.java

  1. 位置: frameworks/base/core/java/android/hardware/Camera.java
  2. 首先不會(huì)去調(diào)用缺省構(gòu)造函數(shù)桐罕,獲取Camera對(duì)象是在Camera.open()獲取的恶座,這個(gè)也是一個(gè)靜態(tài)方法,在這個(gè)方法的基礎(chǔ)上,會(huì)調(diào)用構(gòu)造函數(shù)來(lái)進(jìn)行初始化設(shè)置。
  3. 在這個(gè)類當(dāng)中的主要方法有:
  • public final void setPreviewDisplay(SurfaceHolder holder)
  • public final void takePicture(ShutterCallback shutter, PictureCallback raw,PictureCallback jpeg)
  • public void handleMessage(Message msg)

可以看到在這個(gè)類當(dāng)中,主要涉及

  • 相機(jī)初始化
  • 相機(jī)參數(shù)設(shè)定
  • 相機(jī)處理回調(diào)
  • 相機(jī)調(diào)用JNI(主要目的)
  • 相機(jī)消息處理
Message 解釋
CAMERA_MSG_SHUTTER 處理相機(jī)回調(diào)
CAMERA_MSG_RAW_IMAGE 處理當(dāng)拍照完成且圖片為raw的回調(diào)
CAMERA_MSG_COMPRESSED_IMAGE 處理當(dāng)拍照完成且圖片為JPEG的回調(diào)
CAMERA_MSG_PREVIEW_FRAME 處理獲取預(yù)覽的回調(diào)
CAMERA_MSG_FOCUS 處理獲取聚焦的回調(diào)
  1. 關(guān)于surface:簡(jiǎn)單的說(shuō)Surface對(duì)應(yīng)了一塊屏幕緩沖區(qū),每個(gè)window對(duì)應(yīng)一個(gè)Surface,任何View都要畫(huà)在Surface的Canvas上(后面有原因解釋)椒袍。傳統(tǒng)的view共享一塊屏幕緩沖區(qū),所有的繪制必須在UI線程中進(jìn)行存捺。在SDK的文檔中槐沼,對(duì)Surface的描述是這樣的:“Handle onto a raw buffer that is being managed by the screen compositor”,翻譯成中文就是“由屏幕顯示內(nèi)容合成器(screen compositor)所管理的原始緩沖區(qū)的句柄”捌治,這句話包括下面兩個(gè)意思:

     1岗钩、通過(guò)Surface(因?yàn)镾urface是句柄)就可以獲得原生緩沖器以及其中的內(nèi)容。就像在C++語(yǔ)言中肖油,可以通過(guò)一個(gè)文件的句柄兼吓,就可以獲得文件的內(nèi)容一樣。
     2森枪、原始緩沖區(qū)(a raw buffer)是用于保存當(dāng)前窗口的像素?cái)?shù)據(jù)的视搏。
    

android_hardware_Camera.cpp

  1. 位置:frameworks/base/core/jni/android_hardware_Camera.cpp
  2. 接下來(lái)分析JNI當(dāng)中的幾個(gè)函數(shù):
  • 設(shè)置預(yù)覽顯示方法android_hardware_Camera_setPreviewDisplay()
static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)
{
    LOGV("setPreviewDisplay");
    //強(qiáng)指針指向的Camera审孽,利用native方法來(lái)獲取
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return;

    sp<Surface> surface = NULL;
    if (jSurface != NULL) {
        surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
    }
    //直接調(diào)用底層的方法來(lái)對(duì)Camera設(shè)置預(yù)覽顯示
    if (camera->setPreviewDisplay(surface) != NO_ERROR) {
        jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
    }
}

這個(gè)方法,主要是設(shè)置對(duì)Surface的設(shè)置浑娜,作為一個(gè)Native層的函數(shù)佑力,其對(duì)應(yīng)的camera.java當(dāng)中的方法為:

public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
        if (holder != null) {
            setPreviewDisplay(holder.getSurface());
        } else {
            setPreviewDisplay((Surface)null);
        }
    }

    private native final void setPreviewDisplay(Surface surface);

接下來(lái)繼續(xù)追蹤設(shè)置surface的過(guò)程,可以看到在Native層調(diào)用的一個(gè)方法為:

camera->setPreviewDisplay(surface)

通過(guò)分析可以看到筋遭,這個(gè)的Camera是一個(gè)Camera的類打颤,在這里最終調(diào)用了camera的函數(shù)建芙,進(jìn)入下一步的分析档悠。

Camera.cpp

  1. 位置:/frameworks/base/libs/ui/Camera.cpp
  2. 首先分析camera當(dāng)中的設(shè)置方法:setPreviewDisplay(surface)
status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
{
    LOGV("setPreviewDisplay");
    sp <ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    if (surface != 0) {
        return c->setPreviewDisplay(surface->getISurface());
    } else {
        LOGD("app passed NULL surface");
        return c->setPreviewDisplay(0);
    }
}

可以看到,在這里首先引用一個(gè)ICamera的強(qiáng)指針厅篓,并且進(jìn)一步調(diào)用了以ISurface為參數(shù)的方法响驴,其中的ICamera為一個(gè)接口類透且,是進(jìn)一步與底層進(jìn)行通信的,當(dāng)進(jìn)入Native層之后豁鲤,需要借助BpCamera進(jìn)行轉(zhuǎn)換:
查看進(jìn)一步的BpCamera類秽誊,BpInterface接口類:

status_t setPreviewDisplay(const sp<ISurface>& surface)
    {
        LOGV("setPreviewDisplay");
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        data.writeStrongBinder(surface->asBinder());
        remote()->transact(SET_PREVIEW_DISPLAY, data, &reply);
        return reply.readInt32();
    }

可以看到,這里便是與camera service進(jìn)行通信的代碼畅形,而這里則是通過(guò)Parcel進(jìn)行傳入?yún)?shù)的封裝以及返回的接收养距,最終可以看到诉探,利用remote進(jìn)行的命令傳輸日熬,可以預(yù)想這個(gè)remote是一個(gè)IBinder對(duì)象,這個(gè)命令的傳輸是對(duì)Binder驅(qū)動(dòng)的封裝肾胯,下面的Binder驅(qū)動(dòng)當(dāng)中的open竖席,mmap,ioctl已經(jīng)被封裝了敬肚,只需要最后接收相應(yīng)的以Parcel封裝的返回值即可毕荐。</br>
在這里還想介紹的一點(diǎn)是,在實(shí)現(xiàn)命令時(shí)艳馒,client不需要與驅(qū)動(dòng)直接進(jìn)行通信憎亚,最終還是借助ProcessState以及IPCThreadState來(lái)與底層驅(qū)動(dòng)進(jìn)行通信。

  1. 針對(duì)remote進(jìn)行分析:
  • 首先
BpCamera:public BpInterface<ICamera>
  • 其次
class BpInterface : public INTERFACE, public BpRefBase
{
public:
                                BpInterface(const sp<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

可以看到remote確實(shí)是一個(gè)IBinder類弄慰。

  1. 針對(duì)業(yè)務(wù)碼進(jìn)行分析:
    首先是ICamera當(dāng)中的類型:
enum {
    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
    SET_PREVIEW_DISPLAY,
    SET_PREVIEW_CALLBACK_FLAG,
    START_PREVIEW,
    STOP_PREVIEW,
    AUTO_FOCUS,
    TAKE_PICTURE,
    SET_PARAMETERS,
    GET_PARAMETERS,
    CONNECT,
    LOCK,
    UNLOCK,
    PREVIEW_ENABLED,
    START_RECORDING,
    STOP_RECORDING,
    RECORDING_ENABLED,
    RELEASE_RECORDING_FRAME,
};

進(jìn)一步看IBinder當(dāng)中的業(yè)務(wù)碼對(duì)應(yīng)的是:

/**
     * The first transaction code available for user commands.
     */
    int FIRST_CALL_TRANSACTION  = 0x00000001;
    /**
     * The last transaction code available for user commands.
     */
    int LAST_CALL_TRANSACTION   = 0x00ffffff;

也是相對(duì)應(yīng)的第美。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市陆爽,隨后出現(xiàn)的幾起案子什往,更是在濱河造成了極大的恐慌,老刑警劉巖慌闭,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件别威,死亡現(xiàn)場(chǎng)離奇詭異躯舔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)省古,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)粥庄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人豺妓,你說(shuō)我怎么就攤上這事飒赃。” “怎么了科侈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵载佳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我臀栈,道長(zhǎng)蔫慧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任权薯,我火速辦了婚禮姑躲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盟蚣。我一直安慰自己黍析,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布屎开。 她就那樣靜靜地躺著阐枣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奄抽。 梳的紋絲不亂的頭發(fā)上蔼两,一...
    開(kāi)封第一講書(shū)人閱讀 52,184評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音逞度,去河邊找鬼额划。 笑死,一個(gè)胖子當(dāng)著我的面吹牛档泽,可吹牛的內(nèi)容都是我干的俊戳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼馆匿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抑胎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起甜熔,我...
    開(kāi)封第一講書(shū)人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤圆恤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盆昙,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡羽历,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淡喜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秕磷。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖炼团,靈堂內(nèi)的尸體忽然破棺而出澎嚣,到底是詐尸還是另有隱情,我是刑警寧澤瘟芝,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布易桃,位于F島的核電站,受9級(jí)特大地震影響锌俱,放射性物質(zhì)發(fā)生泄漏晤郑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一贸宏、第九天 我趴在偏房一處隱蔽的房頂上張望造寝。 院中可真熱鬧,春花似錦吭练、人聲如沸诫龙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)签赃。三九已至,卻和暖如春浑侥,著一層夾襖步出監(jiān)牢的瞬間姊舵,已是汗流浹背晰绎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工寓落, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荞下。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓伶选,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尖昏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仰税,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359