在前面的幾篇筆記中,我已經(jīng)把 Camera 控制流的部分梳理得比較清楚了。在 Camera 流程中,還有一個(gè)重要的部分,即數(shù)據(jù)流。
Camera API 1 中,數(shù)據(jù)流主要是通過(guò)函數(shù)回調(diào)的方式,依照從下往上的方向,逐層 return 到 Applications 中。
由于數(shù)據(jù)流的部分相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,所以我就將其與 Camera 的控制流結(jié)合起來(lái),從 takePicture() 方法切入,追蹤一個(gè)比較完整的 Camera 流程,這個(gè)系列的筆記到這篇也就可以結(jié)束了。
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():
獲取一個(gè) ICamera,調(diào)用其 takePicture 接口。
這里直接用 return 的方式調(diào)用,比較簡(jiǎn)單。
// 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);
}
// 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);}
}
如果要自定義一個(gè)對(duì)數(shù)據(jù)進(jìn)行處理的 C++ 功能庫(kù),并將其加入相機(jī)中,我們可以通過(guò)對(duì) HAL 層進(jìn)行一些修改,將 RAW 圖像流向我們的處理過(guò)程,再將處理后的 RAW 圖像傳回 HAL 層(需要在 HAL 層對(duì) RAW 格式進(jìn)行一些處理才能把圖像上傳),最后通過(guò)正常的回調(diào)流程把圖像傳到頂層應(yīng)用中,就可以實(shí)現(xiàn)我們的自定義功能了。
至此,對(duì)于整個(gè) Camera 的框架,及其運(yùn)作方式,我們就已經(jīng)有了比較清晰的了解了。
在 Android 5.0 版本后,Camera 推出了 Camera API 2,它有著全新的流程(但總體架構(gòu)是不會(huì)有大變化的)。接下來(lái)我會(huì)找空余的時(shí)間去學(xué)習(xí)學(xué)習(xí)這個(gè)新的東西,到時(shí)候再另開(kāi)一系列的學(xué)習(xí)筆記吧。