Linux_12:通过多线程获取VENC的H264码流数据

对RV1126进行CMOS摄像头采集,并进行VENC的视频编码处理,最终获取到H264码流。

1.RV1126 VI 模块采集并进行 VENC 编码的流程

RV1126多线程采集VI模块编码VENC并保存到文件,一般分为四个步骤:分别是初始化VI模块、初始化VENC模块、绑定VI和VENC模块、多线程获取每一帧H264码流数

2.VENC基本函数

RK_MPI_VENC_CreateChn

RK_MPI_VENC_DestroyChn

3.代码

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 VENC_CHN 0

void *get_h264_venc_thread(void *args)
{
    pthread_detach(pthread_self());
    FILE* h264_file = fopen("test_venc.rv1126","w+");
    MEDIA_BUFFER mb;

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

        fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1,h264_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 venc_chn_attr;

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

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

    ret = RK_MPI_VENC_CreateChn(VENC_CHN,&venc_chn_attr);
    if(ret)
    {
        printf("RK_MPI_VENC_CreateChn Failed\n");
        return 0;
    }
    else
    {
        printf("RK_MPI_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 vens_chn_s;
    vens_chn_s.enModId = RK_ID_VENC;
    vens_chn_s.s32ChnId = VENC_CHN;

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

    pthread_t pid;

    pthread_create(&pid,NULL,get_h264_venc_thread,NULL);

    while (1)
    {
        sleep(1);
    }

    RK_MPI_VI_DisableChn(CAMERA_ID,VI_CHN);
    RK_MPI_VENC_DestroyChn(VENC_CHN);
    RK_MPI_SYS_UnBind(&vi_chn_s,&vens_chn_s);
    
    return 0;
}

注:

1.摄像头的帧率是25帧

2.码率单位换算

1 Kb = 1024 bit

1 KB = 1024 Byte

1 Mb = 1024 Kb

1 MB = 1024 KB

1 Byte = 8 bit

1 MB = 8Mb

1 Mb = 0.125 MB

1MBps = 1024kBps = 1024*1024Bps = 1024*1024*8bps = 8388608bps (比特率)

3.帧率计算

帧率 = Num / Dem

GOP是帧率的整数倍

相关推荐
corey938 分钟前
Linux 学习 - 第十四周作业
linux·运维·学习
可乐_不渴15 分钟前
# C语言文件操作全解析:从 fopen 到 fclose,一文吃透文件 IO
linux·服务器·c语言
草莓熊Lotso31 分钟前
【C++ 基于微服务的即时通讯系统】网关基建:cpp-httplib 与 WebSocketpp 从入门到实战
linux·开发语言·数据库·c++·redis·微服务·云原生
李纲明33 分钟前
WordPress 媒体库上传失败或一直转圈:先核 PHP 上传限制与目录权限,再查安全插件与对象存储
运维·开发语言·安全·php·wordpress·媒体库·devdiy
志栋智能8 小时前
运维超自动化的版本控制与回滚机制
运维·自动化
中云DDoS CC防护蔡蔡9 小时前
DDOS和CC攻击谁更可怕
运维·服务器·经验分享·网络安全·ddos
Ruiery9 小时前
Linux 6.6内核内存管理深度解析(十六):mmap — 用户态“申请内存“的真相
linux·运维·服务器
ClickHouseDB9 小时前
ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来
运维·数据库·系统架构
欧米欧9 小时前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
Ruiery9 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全