项目1:get_rga_thread线程和low_camera_venc_thread线程获取低分辨率VENC码流数据
一.本章节介绍
本章节主要阐述如何利用get_rga_thread线程和low_camera_venc_thread协作获取1280×720低分辨率编码码流并存入队列。如图所示,具体实现步骤如下:
- 调用get_vi_container获取VI节点
- 将VI节点与RGA节点进行绑定
- 通过get_rga_thread线程获取1280×720原始数据
- 将获取的原始数据送入1280×720低分辨率VENC编码器进行处理
二.低分辨率码流获取的思维导图
该流程图展示了获取1280×720低分辨率编码码流的处理流程。如图所示,整个流程的核心在于:
- 通过get_vi_container获取VI节点
- 调用RK_SYS_MPI_Bind完成VI与RGA节点的绑定
随后系统将:
- 创建get_rga_thread线程,使用RK_MPI_SYS_GetMediaBuffer获取每帧1280×720原始视频数据
- 通过RK_MPI_SYS_SendMediaBuffer将原始数据发送至1280×720的VENC编码器
同时会创建low_camera_venc_thread线程,其工作流程为:
- 调用RK_MPI_SYS_GetMediaBuffer获取每帧1280×720编码视频数据
- 使用putVideoPacketQueue函数将编码数据存入low_video_queue队列
三.代码架构讲解
1.绑定RGA和VI节点
RV1126_VENC_CONTAINER low_venc_container;get_venc_container(1, &low_venc_container);rga_channel.enModId = RK_ID_RGA;rga_channel.s32ChnId = 0;ret = RK_MPI_SYS_Bind(&vi_channel, &rga_channel);if (ret != 0){printf("vi bind rga error\n");return -1;}else{printf("vi bind rga success\n");}
2.创建RGA视频流线程
ret = pthread_create(&pid, NULL, get_rga_thread, NULL);if(ret != 0){printf("create get_rga_thread failed\n");}
3.发送每一帧RGA视频流数据
void * get_rga_thread(void * args)
{MEDIA_BUFFER mb = NULL;while (1){mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, 0 , -1); //获取RGA的数据if(!mb){break;}RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC, 1, mb); //RK_MPI_MB_ReleaseBuffer(mb);}return NULL;
}
4.创建获取低分辨率视频流线程
//VENC线程的参数VENC_PROC_PARAM *low_venc_arg_params = (VENC_PROC_PARAM *)malloc(sizeof(VENC_PROC_PARAM));if (venc_arg_params == NULL){printf("malloc venc arg error\n");free(venc_arg_params);}low_venc_arg_params->vencId = rga_channel.s32ChnId;//创建VENC线程,获取摄像头编码数据ret = pthread_create(&pid, NULL, low_camera_venc_thread, (void *)low_venc_arg_params);if (ret != 0){printf("create camera_venc_thread failed\n");}
5.获取每一帧RGA视频流数据
void *low_camera_venc_thread(void *args)
{pthread_detach(pthread_self());MEDIA_BUFFER mb = NULL;VENC_PROC_PARAM venc_arg = *(VENC_PROC_PARAM *)args;free(args);printf("low_video_venc_thread...\n");while (1){// 从指定通道中获取VENC数据//mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, venc_arg.vencId, -1);mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 1, -1);if (!mb){printf("low_venc break....\n");break;}// int naluType = RK_MPI_MB_GetFlag(mb);// 分配video_data_packet_t结构体video_data_packet_t *video_data_packet = (video_data_packet_t *)malloc(sizeof(video_data_packet_t));// 把VENC视频缓冲区数据传输到video_data_packet的buffer中memcpy(video_data_packet->buffer, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb));// 把VENC的长度赋值给video_data_packet的video_frame_size中video_data_packet->video_frame_size = RK_MPI_MB_GetSize(mb);// video_data_packet->frame_flag = naluType;// 入到视频压缩队列low_video_queue->putVideoPacketQueue(video_data_packet);// printf("#naluType = %d \n", naluType);// 释放VENC资源RK_MPI_MB_ReleaseBuffer(mb);}return NULL;
}
通过结合get_rga_thread和low_camera_thread线程获取1280×720分辨率的编码码流。实现流程如下:
- 首先通过RGA节点和VENC节点进行RK_SYS_MPI_Bind绑定
- 启动get_rga_thread线程获取经RGA处理后的1280×720原始数据
- 调用RK_MPI_SYS_SendMediaBuffer接口将处理后的原始数据发送至低分辨率编码器
随后创建low_camera_thread线程实现:
- 获取1280×720分辨率的编码视频数据
- 将编码数据填充至video_data_packet_t结构体,包含:
- 视频流数据指针(RK_MPI_GetPtr(mb))
- 视频帧长度(RK_MPI_GetSize(mb))
- 将完整的video_data_packet加入队列(low_video_queue->putVideoPacketQueue)
其中video_data_packet_t结构体包含三个关键字段:
- buffer:视频数据缓冲区
- video_frame_size:视频帧长度
- frame_flag:关键帧标识符
核心数据赋值代码:
memcpy(video_data_packet->buffer, RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb));
video_data_packet->video_frame_size = RK_MPI_MB_GetSize(mb);