海思uvc_app源码学习笔记

前言

海思mpp例子里面的uvc_app源码学习笔记。
看了半天,以为是3516读取usb摄像头数据的,结果是实现一个usb摄像头的。可以搞个公对公的usb线测试下。
大概流程是从摄像头获取图像,进行处理或者编码,按照v4l2的标准操作字符设备实现图像的输出。基本思想是一个生产者和消费者的模型,用两个队列做图像缓冲区。

流程

读取配置文件,使用了一个开源的库iniparser库,配置文件格式是ini文件。

    if (create_config_svc("./uvc_app.conf") != 0)
    {
        goto ERR;
    }

UVC全称为USB Video Class,即:USB视频类,UAC全称为USB Audio Class,即:USB音频类。
创建分别用于存放图像或者声音的缓存,实质上是一个链表实现的队列。

    if (create_uvc_cache() != 0)
    {
        goto ERR;
    }
    if (g_uac)
    {
        if (create_uac_cache() != 0)
        {
            goto ERR;
        }
    }

初始化以及运行业务程序。

    if (get_hicamera()->init() != 0 ||
        get_hicamera()->open() != 0 ||
        get_hicamera()->run() != 0)
    {
        goto ERR;
    }

退出时释放资源等等。

hicamera

hicamera结构体可以看作相机或者最顶层方法的封装,包括初始化、打开、关闭、运行等。

static hicamera __hi_camera =
{
    .init = __init,
    .open = __open,
    .close = __close,
    .run = __run,
};

init初始化方法:初始化hiuvc、histream、hiuac、hiaudio。
open打开方法:打开hiuvc、hiaudio。
close关闭方法:关闭hiuvc、histream、hiuac、hiaudio。
run运行方法:启动两个线程运行hiuvc、hiuac。

histream

typedef struct histream
{
    struct stream_control_ops *mpi_sc_ops;
    struct processing_unit_ops *mpi_pu_ops;
    struct input_terminal_ops *mpi_it_ops;
    struct extension_unit_ops *mpi_eu_ops;
    int streaming;
    int exposure_auto_stall;
    int brightness_stall;
} histream;

static struct histream __hi_stream = {
    .mpi_sc_ops = NULL,
    .mpi_pu_ops = NULL,
    .mpi_it_ops = NULL,
    .mpi_eu_ops = NULL,
    .streaming = 0,
    .exposure_auto_stall = 0,
    .brightness_stall = 0,
};

结构体有些复杂,这里是和mpp驱动相关的部分,在sample_venc_config函数中进行注册。

HI_VOID sample_venc_config(HI_VOID)
{
    printf("\n@@@@@ HiUVC App Sample @@@@@\n\n");

    histream_register_mpi_ops(&venc_sc_ops, &venc_pu_ops, &venc_it_ops, HI_NULL);
}
static struct stream_control_ops venc_sc_ops = {
    .init = sample_venc_init,
    .startup = sample_venc_startup,
    .shutdown = sample_venc_shutdown,
    .set_idr = sample_venc_set_idr,
    .set_property = sample_venc_set_property,
};

这里是mpp初始化等等操作,是常规的处理流程。
sample_venc_init mpp初始化:初始化SYS和VB。
sample_venc_startup mpp流媒体开始:VPSS、VENC初始化,使用系统绑定处理图像,可以将原始数据或者编码后的数据放到UVC的队列里面。
sample_venc_shutdown mpp结束:关闭或者停止。

UVC图像节点设置的函数为sample_yuv_dump和__SAMPLE_COMM_VENC_SaveData,前者将YUV数据放入节点中,后者将编码后的数据放入节点中,具体执行哪个函数由一个全局变量__encoder_property控制,可以上位机进行。两个函数都是从free_queue节点中获取空闲图像缓存节点,存放数据放入到ok_queue队列中,是生产者。

static HI_VOID sample_yuv_dump(VIDEO_FRAME_S *pVBuf, FILE *g_pfd)
{
    PIXEL_FORMAT_E enPixelFormat = pVBuf->enPixelFormat;

    uvc_cache_t *uvc_cache = HI_NULL;
    frame_node_t *fnode = HI_NULL;

    sample_yuv_get_buf_size(pVBuf, &g_u32Size);
    g_pUserPageAddr = (HI_CHAR*)HI_MPI_SYS_Mmap(pVBuf->u64PhyAddr[0], g_u32Size);
    if (HI_NULL == g_pUserPageAddr)
    {
        goto ERR;
    }

    //get free cache node
    uvc_cache = uvc_cache_get();
    if (uvc_cache)
    {
        get_node_from_queue(uvc_cache->free_queue, &fnode);
    }

    if (!fnode)
    {
        goto ERR;
    }

    if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == enPixelFormat)
    {
        if (sample_yuv_sp422_to_p422(pVBuf, fnode) != HI_SUCCESS)
        {
            goto ERR;
        }
    }
    else if (PIXEL_FORMAT_YVU_SEMIPLANAR_420 == enPixelFormat)
    {
        sample_yuv_sp420_to_p420(pVBuf, fnode);
    }
    else
    {
    }

ERR:
    if (fnode)
    {
        put_node_to_queue(uvc_cache->ok_queue, fnode);
    }
    if (g_pUserPageAddr)
    {
        HI_MPI_SYS_Munmap(g_pUserPageAddr, g_u32Size);
        g_pUserPageAddr = HI_NULL;
    }
    return;
}

其他操作是一些设置相关的,暂不分析。

hiuvc

hiuvc是对UVC类操作的封装,这里涉及到V4L2的一些知识。

static hiuvc __hi_uvc =
{
    .init = __init,
    .open = __open,
    .close = __close,
    .run = __run,
};

打开方法:打开设备及一些初始化操作。

static int __open()
{
    const char *devpath = "/dev/video0";

    return open_uvc_device(devpath);
}

run运行方法:两个线程以死循环的形式分别跑了run_uvc_data,run_uvc_device函数。
这里需要注意的点是run_uvc_data和run_uvc_device都是使用select在等待前面open的同一个文件描述符,不过一个监听的是可以向其中写入数据,一个监听的是异常情况。
uvc_video_process_userptr是设备文件描述符可写时的处理函数,表示可以将图像视频数据输出,这里使用V4L2_MEMORY_USERPTR用户指针模式,内存由用户进行分配,V4L2_BUF_TYPE_VIDEO_OUTPUT表示视频图像输出。

static int uvc_video_process_userptr(struct uvc_device* dev)
{
    struct v4l2_buffer buf;
    int ret;

    // INFO("#############uvc_video_process_userptr\n");

    memset(&buf, 0, sizeof buf);
    buf.type   = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    buf.memory = V4L2_MEMORY_USERPTR;

    if ((ret = ioctl(dev->fd, VIDIOC_DQBUF, &buf)) < 0)
    {
        return ret;
    }

    uvc_video_fill_buffer_userptr(dev, &buf);

    if ((ret = ioctl(dev->fd, VIDIOC_QBUF, &buf)) < 0)
    {
        LOG("Unable to requeue buffer: %s (%d).\n", strerror(errno), errno);
        return ret;
    }

    return 0;
}

uvc_video_fill_buffer_userptr先获取用于输出图像的缓存,然后从ok_queue队列中取出已经存放好的图像,__waited_node数组指针用于存放上次的图像节点,然后放到free_queue队列中,表示该节点空闲可以再次使用,是消费者。
run_uvc_device运行uvc_events_process函数,主要是对UVC事件的处理函数。

模块分析

把代码大概划分一下模块

模块名作用实现
配置解析模块实现解析配置文件的功能iniparser解析库
缓存模块cache存放图像数据使用单向循环链表实现的队列
V4L2图像数据输出输出图像到上位机V4L2框架

总结

  1. iniparser库的使用
  2. UVC&UAC 总结
  3. 浅析 Hi MPP 中的 uvc_app
  4. V4l2视频输出实现流程
  5. uevent机制:uevent原理分析
  6. 多进程/线程select同一文件问题
  7. V4L2视频采集的基本流程
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 海思IVE_SVP_IVS开发手册.zip是一本关于海思芯片相关开发的手册。海思是华为公司的芯片子公司,致力于推动人工智能与云计算技术在各行业的应用。IVE(Intelligent Video Engine)是其推出的一种高性能、低功耗、高效率的视频处理引擎。SVP(Smart Video Platform)是基于IVE开发的一种智能视频处理平台。IVS(Intelligent Video Surveillance)则是海思针对视频监控行业推出的一种解决方案。 海思IVE_SVP_IVS开发手册为开发者提供了详细的技术规格和应用案例,让其更好地理解和应用IVE、SVP和IVS技术。手册中包含了海思芯片的硬件架构、软件架构、接口介绍、软件开发环境的设置和使用方法等内容。此外,手册还介绍了IVE、SVP和IVS的常见应用场景,如人脸识别、车辆识别、行为分析等。 总之,海思IVE_SVP_IVS开发手册.zip是一本非常有价值的技术手册,对于研究和开发基于海思芯片的视频处理技术的人员来说具有很大的帮助。无论是从理论知识方面,还是从技术应用方面,它都将使开发者更加熟练地应用IVE、SVP和IVS技术,进一步提升其研发能力和技术水平。 ### 回答2: 海思ive_svp_ivs开发手册.zip是一份关于海思SVP平台上的智能视频分析算法开发的手册。该手册详细介绍了SVP平台的各种算法框架,以及如何使用SVP平台上的工具进行开发和调试。手册中包含了很多实用的示例和代码,可以帮助开发人员快速掌握SVP平台上的开发技巧。 此外,该手册也提供了一些使用建议,包括如何进行代码管理、测试和调试、代码优化等方面。这些内容对于开发人员们在开发中会遇到许多问题,提供了一些建议和指导。手册还详细说明了SVP平台上的优势和应用场景,这可以让开发人员更好地理解SVP平台的特点和优势,并为实际应用场景做出相应的开发和调试更好地。 总的来说,海思ive_svp_ivs开发手册.zip是一份非常有价值的开发指南,它不仅提供了相关的开发工具和示例代码,还提供了许多实用的应用建议和优化技巧,非常适合SVP平台上开发智能视频分析算法的开发人员使用。 ### 回答3: 海思ive_svp_ivs开发手册.zip是一份开发手册,专为海思公司旗下的IVE(SVP)智能视频引擎及IVS(智能视频分析)服务而设计的。使用这份手册,开发人员可以掌握IVE和IVS系列产品的开发流程以及使用方法。该手册除了介绍IVE和IVS的理论知识外,还提供了具体的开发指导和实例代码,从而有助于开发人员快速准确地实现相关功能。 该手册主要分为以下几个部分:首先是IVE和IVS的基础知识介绍,包括相关术语解释、工作原理、功能分类等。其次是IVE和IVS的安装与配置,包括软件和硬件环境的配置、IVE SDK的安装等。接着是IVE和IVS的开发指南,包括IVS算法开发指南、IVE应用开发指南等。最后是附录部分,包含了相关技术规范、开发示例、API参考文档等。 综上所述,海思ive_svp_ivs开发手册.zip是一份非常实用的开发指南,对于想要开发和应用IVE和IVS产品的开发人员来说非常有用。通过阅读手册中的内容,开发人员可以更好地理解和掌握IVE和IVS的工作原理,有助于提升开发效率和开发质量,同时也能够推动智能视频领域的发展和创新。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值