1338
- 收藏
- 点赞
- 分享
- 举报
Hi3536编码采用CBR,手动控制编码帧率和码率,报0xa0088003(参数超出合法范围)错误
从网上找到一个读取YUV文件并编码为H264的样例程序,正常运行成功,输入和输出帧率均为30fps,采用CBR固定码率编码,平均码率为6mbps;然后我做实验需要在控制码率一定的情况下编码出不同帧率的码流,于是直接修改VENC_ATTR_H264_CBR_S结构体的目标帧率fr32DstFrmRate为25,编译运行后报错:参数超出合法范围。
程序代码如下:
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include "sample_comm.h"
VIDEO_NORM_E gs_enNorm = VIDEO_ENCODING_MODE_NTSC;
/**
VI_DEV_ATTR_S DEV_ATTR_BT1120_1080P_BASE_1 = {
//interface mode
VI_MODE_BT1120_STANDARD,
//multiplex mode
VI_WORK_MODE_1Multiplex,
{0xFF000000, 0xFF0000},
VI_SCAN_PROGRESSIVE,
{ -1, -1, -1, -1},
VI_INPUT_DATA_UVUV,
{
VI_VSYNC_PULSE, VI_VSYNC_NEG_HIGH, VI_HSYNC_VALID_SINGNAL, VI_HSYNC_NEG_HIGH, VI_VSYNC_NORM_PULSE, VI_VSYNC_VALID_NEG_HIGH,
{
0, 1920, 0,
0, 1080, 0,
0, 0, 0
}
},
VI_PATH_BYPASS,
VI_DATA_TYPE_YUV,
HI_FALSE,
// {0, 0, 1920, 1080}
};
**/
/******************************************************************************
* funciton : 编码通道处理主流程
******************************************************************************/
HI_VOID* SAMPLE_COMM_VENC_GetVencStreamProcEx(HI_VOID)
{
VENC_CHN_ATTR_S stVencChnAttr;
struct timeval TimeoutVal;
fd_set read_fds;
HI_S32 VencFd;
FILE *pFile1, *pFile2;
VENC_CHN_STAT_S stStat;
VENC_STREAM_S stStream;
HI_S32 s32Ret ,frame = 0;
VENC_CHN VencChn = 0;
PAYLOAD_TYPE_E enPayLoadType = PT_H264;
/******************************************************************************************************************
step 1: check & prepare save-file & venc-fd, decide the stream file name, and open file to save stream,Set Venc Fd
********************************************************************************************************************/
pFile1 = fopen("dog_512_8.h264","wb+");
if(pFile1 == NULL)
{
printf("new test.h264 file failed\n");
return -1;
}
pFile2 = fopen("./dog.yuv","rb");
if(pFile2 == NULL)
{
printf("open yuv file failed\n");
return -1;
}
VencFd = HI_MPI_VENC_GetFd(VencChn);
if (VencFd < 0)
{
SAMPLE_PRT("HI_MPI_VENC_GetFd failed with %#x!\n",VencFd);
return NULL;
}
VB_BLK handleY = VB_INVALID_HANDLE;
HI_U64 phyYaddr;
HI_U64 *pVirYaddr;
VIDEO_FRAME_INFO_S *pstFrame = malloc(sizeof(VIDEO_FRAME_INFO_S));
/*************************************************************
step 2: Start to get streams of each channel.
***************************************************************/
while(frame < 450) {
/* 分配物理buffer并且映射到用户空间 */
do
{
handleY = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, 1920 * 1080 * 3 / 2 , NULL);
if (VB_INVALID_HANDLE == handleY) {
SAMPLE_PRT("handleY is VB_INVALID_HANDLE\n");
}
}while (VB_INVALID_HANDLE == handleY);
if(handleY == VB_INVALID_HANDLE)
{
printf("getblock for y failed\n");
return -1;
}else {
printf("handleY is %d\n", handleY);
}
VB_POOL poolID = HI_MPI_VB_Handle2PoolId (handleY);//得到poolID
printf("pool ID = %d\n", poolID);
phyYaddr = HI_MPI_VB_Handle2PhysAddr(handleY);
if( phyYaddr == 0)
{
printf("HI_MPI_VB_Handle2PhysAddr for handleY failed\n");
return -1;
}
pVirYaddr = (HI_U64 *) HI_MPI_SYS_Mmap(phyYaddr, 1920 * 1080 * 3 / 2);
/* 图像帧结构初始化 */
memset(&(pstFrame->stVFrame),0x00,sizeof(VIDEO_FRAME_S));
pstFrame->stVFrame.u32Width = 1920;
pstFrame->stVFrame.u32Height = 1080;
pstFrame->stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
// pstFrame->stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_PLANAR_420;
pstFrame->u32PoolId = poolID;
pstFrame->stVFrame.u32PhyAddr[0] = phyYaddr;
pstFrame->stVFrame.u32PhyAddr[1] = phyYaddr + 1920 * 1080;
pstFrame->stVFrame.pVirAddr[0] = (HI_U64)pVirYaddr;
pstFrame->stVFrame.pVirAddr[1] = (HI_U64)pVirYaddr + 1920 * 1080;
pstFrame->stVFrame.u32Stride[0] = 1920 ;
pstFrame->stVFrame.u32Stride[1] = 1920 ;
pstFrame->stVFrame.u32Field = VIDEO_FIELD_FRAME;
pstFrame->stVFrame.enCompressMode = COMPRESS_MODE_NONE;
pstFrame->stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
pstFrame->stVFrame.u64pts = frame * 33;
pstFrame->stVFrame.u32TimeRef = frame * 2;
s32Ret = fread(pVirYaddr,1920 * 1080 * 3 / 2, 1, pFile2);
if(s32Ret < 0)
{
printf("fread yuv420sp failed\n");
return -1;
}
s32Ret = HI_MPI_VENC_SendFrame(VencChn, pstFrame, -1);
if(s32Ret != 0)
{
printf("HI_MPI_VENC_SendFrame failed %#x\n",s32Ret);
return -1;
}
/* 使用select循环读取编码后的数据 */
FD_ZERO(&read_fds);
FD_SET(VencFd, &read_fds);
TimeoutVal.tv_sec = 2;
TimeoutVal.tv_usec = 0;
s32Ret = select(VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
if (s32Ret < 0)
{
SAMPLE_PRT("select failed!\n");
break;
}
else if (s32Ret == 0)
{
SAMPLE_PRT("get venc stream time out, exit thread\n");
continue;
}
else
{
if (FD_ISSET(VencFd, &read_fds))
{
printf("select has data can read\n");
memset(&stStream, 0, sizeof(stStream));
/* 查询编码器状态 */
s32Ret = HI_MPI_VENC_Query(VencChn, &stStat);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VENC_Query chn[%d] failed with %#x!\n", VencChn, s32Ret);
break;
}
if(0 == stStat.u32CurPacks)
{
SAMPLE_PRT("NOTE: Current frame is NULL!\n");
continue;
}
/* 分配buffer准备读取Pack */
stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
if (NULL == stStream.pstPack)
{
SAMPLE_PRT("malloc stream pack failed!\n");
break;
}
/* 读取编码好的数据 */
stStream.u32PackCount = stStat.u32CurPacks;
s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, HI_TRUE);
if (HI_SUCCESS != s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);
break;
}
/* 保存读取到的编码数据 */
s32Ret = SAMPLE_COMM_VENC_SaveStream(enPayLoadType, pFile1, &stStream);
if (HI_SUCCESS != s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
SAMPLE_PRT("save stream failed with %#x\n", s32Ret);
break;
}
/* 释放buffer给编码通道 */
s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);
if (HI_SUCCESS != s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
break;
}
free(stStream.pstPack);
stStream.pstPack = NULL;
}
}
// HI_MPI_VI_ReleaseFrame(ViChn, pstFrame);
HI_MPI_VB_ReleaseBlock(handleY);
HI_MPI_VB_DestroyPool(poolID);
printf("frame %d\n",frame);
frame++;
}
fclose(pFile1);
fclose(pFile2);
return HI_SUCCESS;
}
/******************************************************************************
* function : H.264@1080p@30fps+H.264@VGA@30fps
******************************************************************************/
HI_S32 SAMPLE_VENC_1080P_CLASSIC(HI_VOID)
{
PAYLOAD_TYPE_E enPayLoad = PT_H264;
PIC_SIZE_E enSize = PIC_HD1080;
VB_CONF_S stVbConf;
// VPSS_GRP VpssGrp;
// VPSS_CHN VpssChn;
// VPSS_GRP_ATTR_S stVpssGrpAttr;
// VPSS_CHN_ATTR_S stVpssChnAttr;
// VPSS_CHN_MODE_S stVpssChnMode;
VENC_CHN VencChn;
SAMPLE_RC_E enRcMode= SAMPLE_RC_CBR;
// SAMPLE_RC_E enRcMode= SAMPLE_RC_VBR;
HI_S32 s32ChnNum=1;
HI_S32 s32Ret = HI_SUCCESS;
HI_U32 u32BlkSize;
SIZE_S stSize;
/******************************************
step 1: 初始化系统
******************************************/
memset(&stVbConf,0,sizeof(VB_CONF_S));
stVbConf.u32MaxPoolCnt = 128;
u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,enSize, SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);
stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;
stVbConf.astCommPool[0].u32BlkCnt = 20;
printf("--------blksize = %d--------\n",u32BlkSize);
/******************************************
step 2: 初始化mmp
******************************************/
s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("system init failed with %d!\n", s32Ret);
goto END_VENC_1080P_CLASSIC_0;
}
/******************************************
step 4: 启动venc编码通道
******************************************/
VencChn = 0;
s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad, gs_enNorm, enSize, enRcMode);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("Start Venc failed! %#x\n", s32Ret);
goto END_VENC_1080P_CLASSIC_5;
}
/******************************************
step 5: 采集帧,处理帧,保存帧
******************************************/
s32Ret = SAMPLE_COMM_VENC_GetVencStreamProcEx();
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("Start Venc failed---! %#x\n",s32Ret);
goto END_VENC_1080P_CLASSIC_5;
}
/******************************************
step 6: exit process
******************************************/
END_VENC_1080P_CLASSIC_5:
END_VENC_1080P_CLASSIC_0:
SAMPLE_COMM_VENC_Stop(VencChn);
SAMPLE_COMM_SYS_Exit();
return s32Ret;
}
/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_VENC_HandleSig(HI_S32 signo)
{
if (SIGINT == signo || SIGTERM == signo)
{
// SAMPLE_COMM_ISP_Stop();
SAMPLE_COMM_SYS_Exit();
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
}
exit(-1);
}
/******************************************************************************
* function : main()
* Description : video venc sample
******************************************************************************/
int main(int argc, char* argv[])
{
HI_S32 s32Ret;
signal(SIGINT, SAMPLE_VENC_HandleSig);
signal(SIGTERM, SAMPLE_VENC_HandleSig);
/* 开启编码流程 */
s32Ret = SAMPLE_VENC_1080P_CLASSIC();
if (HI_SUCCESS == s32Ret)
{
printf("program exit normally!\n");
}
else
{
printf("program exit abnormally!\n");
}
exit(s32Ret);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
然后我修改帧率和码率是直接在SDK的sample中的sample_comm_venc.c中SAMPLE_COMM_VENC_Start()函数的CBR部分修改的。
logmpp的输出如下:
运行时查看venc调试信息如下(好像没有获取到我的输入帧率和目标帧率):
麻烦各位大神帮忙看一下
我来回答
回答4个
时间排序
认可量排序
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2020-05-18 17:56:37
-
2019-03-13 15:27:13
-
2020-07-22 17:24:15
-
2018-11-19 08:53:29
-
2020-08-06 12:57:35
-
2020-03-17 18:14:42
-
2015-05-11 18:09:10
-
2019-08-30 09:57:03
-
2020-07-23 17:45:58
-
2017-09-20 15:05:29
-
2020-10-29 11:14:15
-
2019-07-12 18:29:38
-
2013-01-29 23:51:10
-
2018-02-24 18:14:23
-
2016-11-08 13:43:18
-
2019-03-13 15:57:54
-
2017-08-29 16:15:42
-
2018-03-01 15:56:14
-
2018-01-18 13:56:49
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认