通过多线程同时获取H264和H265码流

news2025/3/14 20:37:31

目录

一.RV1126 VI采集摄像头数据并同时编码H264、H265的大概流程​编辑​编辑

1.1初始化VI模块:

1.2H264、H265的VENC模块初始化:

1.3VI分别绑定H264的VENC层和H265的VENC层:

​​​​​​​1.4开启H264线程采集H264的VENC数据:

​​​​​​​1.5开启H265线程采集H265的VENC数据:

二.代码实战:


一.RV1126 VI采集摄像头数据并同时编码H264、H265的大概流程

RV1126利用多线程同时获取H264文件、H265文件的过程一般分为上图的7步骤,分别是:VI模块的初始化、H264的VENC模块初始化、H265的VENC模块初始化、VI绑定H264的VENC模块、VI绑定H265的VENC模块,开启H264线程获取H264码流并保存、开启H265线程获取H265码流并保存。

​​​​​​​1.1初始化VI模块:

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

VI_CHN_ATTR_S  vi_chn_attr;

。。。。。。。。。。。。。。。(这里是设置VI的属性)

ret = RK_MPI_VI_SetChnAttr(CAMERA_ID, 0, &vi_chn_attr);

ret |= RK_MPI_VI_EnableChn(CAMERA_ID, 0);

​​​​​​​1.2H264、H265的VENC模块初始化:

VENC_CHN_ATTR_S  h264_venc_chn_attr;

..................................

RK_MPI_VENC_CreateChn(H264_VENC_CHN, &h264_venc_chn_attr);

VENC_CHN_ATTR_S  h265_venc_chn_attr;

..................................

RK_MPI_VENC_CreateChn(H265_VENC_CHN, &h265_venc_chn_attr);

注意:这里需要创建两个编码器层,分别是H264编码器和H265编码器。

​​​​​​​1.3VI分别绑定H264的VENC层和H265的VENC层:

VI节点分别绑定H264的VENC节点和H265节点,伪代码如下:

//VI模块节点的设置

MPP_CHN_S vi_chn_s;

vi_chn_s.enModId = RK_ID_VI;

vi_chn_s.s32ChnId = 0;

//H264的VENC模块节点设置

MPP_CHN_S h264_venc_chn_s;

h264_venc_chn_s.enModId = RK_ID_VENC;

h264_venc_chn_s.s32ChnId = H264_VENC_CHN;

ret = RK_MPI_SYS_Bind(&vi_chn_s, &h264_venc_chn_s);

//H265的VENC模块节点设置

MPP_CHN_S h265_venc_chn_s;

h265_venc_chn_s.enModId = RK_ID_VENC;

h265_venc_chn_s.s32ChnId = H265_VENC_CHN;

ret = RK_MPI_SYS_Bind(&vi_chn_s, &h265_venc_chn_s);

​​​​​​​1.4开启H264线程采集H264的VENC数据:

开启一个线程去采集每一帧H264的VENC模块数据,使用的API是RK_MPI_SYS_GetMediaBuffer, 模块ID是RK_ID_VENC,通道号ID是H264 VENC创建的ID号这个API伪代码如下

while(1)

{

  .........................

  mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, H264_VENC_CHN, -1);

  fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h264_file);

.......................

}

​​​​​​​1.5开启H265线程采集H265的VENC数据:

开启一个线程去采集每一帧H265的VENC模块数据,使用的API是RK_MPI_SYS_GetMediaBuffer, 模块ID是RK_ID_VENC,通道号ID是H265 VENC创建的ID号这个API伪代码如下

while(1)

{

  .........................

  mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, H265_VENC_CHN, -1);

  fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h265_file);

.......................

}

二.代码实战:

#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 "common/sample_common.h"
#include "rkmedia_api.h"

#define CAMERA_PATH "rkispp_scale0"
#define CAMERA_ID 0
#define CAMERA_CHN 0
#define H264_VENC_CHN 0
#define H265_VENC_CHN 1

//创建线程获取H264码流数据并保存
void * get_h264_stream_thread(void * args)
{
    pthread_detach(pthread_self());
    FILE * h264_file = fopen("test_camera.h264", "w+");
    MEDIA_BUFFER mb ;

    while (1)
    {
        //获取每一帧H264编码码流
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, H264_VENC_CHN, -1);
        if(!mb)
        {
            printf("Get H264_Venc Buffer break....\n");
            break;
        }

        fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h264_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }
    
    return NULL;
}

//创建线程获取H265码流数据并保存
void * get_h265_stream_thread(void * args)
{
    pthread_detach(pthread_self());
    FILE * h265_file = fopen("test_camera.h265", "w+");
    MEDIA_BUFFER mb ;

    while (1)
    {
        //获取每一帧H265编码码流
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, H265_VENC_CHN , -1);
        if(!mb)
        {
            printf("Get H265_VENC Buffer break...\n");
            break;
        }

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

    return NULL;
}

int main(int argc, char *argv[])
{
    int ret;
    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.enBufType = VI_CHN_BUF_TYPE_MMAP;//设置VI获取类型
    vi_chn_attr.u32BufCnt = 3; //设置缓冲数量
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL; //设置VI工作类型
    ret = RK_MPI_VI_SetChnAttr(CAMERA_ID, CAMERA_CHN, &vi_chn_attr);
    if(ret)
    {
        printf("Vi Set Attr Failed.....\n");
        return 0;
    }
    else
    {
        printf("Vi Set Attr Success.....\n");
    }

    ret = RK_MPI_VI_EnableChn(CAMERA_ID, CAMERA_CHN);
    if(ret)
    {
        printf("Vi Enable Attr Failed.....\n");
        return 0;
    }
    else
    {
        printf("Vi Enable Attr Success.....\n");
    }

    VENC_CHN_ATTR_S h264_venc_chn_attr;
    //******   H264  设置VENC基础属性   ************************//
    h264_venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264; //设置编码器类型
    h264_venc_chn_attr.stVencAttr.u32PicWidth = 1920;//设置编码分辨率宽度
    h264_venc_chn_attr.stVencAttr.u32PicHeight = 1080;//设置编码分辨率高度
    h264_venc_chn_attr.stVencAttr.u32VirWidth = 1920;//设置编码分辨率虚宽
    h264_venc_chn_attr.stVencAttr.u32VirHeight = 1080;//设置编码分辨率虚高
    h264_venc_chn_attr.stVencAttr.u32Profile = 66;//设置编码等级
    h264_venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;//设置编码图像类型
    h264_venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;//设置编码的旋转角度

    //********* H264 设置H264码率控制属性  *******************//
    h264_venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; //设置H264的CBR码率控制模式
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;//设置GOP关键帧间隔
    //25/1 NUM/DEN == FrameRate
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1; //设置源帧率分母
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;//设置源帧率分子
    h264_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;//设置目标帧率分母
    h264_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;//设置目标帧率分子
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608; //设置码率大小
    ret = RK_MPI_VENC_CreateChn(H264_VENC_CHN, &h264_venc_chn_attr);
    if(ret)
    {
        printf("Create H264 Venc Failed .....\n");
        return 0;
    }
    else
    {
        printf("Create H264 Venc Success .....\n");
    }

    VENC_CHN_ATTR_S h265_venc_chn_attr;
    //******   H265  设置VENC基础属性   ************************//
    h265_venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H265;//设置编码器类型
    h265_venc_chn_attr.stVencAttr.u32PicWidth = 1920;//设置编码分辨率宽度
    h265_venc_chn_attr.stVencAttr.u32PicHeight = 1080;//设置编码分辨率高度
    h265_venc_chn_attr.stVencAttr.u32VirWidth = 1920;//设置编码分辨率虚宽
    h265_venc_chn_attr.stVencAttr.u32VirHeight = 1080;//设置编码分辨率虚高
    h265_venc_chn_attr.stVencAttr.u32Profile = 77;//设置编码等级
    h265_venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;//设置编码图像类型
    h265_venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;//设置编码的旋转角度
    //********* H265 VENC RCMODE Set  *******************//
    h265_venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;//设置H265的CBR码率控制模式
    h265_venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;//设置GOP关键帧间隔
    //25/1 NUM/DEN == FrameRate
    h265_venc_chn_attr.stRcAttr.stH265Cbr.u32SrcFrameRateDen = 1; //设置源帧率分母
    h265_venc_chn_attr.stRcAttr.stH265Cbr.u32SrcFrameRateNum = 25;//设置源帧率分子
    h265_venc_chn_attr.stRcAttr.stH265Cbr.fr32DstFrameRateDen = 1;//设置目标帧率分母
    h265_venc_chn_attr.stRcAttr.stH265Cbr.fr32DstFrameRateNum = 25;//设置目标帧率分子
    h265_venc_chn_attr.stRcAttr.stH265Cbr.u32BitRate = 8388608; //设置码率大小
    ret = RK_MPI_VENC_CreateChn(H265_VENC_CHN, &h265_venc_chn_attr);
    if(ret)
    {
        printf("Create H265 Venc Failed .....\n");
        return 0;
    }
    else
    {
        printf("Create H265 Venc Success .....\n");
    }

    //VI_CHN
    MPP_CHN_S vi_chn_s;
    vi_chn_s.enModId = RK_ID_VI;
    vi_chn_s.s32ChnId = CAMERA_CHN;

    //H264_VENC_CHN
    MPP_CHN_S h264_chn_s;
    h264_chn_s.enModId = RK_ID_VENC;
    h264_chn_s.s32ChnId = H264_VENC_CHN;

    //H265_VENC_CHN
    MPP_CHN_S h265_chn_s;
    h265_chn_s.enModId = RK_ID_VENC;
    h265_chn_s.s32ChnId = H265_VENC_CHN;


    //VI Bind H264_VENC
    ret = RK_MPI_SYS_Bind(&vi_chn_s, &h264_chn_s);
    if(ret)
    {
        printf("Vi Bind H264_Venc Failed .....\n");
    }
    else
    {
        printf("Vi Bind H264_Venc Success .....\n");
    }


    //VI Bind H265_VENC
    ret = RK_MPI_SYS_Bind(&vi_chn_s, &h265_chn_s);
    if(ret)
    {
        printf("Vi Bind H265_Venc Failed .....\n");
    }
    else
    {
        printf("Vi Bind H265_Venc Success .....\n");
    }

    pthread_t h264_pid, h265_pid;

    pthread_create(&h264_pid, NULL, get_h264_stream_thread, NULL);//创建线程获取H264码流数据并保存
    pthread_create(&h265_pid, NULL, get_h265_stream_thread, NULL);//创建线程获取H265码流数据并保存

    while (1)
    {
        sleep(1);
    }

    RK_MPI_SYS_UnBind(&vi_chn_s, &h264_chn_s);
    RK_MPI_SYS_UnBind(&vi_chn_s, &h265_chn_s);
    RK_MPI_VI_DisableChn(0, 0);
    RK_MPI_VENC_DestroyChn(0);
    RK_MPI_VENC_DestroyChn(1);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311323.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepSeek V3 源码:从入门到放弃!

从入门到放弃 花了几天时间&#xff0c;看懂了DeepSeek V3 源码的逻辑。源码的逻辑是不难的&#xff0c;但为什么模型结构需要这样设计&#xff0c;为什么参数需要这样设置呢&#xff1f;知其然&#xff0c;但不知其所以然。除了模型结构以外&#xff0c;模型的训练数据、训练…

海量数据融合互通丨TiDB 在安徽省住房公积金监管服务平台的应用实践

导读 安徽省住房公积金监管服务平台通过整合全省 17 家公积金中心的数据&#xff0c;致力于实现数据共享、规范化管理与高效数据分析。为了应对海量数据处理需求&#xff0c;安徽省选择 TiDB 作为底层数据库&#xff0c;利用其分布式架构和 HTAP 能力&#xff0c;实现了快速的…

Linux12-UDP\TCP

一、UDP 1.特点: 尽最大努力交付,存在丢包的可能 无连接 面向数据报 机制简单,传输效率高 2.应用场景: 1.画面传输 VNC 直播:要求实时性高、允许数据丢失、 二、TCP 1.特点: 面向数据流(流式套接字) 建立连接 安全可靠的传输协议 三次握手:TCP建立连接时,…

【HeadFirst系列之HeadFirst设计模式】第14天之与设计模式相处:真实世界中的设计模式

与设计模式相处&#xff1a;真实世界中的设计模式 设计模式是软件开发中的经典解决方案&#xff0c;它们帮助我们解决常见的设计问题&#xff0c;并提高代码的可维护性和可扩展性。在《Head First设计模式》一书中&#xff0c;作者通过生动的案例和通俗的语言&#xff0c;深入…

自由学习记录(42)

可能会出现到后面没有教程可以看&#xff0c;走不动&#xff0c;&#xff0c;但还是尝试吧 过程远比想象的要多 那连Live2d的这些脚本怎么控制的都要了解一下 ------------ 文件类型和扩展名 | 编辑手册 | Live2D Manuals & Tutorials 全部导入之后 在这下载SDK Live2D…

excel vlookup的精确查询、模糊查询、反向查询、多列查询

目录 入门 精确查询 模糊查询 反向查询 (搭配 if 函数) 多列查询 (搭配 match 函数) 入门 精确查询 需求: 查找 学生编号是008 所在的班级 操作: 在I2单元格输入公式如下,VLOOKUP(H2,B1:E12,4,FALSE), 得出结果 看一下vlookup 公式每一个参数应该怎么写? 语法: vlookup…

安装remixd,在VScode创建hardhat

在终端&#xff0c;以管理员身份&#xff0c;cmd 需要科学上网 npm install -g remix-project/remixd 在vscode插件中&#xff0c;安装solidity插件&#xff0c;是暗灰色那款 1.将nodeJs的版本升级至18以上 2.在vscode打开一个新的文件&#xff0c;在终端输入 npx hardhat 3.…

【Python爬虫】利用代理IP爬取跨境电商AI选品分析

引言 随着DeepSeek的流行&#xff0c;越来越多的用户开始尝试将AI工具融入到日常工作当中&#xff0c;借助AI的强大功能提高工作效率。最近又掀起了一波企业出海的小高潮&#xff0c;那么如果是做跨境电商业务&#xff0c;怎么将AI融入工作流中呢&#xff1f;在做跨境电商的时候…

捣鼓180天,我写了一个相册小程序

&#x1f64b;为什么要做土著相册这样一个产品&#xff1f; ➡️在高压工作之余&#xff0c;我喜欢浏览B站上的熊猫幼崽视频来放松心情。有天在家族群里看到了大嫂分享的侄女卖萌照片&#xff0c;同样感到非常解压。于是开始翻阅过去的聊天记录&#xff0c;却发现部分图片和视…

洛谷 P1480 A/B Problem(高精度详解)c++

题目链接&#xff1a;P1480 A/B Problem - 洛谷 1.题目分析 1&#xff1a;说明这里是高精度除以低精度的形式&#xff0c;为什么不是高精度除以高精度的形式&#xff0c;是因为它很少见&#xff0c;它的模拟方式是用高精度减法来做的&#xff0c;并不能用小学列竖式的方法模拟…

图像滑块对比功能的开发记录

背景介绍 最近&#xff0c;公司需要开发一款在线图像压缩工具&#xff0c;其中的一个关键功能是让用户直观地比较压缩前后的图像效果。因此&#xff0c;我们设计了一个对比组件&#xff0c;它允许用户通过拖动滑块&#xff0c;动态调整两张图像的显示区域&#xff0c;从而清晰…

基于Arcgis的python脚本实现相邻矢量面的高度字段取平均值

文章目录 背景效果实现逻辑步骤1、准备数据2、python脚本3、执行通过脚本工具箱来执行背景 在地理信息系统(GIS)数据处理或三维建模等实际应用场景中,我们常常会遇到需要对矢量面数据进行精细化处理的需求。其中一个常见的任务便是对相邻的矢量面中的高度字段开展特定操作。…

Golang的网络流量控制

# Golang的网络流量控制 什么是网络流量控制&#xff1f; 网络流量控制是指针对网络数据传输过程中的流量进行管理和调控的一种技术手段。通过网络流量控制&#xff0c;我们可以对网络中的数据传输速率、带宽使用情况、数据包丢失率等进行监控和调整&#xff0c;以达到优化网络…

Python教程(一):基本语法、流程控制、数据容器

Python&#xff08;一&#xff09; 文章目录 Python&#xff08;一&#xff09;一、基础语法二、数据类型2.1 字符串2.2 空值2.3 类型转换&运算符 三、流程控制3.1 条件判断3.2 循环3.2.1 while循环3.2.2 for循环 四、数据结构4.1 字符串str4.1.1 字符串的格式化输出4.1.1.…

【AI深度学习基础】PyTorch初探

引言 PyTorch 是由 Facebook 开源的深度学习框架&#xff0c;专门针对 GPU 加速的深度神经网络编程&#xff0c;它的核心概念包括张量&#xff08;Tensor&#xff09;、计算图和自动求导机制。PyTorch作为Facebook开源的深度学习框架&#xff0c;凭借其动态计算图和直观的API设…

UE4 组件 (对话组件)

制作一个可以生成对话气泡&#xff0c;显示对话台词的简单组件。这个组件要的变量&#xff1a;台词&#xff08;外部传入&#xff09;。功能&#xff1a;开始对话&#xff08;生成气泡UI&#xff09; &#xff0c;结束对话。 一、对话组件创建 二、开始对话事件 1、注意这里获…

blender看不到导入的模型

参考&#xff1a;blender 快捷键 常见问题_blender材质预览快捷键-CSDN博客 方法一&#xff1a;视图-裁剪起点&#xff0c;设置一个很大的值 方法二&#xff1a;选中所有对象&#xff0c;对齐视图-视图对齐活动项-选择一个视图

【慕课网wiki项目学习笔记01】Spring Boot 项目搭建

2-2 新建SpringBoot项目 一、创建SpringBoot项目 &#xff08;1&#xff09;在SpringBoot官网创建 &#xff08;2.1&#xff09;在 IDEA 中创建 Group&#xff1a;公司名 Artifact&#xff1a;项目名 创建成功后开始下载Maven依赖&#xff08;选择右下角的Import Changes&…

【高分论文密码】AI大模型和R语言的全类型科研图形绘制,从画图、标注、改图、美化、组合、排序分解科研绘图每个步骤

在科研成果竞争日益激烈的当下&#xff0c;「一图胜千言」已成为高水平SCI期刊的硬性门槛——数据显示很多情况的拒稿与图表质量直接相关。科研人员普遍面临的工具效率低、设计规范缺失、多维数据呈现难等痛点&#xff0c;因此科研绘图已成为成果撰写中的至关重要的一个环节&am…

vue3-pc-template后台管理之角色管理与功能权限配置实践

在开发企业级应用时&#xff0c;权限控制无疑是至关重要且不可或缺的一部分。合理的权限控制不仅能够有效保障系统的安全性&#xff0c;还能确保不同用户角色在系统中拥有合适的操作权限&#xff0c;从而提高系统的使用效率和稳定性。本文将详细介绍如何在 Vue3 项目中实现功能…