sipeed / LicheeRV-Nano-Build

LicheeRV-Nano-Build
103 stars 39 forks source link

请教sample_venc样例使用摄像头输入的使用方法 #20

Closed 981213 closed 5 months ago

981213 commented 6 months ago

我想开发一个需要摄像头采集视频并进行视频编码的应用。我注意到样例代码的sample_venc中有 BIND_VI_VPSS_VENC 和 VI_VPSS_VENC_SBM_MODE 两个testmode,但是并没有相应的使用帮助。 尝试根据代码猜测运行参数如下,执行后程序无报错退出,并没有创建相应视频文件。

# /tmp/sample_venc --bindmode=1 --testMode=2 -c 265 --viWidth=2560 --viHeight=1440 -w 2560 -h 1440 -o /tmp/vo -n 60
[SAMPLE_COMM_SNS_ParseIni]-2164: Parse /mnt/data/sensor_cfg.ini
[parse_source_devnum]-1757: devNum =  1
[parse_sensor_name]-1838: sensor =  GCORE_GC4653_MIPI_4M_30FPS_10BIT
[parse_sensor_busid]-1867: bus_id =  4
[parse_sensor_i2caddr]-1878: sns_i2c_addr =  29
[parse_sensor_mipidev]-1889: mipi_dev =  0
[parse_sensor_laneid]-1900: Lane_id =  4, 3, 2, -1, -1
[parse_sensor_pnswap]-1911: pn_swap =  0, 0, 0, 0, 0
[parse_sensor_mclken]-1933: mclk_en =  1
[parse_sensor_mclk]-1944: mclk =  1
[SAMPLE_PLAT_SYS_INIT]-72: common pool[0] BlkSize 5652480
ISP Vipipe(0) Allocate pa(0x8de20000) va(0x0x3fdb225000) size(291424)
stSnsrMode.u16Width 2560 stSnsrMode.u16Height 1440 25.000000 wdrMode 0 pstSnsObj 0x1062d0
[SAMPLE_COMM_VI_StartMIPI]-494: sensor 0 stDevAttr.devno 0
awbInit ver 6.9@2021500
0 R:1400 B:3100 CT:2850
1 R:1500 B:2500 CT:3900
2 R:2300 B:1600 CT:6500
Golden 1024 1024 1024
WB Quadratic:0
isWdr:0
ViPipe:0,===GC4653 1440P 30fps 10bit LINEAR Init OK!===
********************************************************************************
cvi_bin_isp message
gerritId:      97347          commitId:      fc6ce647       
md5:           d6db2297ddfd44e8252c1f3f888f47b2
sensorNum      1              
sensorName0    4653           

PQBIN message
gerritId:      
              commitId:      fc6ce647       
md5:           d6db2297ddfd44e8252c1f3f888f47b2
sensorNum      1              
sensorName0    4653           

author:        lxowalle       desc:          gc4653 30fps   
createTime:    2024-03-26 13:41:34version:                      
tool Version:       v3.0.5.48           mode:      
********************************************************************************
[SAMPLE_COMM_ISP_Thread]-95: ISP Dev 0 running!
0 R:1298 B:3773 CT:2688
1 R:1629 B:2599 CT:3890
2 R:2430 B:1675 CT:7300
Golden 1629 1024 2599
wdrLEOnly:1

想请问一下是否有这个样例使用摄像头输入的命令行使用方法,或者是否有其它使用摄像头输入视频并进行视频编码的样例?

lxowalle commented 5 months ago

现在还没有提供其他相关的示例,可以先自己看看算能的文档,很详细的介绍了API的参数含义https://doc.sophgo.com/cvitek-develop-docs/master/docs_latest_release/CV180x_CV181x/zh/01.software/MPI/Media_Processing_Software_Development_Reference/build/html/7_Video_Encoding/API_Reference.html

981213 commented 5 months ago

糊出来了。。但是问题比较多 我另开Issue问。

#include "cvi_venc.h"
#include <stdbool.h>
#include <stdio.h>
#include <cvi_sys.h>

#include <sample_comm.h>

static SAMPLE_VI_CONFIG_S g_stViConfig;
static SAMPLE_INI_CFG_S g_stIniCfg;

CVI_S32 sys_vpss_init(VPSS_GRP VpssGrp, SIZE_S stSizeIn, SIZE_S stSizeOut)
{
    VPSS_GRP_ATTR_S stVpssGrpAttr;
    VPSS_CHN VpssChn = VPSS_CHN0;
    CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM] = { 0 };
    VPSS_CHN_ATTR_S astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
    CVI_S32 s32Ret = CVI_SUCCESS;

    stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
    stVpssGrpAttr.enPixelFormat =
        SAMPLE_PIXEL_FORMAT; // PIXEL_FORMAT_YUYV / SAMPLE_PIXEL_FORMAT / PIXEL_FORMAT_UYVY / PIXEL_FORMAT_YUV_400
    stVpssGrpAttr.u32MaxW = stSizeIn.u32Width;
    stVpssGrpAttr.u32MaxH = stSizeIn.u32Height;
    stVpssGrpAttr.u8VpssDev = 0;

    astVpssChnAttr[VpssChn].u32Width = stSizeOut.u32Width;
    astVpssChnAttr[VpssChn].u32Height = stSizeOut.u32Height;
    astVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR;
    astVpssChnAttr[VpssChn].enPixelFormat = SAMPLE_PIXEL_FORMAT;
    astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = 30;
    astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = 30;
    astVpssChnAttr[VpssChn].u32Depth = 0;
    astVpssChnAttr[VpssChn].bMirror = CVI_FALSE;
    astVpssChnAttr[VpssChn].bFlip = CVI_FALSE;
    astVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_AUTO;
    astVpssChnAttr[VpssChn].stAspectRatio.bEnableBgColor = CVI_TRUE;
    astVpssChnAttr[VpssChn].stAspectRatio.u32BgColor = COLOR_RGB_BLACK;
    astVpssChnAttr[VpssChn].stNormalize.bEnable = CVI_FALSE;

    /*start vpss*/
    abChnEnable[0] = CVI_TRUE;
    s32Ret = SAMPLE_COMM_VPSS_Init(VpssGrp, abChnEnable, &stVpssGrpAttr,
                       astVpssChnAttr);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("init vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto error;
    }

    s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr,
                    astVpssChnAttr);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
        goto error;
    }

    return s32Ret;
error:
    return s32Ret;
}

static int sys_vi_init(void)
{
    MMF_VERSION_S stVersion;
    SAMPLE_INI_CFG_S stIniCfg;
    SAMPLE_VI_CONFIG_S stViConfig;

    PIC_SIZE_E enPicSize;
    SIZE_S stSize;
    CVI_S32 s32Ret = CVI_SUCCESS;
    LOG_LEVEL_CONF_S log_conf;

    CVI_SYS_GetVersion(&stVersion);
    SAMPLE_PRT("MMF Version:%s\n", stVersion.version);

    log_conf.enModId = CVI_ID_LOG;
    log_conf.s32Level = CVI_DBG_INFO;
    CVI_LOG_SetLevelConf(&log_conf);

    // Get config from ini if found.
    if (SAMPLE_COMM_VI_ParseIni(&stIniCfg)) {
        SAMPLE_PRT("Parse complete\n");
    }

    //Set sensor number
    CVI_VI_SetDevNum(stIniCfg.devNum);
    /************************************************
     * step1:  Config VI
     ************************************************/
    s32Ret = SAMPLE_COMM_VI_IniToViCfg(&stIniCfg, &stViConfig);
    if (s32Ret != CVI_SUCCESS)
        return s32Ret;

    memcpy(&g_stViConfig, &stViConfig, sizeof(SAMPLE_VI_CONFIG_S));
    memcpy(&g_stIniCfg, &stIniCfg, sizeof(SAMPLE_INI_CFG_S));

    printf("Pixel format: %d\n", stViConfig.astViInfo[0].stChnInfo.enPixFormat);
    /************************************************
     * step2:  Get input size
     ************************************************/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stIniCfg.enSnsType[0],
                        &enPicSize);
    if (s32Ret != CVI_SUCCESS) {
        CVI_TRACE_LOG(
            CVI_DBG_ERR,
            "SAMPLE_COMM_VI_GetSizeBySensor failed with %#x\n",
            s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed with %#x\n",
               s32Ret);
        return s32Ret;
    }

    /************************************************
     * step3:  Init modules
     ************************************************/
    s32Ret = SAMPLE_PLAT_SYS_INIT(stSize);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("sys init failed. s32Ret: 0x%x !\n", s32Ret);
        return s32Ret;
    }

    VI_VPSS_MODE_S vivpssmode;
    VPSS_MODE_S stVPSSMode;
    vivpssmode.aenMode[0] = vivpssmode.aenMode[1] = VI_OFFLINE_VPSS_ONLINE;
    stVPSSMode.enMode = VPSS_MODE_SINGLE;
    stVPSSMode.aenInput[0] = VPSS_INPUT_ISP;
    stVPSSMode.ViPipe[0] = 0;
    s32Ret = CVI_SYS_SetVIVPSSMode(&vivpssmode);
    if (s32Ret != CVI_SUCCESS) {
        CVI_TRACE_LOG(CVI_DBG_ERR,
                  "CVI_SYS_SetVIVPSSMode failed with %#x\n",
                  s32Ret);
        return s32Ret;
    }

    s32Ret = CVI_SYS_SetVPSSModeEx(&stVPSSMode);
    if (s32Ret != CVI_SUCCESS) {
        CVI_TRACE_LOG(CVI_DBG_ERR,
                  "CVI_SYS_SetVPSSModeEx failed with %#x\n",
                  s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_PLAT_VI_INIT(&stViConfig);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("vi init failed. s32Ret: 0x%x !\n", s32Ret);
        return s32Ret;
    }

    SIZE_S size_out;
    SAMPLE_COMM_SYS_GetPicSize(PIC_720P, &size_out);
    s32Ret = sys_vpss_init(0, stSize, size_out);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("vpss init failed. s32Ret: 0x%x !\n", s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(0, 0, 0);
    if (s32Ret != CVI_SUCCESS) {
        SAMPLE_PRT("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
        return s32Ret;
    }

    return CVI_SUCCESS;
}

static void sys_vi_deinit(void)
{
    CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM] = { 1 };
    SAMPLE_COMM_VI_UnBind_VPSS(0, 0, 0);

    SAMPLE_COMM_VPSS_Stop(0, abChnEnable);

    SAMPLE_COMM_VI_DestroyIsp(&g_stViConfig);

    SAMPLE_COMM_VI_DestroyVi(&g_stViConfig);

    SAMPLE_COMM_SYS_Exit();
}

static int sys_venc_h264_init()
{
    CVI_S32 s32Ret;
    VENC_CHN ch = 0;
    VENC_CHN_ATTR_S venc_chn_attr = {
        .stVencAttr = {
            .enType = PT_H264,
            .u32MaxPicWidth = 1280,
            .u32MaxPicHeight = 720,
            .u32BufSize = 1024 * 1024,
            .u32Profile = 66,
            .bByFrame = CVI_TRUE,
            .u32PicWidth = 1280,
            .u32PicHeight = 720,
            .bSingleCore = CVI_TRUE,
            .bEsBufQueueEn = CVI_FALSE,
            .bIsoSendFrmEn = CVI_FALSE,
        },
        .stRcAttr = {
            .enRcMode = VENC_RC_MODE_H264CBR,
            .stH264Cbr = {
                .u32Gop = 60,
                .u32StatTime = 3,
                .u32SrcFrameRate = 30,
                .fr32DstFrameRate = 30,
                .u32BitRate = 2048,
                .bVariFpsEn = CVI_FALSE,
            }
        },
        .stGopAttr = {
            .enGopMode = VENC_GOPMODE_NORMALP,
            .stNormalP = {
                .s32IPQpDelta = 2
            }
        },
    };

    s32Ret = CVI_VENC_CreateChn(ch, &venc_chn_attr);
    if (s32Ret != CVI_SUCCESS) {
        printf("CVI_VENC_CreateChn [%d] failed with %d\n", ch, s32Ret);
        return s32Ret;
    }

    SAMPLE_COMM_VPSS_Bind_VENC(0, 0, 0);

    VENC_RECV_PIC_PARAM_S stRecvParam;
    stRecvParam.s32RecvPicNum = -1;
    s32Ret = CVI_VENC_StartRecvFrame(ch, &stRecvParam);
    if (s32Ret != CVI_SUCCESS) {
        printf("CVI_VENC_StartRecvPic failed with %d\n", s32Ret);
        return CVI_FAILURE;
    }

    return s32Ret;
}

static void sys_venc_deinit()
{
    CVI_S32 s32Ret;
    SAMPLE_COMM_VPSS_UnBind_VENC(0, 0, 0);
    CVI_VENC_StopRecvFrame(0);
        s32Ret = CVI_VENC_ResetChn(0);
    if (s32Ret != CVI_SUCCESS) {
        CVI_VENC_ERR("CVI_VENC_ResetChn vechn[%d] failed with %#x!\n",
                0, s32Ret);
    }
    CVI_VENC_DestroyChn(0);
}

static int venc_save_stream_one(FILE *fp)
{
    CVI_S32 s32Ret;
    VENC_CHN VencChn = 0;
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream = {};
    s32Ret = CVI_VENC_QueryStatus(VencChn, &stStat);
    if (s32Ret != CVI_SUCCESS) {
        CVI_VENC_ERR("CVI_VENC_QueryStatus, Vench = %d, s32Ret = %d\n",
                 VencChn, s32Ret);
        return s32Ret;
    }
    if (!stStat.u32CurPacks) {
        CVI_VENC_ERR("u32CurPacks = NULL!\n");
        return s32Ret;
    }
    stStream.pstPack =
        (VENC_PACK_S *)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
    if (stStream.pstPack == NULL) {
        CVI_VENC_ERR("malloc memory failed!\n");
        return s32Ret;
    }

    int retry = 0;
    s32Ret = CVI_VENC_GetStream(VencChn, &stStream, 1000);
    for (retry = 0; s32Ret == CVI_ERR_VENC_BUSY && retry < 10; retry++) {
        printf("CVI_VENC_GetStream, VencChn Retry= %d,s32Ret = 0x%X\n",
               retry, s32Ret);
    }
    if (s32Ret != CVI_SUCCESS) {
        if (s32Ret == CVI_ERR_VENC_BUSY) {
            printf("CVI_VENC_GetStream, VencChn Retry= %d,s32Ret = 0x%X\n",
                   retry, s32Ret);
            goto out;
        } else {
            printf("CVI_VENC_GetStream, VencChn = %d, s32Ret = 0x%X\n",
                   VencChn, s32Ret);
            goto out;
        }
    }
    puts("get stream one");
    VENC_PACK_S *ppack;
    for (CVI_U32 i = 0; i < stStream.u32PackCount; i++) {
        ppack = &stStream.pstPack[i];
        fwrite(ppack->pu8Addr + ppack->u32Offset,
               ppack->u32Len - ppack->u32Offset, 1, fp);
    }

    s32Ret = CVI_VENC_ReleaseStream(VencChn, &stStream);
    if (s32Ret != CVI_SUCCESS) {
        CVI_VENC_ERR("CVI_VENC_ReleaseStream, s32Ret = %d\n", s32Ret);
        goto out;
    }

out:
    free(stStream.pstPack);
    return s32Ret;
}

static int venc_save_stream(int framecnt)
{
    int s32Ret;
    int venc_fd = CVI_VENC_GetFd(0);
    if (venc_fd <= 0) {
        printf("Venc failed to get fd %x\n", venc_fd);
        return venc_fd;
    }

    FILE *fp = fopen("stream.h264", "wb");
    if (!fp) {
        puts("failed to open file for writing");
        return -1;
    }

    while (framecnt--) {
        // this doesn't work
        // struct timeval TimeoutVal;
        // fd_set read_fds;

        // FD_ZERO(&read_fds);
        // FD_SET(venc_fd, &read_fds);
        // TimeoutVal.tv_sec  = 3;
        // TimeoutVal.tv_usec = 0;
        // s32Ret = select(venc_fd + 1, &read_fds, NULL, NULL, &TimeoutVal);
        // if (s32Ret < 0) {
        //  SAMPLE_PRT("select failed!\n");
        //  return s32Ret;
        // } else if (s32Ret == 0) {
        //  SAMPLE_PRT("select time out??\n");
        // } else if (!FD_ISSET(venc_fd, &read_fds)) {
        //  SAMPLE_PRT("select return not set??\n");
        // }

        s32Ret = venc_save_stream_one(fp);
        if (s32Ret) {
            printf("failed to save one stream\n");
            return s32Ret;
        }
    }
    return 0;
}

int main()
{
    sys_vi_init();
    sys_venc_h264_init();
    venc_save_stream(60);
    sys_venc_deinit();
    sys_vi_deinit();
    return 0;
}