文章目录
- 前言
-
-
- 2.RV1126的视频输入vi模块
-
- 2.1什么是VI模块
- 2.3RV1126VI模块主要API
-
- RK_MPI_SYS_Init()
- RK_MPI_VI_SetChnAttr
- RK_MPI_VI_EnableChn
- [RK_S32 RK_MPI_VI_DisableChn](#RK_S32 RK_MPI_VI_DisableChn)
- RK_MPI_VI_StartStream
- RK_MPI_SYS_GetMediaBuffer
- RK_MPI_MB_GetPtr
- RK_MPI_MB_GetSize
- RK_MPI_MB_ReleaseBuffer
- 练习
-
前言
本文旨在记录并复习自身所学知识,如有错误请评论区指出,图片及知识点来源于网络,如有侵权请联系删除~
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;
}