rv1108-evb-v12 sdk的视频拍照的流程

以下是rv1108-evb-v12  SDK中的视频拍照的代码流程梳理:

当飞机接收到地面段发送的拍照指令后,回调函数tcp_func_take_photo开始执行。


tcp_func_take_photo主要实现两部分的功能:

首先通过struct photo_param *photo_param = parameter_get_photo_param();获取地面端用户设置的拍照的参数:包括是否连续拍照,以及如果连续牌照,连续拍摄的次数。

1.检查sd卡是否异常----if(access("/mnt/sdcard", W_OK))//判断sd卡是否可写

如果不可写,点用函数hg_api_send_udp_response向地面端发送DRONE_CHECK_SDCARD_EXCEPTION命令,并return -1结束回调。

可写的情况下调用函数hg_api_getSdSizeInfo(&u32SdTotalMBytes, &u32SdFreeMBytes);获取当前sd卡的总的容量的大小,以及剩余的容量大小。如果剩余的容量大小小于100bytes,就通过hg_api_send_udp_response向地面端发送TF_STORAGE_SPACE_NOT_ENOUGH_FAIL的命令,并return -1结束回调。   

2.通过上一步的操作,sd检测完毕,接下来就可以执行拍照的流程

通过if (0 == photo_param->photo_mode)查看拍照参数以确定用户拍照是连续拍照还是单次牌照。如果 photo_param->photo_mode为0,就是单次拍照,在拍照函数video_record_takephoto(1);参数为1,如果是多次拍照,就将video_record_takephoto(photo_param->continuous_photo_num);就用户设置的连续拍照的次数作为参数传递。

tcp_func_take_photo
    hg_api_getSdSizeInfo(&u32SdTotalMBytes, &u32SdFreeMBytes);//获取当前设备的总的sdcard的大小和剩余的sdcard的大小。如果剩余的sdcard的大小小于100bytes,就会结束回调。并向地面端发送TF_STORAGE_SPACE_NOT_ENOUGH_FAIL的指令
    video_record_takephoto(1);//拍照的具体实现。

接下来分析video_record_takephoto函数:

这个函数在app/video/process/video.cpp中实现的extern "C" int video_record_takephoto(unsigned int num),由于实在cpp文件中实现的,在前面加上了extern "C"使用c编译器编译。

这个函数的主要实现功能:

1.通过getfastvideo();获取video的链表头。

2.遍历链表中的所有节点

将本次拍照需要拍摄的次数,做一个设置。

3.如果回调函数rec_event_call不为空,则执行毁掉函数(*rec_event_call)(CMD_PHOTOEND, (void *)0, (void *)1);

回调函数rec_event_call的具体的定义实在同一个文件video.cpp中:static void (*rec_event_call)(int cmd, void *msg0, void *msg1);这个函数指针的赋值是在同一文件video.cpp中:

extern "C" int REC_RegEventCallback(void (*call)(int cmd, void *msg0, void *msg1))
{
    rec_event_call = call;
    return 0;
}

通过上面对tcp_func_take_photovideo_record_takephoto的分析大概知道了当地面断用户发送拍照指令后,飞机端回调的执行情况,但是对拍照文件的保存 命名和传输还没有设计到。接下来分析上述的REC_RegEventCallback也就是回调函数的注册是在代码的那个地方。

在文件app/video/public_interface.c中有对REC_RegEventCallback(record_event_callback);的调用。注册的回调函数record_event_callback:

void record_event_callback(int cmd, void *msg0, void *msg1)
{
    switch (cmd) {
    case CMD_UPDATETIME:
        api_send_msg(MSG_VIDEO_UPDATETIME, TYPE_BROADCAST, msg0, NULL);
        break;
        break;
    case CMD_PHOTOEND:
        api_send_msg(MSG_VIDEO_PHOTO_END, TYPE_BROADCAST, msg0, msg1);
        break;
    }
}

根据上面回调函数(*rec_event_call)(CMD_PHOTOEND, (void *)0, (void *)1);执行的参数来看本次回调的执行是api_send_msg(MSG_VIDEO_PHOTO_END, TYPE_BROADCAST, msg0, msg1);继续跟进:

void api_send_msg(int id, int type, void *msg0, void *msg1)
{
    struct public_message msgdata;

    msgdata.id = id;
    msgdata.type = type;
    dispatch_msg(&msgdata, msg0, msg1);
}

从函数的具体实现可以发现里面主要调用了dispatch_msg(&msgdata, msg0, msg1);函数,这个函数就是轮讯链表,并且执行链表中的节点成员函数指针指向的函数。所以接下来就是要分析,链表中的节点成员函数指针是在哪里赋值注册的。

void dispatch_msg(void *msg, void *prama0, void *param1)
{
    struct type_node *p = g_listHead;

    if (!p) {
        printf("list is NULL \n");
        return;
    }
    do {
        if (p->callback)
            p->callback(msg, prama0, param1);
        p = p->next;
    } while (p);
}

上面讨论到了链表中的成员函数指针的执行,下面分析链表中的函数指针的赋值,也就是回调函数的注册。

与函数dispatch_msg在同一个文件msg_list_manager.c中的appendList(struct type_node *l, fun_cb cb)就是对链表中的回调函数的注册,所以接下来找到调用appendList(struct type_node *l, fun_cb cb)函数的地方。

struct type_node *reg_entry(fun_cb cb)
{
    return appendList(g_listHead, cb);
}

接着查找调用reg_entry(fun_cb cb)地方:

通过搜索发现有两个地方调用了这个函数,分别是:

1.app/video/public_interface.c 中的函数api_poweron_init(fun_cb cb)的参数,也就是调用这个函数的camera_ui.c中的ui_msg_manager_cb函数。

2.app/video/wifi_setting_interface.c中的reg_msg_manager_cb注册的回调函数是wifi_msg_manager_cb函数。


下面具体分析,当地面端的用户点击拍照后,飞机上具体执行的是上面哪一个回调。

猜你喜欢

转载自blog.csdn.net/u010299133/article/details/84671660
今日推荐