RV1126 NO.7 :多线程获取VI模块的YUV数据

这章文档节各位学员就可以对RV1126的采集VI摄像头模块的流程有更深刻的了解。后面需要源代码的可以私信我或在评论区扣1

1.RV1126 VI模块采集摄像头YUV数据的流程

RV1126多线程采集VI模块的数据,一般分为三个步骤:分别是初始化VI模块、启动VI模块开启采集、开启多线程采集VI数据并保存到本地。

1.1初始化VI模块:

VI模块的初始化实际上就是对VI_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_VI_SetChnAttr设置VI模块并使能RK_MPI_VI_EnableChn

1.2​​​​​​​启动VI模块:

设置完上面的VI模块后,就要开启VI模块的工作,使用的API是RK_MPI_VI_StartStream

1.3​​​​​​​使用多线程的方式去采集:

开启一个线程去采集每一帧VI模块的数据,使用的API是RK_MPI_SYS_GetMediaBuffer,这个API的具体作用是获取指定通道中的数据,具体的定义如下:

enModID:模块号ID,模块号指的是目前使用的是哪个模块如:VI模块(RK_ID_VI)、VENC模块(RK_ID_VENC)

s32ChnID:通道号ID,这里的通道号跟初始化通道的ID号一致。

S32MilliSec:默认是-1,阻塞状态。

注意:RK_MPI_SYS_GetMediaBuffer获取的数据是一个整体的数据,换言之这个数据包含了缓冲区指针和缓冲区大小。如下图:

拿到整体数据后,我们就要对整体数据进行分割操作。所谓的分割操作,就是要获取整体数据里面的缓冲区指针缓冲区大小。那具体的我们来看看下面的API是怎么获取到它的具体数据。

缓冲区指针的获取:

RK_MPI_MB_GetPtr就是获取每一帧的具体指针,也就是我们每一帧数据。

缓冲区长度的获取

RK_MPI_MB_GetSize就是获取每一帧数据的长度。

获取完具体的缓冲区数据和缓冲区大小之后,就开始写入文件。写入文件的操作就是fwrite就可以写入。

好的,上述流程已经梳理完毕,开始主代码实战,不懂可以看我写的注释

#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "rkmedia_api.h"

#define CAMERA_PATH "rkispp_scale0"
#define PIPE_ID 0
#define CHN_ID 0

static bool quit = false;

void handle_quit_signal(int sig)
{
    printf("vi_program quit....\n");
    quit = true;
}

//获取视频流线程
void * get_camera_vi_thread(void * args)
{
    MEDIA_BUFFER mb = NULL;
    FILE * nv12_file = fopen("test_camera.nv12", "w+");

    while (!quit)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, CHN_ID, -1);
        if(!mb)
        {
            printf("get Vi mb break....\n");
            break;
        }

        fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), nv12_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }
}


int main(int argc, char *argv[])
{

    signal(SIGINT, handle_quit_signal);
    //vi模块的初始化
    int ret;
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = CAMERA_PATH;// 视频设备路径(如 "/dev/video0"
    vi_chn_attr.u32Width = 1920;// 视频宽度(1920像素)
    vi_chn_attr.u32Height = 1080; 视频高度(1920像素)
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;// 像素格式(NV12是YUV格式的一种)420
    vi_chn_attr.u32BufCnt = 3;// 缓冲区数量(用于双缓冲/三缓冲)
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;// 缓冲区类型(内存映射)
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;// 工作模式(正常模式)
    ret = RK_MPI_VI_SetChnAttr(PIPE_ID, CHN_ID, &vi_chn_attr);//设置视频通道属性
    if(ret)
    {
        printf("Create VI Failed...\n");
        return -1;
    }
    else
    {
        printf("Create VI Success...\n");
    }
    //启用视频通道
    ret = RK_MPI_VI_EnableChn(PIPE_ID, CHN_ID);
    if(ret)
    {
        printf("Enable VI Failed...\n");
        return -1;
    }
    else
    {
        printf("Enable VI Success...\n");
    }
    //启动视频流,此时摄像头开始采集数据
    ret = RK_MPI_VI_StartStream(PIPE_ID, CHN_ID);
    if(ret)
    {
        printf("RK_MPI_VI_StartStream Failed...\n");
        return -1;
    }
    else
    {
        printf("RK_MPI_VI_StartStream Success...\n");
    }

    pthread_t pid;
    pthread_create(&pid, NULL, get_camera_vi_thread, NULL);//创建视频循环采集线程

    while (!quit)
    {
       sleep(1);
    }
    //禁用视频通道,避免资源泄露
    RK_MPI_VI_DisableChn(0, 0);
    
    return 0;
}

好的,这就是简单的多线程VI数据采集,看不懂的可以私信我。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值