RV1126音视频学习(二)-----VI模块

文章目录


前言

本文旨在记录并复习自身所学知识,如有错误请评论区指出,图片及知识点来源于网络,如有侵权请联系删除~


2.RV1126的视频输入vi模块

V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。在Linux中,视频设备是设备文件,可以像访问普通文件一样对其进行读写

2.1什么是VI模块

RV1126的VI模块指的是视频输入模块,它的作用是读取sensor的数据。VI模块底层就是对V4L2驱动架构接口的一系列的封装,它本质上还是依赖Linux底层的V4L2驱动架构并向应用层提供对应的设备文件节点,比方说(/dev/video*)*。而 VI模块可以通过操作类似于/dev/video这样的设备节点来读取摄像头数据。

2.2RV1126的VI模块重要参数

成员名称 描述
pcVideoNode video节点路径
u32Width video宽度
u32Height video高度
enPixFmt video格式
u32BufCnt vi捕捉视频缓冲区计数
enBufType vi缓冲区类型
enWorkMode vi通道工作模式
2.3RV1126VI模块主要API
RK_MPI_SYS_Init()
c 复制代码
RK_S32 RK_MPI_SYS_Init(void);
功能
	用于初始化RKMedia系统,必须在使用其他RKMedia函数之前调用
头文件
    rkmedia_api.h
库文件
    libeasymedia.so
返回值
    成功 0
    失败 错误码
RK_MPI_VI_SetChnAttr
c 复制代码
RK_MPI_VI_SetChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, const VI_CHN_ATTR_S *pstChnAttr);
功能
	用于设置VI(视频采集)通道的属性,包括分辨率、帧率、像素格式等
头文件
    rkmedia_api.h
库文件
    libeasymedia.so
参数
    ViPipe    VI 管道号。 一般写0
    ViChn    VI 通道号。取值范围:[0, VI_MAX_CHN_NUM)]    一般写0
    pstChnAttr    VI 通道属性结构体指针    
返回值
    成功 0
    失败 错误码
typedef struct rkVI_CHN_ATTR_S 
{
    const RK_CHAR *pcVideoNode;摄像头的节点 rkispp_sicale0详情见数据手册
    RK_U32 u32Width;视频的宽与摄像头的参数一致
    RK_U32 u32Height;视频的高与摄像头的参数一致   
    IMAGE_TYPE_E enPixFmt; 采集的视频的格式
    RK_U32 u32BufCnt; // VI capture video buffer cnt.缓冲帧的大小 3-5
    // VI capture video buffer type.
    VI_CHN_BUF_TYPE enBufType;    视频数据的存储方式    DMA(直接访问)/内存映射
    VI_CHN_WORK_MODE enWorkMode;    工作模式    
} VI_CHN_ATTR_S;
RK_MPI_VI_EnableChn
c 复制代码
 RK_S32 RK_MPI_VI_EnableChn(VI_PIPE ViPipe, VI_CHN ViChn);
功能
	用于使能VI通道,启动视频采集
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    ViPipe    VI 管道号
    ViChn    VI 通道号。取值范围:[0, VI_MAX_CHN_NUM]
返回值
    成功 0
    失败 错误码
RK_S32 RK_MPI_VI_DisableChn
c 复制代码
功能
	用于失能VI通道,关闭视频采集
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    ViPipe    VI 管道号
    ViChn    VI 通道号。取值范围:[0, VI_MAX_CHN_NUM]
返回值
    成功 0
    失败 错误码
RK_MPI_VI_StartStream
c 复制代码
RK_S32 RK_MPI_VI_StartStream(VI_PIPE ViPipe, VI_CHN ViChn);
功能
	用于启动视频流
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    ViPipe    VI 管道号
    ViChn    VI 通道号。取值范围:[0, VI_MAX_CHN_NUM]
返回值
    成功 0
    失败 错误码
RK_MPI_SYS_GetMediaBuffer
c 复制代码
MEDIA_BUFFER RK_MPI_SYS_GetMediaBuffer(MOD_ID_E enModID, RK_S32 s32ChnID, 
                          				RK_S32 s32MilliSec);
功能
	用于从指定通道中获取数据
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    enModID    模块号
    s32ChnID   通道号
    s32MilliSec -1:阻塞,>=0:阻塞等待时间。
返回值
    成功 0
    失败 错误码
注意
    该接口会自动触发RK_MPI_SYS_StartGetMediaBuffer
返回值类型:
    typedef void *MEDIA_BUFFER;//数据缓冲区指针
RK_MPI_MB_GetPtr
c 复制代码
void *RK_MPI_MB_GetPtr(MEDIA_BUFFER mb);
功能
	用于从指定的MEDIA_BUFFER中获取缓冲区数据指针。
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    mb 缓冲区指针
返回值
    成功 0
    失败 错误码
RK_MPI_MB_GetSize
c 复制代码
size_t RK_MPI_MB_GetSize(MEDIA_BUFFER mb);
功能
	用于从指定的MEDIA_BUFFER中获取缓冲区数据大小。
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    mb 缓冲区指针
返回值
    成功 0
    失败 错误码
RK_MPI_MB_ReleaseBuffer
c 复制代码
RK_S32 RK_MPI_MB_ReleaseBuffer(MEDIA_BUFFER mb);
功能
	用于释放缓冲区。
头文件
    rkmedia_api.h
库文件:
    libeasymedia.so
参数
    mb 缓冲区指针
返回值
    成功 0
    失败 错误码
练习

用采集一段YUV数据并播放出来

c 复制代码
#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;
// 读取信号ctrl+c结束程序
void sigint_handler(int signum)
{
    printf("program quit...\n");
    quit = true;
}
void *get_camera_vi_thread(void *arg)
{
    // 定义一个缓存指针用于指向存储VI数据的区域
    MEDIA_BUFFER mb = NULL;
    // 打开/创建一个存储视频流数据的文件
    FILE *nv12_file = fopen("test_camera.nv12", "w+");
    while (!quit)
    {
        // 获取VI模块通道0的Media_BUFFER
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, CHN_ID, -1);
        if (!mb)
        {
            printf("get Media break...\n");
            break;
        }
        printf("get Media success...\n");
        // 向存储YUV数据的文件中写入读到的数据
        fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), nv12_file);
        RK_MPI_MB_ReleaseBuffer(mb); // 回收资源
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    signal(SIGINT, sigint_handler);
    int ret;
    // 初始化VI通道属性结构体
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = CAMERA_PATH;
    vi_chn_attr.u32Width = 1920;
    vi_chn_attr.u32Height = 1080;
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
    vi_chn_attr.u32BufCnt = 3;
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
    // 设置VI通道属性
    ret = RK_MPI_VI_SetChnAttr(PIPE_ID, CHN_ID, &vi_chn_attr);
    if (ret)
    {
        printf("Create channel faile...\n");
        return -1;
    }
    printf("Create channel success...\n");

    // 使能通道0
    ret = RK_MPI_VI_EnableChn(PIPE_ID, CHN_ID);
    if (ret)
    {
        printf("Enable channel faile...\n");
        return -1;
    }
    printf("Enable channel success...\n");

    // 启动VI模块视频流
    ret = RK_MPI_VI_StartStream(PIPE_ID, CHN_ID);
    if (ret)
    {
        printf("Start VI stream fail...\n");
        return -1;
    }
    else
    {
        printf("Start VI stream success...\n");
    }

    // 创建多线程获取VI采集到的YUV数据
    pthread_t tid;
    pthread_create(&tid, NULL, get_camera_vi_thread, NULL);

    // 阻塞等待采集结束
    while (!quit)
    {
        sleep(1);
    }
    // 回收线程资源
    pthread_join(tid, NULL);
    // 关闭通道
    RK_MPI_VI_DisableChn(0, 0);
    return 0;
}
相关推荐
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
sanguine__5 小时前
Web APIs学习 (操作DOM BOM)
学习
darkdragonking6 小时前
FLV视频封装格式详解
音视频
数据的世界017 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐7 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
元争栈道8 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
元争栈道9 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
OopspoO9 小时前
qcow2镜像大小压缩
学习·性能优化
A懿轩A10 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒10 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin