大家好
我使用DM6467t进行1080P的h264编码,但总是在回放的时候不连续,我使用CCS进行h264编码的处理,代码如下:
1. 在DSP端采集h264编码器
…
/* Initialize H264 parameters */
gVidEncObj.prm.videncParams.size = sizeof(IH264FHDVENC_Params);
gVidEncObj.prm = IH264FHDVENC_PARAMS;
gVidEncObj.prm.videncParams.encodingPreset = 0; /* N/A */
/* Set rate control type, CBR or VBR */
if (data->rateCtlType == VIDENC_RC_OFF)
gVidEncObj.prm.videncParams.rateControlPreset = IVIDEO_NONE;
else if (data->rateCtlType == VIDENC_RC_VBR)
gVidEncObj.prm.videncParams.rateControlPreset = IVIDEO_STORAGE;
else gVidEncObj.prm.videncParams.rateControlPreset = IVIDEO_LOW_DELAY;
/* Set Video size, max is 1920 x 1088 */
gVidEncObj.prm.videncParams.maxWidth = data->maxWidth;
gVidEncObj.prm.videncParams.maxHeight = data->maxHeight;
gVidEncObj.prm.videncParams.maxFrameRate = data->maxFrameRate * 1000;
gVidEncObj.prm.videncParams.maxBitRate = data->maxBitRate;
gVidEncObj.prm.videncParams.dataEndianness = XDM_LE_32;
gVidEncObj.prm.videncParams.maxInterFrameInterval = 0; /* N/A */
gVidEncObj.prm.videncParams.inputChromaFormat = H264FHDVENC_TI_422SP;
gVidEncObj.prm.videncParams.inputContentType = IVIDEO_PROGRESSIVE;
gVidEncObj.prm.videncParams.reconChromaFormat = XDM_CHROMA_NA;
/* Profile ID and level ID */
gVidEncObj.prm.profileIdc = data->profileId;
gVidEncObj.prm.levelIdc = data->levelId;
gVidEncObj.prm.EntropyCodingMode = 0; /* Mode of entropy coding to be used for encoding. */
/* Video dynamic parameter */
gVidEncObj.dyn.videncDynamicParams.size = sizeof(IH264FHDVENC_DynamicParams);
gVidEncObj.dyn.videncDynamicParams.inputWidth = gVidEncObj.prm.videncParams.maxWidth;
gVidEncObj.dyn.videncDynamicParams.inputHeight = gVidEncObj.prm.videncParams.maxHeight;
gVidEncObj.dyn.videncDynamicParams.refFrameRate = gVidEncObj.prm.videncParams.maxFrameRate;
gVidEncObj.dyn.videncDynamicParams.targetFrameRate = gVidEncObj.prm.videncParams.maxFrameRate;
gVidEncObj.dyn.videncDynamicParams.targetBitRate = gVidEncObj.prm.videncParams.maxBitRate;
gVidEncObj.dyn.videncDynamicParams.intraFrameInterval = data->maxFrameRate;
gVidEncObj.dyn.videncDynamicParams.generateHeader = XDM_ENCODE_AU;
gVidEncObj.dyn.videncDynamicParams.captureWidth = 0; /* N/A */
gVidEncObj.dyn.videncDynamicParams.forceFrame = IVIDEO_NA_FRAME;
gVidEncObj.dyn.videncDynamicParams.interFrameInterval = 0; /* N/A */
gVidEncObj.dyn.videncDynamicParams.mbDataFlag = 0; /* N/A */
gVidEncObj.dyn.OutBufSize = -1;
gVidEncObj.dyn.QPISlice = 28; /* Initial Quantization Parameter, [0,51], Default: 28 */
gVidEncObj.dyn.QPSlice = 28; /* Initial Quantization Parameter, [0,51], Default: 28 */
gVidEncObj.dyn.RateCtrlQpMax = 51; /* This is the maximum value of the QP, [0,51] */
gVidEncObj.dyn.RateCtrlQpMin = 0; /* This is the minimum value of the QP, [0,51] */
gVidEncObj.dyn.NumRowsInSlice = 0; /* N/A */
gVidEncObj.dyn.LfDisableIdc = 0; /* Loop filter, default is enable */
gVidEncObj.dyn.LFAlphaC0Offset = 0; /* This is the Alpha and C0 offset for the H.264 loop filter value divided by 2. [-6,+6], Default: 0 */
gVidEncObj.dyn.LFBetaOffset = 0; /* This is the Beta and C0 offset for the H.264 loop filter value divided by 2. [-6,+6], Default: 0 */
gVidEncObj.dyn.ChromaQPOffset = 0; /* The chroma QP offset for determining the QP of the chrominance blocks based on the QP of the luminance blocks. Valid range is [-12, 12], Default: 0*/
gVidEncObj.dyn.SecChromaQPOffset = 0; /* The Second Chroma QP Offset for determining the QP of the Cr blocks based on the QP of the luminance blocks. This is used in High profile only. The valid range is [-12, 12]. Default: 0*/
gVidEncObj.dyn.PicAFFFlag = 0; /* N/A */
gVidEncObj.dyn.PicOrderCountType = 0; /* N/A */
gVidEncObj.dyn.AdaptiveMBs = 0; /* N/A */
gVidEncObj.dyn.SEIParametersFlag = 0; /* N/A */
gVidEncObj.dyn.VUIParametersFlag = 0; /* N/A */
gVidEncObj.dyn.NALUnitCallback = 0; /* N/A */
gVidEncObj.dyn.SkipStartCodesInCallback = 1; /* N/A */
gVidEncObj.dyn.Intra4x4EnableFlag = 3; /* Enable 4×4 intra modes in both I and P Pictures */
gVidEncObj.dyn.BlockingCallFlag = 0; /* N/A */
gVidEncObj.dyn.MESelect = 1; /* N/A */
gVidEncObj.dyn.ME1080iMode = 0; /* N/A */
gVidEncObj.dyn.MVDataFlag = 0; /* N/A */
gVidEncObj.dyn.Transform8x8DisableFlag = 1; /* N/A */
gVidEncObj.dyn.Intra8x8EnableFlag = 0; /* N/A */
gVidEncObj.dyn.InterlaceReferenceMode = 0; /* N/A */
gVidEncObj.dyn.ChromaConversionMode = 0; /* 422 to 420 Chroma conversion mode select, 0: Line drop, 1: Average */
gVidEncObj.dyn.maxDelay = 1000; /* Maximum delay (in milli-seconds) */
gVidEncObj.dyn.MaxSlicesSupported_IFrame= 263; /* Maximum number of slices supported */
gVidEncObj.dyn.MaxSlicesSupported_PFrame= 263; /* Maximum number of slices supported */
gVidEncObj.dyn.sliceCodingParams.sliceCodingPreset = IH264_SLICECODING_DEFAULT;
gVidEncObj.dyn.sliceCodingParams.sliceMode = IH264_SLICEMODE_BYTES;
gVidEncObj.dyn.sliceCodingParams.sliceUnitSize = 1500; /* NALU size, MTU size */
gVidEncObj.dyn.sliceCodingParams.streamFormat = IH264_BYTE_STREAM;
…
2. 执行h264编码
status.videncStatus.size = sizeof(IH264FHDVENC_Status);
inArgs.videncInArgs.size = sizeof(IH264FHDVENC_InArgs);
inArgs.videncInArgs.inputID = 0;
outArgs.videncOutArgs.size = sizeof(IH264FHDVENC_OutArgs);
gVidEncObj.dyn.videncDynamicParams.inputWidth = prm->width;
gVidEncObj.dyn.videncDynamicParams.inputHeight = prm->height;
gVidEncObj.inBuf.frameWidth = gVidEncObj.dyn.videncDynamicParams.inputWidth;
gVidEncObj.inBuf.framePitch = gVidEncObj.dyn.videncDynamicParams.inputWidth;
gVidEncObj.inBuf.frameHeight = gVidEncObj.dyn.videncDynamicParams.inputHeight;
/* Frame rate */
if (prm->frameRate!=0)
{
gVidEncObj.dyn.videncDynamicParams.refFrameRate = prm->frameRate * 1000;
gVidEncObj.dyn.videncDynamicParams.targetFrameRate = prm->frameRate * 1000;
gVidEncObj.dyn.videncDynamicParams.intraFrameInterval = prm->frameRate;
}
/* Bit rate in bps */
if (prm->bitRate!=0)
{
gVidEncObj.dyn.videncDynamicParams.targetBitRate = prm->bitRate;
}
/* Prepares video input buffer */
len = gVidEncObj.dyn.videncDynamicParams.inputWidth * gVidEncObj.dyn.videncDynamicParams.inputHeight;
/* Configure Output buffer */
gVidEncObj.outBuf.bufs[0] = (XDAS_Int8 *)prm->outAddr;
for (idx=1; idx<gVidEncObj.outBuf.numBufs; idx++) {
gVidEncObj.outBuf.bufs[idx] = gVidEncObj.outBuf.bufs[idx-1] + gVidEncObj.outBuf.bufSizes[idx-1];
}
BCACHE_wbInvAll();
/* Do Key frame encoder, SPS + PPS + IDR */
len = 0;
outArgs.videncOutArgs.inputFrameSkip = 0;
if (prm->forceKey)
{
/* Generate frame header with SPS and PPS */
gVidEncObj.dyn.videncDynamicParams.generateHeader = XDM_GENERATE_HEADER;
H264FHDVENC_control(gVidEncObj.hdl, XDM_SETPARAMS, &gVidEncObj.dyn, &status);
if (H264FHDVENC_encode(gVidEncObj.hdl, &gVidEncObj.inBuf, &gVidEncObj.outBuf, &inArgs, &outArgs) != XDM_EOK)
{
st->bytesGenerated = 0;
return -1;
}
len = outArgs.videncOutArgs.bytesGenerated;
/* Generate IDR frame offset from header */
gVidEncObj.outBuf.bufs[0] = (XDAS_Int8 *)(prm->outAddr + len);
for (idx=1; idx<gVidEncObj.outBuf.numBufs; idx++) {
gVidEncObj.outBuf.bufs[idx] = gVidEncObj.outBuf.bufs[idx-1] + gVidEncObj.outBuf.bufSizes[idx-1];
}
gVidEncObj.dyn.videncDynamicParams.generateHeader = XDM_ENCODE_AU;
gVidEncObj.dyn.videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME;
H264FHDVENC_control(gVidEncObj.hdl, XDM_SETPARAMS, &gVidEncObj.dyn, &status);
}
else
{
/* Generate P frame */
gVidEncObj.dyn.videncDynamicParams.generateHeader = XDM_ENCODE_AU;
gVidEncObj.dyn.videncDynamicParams.forceFrame = IVIDEO_NA_FRAME;
H264FHDVENC_control(gVidEncObj.hdl, XDM_SETPARAMS, &gVidEncObj.dyn, &status);
}
if (H264FHDVENC_encode(gVidEncObj.hdl, &gVidEncObj.inBuf, &gVidEncObj.outBuf, &inArgs, &outArgs) != XDM_EOK)
{
st->bytesGenerated = 0;
return -1;
}
…
我想知道问题是否出自编码器或编码器的配置上。
谢谢!!
Chris Meng:
你好,
请问你使用的是CBR么?如果是,请问你编码的分辨率和码流分别是多少?CBR在低码率情况下,为了达到码流控制,是允许丢帧的,这是不是你看到的不连续的现象?
You Richard:
回复 Chris Meng:
你好,
我在接收端接收到图像是完整的,没有丢帧的情况,我采用live555传输视频,但有个情况很奇怪,就是在第一个P帧和IDR帧的时间间隔比较大。我给出一个视频,请你看看是什么原因导致的,我的视频是1080P的。
谢谢
Richard
Chris Meng:
回复 You Richard:
你好,
你给的视频我这里VLC播放不出来,说是文件有错误。
You Richard:
回复 Chris Meng:
你好,
用暴风/QQ影音可以播放的,这个有什么不同的地方吗,如果是解码的问题,我6467T端应用怎么来满足它呢,但VLC播放视频流是可以的,只是不连续而已!
谢谢!
Richard