searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

qemu camera简介

2023-09-26 09:58:10
55
0

代码路径

主要代码路径如下:
android/android-emu/android/camera/camera-service.cpp
android/android-emu/android/camera/camera-capture-cloud.cpp
android/android-emu/android/camera/camera-format-converters.c
 

初始化

代码路径:android/android-emu/android/camera/camera-service.cpp
android_camera_service_init
---_camera_service_init  初始化摄像头
---qemud_service_register   在qemu中注册服务名为camera的服务, camera service的descriptor, camera service的连接函数
---_camera_service_connect
 
void android_camera_service_init(void) {
    static int _inited = 0;
    if (!_inited) {
        _camera_service_init(&_camera_service_desc);
        QemudService*  serv = qemud_service_register( SERVICE_NAME, 0,
                &_camera_service_desc,
                _camera_service_connect,
                NULL,
                NULL);
       ....
    }
}
 
_camera_service_init
传进参数:CameraServiceDesc* csd
主要是填充camera service的descriptor CameraServiceDesc相关字段,初始化前后摄像头
--_virtualscenecamera_setup_back
--_virtualscenecamera_setup_front

 

static void _camera_service_init(CameraServiceDesc* csd)
{
    ...
    _virtualscenecamera_setup_back(csd);
    _virtualscenecamera_setup_front(csd);
    ...
}
 
_camera_service_connect
---camera_cloud_device_init  在camera-capture-cloud.cpp中实现
 
---_camera_client_create、qemud_client_new  如果client_param为空,直接调用qemud_client_new在qemu中添加camera factory 客户端,数据接收函数_factory_client_recv。
       否则,根据传进来的client参数,调用_camera_client_create创建摄像头客户端,调用qemud_client_new在qemu中添加此客户端,数据接收函数_camera_client_recv。
 
static QemudClient*
_camera_service_connect(void*          opaque,
                        QemudService*  serv,
                        int            channel,
                        const char*    client_param)
{
    ...  
    #if FIXED_CAMERA_WITH_VIRTUALSCENE == 1
    camera_cloud_device_init();
    #endif
    if (client_param == NULL || *client_param == '\0') {
        /* This is an emulated camera factory client. */
        client = qemud_client_new(serv, channel, client_param, csd,
                                  _factory_client_recv, _factory_client_close,
                                  NULL, NULL);
    } else {
        /* This is an emulated camera client. */
        CameraClient* cc = _camera_client_create(csd, client_param);
        if (cc != NULL) {
            client = qemud_client_new(serv, channel, client_param, cc,
                                      _camera_client_recv, _camera_client_close,
                                      _camera_client_save, _camera_client_load);
        }
    }
 
    return client;
}
 
camera_cloud_device_init
代码路径:android/android-emu/android/camera/camera-capture-cloud.cpp
主要是注册 spice回调摄像头的接口,摄像头插入、摄像头拔出、摄像头数据传输、摄像头信息清除回调函数

 

void camera_cloud_device_init() {
    mCameraIndex = 0;
    mbIsNeedCapture = false;
 
    if (mCamInterface == NULL) {
        printf("[camera] %s %d: new camera instrface\n", __func__, __LINE__);
        mCamInterface = new SpiceCameraInterface();
    }
    mCamInterface->context = NULL;
    mCamInterface->camera_plug = cameraPlugCallback;
    mCamInterface->camera_unplug = cameraUnplugCallback;
    mCamInterface->camera_data = cameraDataCallback;
    mCamInterface->camera_clear = cameraInfoClearCallback;
    RedsState *reds = (RedsState*)spice_server_get();
    spice_server_set_camera_interface(reds, mCamInterface);
}
 
_camera_client_create
---_camera_service_get_camera_info_by_device_name 根据传进来的param的摄像头设备名字,获取摄像头相关信息
---注册摄像头操作函数。这些函数在camera-capture-cloud.cpp中实现
camera_cloud_device_open、camera_cloud_device_close:摄像头打开和关闭
camera_cloud_device_start_capturing、camera_cloud_device_stop_capturing:摄像头开始和停止capturing
camera_cloud_device_read_frame:读取摄像头数据帧的函数
camera_cloud_device_setFlashmode:设置Flashmode的函数
static CameraClient*
_camera_client_create(CameraServiceDesc* csd, const char* param)
{
     
    ci = _camera_service_get_camera_info_by_device_name(csd, cc->device_name);
    if (ci == NULL) {
        E("%s: Cannot find camera info for device '%s'",
          __FUNCTION__, cc->device_name);
        _camera_client_free(cc);
        return NULL;
    }
        cc->open = camera_cloud_device_open;
        cc->start_capturing = camera_cloud_device_start_capturing;
        cc->stop_capturing = camera_cloud_device_stop_capturing;
        cc->read_frame = camera_cloud_device_read_frame;
        cc->close = camera_cloud_device_close;
        cc->setFlashmode = camera_cloud_device_setFlashmode;
 
}
 
 

摄像头数据处理

cameraDataCallback
spice会回调cameraDataCallback,把摄像头的数据传到qemu中
 
static void cameraDataCallback(unsigned char *data, int info_len, void *context) {
    if (mFramebufferData.size() >= info_len) {
        memcpy(&(mFramebufferData[0]), data, info_len);
    }
}
 
_camera_client_recv
主要是调用了camera_client_handle_event
 
static void
_camera_client_recv(void*         opaque,
                    uint8_t*      msg,
                    int           msglen,
                    QemudClient*  client)
{
    CameraClient* cc = (CameraClient*)opaque;
    if (V1) {
        if (!cc->eventHandlerThread.isStarted()) {
            cc->eventHandlerThread.start();
        }
        cc->eventHandlerThread.enqueue({OPERATION, msg, msglen, client});
    } else {
        camera_client_handle_event(cc, msg, msglen, client);
    }
}
 
camera_client_handle_event
根据摄像头client的请求事件,调用不同函数进行处理,其中_camera_client_query_frame就是处理摄像头的数据帧
 
static void
camera_client_handle_event(CameraClient*  cc,
                            uint8_t*       msg,
                            int            msglen,
                            QemudClient*   client) {
  
    ...
    /* Dispatch the query to an appropriate handler. */
    if (!strcmp(query_name, _query_frame)) {
        /* A frame is queried. */
        if (V1) {
            _camera_client_query_frame_v1(cc, client, query_param);
        } else {
            _camera_client_query_frame(cc, client, query_param);
        }
    } else if (!strcmp(query_name, _query_connect)) {
        /* Camera connection is queried. */
        _camera_client_query_connect(cc, client, query_param);
    } else if (!strcmp(query_name, _query_disconnect)) {
        /* Camera disnection is queried. */
        _camera_client_query_disconnect(cc, client, query_param);
    } else if (!strcmp(query_name, _query_start)) {
        /* Start capturing is queried. */
        if (V1) {
            _camera_client_query_start_v1(cc, client, query_param);
        } else {
            _camera_client_query_start(cc, client, query_param);
        }
    } else if (!strcmp(query_name, _query_stop)) {
        /* Stop capturing is queried. */
        _camera_client_query_stop(cc, client, query_param);
    }else if(!strcmp(query_name,_query_flash)) {
    printf("%s: Camera client query: '%s'", __FUNCTION__, (char*)msg);
    _camera_client_query_flash(cc, client, query_param);
    } else {
        E("%s: Unknown query '%s'", __FUNCTION__, (char*)msg);
        _qemu_client_reply_ko(client, "Unknown query");
    }
}
 
_camera_client_query_frame
主要是调用cc->read_frame,也就是camera_cloud_device_read_frame
 
static void
_camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
{
    ...
    repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
                            exp_comp);
    ...
}
 
camera_cloud_device_read_frame
主要是调用convert_frame对摄像头数据进行处理。
 
int camera_cloud_device_read_frame(CameraDevice* ccd,
                             ClientFrame* result_frame,
                             float r_scale,
                             float g_scale,
                             float b_scale,
                             float exp_comp) {
    ...
    // Convert frame to the receiving buffers.
    res = convert_frame(mFramebufferData.data(), CLOUD_CAMERA_PIXEL_FORMAT,
                         mFramebufferData.size(), mFramebufferWidth,
                         mFramebufferHeight, result_frame, r_scale, g_scale,
                         b_scale, exp_comp);
    ...
}
 
convert_frame
代码路径:android/android-emu/android/camera/camera-format-converters.c
在这个函数,我们可以调用libyuv库的相关接口对摄像头数据旋转、放大缩小、填黑边等操作
 
0条评论
0 / 1000
黄****养
3文章数
0粉丝数
黄****养
3 文章 | 0 粉丝
黄****养
3文章数
0粉丝数
黄****养
3 文章 | 0 粉丝
原创

qemu camera简介

2023-09-26 09:58:10
55
0

代码路径

主要代码路径如下:
android/android-emu/android/camera/camera-service.cpp
android/android-emu/android/camera/camera-capture-cloud.cpp
android/android-emu/android/camera/camera-format-converters.c
 

初始化

代码路径:android/android-emu/android/camera/camera-service.cpp
android_camera_service_init
---_camera_service_init  初始化摄像头
---qemud_service_register   在qemu中注册服务名为camera的服务, camera service的descriptor, camera service的连接函数
---_camera_service_connect
 
void android_camera_service_init(void) {
    static int _inited = 0;
    if (!_inited) {
        _camera_service_init(&_camera_service_desc);
        QemudService*  serv = qemud_service_register( SERVICE_NAME, 0,
                &_camera_service_desc,
                _camera_service_connect,
                NULL,
                NULL);
       ....
    }
}
 
_camera_service_init
传进参数:CameraServiceDesc* csd
主要是填充camera service的descriptor CameraServiceDesc相关字段,初始化前后摄像头
--_virtualscenecamera_setup_back
--_virtualscenecamera_setup_front

 

static void _camera_service_init(CameraServiceDesc* csd)
{
    ...
    _virtualscenecamera_setup_back(csd);
    _virtualscenecamera_setup_front(csd);
    ...
}
 
_camera_service_connect
---camera_cloud_device_init  在camera-capture-cloud.cpp中实现
 
---_camera_client_create、qemud_client_new  如果client_param为空,直接调用qemud_client_new在qemu中添加camera factory 客户端,数据接收函数_factory_client_recv。
       否则,根据传进来的client参数,调用_camera_client_create创建摄像头客户端,调用qemud_client_new在qemu中添加此客户端,数据接收函数_camera_client_recv。
 
static QemudClient*
_camera_service_connect(void*          opaque,
                        QemudService*  serv,
                        int            channel,
                        const char*    client_param)
{
    ...  
    #if FIXED_CAMERA_WITH_VIRTUALSCENE == 1
    camera_cloud_device_init();
    #endif
    if (client_param == NULL || *client_param == '\0') {
        /* This is an emulated camera factory client. */
        client = qemud_client_new(serv, channel, client_param, csd,
                                  _factory_client_recv, _factory_client_close,
                                  NULL, NULL);
    } else {
        /* This is an emulated camera client. */
        CameraClient* cc = _camera_client_create(csd, client_param);
        if (cc != NULL) {
            client = qemud_client_new(serv, channel, client_param, cc,
                                      _camera_client_recv, _camera_client_close,
                                      _camera_client_save, _camera_client_load);
        }
    }
 
    return client;
}
 
camera_cloud_device_init
代码路径:android/android-emu/android/camera/camera-capture-cloud.cpp
主要是注册 spice回调摄像头的接口,摄像头插入、摄像头拔出、摄像头数据传输、摄像头信息清除回调函数

 

void camera_cloud_device_init() {
    mCameraIndex = 0;
    mbIsNeedCapture = false;
 
    if (mCamInterface == NULL) {
        printf("[camera] %s %d: new camera instrface\n", __func__, __LINE__);
        mCamInterface = new SpiceCameraInterface();
    }
    mCamInterface->context = NULL;
    mCamInterface->camera_plug = cameraPlugCallback;
    mCamInterface->camera_unplug = cameraUnplugCallback;
    mCamInterface->camera_data = cameraDataCallback;
    mCamInterface->camera_clear = cameraInfoClearCallback;
    RedsState *reds = (RedsState*)spice_server_get();
    spice_server_set_camera_interface(reds, mCamInterface);
}
 
_camera_client_create
---_camera_service_get_camera_info_by_device_name 根据传进来的param的摄像头设备名字,获取摄像头相关信息
---注册摄像头操作函数。这些函数在camera-capture-cloud.cpp中实现
camera_cloud_device_open、camera_cloud_device_close:摄像头打开和关闭
camera_cloud_device_start_capturing、camera_cloud_device_stop_capturing:摄像头开始和停止capturing
camera_cloud_device_read_frame:读取摄像头数据帧的函数
camera_cloud_device_setFlashmode:设置Flashmode的函数
static CameraClient*
_camera_client_create(CameraServiceDesc* csd, const char* param)
{
     
    ci = _camera_service_get_camera_info_by_device_name(csd, cc->device_name);
    if (ci == NULL) {
        E("%s: Cannot find camera info for device '%s'",
          __FUNCTION__, cc->device_name);
        _camera_client_free(cc);
        return NULL;
    }
        cc->open = camera_cloud_device_open;
        cc->start_capturing = camera_cloud_device_start_capturing;
        cc->stop_capturing = camera_cloud_device_stop_capturing;
        cc->read_frame = camera_cloud_device_read_frame;
        cc->close = camera_cloud_device_close;
        cc->setFlashmode = camera_cloud_device_setFlashmode;
 
}
 
 

摄像头数据处理

cameraDataCallback
spice会回调cameraDataCallback,把摄像头的数据传到qemu中
 
static void cameraDataCallback(unsigned char *data, int info_len, void *context) {
    if (mFramebufferData.size() >= info_len) {
        memcpy(&(mFramebufferData[0]), data, info_len);
    }
}
 
_camera_client_recv
主要是调用了camera_client_handle_event
 
static void
_camera_client_recv(void*         opaque,
                    uint8_t*      msg,
                    int           msglen,
                    QemudClient*  client)
{
    CameraClient* cc = (CameraClient*)opaque;
    if (V1) {
        if (!cc->eventHandlerThread.isStarted()) {
            cc->eventHandlerThread.start();
        }
        cc->eventHandlerThread.enqueue({OPERATION, msg, msglen, client});
    } else {
        camera_client_handle_event(cc, msg, msglen, client);
    }
}
 
camera_client_handle_event
根据摄像头client的请求事件,调用不同函数进行处理,其中_camera_client_query_frame就是处理摄像头的数据帧
 
static void
camera_client_handle_event(CameraClient*  cc,
                            uint8_t*       msg,
                            int            msglen,
                            QemudClient*   client) {
  
    ...
    /* Dispatch the query to an appropriate handler. */
    if (!strcmp(query_name, _query_frame)) {
        /* A frame is queried. */
        if (V1) {
            _camera_client_query_frame_v1(cc, client, query_param);
        } else {
            _camera_client_query_frame(cc, client, query_param);
        }
    } else if (!strcmp(query_name, _query_connect)) {
        /* Camera connection is queried. */
        _camera_client_query_connect(cc, client, query_param);
    } else if (!strcmp(query_name, _query_disconnect)) {
        /* Camera disnection is queried. */
        _camera_client_query_disconnect(cc, client, query_param);
    } else if (!strcmp(query_name, _query_start)) {
        /* Start capturing is queried. */
        if (V1) {
            _camera_client_query_start_v1(cc, client, query_param);
        } else {
            _camera_client_query_start(cc, client, query_param);
        }
    } else if (!strcmp(query_name, _query_stop)) {
        /* Stop capturing is queried. */
        _camera_client_query_stop(cc, client, query_param);
    }else if(!strcmp(query_name,_query_flash)) {
    printf("%s: Camera client query: '%s'", __FUNCTION__, (char*)msg);
    _camera_client_query_flash(cc, client, query_param);
    } else {
        E("%s: Unknown query '%s'", __FUNCTION__, (char*)msg);
        _qemu_client_reply_ko(client, "Unknown query");
    }
}
 
_camera_client_query_frame
主要是调用cc->read_frame,也就是camera_cloud_device_read_frame
 
static void
_camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
{
    ...
    repeat = cc->read_frame(cc->camera, &frame, r_scale, g_scale, b_scale,
                            exp_comp);
    ...
}
 
camera_cloud_device_read_frame
主要是调用convert_frame对摄像头数据进行处理。
 
int camera_cloud_device_read_frame(CameraDevice* ccd,
                             ClientFrame* result_frame,
                             float r_scale,
                             float g_scale,
                             float b_scale,
                             float exp_comp) {
    ...
    // Convert frame to the receiving buffers.
    res = convert_frame(mFramebufferData.data(), CLOUD_CAMERA_PIXEL_FORMAT,
                         mFramebufferData.size(), mFramebufferWidth,
                         mFramebufferHeight, result_frame, r_scale, g_scale,
                         b_scale, exp_comp);
    ...
}
 
convert_frame
代码路径:android/android-emu/android/camera/camera-format-converters.c
在这个函数,我们可以调用libyuv库的相关接口对摄像头数据旋转、放大缩小、填黑边等操作
 
文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0