目录
1.3 RK_MPI_SYS_SendMediaBuffer函数
3.1 VI,RGA,两个VENC(HIGH和LOW)初始化配置
一。前置知识
1.1 VENC 知识
1.2 RGA知识
1.3 RK_MPI_SYS_SendMediaBuffer函数
RK_S32 RK_MPI_SYS_SendMediaBuffer(MOD_ID_E enModID, RK_S32 s32ChnID, MEDIA_BUFFER buffer);
1.3.1函数概述:
用于在不同的模块 和通道 之间传递多媒体数据(即 MEDIA_BUFFER),实现 MPP 内部数据流的“手动”连接,允许开发者将数据从一个处理单元发送到另一个处理单元。
1.3.2参数详解
enModID: 目标模块标识符
常用模块:RK_ID_VI(视频输入)、RK_ID_VPSS(视频处理)、RK_ID_VENC(视频编码)、RK_ID_RGA(图形处理)s32ChnID: 目标模块的通道号,从0开始
buffer: 多媒体数据缓冲区句柄,可来自其他模块或应用程序创建
返回值
类型:
RK_S32(有符号32位整数)含义: 函数执行状态。
成功: 返回
RK_SUCCESS(通常值为0)。失败: 返回一个错误码(非0值),用于指示失败的原因。例如:
RK_ERR_SYS_NOTREADY: 系统未初始化。
RK_ERR_SYS_NOT_PERM: 操作不允许(如格式不匹配)。
RK_ERR_SYS_TIMEOUT: 操作超时(目标模块的输入缓冲区已满)
1.3.3 重要注意事项
-
绑定关系: 在发送数据之前,必须确保目标模块和通道已经创建并初始化成功。通常需要在系统初始化(
RK_MPI_SYS_Init)之后,分别对各个模块进行初始化。 -
数据格式匹配: 发送的
MEDIA_BUFFER的数据格式(如图像宽度、高度、像素格式)必须与目标通道所期望的输入格式兼容,否则发送会失败。 -
缓冲区管理: 当
MEDIA_BUFFER被成功发送后,你不应该再继续使用或修改这个缓冲区,因为它已经交由目标模块管理。目标模块处理完毕后,通常会通过相应的Get函数返回一个新的MEDIA_BUFFER句柄,或者释放该缓冲区。 -
阻塞与非阻塞: 这个函数通常是阻塞的。如果目标模块的输入缓冲区已满,函数会等待直到有空间可以写入或超时。超时时间可以在创建通道时进行配置。
-
与 Bind 的区别: MPP 还提供了
RK_MPI_SYS_Bind函数,可以自动将两个模块连接起来,数据会自动流动,无需手动Send。SendMediaBuffer提供了更灵活的控制,适用于Bind无法满足的复杂场景或需要应用程序介入处理的场景
二。程序框架

使用VENC对视频进行码流处理,支持不同分辨率的编码,但是VI输出原始分辨率为1920*1080,不能直接通过设置VENC的分辨率进行降分辨率。需要通过RGA进行处理,将分辨率降低,在用过VENC编码输出。
三。编码实战
3.1 VI,RGA,两个VENC(HIGH和LOW)初始化配置
3.2 模块绑定
主要是两个:
VI直接绑定到HIGH_VENC,因为二者的分辨率一致都是1920*1080
MPP_CHN_S vi_chn_s;
vi_chn_s.enModId = RK_ID_VI;
vi_chn_s.s32ChnId = VI_CHN_ID;
MPP_CHN_S high_chn_s;
high_chn_s.enModId = RK_ID_VENC;
high_chn_s.s32ChnId = HIGH_VENC_CHN;
/**vi bind the high-resolution VENC module **/
ret = RK_MPI_SYS_Bind(&vi_chn_s,&high_chn_s);
if (ret)
{
printf("VI Bind High Venc Failed.....\n");
return -1;
}
else
{
printf("VI Bind High Venc Success.....\n");
}
VI与RGA绑定,将1920*1080通过RGA进行分辨率处理程序1280*720,。
MPP_CHN_S rga_chn_s;
rga_chn_s.enModId = RK_ID_RGA;
rga_chn_s.s32ChnId = RGA_CHN_ID;
/**vi bind the RGA module **/
ret = RK_MPI_SYS_Bind(&vi_chn_s, &rga_chn_s);
if (ret)
{
printf("VI Bind RGA Failed.....\n");
return -1;
}
else
{
printf("VI Bind RGA Success.....\n");
}
3.3 pthread_t 建立多线程分别处理
pthread_t high_venc_pid;
pthread_t rga_pid;
pthread_t low_venc_pid;
pthread_create(&high_venc_pid, NULL, get_high_venc_thread, NULL); //创建多线程获取高分辨率的编码码流
pthread_create(&high_venc_pid, NULL, rga_handle_thread, NULL);//创建多线程获取RGA码流并发送到低分辨率编码器
pthread_create(&high_venc_pid, NULL, get_low_venc_thread, NULL);//创建多线程获取低分辨率编码码流
//创建多线程获取高分辨率的编码码流
void *get_high_venc_thread(void * args)
{
pthread_detach(pthread_self());
/*
pthread_detach(pthread_self());
作用:
将调用此代码的线程设置为分离状态(detached state)
分离状态的线程在结束时会自动释放资源,不需要其他线程调用 pthread_join() 来回收
*/
FILE * high_venc_file = fopen("test_high_venc_20251118.h264","w+");
MEDIA_BUFFER mb;
while(1)
{
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,HIGH_VENC_CHN,-1);
if(!mb)
{
printf(" Get High Venc break .....\n");
break;
}
printf("Get High Venc Success.....\n");
fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1,high_venc_file);
RK_MPI_MB_ReleaseBuffer(mb);
}
return NULL;
}
void *rga_handle_thread(void *args)
{
pthread_detach(pthread_self());
MEDIA_BUFFER mb;
while(1)
{
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA,RGA_CHN_ID,-1);
if (!mb)
{
printf("Get RGA break.....\n");
}
printf("Get RGA Success.....\n");
////发送每一帧RGA数据到低分辨率编码器
RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC,LOW_VENC_CHN,mb);
RK_MPI_MB_ReleaseBuffer(mb);
}
}
void *get_low_venc_thread(void * args)
{
pthread_detach(pthread_self());
/*
pthread_detach(pthread_self());
作用:
将调用此代码的线程设置为分离状态(detached state)
分离状态的线程在结束时会自动释放资源,不需要其他线程调用 pthread_join() 来回收
*/
FILE * low_venc_file = fopen("test_low_venc_20251118.h264","w+");
MEDIA_BUFFER mb;
while(1)
{
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,LOW_VENC_CHN,-1);
if(!mb)
{
printf(" Get LOW Venc break .....\n");
break;
}
printf("Get LOW Venc Success.....\n");
fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1,low_venc_file);
RK_MPI_MB_ReleaseBuffer(mb);
}
return NULL;
}
需要注意的是:低分辨率的数据是通过RGA获取,然后再传递给VENC进行编码处理,需要用到
RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC,LOW_VENC_CHN,mb);
功能:用于在不同的模块 和通道 之间传递多媒体数据
实现不同线程之间信息传递
3.4 编译
第一次编译:


问题:VENC 缓冲区溢出问题,存储buffer数据没有及时提取走
VENC的获取缓冲数据失败,错误状态为0编码
错误分析:
Mode[AENC]:Chn[0] in status[0]:音频编码通道 0 状态为 0(未就绪)
this operation is not allowed!:不允许执行获取缓冲区操作通道 0 和通道 1 都出现相同问题
问题定位:


模块ID拼写错误:应该为RK_ID_VENC才是视频的数据,而我使用了RK_ID_AENC为音频模块数据
第二次编译:

3.5结果

1703

被折叠的 条评论
为什么被折叠?



