当前位置: 首页 > article >正文

Jetson AGX Orin v4l2 cuda 视频解码

Jeston AGX Orin 读取 Gmsl 相机, 基于cuda 实现 解码 rgb 图像进行识别.

在这里插入图片描述

Sample:/usr/src/jetson_multimedia_api/samples/18_v4l2_camera_cuda_rgb/


代码

  • open_device
static void open_device(const char* dev_name)
{
    struct stat st;
    if (-1 == stat(dev_name, &st)) {
        fprintf(stderr, "Cannot identify '%s': %d, %s\n",
            dev_name, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    if (!S_ISCHR(st.st_mode)) {
        fprintf(stderr, "%s is no device\n", dev_name);
        exit(EXIT_FAILURE);
    }

    fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);

    if (-1 == fd) {
        fprintf(stderr, "Cannot open '%s': %d, %s\n",
            dev_name, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
}
  • init_device
static int init_device(const char* dev_name, int width, int height)
{
    struct v4l2_capability cap;
    struct v4l2_cropcap cropcap;
    struct v4l2_crop crop;
    struct v4l2_format fmt;
    unsigned int min;

    if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
        if (EINVAL == errno) {
            fprintf(stderr, "%s is no V4L2 device\n", dev_name);
        }
        return -1;
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        fprintf(stderr, "%s is no video capture device\n",
            dev_name);
        exit(EXIT_FAILURE);
    }

    switch (io) {
    case IO_METHOD_READ:
        if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
            fprintf(stderr, "%s does not support read i/o\n",
                dev_name);
            exit(EXIT_FAILURE);
        }

        break;

    case IO_METHOD_MMAP:
    case IO_METHOD_USERPTR:
        if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
            fprintf(stderr, "%s does not support streaming i/o\n",
                dev_name);
            exit(EXIT_FAILURE);
        }

        break;
    }

    /* Select video input, video standard and tune here. */
    CLEAR(cropcap);

    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c = cropcap.defrect; /* reset to default */

        if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
            switch (errno) {
            case EINVAL:
                /* Cropping not supported. */
                break;
            default:
                /* Errors ignored. */
                break;
            }
        }
    }
    else {
        /* Errors ignored. */
    }


    CLEAR(fmt);

    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = width;
    fmt.fmt.pix.height = height;
    fmt.fmt.pix.pixelformat = pixel_format;
    fmt.fmt.pix.field = field;

    if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
        return -1;

    /* Note VIDIOC_S_FMT may change width and height. */

    /* Buggy driver paranoia. */
    min = fmt.fmt.pix.width * 2;
    if (fmt.fmt.pix.bytesperline < min)
        fmt.fmt.pix.bytesperline = min;
    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
    if (fmt.fmt.pix.sizeimage < min)
        fmt.fmt.pix.sizeimage = min;

    switch (io) {
    case IO_METHOD_READ:
        init_read(fmt.fmt.pix.sizeimage);
        break;

    case IO_METHOD_MMAP:
        init_mmap(dev_name);
        break;

    case IO_METHOD_USERPTR:
        init_userp(dev_name, fmt.fmt.pix.sizeimage);
        break;
    }
    return 0;
}
  • init_cuda
static void init_cuda(int width, int height)
{
    /* Check unified memory support. */
    if (cuda_zero_copy) {
        cudaDeviceProp devProp;
        cudaGetDeviceProperties(&devProp, 0);
        if (!devProp.managedMemory) {
            printf("CUDA device does not support managed memory.\n");
            cuda_zero_copy = false;
        }
    }

    /* Allocate output buffer. */
    size_t size = width * height * 3;
    if (cuda_zero_copy) {
        cudaMallocManaged(&cuda_out_buffer, size, cudaMemAttachGlobal);
    }
    else {
        cuda_out_buffer = (unsigned char*)malloc(size);
    }

    cudaDeviceSynchronize();
}
  • start_capturing
static void start_capturing(void)
{
    unsigned int i;
    enum v4l2_buf_type type;

    switch (io) {
    case IO_METHOD_READ:
        /* Nothing to do. */
        break;

    case IO_METHOD_MMAP:
        for (i = 0; i < n_buffers; ++i) {
            struct v4l2_buffer buf;

            CLEAR(buf);

            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            buf.index = i;

            if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
                errno_exit("VIDIOC_QBUF");
        }

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
            errno_exit("VIDIOC_STREAMON");

        break;

    case IO_METHOD_USERPTR:
        for (i = 0; i < n_buffers; ++i) {
            struct v4l2_buffer buf;

            CLEAR(buf);

            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_USERPTR;
            buf.index = i;
            buf.m.userptr = (unsigned long)buffers[i].start;
            buf.length = buffers[i].length;

            if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
                errno_exit("VIDIOC_QBUF");
        }

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
            errno_exit("VIDIOC_STREAMON");

        break;
    }
}
  • mainloop/read_frame
// 基于cuda,将yuv数据转换rgb. 后续可进行识别等逻辑处理.
static void process_image(void* p, int count)
{
    printf("CUDA format conversion on frame %p\n", p);
    gpuConvertYUYVtoRGB((unsigned char*)p, cuda_out_buffer, width_, height_);

    /* Save image. */
    if (count == 0) {
        cv::Mat img = cv::Mat(height_, width_, CV_8UC3, cuda_out_buffer);
        cv::Mat img_bgr;
        cv::cvtColor(img, img_bgr, cv::COLOR_RGB2BGR);
        cv::imwrite("out.jpg", img_bgr);
    }
}
static int read_frame(int count)
{
    struct v4l2_buffer buf;
    unsigned int i;
    switch (io) {
    case IO_METHOD_READ:
        if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
            switch (errno) {
            case EAGAIN:
                return 0;
            case EIO:
                /* Could ignore EIO, see spec. */
                /* fall through */
            default:
                errno_exit("read");
            }
        }
        process_image(buffers[0].start, count);
        break;

    case IO_METHOD_MMAP:
        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
            switch (errno) {
            case EAGAIN:
                return 0;
            case EIO:
                /* Could ignore EIO, see spec. */
                /* fall through */
            default:
                errno_exit("VIDIOC_DQBUF");
            }
        }

        assert(buf.index < n_buffers);
        process_image(buffers[buf.index].start, count);
        if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
            errno_exit("VIDIOC_QBUF");
        break;
    case IO_METHOD_USERPTR:
        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_USERPTR;
        if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
            switch (errno) {
            case EAGAIN:
                return 0;
            case EIO:
                /* Could ignore EIO, see spec. */
                /* fall through */
            default:
                errno_exit("VIDIOC_DQBUF");
            }
        }
        for (i = 0; i < n_buffers; ++i)
            if (buf.m.userptr == (unsigned long)buffers[i].start
                && buf.length == buffers[i].length)
                break;
        assert(i < n_buffers);
        process_image((void*)buf.m.userptr, count);
        if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
            errno_exit("VIDIOC_QBUF");
        break;
    }
    return 1;
}

static void mainloop(int count)
{
    while (count-- > 0) {
        for (;;) {
            fd_set fds;
            struct timeval tv;
            int r;
            FD_ZERO(&fds);
            FD_SET(fd, &fds);
            /* Timeout. */
            tv.tv_sec = 2;
            tv.tv_usec = 0;
            r = select(fd + 1, &fds, NULL, NULL, &tv);
            if (-1 == r) {
                if (EINTR == errno)
                    continue;
                errno_exit("select");
            }
            if (0 == r) {
                fprintf(stderr, "select timeout\n");
                exit(EXIT_FAILURE);
            }
            if (read_frame(count))
                break;
            /* EAGAIN - continue select loop. */
        }
    }
}

  • stop_capturing
static void stop_capturing(void)
{
    enum v4l2_buf_type type;

    switch (io) {
    case IO_METHOD_READ:
        /* Nothing to do. */
        break;

    case IO_METHOD_MMAP:
    case IO_METHOD_USERPTR:
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
            errno_exit("VIDIOC_STREAMOFF");
        break;
    }
}
  • uninit_device
static void uninit_device(void)
{
    unsigned int i;
    switch (io) {
    case IO_METHOD_READ:
        free(buffers[0].start);
        break;
    case IO_METHOD_MMAP:
        for (i = 0; i < n_buffers; ++i)
            if (-1 == munmap(buffers[i].start, buffers[i].length))
                errno_exit("munmap");
        break;
    case IO_METHOD_USERPTR:
        for (i = 0; i < n_buffers; ++i) {
            if (cuda_zero_copy) {
                cudaFree(buffers[i].start);
            }
            else {
                free(buffers[i].start);
            }
        }
        break;
    }
    free(buffers);
    if (cuda_zero_copy) {
        cudaFree(cuda_out_buffer);
    }
}
  • close_device
static void close_device(void)
{
    if (-1 == close(fd))
        errno_exit("close");
    fd = -1;
}
  • 实现顺序
    • open_device - init_device - init_cuda - start_capturing - mainloop - stop_capturing - uninit_device - close_device
int main(int argc, char const* argv[])
{
    int count = 1000;
    const char* dev = "/dev/video5";
    open_device(dev);
    init_device(dev, 1920, 1080);
    init_cuda(1920, 1080);
    start_capturing();
    mainloop(count);
    stop_capturing();
    uninit_device();
    close_device();
    exit(EXIT_SUCCESS);
    return 0;
}

完整代码实现: Jeston Agx Orin, 读取gmsl相机,cuda解码rgb数据

在这里插入图片描述


http://www.kler.cn/a/403760.html

相关文章:

  • STM32芯片EXIT外部中断的配置与原理以及模板代码(标准库)
  • 葡萄酒(wine)数据集——LDA、贝叶斯判别分析
  • Nacos实现IP动态黑白名单过滤
  • Python设计模式详解之1 —— 单例模式
  • 泷羽sec学习打卡-网络七层杀伤链1
  • ip代理池新玩法,收集全网可用代理01,初次验证存活ip
  • 共享单车管理系统项目学习实战
  • PC上浏览器是如何查询DNS 缓存的?
  • 激光slam学习笔记5---ubuntu2004部署运行fastlivo踩坑记录
  • 联通大数据面试题及参考答案
  • Android 源码编译资料集
  • vue3中pinia状态管理库使用以及持久化配置方法总结
  • 基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
  • canva 画图 UI 设计
  • 69.x的平方根-力扣(LeetCode)
  • MySQL 8.4.3 Windows绿色安装与主从配置
  • canvas绘制圆角矩形
  • 修改一下达梦disql 提示符
  • OneToMany 和 ManyToOne
  • 使用数据库批量插入与循环单个插入:优势与区别
  • MyBatis的resultType和resultMap区别
  • 力扣 LeetCode 112. 路径总和(Day8:二叉树)
  • 失落的Apache JDBM(Java Database Management)
  • 【项目实战】基于 LLaMA-Factory 通过 LoRA 微调 Qwen2
  • 2024信创数据库TOP30之蚂蚁集团OceanBase
  • 最新智能AI问答运营系统(SparkAi)一站式AIGC系统,GPT-4.0/GPT-4o多模态模型+联网搜索提问+AI绘画+管理后台,用户会员套餐