Linux_14:通过多线程同时获取H264和H265码流、分别获取高低分辨率

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

通过代码的方式同时获取H264,H265码流并且分别保存到H264文件和H265文件。

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

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

注:创建两个VENC,分别是H264和H265

将同一个VI通道与两个VENC通道同时绑定

cs 复制代码
#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 "include/rkmedia/rkmedia_api.h"

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

void *get_h264_stream_thread(void *argc)
{
    pthread_detach(pthread_self());
    FILE *h264_file = fopen("test_camera.h264","w+");
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,H264_VENC_CHN,-1);
        if(!mb)
        {
            printf("RK_MPI_SYS_GetMediaBuffer H264 Failed\n");
            break;
        }
        else
        {
            printf("RK_MPI_SYS_GetMediaBuffer H264 Success\n");
        }

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

        RK_MPI_MB_ReleaseBuffer(mb);
    }
    
    return NULL;
}

void *get_h265_stream_thread(void *argc)
{
    pthread_detach(pthread_self());
    FILE *h265_file = fopen("test_camera.h265","w+");
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,H265_VENC_CHN,-1);
        if(!mb)
        {
            printf("RK_MPI_SYS_GetMediaBuffer H265 Failed\n");
            break;
        }
        else
        {
            printf("RK_MPI_SYS_GetMediaBuffer H265 Success\n");
        }

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

        RK_MPI_MB_ReleaseBuffer(mb);
    }
    
    return NULL;
}

int main()
{
    int ret;
    
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = CAMERA_PATH;
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
    vi_chn_attr.u32Width = 1920;
    vi_chn_attr.u32Height = 1080;
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;
    vi_chn_attr.u32BufCnt = 3;
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;

    ret = RK_MPI_VI_SetChnAttr(CAMERA_ID,VI_CHN,&vi_chn_attr);
    if(ret)
    {
        printf("RK_MPI_VI_SetChnAttr Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VI_SetChnAttr Success\n");
    }

    ret = RK_MPI_VI_EnableChn(CAMERA_ID,VI_CHN);
    if(ret)
    {
        printf("RK_MPI_VI_EnableChn Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VI_EnableChn Success\n");
    }

    VENC_CHN_ATTR_S h264_venc_chn_attr;

    h264_venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
    h264_venc_chn_attr.stVencAttr.bByFrame =  RK_FALSE;
    h264_venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
    h264_venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;
    h264_venc_chn_attr.stVencAttr.u32PicWidth = 1920;
    h264_venc_chn_attr.stVencAttr.u32PicHeight = 1080;
    h264_venc_chn_attr.stVencAttr.u32Profile = 66;
    h264_venc_chn_attr.stVencAttr.u32VirWidth = 1920;
    h264_venc_chn_attr.stVencAttr.u32VirHeight = 1080;

    h264_venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608;
    h264_venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;

    ret = RK_MPI_VENC_CreateChn(H264_VENC_CHN,&h264_venc_chn_attr);
    if(ret)
    {
        printf("RK_MPI_VENC_CreateChn H264 Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VENC_CreateChn H264 Success\n");
    }

    VENC_CHN_ATTR_S h265_venc_chn_attr_s;

    h265_venc_chn_attr_s.stVencAttr.enType = RK_CODEC_TYPE_H265;
    h265_venc_chn_attr_s.stVencAttr.imageType = IMAGE_TYPE_NV12;
    h265_venc_chn_attr_s.stVencAttr.enRotation = VENC_ROTATION_0;
    h265_venc_chn_attr_s.stVencAttr.bByFrame = RK_FALSE;
    h265_venc_chn_attr_s.stVencAttr.u32PicWidth = 1920;
    h265_venc_chn_attr_s.stVencAttr.u32PicHeight = 1080;
    h265_venc_chn_attr_s.stVencAttr.u32Profile = 77;
    h265_venc_chn_attr_s.stVencAttr.u32VirWidth = 1920;
    h265_venc_chn_attr_s.stVencAttr.u32VirHeight = 1080;

    h265_venc_chn_attr_s.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.fr32DstFrameRateNum = 25;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.fr32DstFrameRateDen = 1;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.u32SrcFrameRateNum = 25;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.u32SrcFrameRateDen = 1;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.u32BitRate = 8388608;
    h265_venc_chn_attr_s.stRcAttr.stH265Cbr.u32Gop = 25;

    ret = RK_MPI_VENC_CreateChn(H265_VENC_CHN,&h265_venc_chn_attr_s);
    if(ret)
    {
        printf("RK_MPI_VENC_CreateChn H265 Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VENC_CreateChn H265 Success\n");
    }

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

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

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

    ret = RK_MPI_SYS_Bind(&vi_chn_s,&h264_chn_s);
    if(ret)
    {
        printf("RK_MPI_SYS_Bind H264 Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_SYS_Bind H264 Success\n");
    }

    ret = RK_MPI_SYS_Bind(&vi_chn_s,&h265_chn_s);
    if(ret)
    {
        printf("RK_MPI_SYS_Bind H265 Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_SYS_Bind H265 Success\n");
    }

    pthread_t h264_pid,h265_pid;

    pthread_create(&h264_pid,NULL,get_h264_stream_thread,NULL);
    pthread_create(&h265_pid,NULL,get_h265_stream_thread,NULL);

    while(1)
    {
        sleep(2);
    }

    RK_MPI_SYS_UnBind(&vi_chn_s,&h264_chn_s);
    RK_MPI_SYS_UnBind(&vi_chn_s,&h265_chn_s);

    RK_MPI_VI_DisableChn(CAMERA_ID,VI_CHN);
    RK_MPI_VENC_DestroyChn(H264_VENC_CHN);
    RK_MPI_VENC_DestroyChn(H265_VENC_CHN);

    return 0;
}

3.通过多线程分别获取高分辨率(1920 * 1080)和低分辨率(1280 * 720)的码流数据

通过代码的方式同时低分辨率和高分辨率的码流数据,并且同时保存到高分辨率编码文件和低分辨率编码文件(编码方式都是以H264为例)

4.RV1126 VI 采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程

RV1126利用多线程同时获取高分辨率编码文件、低分辨率编码文件,一般要分为上图8个步骤:VI模块初始化、RGA图像模块初始化、高分辨率编码器的初始化、低分辨率编码器的初始化、VI绑定高分辨率VENC编码器、创建多线程获取高分辨率编码数据、创建多线程获取低分辨率数据并传输到编码器、创建多线程获取低分辨率编码数据。

注:VI一个绑定高分辨率的VENC通道,另一个绑定RGA模块,在线程中将RGA的码流传给低分辨率VENC通道。

cs 复制代码
#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 "include/rkmedia/rkmedia_api.h"

#define CAMERA_PATH "rkispp_scale0"
#define CAMERA_ID 0
#define VI_CHN 0
#define RGA_CHN 0
#define HIGH_VENC_CHN 0
#define LOW_VENC_CHN 1

void *get_high_venc_thread(void *argc)
{
    pthread_detach(pthread_self());
    FILE* high_venc_file = fopen("test_high_venc.h264","w+");
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,HIGH_VENC_CHN,-1);
        if(!mb)
        {
            printf("High Venc MB Faailed\n");
            break;
        }

        printf("High Venc MB 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*argc)
{
    pthread_detach(pthread_self());
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA,RGA_CHN,-1);
        if(!mb)
        {
            printf("RGA MB Faailed\n");
            break;
        }

        printf("RGA MB Success\n");
        RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC,LOW_VENC_CHN,mb);
        RK_MPI_MB_ReleaseBuffer(mb);
    }

    return NULL;
}

void *get_low_venc_thread(void *argc)
{
    pthread_detach(pthread_self());
    FILE* low_venc_file = fopen("test_low_venc.h264","w+");
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,LOW_VENC_CHN,-1);
        if(!mb)
        {
            printf("LOW Venc MB Faailed\n");
            break;
        }

        printf("LOW Venc MB Success\n");
        fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1,low_venc_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }

    return NULL;
}

int main()
{
    int ret;
    RK_MPI_SYS_Init();
      
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = CAMERA_PATH;
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
    vi_chn_attr.u32Width = 1920;
    vi_chn_attr.u32Height = 1080;
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;
    vi_chn_attr.u32BufCnt = 3;
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;

    ret = RK_MPI_VI_SetChnAttr(CAMERA_ID,VI_CHN,&vi_chn_attr);
    if(ret)
    {
        printf("RK_MPI_VI_SetChnAttr Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VI_SetChnAttr Success\n");
    }

    ret = RK_MPI_VI_EnableChn(CAMERA_ID,VI_CHN);
    if(ret)
    {
        printf("RK_MPI_VI_EnableChn Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_VI_EnableChn Success\n");
    }

    RGA_ATTR_S rga_attr;

    rga_attr.stImgIn.imgType = IMAGE_TYPE_NV12;
    rga_attr.stImgIn.u32Width = 1920;
    rga_attr.stImgIn.u32Height = 1080;
    rga_attr.stImgIn.u32HorStride = 1920;
    rga_attr.stImgIn.u32VirStride = 1080;
    rga_attr.stImgIn.u32X = 0;
    rga_attr.stImgIn.u32Y = 0;

    rga_attr.stImgOut.imgType = IMAGE_TYPE_NV12;
    rga_attr.stImgOut.u32Width = 1280;
    rga_attr.stImgOut.u32Height = 720;
    rga_attr.stImgOut.u32HorStride = 1280;
    rga_attr.stImgOut.u32VirStride = 720;
    rga_attr.stImgOut.u32X = 0;
    rga_attr.stImgOut.u32Y = 0;

    rga_attr.bEnBufPool = RK_TRUE;
    rga_attr.enFlip = RGA_FLIP_H;
    rga_attr.u16BufPoolCnt = 3;
    rga_attr.u16Rotaion = 0;

    ret = RK_MPI_RGA_CreateChn(RGA_CHN,&rga_attr);
    if(ret)
    {
        printf("RK_MPI_RGA_CreateChn Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_RGA_CreateChn Success\n");
    }

    VENC_CHN_ATTR_S hige_venc_chn_attr;

    hige_venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
    hige_venc_chn_attr.stVencAttr.bByFrame = RK_FALSE;
    hige_venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;
    hige_venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
    hige_venc_chn_attr.stVencAttr.u32Profile = 66;
    hige_venc_chn_attr.stVencAttr.u32PicWidth = 1920;
    hige_venc_chn_attr.stVencAttr.u32PicHeight = 1080;
    hige_venc_chn_attr.stVencAttr.u32VirWidth = 1920;
    hige_venc_chn_attr.stVencAttr.u32VirHeight = 1080;

    hige_venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;
    hige_venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608;

    ret = RK_MPI_VENC_CreateChn(HIGH_VENC_CHN,&hige_venc_chn_attr);
    if(ret)
    {
        printf("HIGH_VENC_CreateChn Failed\n");
        return 0;
    }
    else
    {
        printf("HIGH_VENC_CreateChn Success\n");
    }
    
    VENC_CHN_ATTR_S low_venc_chn_attr;

    low_venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
    low_venc_chn_attr.stVencAttr.bByFrame = RK_FALSE;
    low_venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;
    low_venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
    low_venc_chn_attr.stVencAttr.u32Profile = 66;
    low_venc_chn_attr.stVencAttr.u32PicWidth = 1280;
    low_venc_chn_attr.stVencAttr.u32PicHeight = 720;
    low_venc_chn_attr.stVencAttr.u32VirWidth = 1280;
    low_venc_chn_attr.stVencAttr.u32VirHeight = 720;

    low_venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    low_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;
    low_venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
    low_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;
    low_venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
    low_venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;
    low_venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608;

    ret = RK_MPI_VENC_CreateChn(LOW_VENC_CHN,&low_venc_chn_attr);
    if(ret)
    {
        printf("LOW_VENC_CreateChn Failed\n");
        return 0;
    }
    else
    {
        printf("LOW_VENC_CreateChn Success\n");
    }

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

    MPP_CHN_S rga_chn_s;
    rga_chn_s.enModId = RK_ID_RGA;
    rga_chn_s.s32ChnId = RGA_CHN;

    ret = RK_MPI_SYS_Bind(&vi_chn_s,&rga_chn_s);
    if(ret)
    {
        printf("VI Bind RGA Failed\n");
        return 0;
    }
    else
    {
        printf("VI Bind RGA Success\n");
    }

    MPP_CHN_S high_vnec_chn_s;
    high_vnec_chn_s.enModId = RK_ID_VENC;
    high_vnec_chn_s.s32ChnId = HIGH_VENC_CHN;

    ret = RK_MPI_SYS_Bind(&vi_chn_s,&high_vnec_chn_s);
    if(ret)
    {
        printf("VI Bind HIGH_VNEC Failed\n");
        return 0;
    }
    else
    {
        printf("VI Bind HIGH_VNEC Success\n");
    }

    pthread_t high_venc_pid;
    pthread_t low__venc_pid;
    pthread_t rga_pid;

    pthread_create(&high_venc_pid,NULL,get_high_venc_thread,NULL);
    pthread_create(&rga_pid,NULL,rga_handle_thread,NULL);
    pthread_create(&low__venc_pid,NULL,get_low_venc_thread,NULL);

    while (1)
    {
        sleep(2);
    }
    

    RK_MPI_SYS_UnBind(&vi_chn_s,&rga_chn_s);
    RK_MPI_SYS_UnBind(&vi_chn_s,&high_vnec_chn_s);

    RK_MPI_VI_DisableChn(CAMERA_ID,VI_CHN);
    RK_MPI_RGA_DestroyChn(RGA_CHN);
    RK_MPI_VENC_DestroyChn(HIGH_VENC_CHN);
    RK_MPI_VENC_DestroyChn(LOW_VENC_CHN);

    return 0;
}
相关推荐
安科士andxe6 小时前
深入解析|安科士1.25G CWDM SFP光模块核心技术,破解中长距离传输痛点
服务器·网络·5g
YJlio8 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
CTRA王大大9 小时前
【网络】FRP实战之frpc全套配置 - fnos飞牛os内网穿透(全网最通俗易懂)
网络
小白同学_C9 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
今天只学一颗糖9 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
2601_949146539 小时前
Shell语音通知接口使用指南:运维自动化中的语音告警集成方案
运维·自动化
儒雅的晴天9 小时前
大模型幻觉问题
运维·服务器
testpassportcn9 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
通信大师10 小时前
深度解析PCC策略计费控制:核心网产品与应用价值
运维·服务器·网络·5g