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
- 位置: frameworks/base/core/java/android/hardware/Camera.java
- 首先不會(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è)置。
- 在這個(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) |
-
關(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
- 位置:frameworks/base/core/jni/android_hardware_Camera.cpp
- 接下來(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
- 位置:/frameworks/base/libs/ui/Camera.cpp
- 首先分析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)行通信。
- 針對(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類弄慰。
- 針對(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)的第美。