staticvoid android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType)
{ALOGV("takePicture");JNICameraContext* context;sp<Camera> camera = get_native_camera(env, thiz, &context);if (camera == 0) return;/** When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback* buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the* notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY* is enabled to receive the callback notification but no data.** Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the* Java application.*/if (msgType & CAMERA_MSG_RAW_IMAGE) {ALOGV("Enable raw image callback buffer");if (!context->isRawImageCallbackBufferAvailable()) {ALOGV("Enable raw image notification, since no callback buffer exists");msgType &= ~CAMERA_MSG_RAW_IMAGE;msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY;}}if (camera->takePicture(msgType) != NO_ERROR) {jniThrowRuntimeException(env, "takePicture failed");return;}
}
2.3 C/C++ Libraries
2.3.1 Camera.cpp
位置:frameworks/av/camera/Camera.cpp
takePicture():
獲取一個 ICamera,調用其 takePicture 接口。
這里直接用 return 的方式調用,比較簡單。
// take a picture
status_t Camera::takePicture(int msgType)
{ALOGV("takePicture: 0x%x", msgType);sp <::android::hardware::ICamera> c = mCamera;if (c == 0) return NO_INIT;return c->takePicture(msgType);
}
2.3.2 ICamera.cpp
位置:frameworks/av/camera/ICamera.cpp
takePicture():
利用 Binder 機制發送相應指令到服務端。
實際調用到的是 CameraClient::takePicture() 函數。
// take a picture - returns an IMemory (ref-counted mmap)
status_t takePicture(int msgType)
{ALOGV("takePicture: 0x%x", msgType);Parcel data, reply;data.writeInterfaceToken(ICamera::getInterfaceDescriptor());data.writeInt32(msgType);remote()->transact(TAKE_PICTURE, data, &reply);status_t ret = reply.readInt32();return ret;
}
// take a picture - image is returned in callback
status_t CameraClient::takePicture(int msgType) {LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);Mutex::Autolock lock(mLock);status_t result = checkPidAndHardware();if (result != NO_ERROR) return result;if ((msgType & CAMERA_MSG_RAW_IMAGE) &&(msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"" cannot be both enabled");return BAD_VALUE;}// We only accept picture related message types// and ignore other types of messages for takePicture().int picMsgType = msgType& (CAMERA_MSG_SHUTTER |CAMERA_MSG_POSTVIEW_FRAME |CAMERA_MSG_RAW_IMAGE |CAMERA_MSG_RAW_IMAGE_NOTIFY |CAMERA_MSG_COMPRESSED_IMAGE);enableMsgType(picMsgType);return mHardware->takePicture();
}
// callback from camera service when frame or image is readyvoid Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,camera_frame_metadata_t *metadata)
{sp<CameraListener> listener;{Mutex::Autolock _l(mLock);listener = mListener;}if (listener != NULL) {listener->postData(msgType, dataPtr, metadata);}
}
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr,camera_frame_metadata_t *metadata)
{// VM pointer will be NULL if object is releasedMutex::Autolock _l(mLock);JNIEnv *env = AndroidRuntime::getJNIEnv();if (mCameraJObjectWeak == NULL) {ALOGW("callback on dead camera object");return;}int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA;// return data based on callback typeswitch (dataMsgType) {case CAMERA_MSG_VIDEO_FRAME:// should never happenbreak;// For backward-compatibility purpose, if there is no callback// buffer for raw image, the callback returns null.case CAMERA_MSG_RAW_IMAGE:ALOGV("rawCallback");if (mRawImageCallbackBuffers.isEmpty()) {env->CallStaticVoidMethod(mCameraJClass, fields.post_event,mCameraJObjectWeak, dataMsgType, 0, 0, NULL);} else {copyAndPost(env, dataPtr, dataMsgType);}break;// There is no data.case0:break;default:ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get());copyAndPost(env, dataPtr, dataMsgType);break;}// post frame metadata to Javaif (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) {postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata);}
}
如果要自定義一個對數據進行處理的 C++ 功能庫,并將其加入相機中,我們可以通過對 HAL 層進行一些修改,將 RAW 圖像流向我們的處理過程,再將處理后的 RAW 圖像傳回 HAL 層(需要在 HAL 層對 RAW 格式進行一些處理才能把圖像上傳),最后通過正常的回調流程把圖像傳到頂層應用中,就可以實現我們的自定義功能了。
至此,對于整個 Camera 的框架,及其運作方式,我們就已經有了比較清晰的了解了。
在 Android 5.0 版本后,Camera 推出了 Camera API 2,它有著全新的流程(但總體架構是不會有大變化的)。接下來我會找空余的時間去學習學習這個新的東西,到時候再另開一系列的學習筆記吧。