• Android4.4 Camera callback注册和回调过程分析


    一、注册过程

    camera的callback是在cameraclient中的initialize接口中注册的,而这个接口是由上层初始化调用的。

    1. status_t CameraClient::initialize(camera_module_t *module) {
    2. int callingPid = getCallingPid();
    3. status_t res;
    4. LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
    5. // Verify ops permissions
    6. res = startCameraOps();
    7. if (res != OK) {
    8. return res;
    9. }
    10. char camera_device_name[10];
    11. snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
    12. mHardware = new CameraHardwareInterface(camera_device_name);
    13. res = mHardware->initialize(&module->common);
    14. if (res != OK) {
    15. ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
    16. __FUNCTION__, mCameraId, strerror(-res), res);
    17. mHardware.clear();
    18. return NO_INIT;
    19. }
    20. mHardware->setCallbacks(notifyCallback,
    21. dataCallback,
    22. dataCallbackTimestamp,
    23. (void *)mCameraId);
    24. // Enable zoom, error, focus, and metadata messages by default
    25. enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
    26. CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
    27. LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    28. return OK;
    29. }
    • 1

    res = mHardware->initialize(&module->common);
    调用接口头文件作为和HAL通信的桥梁,其实就是一层接口封装:
    CameraHardwareInterface.h

    1. status_t initialize(hw_module_t *module)
    2. {
    3. ALOGI("Opening camera %s", mName.string());
    4. int rc = module->methods->open(module, mName.string(),
    5. (hw_device_t **)&mDevice);
    6. if (rc != OK) {
    7. ALOGE("Could not open camera %s: %d", mName.string(), rc);
    8. return rc;
    9. }
    10. initHalPreviewWindow();
    11. return rc;
    12. }
    • 1

    在这边调用open函数打开camera。这边的open在HAL已经注册。

    1. static int camera_device_open(const hw_module_t* module, const char* name,
    2. hw_device_t** device);
    3. static struct hw_module_methods_t camera_module_methods = {
    4. open: camera_device_open
    5. };
    • 1

    所以当上层传的id 也就是open的第一个参数module能够与cameraHAL匹配,就会调用到cameraHAL层的接口:camera_device_open

    而这个函数camera_device_open 起着关键的作用,初始化注册camera相关的接口,让HAL层的接口与Framework层CamaraClient 的接口一一对应。

    1. int camera_device_open(const hw_module_t* module, const char* name,
    2. hw_device_t** device)
    3. {
    4. int rv = 0;
    5. int cameraid;
    6. rk_camera_device_t* camera_device = NULL;
    7. camera_device_ops_t* camera_ops = NULL;
    8. android::CameraHal* camera = NULL;
    9. android::Mutex::Autolock lock(gCameraHalDeviceLock);
    10. LOGI("camera_device open : name = %s", name);
    11. if (name != NULL) {
    12. cameraid = atoi(name);
    13. if(cameraid > gCamerasNumber) {
    14. LOGE("camera service provided cameraid out of bounds, "
    15. "cameraid = %d, num supported = %d",
    16. cameraid, gCamerasNumber);
    17. rv = -EINVAL;
    18. goto fail;
    19. }
    20. if(gCamerasOpen >= CAMERAS_SUPPORTED_SIMUL_MAX) {
    21. LOGE("maximum number(%d) of cameras already open",gCamerasOpen);
    22. rv = -ENOMEM;
    23. goto fail;
    24. }
    25. camera_device = (rk_camera_device_t*)malloc(sizeof(*camera_device));
    26. if(!camera_device) {
    27. LOGE("camera_device allocation fail");
    28. rv = -ENOMEM;
    29. goto fail;
    30. }
    31. camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
    32. if(!camera_ops) {
    33. LOGE("camera_ops allocation fail");
    34. rv = -ENOMEM;
    35. goto fail;
    36. }
    37. memset(camera_device, 0, sizeof(*camera_device));
    38. memset(camera_ops, 0, sizeof(*camera_ops));
    39. camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
    40. camera_device->base.common.version = 0;
    41. camera_device->base.common.module = (hw_module_t *)(module);
    42. camera_device->base.common.close = camera_device_close;
    43. camera_device->base.ops = camera_ops;
    44. camera_ops->set_preview_window = camera_set_preview_window;
    45. camera_ops->set_callbacks = camera_set_callbacks;
    46. camera_ops->enable_msg_type = camera_enable_msg_type;
    47. camera_ops->disable_msg_type = camera_disable_msg_type;
    48. camera_ops->msg_type_enabled = camera_msg_type_enabled;
    49. camera_ops->start_preview = camera_start_preview;
    50. camera_ops->stop_preview = camera_stop_preview;
    51. camera_ops->preview_enabled = camera_preview_enabled;
    52. camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
    53. camera_ops->start_recording = camera_start_recording;
    54. camera_ops->stop_recording = camera_stop_recording;
    55. camera_ops->recording_enabled = camera_recording_enabled;
    56. camera_ops->release_recording_frame = camera_release_recording_frame;
    57. camera_ops->auto_focus = camera_auto_focus;
    58. camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
    59. camera_ops->take_picture = camera_take_picture;
    60. camera_ops->cancel_picture = camera_cancel_picture;
    61. camera_ops->set_parameters = camera_set_parameters;
    62. camera_ops->get_parameters = camera_get_parameters;
    63. camera_ops->put_parameters = camera_put_parameters;
    64. camera_ops->send_command = camera_send_command;
    65. camera_ops->release = camera_release;
    66. camera_ops->dump = camera_dump;
    67. *device = &camera_device->base.common;
    68. // -------- RockChip specific stuff --------
    69. camera_device->cameraid = cameraid;
    70. camera = new android::CameraHal(cameraid);
    71. if(!camera) {
    72. LOGE("Couldn't create instance of CameraHal class");
    73. rv = -ENOMEM;
    74. goto fail;
    75. }
    76. gCameraHals[cameraid] = camera;
    77. gCamerasOpen++;
    78. }
    79. return rv;
    80. fail:
    81. if(camera_device) {
    82. free(camera_device);
    83. camera_device = NULL;
    84. }
    85. if(camera_ops) {
    86. free(camera_ops);
    87. camera_ops = NULL;
    88. }
    89. if(camera) {
    90. delete camera;
    91. camera = NULL;
    92. }
    93. *device = NULL;
    94. return rv;
    95. }
    • 1

    这个open的操作也把CameraHal类初始化了,一系列线程都起来处于loop状态了。

    这里继续看 CameraClient的initialize

    1. status_t CameraClient::initialize(camera_module_t *module) {
    2. int callingPid = getCallingPid();
    3. status_t res;
    4. LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
    5. // Verify ops permissions
    6. res = startCameraOps();
    7. if (res != OK) {
    8. return res;
    9. }
    10. char camera_device_name[10];
    11. snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
    12. mHardware = new CameraHardwareInterface(camera_device_name);
    13. res = mHardware->initialize(&module->common);
    14. if (res != OK) {
    15. ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
    16. __FUNCTION__, mCameraId, strerror(-res), res);
    17. mHardware.clear();
    18. return NO_INIT;
    19. }
    20. mHardware->setCallbacks(notifyCallback,
    21. dataCallback,
    22. dataCallbackTimestamp,
    23. (void *)mCameraId);
    24. // Enable zoom, error, focus, and metadata messages by default
    25. enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
    26. CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
    27. LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    28. return OK;
    29. }
    • 1

    callback的注册也是在这边初始化的时候就注册好了:

    1. mHardware->setCallbacks(notifyCallback,
    2. dataCallback,
    3. dataCallbackTimestamp,
    4. (void *)mCameraId);
    • 1

    对应下层也在接口层文件里:

    1. void setCallbacks(notify_callback notify_cb,
    2. data_callback data_cb,
    3. data_callback_timestamp data_cb_timestamp,
    4. void* user)
    5. {
    6. mNotifyCb = notify_cb;
    7. mDataCb = data_cb;
    8. mDataCbTimestamp = data_cb_timestamp;
    9. mCbUser = user;
    10. ALOGV("%s(%s)", __FUNCTION__, mName.string());
    11. if (mDevice->ops->set_callbacks) {
    12. mDevice->ops->set_callbacks(mDevice,
    13. __notify_cb,
    14. __data_cb,
    15. __data_cb_timestamp,
    16. __get_memory,
    17. this);
    18. }
    19. }
    • 1

    主要的内容是把上层传下来的值进行赋值到本地变量中,另外最终要的就是判断set_callbacks这个接口是否被初始化,这个接口在open camera的时候就被初始化了:

    camera_ops->set_callbacks = camera_set_callbacks;

    这里 mDevice->ops->set_callbacks和camera_ops->set_callbacks指的是同一个结构体里面的接口。认真留意一下,这边的封装setcallbacks加了一个函数指针__get_memory,他的实现也是在这个文件里CameraHardwareInterfece.h里面。这里留意一下即可,会关系到后面camera的内存申请过程。记住这个回调是在这里注册的即可。
    接下来就是真正的注册callback:

    1. static void __data_cb(int32_t msg_type,
    2. const camera_memory_t *data, unsigned int index,
    3. camera_frame_metadata_t *metadata,
    4. void *user)
    5. {
    6. ALOGV("%s", __FUNCTION__);
    7. CameraHardwareInterface *__this =
    8. static_cast<CameraHardwareInterface *>(user);
    9. sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
    10. if (index >= mem->mNumBufs) {
    11. ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
    12. index, mem->mNumBufs);
    13. return;
    14. }
    15. __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
    16. }
    • 1

    发现他的原理就是把刚才存到本地的callback接口包装了一下,不过这里大有文章,底层callback的数据类型是camera_memory_t,在这一层被转换成mem->mBuffers[index]类型也就是IMemory的类型跟在CameraClient类中的callback 参数类型一致,可以理解为适配吧。

    这边的操作是把data->handle这个句柄用c++里面的强制转换成CameraHeapMemory类这边在另外一篇文章会详细说明camera的整体数据流方向和内存管理方式。

    到这里camera 初始化完成。

    继续看camerahal层setcallbacks的实现:

    1. void CameraHal::setCallbacks(camera_notify_callback notify_cb,
    2. camera_data_callback data_cb,
    3. camera_data_timestamp_callback data_cb_timestamp,
    4. camera_request_memory get_memory,
    5. void *user)
    6. {
    7. LOG_FUNCTION_NAME
    8. Mutex::Autolock lock(mLock);
    9. mEventNotifier->setCallbacks(notify_cb, data_cb,data_cb_timestamp,get_memory,user);
    10. LOG_FUNCTION_NAME_EXIT
    11. }
    • 1

    会调用到:

    1. void AppMsgNotifier::setCallbacks(camera_notify_callback notify_cb,
    2. camera_data_callback data_cb,
    3. camera_data_timestamp_callback data_cb_timestamp,
    4. camera_request_memory get_memory,
    5. void *user)
    6. {
    7. LOG_FUNCTION_NAME
    8. mNotifyCb = notify_cb;
    9. mDataCb = data_cb;
    10. mDataCbTimestamp = data_cb_timestamp;
    11. mRequestMemory = get_memory;
    12. mCallbackCookie = user;
    13. LOG_FUNCTION_NAME_EXIT
    14. }
    • 1

    到这里成功注册到hal层里的函数指针上。留意这个初始化:
    mRequestMemory = get_memory;这是申请memmory的过程。

    二、回调过程

    这是注册过程,反过来看一下回调过程:

    mDataCb(CAMERA_MSG_PREVIEW_FRAME, tmpPreviewMemory, 0,NULL,mCallbackCookie);
    • 1

    上面是camerahal层的回调调用。会调到cameraclient层的datacallback不过中间有一个隐式的转换过程:
    他先回回调到camerahardwareinterface中的callback:

    1. static void __data_cb(int32_t msg_type,
    2. const camera_memory_t *data, unsigned int index,
    3. camera_frame_metadata_t *metadata,
    4. void *user)
    5. {
    6. ALOGV("%s", __FUNCTION__);
    7. CameraHardwareInterface *__this =
    8. static_cast<CameraHardwareInterface *>(user);
    9. sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
    10. if (index >= mem->mNumBufs) {
    11. ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
    12. index, mem->mNumBufs);
    13. return;
    14. }
    15. __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
    16. }
    • 1

    上面的代码把hal层camera_memory_t类型的数据转换成CameraHeapMemory的类型,最后回调到上层的是IMemory类型的mem->mBuffers[index];接下来是回调到cameraclient的dataCallback:

    1. void CameraClient::dataCallback(int32_t msgType,
    2. const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
    3. LOG2("dataCallback(%d)", msgType);
    4. Mutex* lock = getClientLockFromCookie(user);
    5. if (lock == NULL) return;
    6. Mutex::Autolock alock(*lock);
    7. CameraClient* client =
    8. static_cast<CameraClient*>(getClientFromCookie(user));
    9. if (client == NULL) return;
    10. if (!client->lockIfMessageWanted(msgType)) return;
    11. if (dataPtr == 0 && metadata == NULL) {
    12. ALOGE("Null data returned in data callback");
    13. client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
    14. return;
    15. }
    16. switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
    17. case CAMERA_MSG_PREVIEW_FRAME:
    18. client->handlePreviewData(msgType, dataPtr, metadata);
    19. break;
    20. case CAMERA_MSG_POSTVIEW_FRAME:
    21. client->handlePostview(dataPtr);
    22. break;
    23. case CAMERA_MSG_RAW_IMAGE:
    24. client->handleRawPicture(dataPtr);
    25. break;
    26. case CAMERA_MSG_COMPRESSED_IMAGE:
    27. client->handleCompressedPicture(dataPtr);
    28. break;
    29. default:
    30. client->handleGenericData(msgType, dataPtr, metadata);
    31. break;
    32. }
    33. }
    • 1

    最开始client对象的获取要考虑到安全性:源代码中是这么解释的。
    // Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
    be acquired for this to be safe

    这里会继续调用到:

    1. case CAMERA_MSG_PREVIEW_FRAME:
    2. client->handlePreviewData(msgType, dataPtr, metadata);
    • 1

    具体实现:

    1. void CameraClient::handlePreviewData(int32_t msgType,
    2. const sp<IMemory>& mem,
    3. camera_frame_metadata_t *metadata) {
    4. ssize_t offset;
    5. size_t size;
    6. sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
    7. // local copy of the callback flags
    8. int flags = mPreviewCallbackFlag;
    9. // is callback enabled?
    10. if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
    11. // If the enable bit is off, the copy-out and one-shot bits are ignored
    12. LOG2("frame callback is disabled");
    13. mLock.unlock();
    14. return;
    15. }
    16. // hold a strong pointer to the client
    17. sp<ICameraClient> c = mRemoteCallback;
    18. // clear callback flags if no client or one-shot mode
    19. if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
    20. LOG2("Disable preview callback");
    21. mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
    22. CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
    23. CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
    24. disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
    25. }
    26. if (c != 0) {
    27. // Is the received frame copied out or not?
    28. if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
    29. LOG2("frame is copied");
    30. copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
    31. } else {
    32. LOG2("frame is forwarded");
    33. mLock.unlock();
    34. c->dataCallback(msgType, mem, metadata);
    35. }
    36. } else {
    37. mLock.unlock();
    38. }
    39. }
    • 1

    这里会对data数据进行处理:
    sp heap = mem->getMemory(&offset, &size);

    其实传到上层的一整个过程基本就是拆了再装,装了再拆,具体细节会在camera memory篇章深入分析。

    继续调用datacallback会通过binder机制调用上层的接口。此时的客户端是libcameraservice,服务端是camera client。与callback相关的binder类:
    BpCameraClient,BnCameraClient,ICameraClient
    各自的角色这里就不在赘述。

    此时到上层的BnCameraClient看,

    1. case DATA_CALLBACK: {
    2. ALOGV("DATA_CALLBACK");
    3. CHECK_INTERFACE(ICameraClient, data, reply);
    4. int32_t msgType = data.readInt32();
    5. sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
    6. camera_frame_metadata_t *metadata = NULL;
    7. if (data.dataAvail() > 0) {
    8. metadata = new camera_frame_metadata_t;
    9. metadata->number_of_faces = data.readInt32();
    10. metadata->faces = (camera_face_t *) data.readInplace(
    11. sizeof(camera_face_t) * metadata->number_of_faces);
    12. }
    13. dataCallback(msgType, imageData, metadata);
    14. if (metadata) delete metadata;
    15. return NO_ERROR;
    16. } break;
    • 1

    首先是通过binder端口获取data数据:
    sp imageData = interface_cast(data.readStrongBinder());

    然后调用dataCallback

    在这种CS模式下,上层的Camera继承了BnCameraClient,所以相关的实现都在Camer类中:

    1. // callback from camera service when frame or image is ready
    2. void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
    3. camera_frame_metadata_t *metadata)
    4. {
    5. sp<CameraListener> listener;
    6. {
    7. Mutex::Autolock _l(mLock);
    8. listener = mListener;
    9. }
    10. if (listener != NULL) {
    11. listener->postData(msgType, dataPtr, metadata);
    12. }
    13. }
    • 1

    我们先看下这个监听的实例是在什么时候初始化的,想象一下不难知道应该是在camera初始化的时候:

    1. // connect to camera service
    2. static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    3. jobject weak_this, jint cameraId, jstring clientPackageName)
    4. {
    5. // Convert jstring to String16
    6. const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
    7. jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    8. String16 clientName(rawClientName, rawClientNameLen);
    9. env->ReleaseStringChars(clientPackageName, rawClientName);
    10. sp<Camera> camera = Camera::connect(cameraId, clientName,
    11. Camera::USE_CALLING_UID);
    12. if (camera == NULL) {
    13. jniThrowRuntimeException(env, "Fail to connect to camera service");
    14. return;
    15. }
    16. // make sure camera hardware is alive
    17. if (camera->getStatus() != NO_ERROR) {
    18. jniThrowRuntimeException(env, "Camera initialization failed");
    19. return;
    20. }
    21. jclass clazz = env->GetObjectClass(thiz);
    22. if (clazz == NULL) {
    23. jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
    24. return;
    25. }
    26. // We use a weak reference so the Camera object can be garbage collected.
    27. // The reference is only used as a proxy for callbacks.
    28. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
    29. context->incStrong((void*)android_hardware_Camera_native_setup);
    30. camera->setListener(context);
    31. // save context in opaque field
    32. env->SetIntField(thiz, fields.context, (int)context.get());
    33. }
    • 1

    camera->setListener(context);这个就是把初始化的好的context存到camera类里的成员变量里。

    这里会调到java-c接口文件中接口,在android_hardware_Camera.cpp文件里:
    class JNICameraContext: public CameraListener

    1. void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr,
    2. camera_frame_metadata_t *metadata)
    3. {
    4. // VM pointer will be NULL if object is released
    5. Mutex::Autolock _l(mLock);
    6. JNIEnv *env = AndroidRuntime::getJNIEnv();
    7. if (mCameraJObjectWeak == NULL) {
    8. ALOGW("callback on dead camera object");
    9. return;
    10. }
    11. int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA;
    12. // return data based on callback type
    13. switch (dataMsgType) {
    14. case CAMERA_MSG_VIDEO_FRAME:
    15. // should never happen
    16. break;
    17. // For backward-compatibility purpose, if there is no callback
    18. // buffer for raw image, the callback returns null.
    19. case CAMERA_MSG_RAW_IMAGE:
    20. ALOGV("rawCallback");
    21. if (mRawImageCallbackBuffers.isEmpty()) {
    22. env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
    23. mCameraJObjectWeak, dataMsgType, 0, 0, NULL);
    24. } else {
    25. copyAndPost(env, dataPtr, dataMsgType);
    26. }
    27. break;
    28. // There is no data.
    29. case 0:
    30. break;
    31. default:
    32. ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get());
    33. copyAndPost(env, dataPtr, dataMsgType);
    34. break;
    35. }
    36. // post frame metadata to Java
    37. if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) {
    38. postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata);
    39. }
    40. }
    • 1

    根据回调的类型继续调用copyAndPost(env, dataPtr, dataMsgType);

    1. void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
    2. {
    3. jbyteArray obj = NULL;
    4. // allocate Java byte array and copy data
    5. if (dataPtr != NULL) {
    6. ssize_t offset;
    7. size_t size;
    8. sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
    9. ALOGV("copyAndPost: off=%ld, size=%d", offset, size);
    10. uint8_t *heapBase = (uint8_t*)heap->base();
    11. if (heapBase != NULL) {
    12. const jbyte* data = reinterpret_cast<const jbyte*>(heapBase + offset);
    13. if (msgType == CAMERA_MSG_RAW_IMAGE) {
    14. obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size);
    15. } else if (msgType == CAMERA_MSG_PREVIEW_FRAME && mManualBufferMode) {
    16. obj = getCallbackBuffer(env, &mCallbackBuffers, size);
    17. if (mCallbackBuffers.isEmpty()) {
    18. ALOGV("Out of buffers, clearing callback!");
    19. mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
    20. mManualCameraCallbackSet = false;
    21. if (obj == NULL) {
    22. return;
    23. }
    24. }
    25. } else {
    26. ALOGV("Allocating callback buffer");
    27. obj = env->NewByteArray(size);
    28. }
    29. if (obj == NULL) {
    30. ALOGE("Couldn't allocate byte array for JPEG data");
    31. env->ExceptionClear();
    32. } else {
    33. env->SetByteArrayRegion(obj, 0, size, data);
    34. }
    35. } else {
    36. ALOGE("image heap is NULL");
    37. }
    38. }
    39. // post image data to Java
    40. env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
    41. mCameraJObjectWeak, msgType, 0, 0, obj);
    42. if (obj) {
    43. env->DeleteLocalRef(obj);
    44. }
    45. }
    • 1

    这里就会调用java的接口,把data数据发到java层,java层有一个函数会来接受这个:

    1. @Override
    2. public void handleMessage(Message msg) {
    3. switch(msg.what) {
    4. case CAMERA_MSG_SHUTTER:
    5. if (mShutterCallback != null) {
    6. mShutterCallback.onShutter();
    7. }
    8. return;
    9. case CAMERA_MSG_RAW_IMAGE:
    10. if (mRawImageCallback != null) {
    11. mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
    12. }
    13. return;
    14. case CAMERA_MSG_COMPRESSED_IMAGE:
    15. if (mJpegCallback != null) {
    16. mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
    17. }
    18. return;
    19. case CAMERA_MSG_PREVIEW_FRAME:
    20. PreviewCallback pCb = mPreviewCallback;
    21. if (pCb != null) {
    22. if (mOneShot) {
    23. // Clear the callback variable before the callback
    24. // in case the app calls setPreviewCallback from
    25. // the callback function
    26. mPreviewCallback = null;
    27. } else if (!mWithBuffer) {
    28. // We're faking the camera preview mode to prevent
    29. // the app from being flooded with preview frames.
    30. // Set to oneshot mode again.
    31. setHasPreviewCallback(true, false);
    32. }
    33. pCb.onPreviewFrame((byte[])msg.obj, mCamera);
    34. }
    35. return;
    36. case CAMERA_MSG_POSTVIEW_FRAME:
    37. if (mPostviewCallback != null) {
    38. mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera);
    39. }
    40. return;
    41. case CAMERA_MSG_FOCUS:
    42. AutoFocusCallback cb = null;
    43. synchronized (mAutoFocusCallbackLock) {
    44. cb = mAutoFocusCallback;
    45. }
    46. if (cb != null) {
    47. boolean success = msg.arg1 == 0 ? false : true;
    48. cb.onAutoFocus(success, mCamera);
    49. }
    50. return;
    51. case CAMERA_MSG_ZOOM:
    52. if (mZoomListener != null) {
    53. mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera);
    54. }
    55. return;
    56. case CAMERA_MSG_PREVIEW_METADATA:
    57. if (mFaceListener != null) {
    58. mFaceListener.onFaceDetection((Face[])msg.obj, mCamera);
    59. }
    60. return;
    61. case CAMERA_MSG_ERROR :
    62. Log.e(TAG, "Error " + msg.arg1);
    63. if (mErrorCallback != null) {
    64. mErrorCallback.onError(msg.arg1, mCamera);
    65. }
    66. return;
    67. case CAMERA_MSG_FOCUS_MOVE:
    68. if (mAutoFocusMoveCallback != null) {
    69. mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera);
    70. }
    71. return;
    72. default:
    73. Log.e(TAG, "Unknown message type " + msg.what);
    74. return;
    75. }
    76. }
    77. }
    • 1

    这里调到java层了,就不分析了。

  • 相关阅读:
    新人必看!手把手教你如何使用浏览器表格插件(上)
    opencv图像旋转
    8、docker 安装 nginx
    一款内网信息收集利用工具
    【Linxu工具】:vim使用及简单配置
    『互联网架构』kafka发展历程和安装部署
    基于麒麟服务器V10的.NET部署、运行 + 金仓数据库
    Windows客户端下pycharm配置跳板机连接内网服务器
    C++ 中的 lowbit
    webpack:两小时极速入门
  • 原文地址:https://blog.csdn.net/cqn2bd2b/article/details/126399215