下面函数实现从camera -> yuv -> encoder -> stream buffer -> decoder -> yuv buffer -> display
void H264codecLoopBack(void)
{
//编码变量初始化(encoder init)
int ret;
unsigned int width, height;
unsigned int frame_rate, bitrate, gop_num;
unsigned int intraqp, qpmax;
float gamma;
unsigned int num_slices;
width = 640;
height = 480;
frame_rate = 25;
bitrate = 900;
gop_num = 12;
intraqp = 24;// (25 25)
qpmax = 24;//32;//50;(12,20,22)
gamma = 0.75;
long sizef;
//====================================================================
int nLoop;
DWORD t1, t2, t_diff; // tick for performance measurement
int perf_disp_period = 100;
wchar_t str_performance[8];
float fps;
//decoder
unsigned char *pStrmBuf;
int nFrameLeng;
unsigned char *pYUVBuf;
int nYUVLeng;
FRAMEX_CTX *pFrameExCtx;
unsigned char *delimiter;
int delimiter_leng;
FRAMEX_STRM_PTR file_strm;
SSBSIP_H264_STREAM_INFO stream_info;
SIZE_IMG_IDX size_img_idx;
//=================================================================================
#ifdef CODEC_FLAG
//Encoder init
//初始化编码器
//////////////////////////////////////
/// 1. Create new instance ///
/// (SsbSipH264EncodeInit) ///
//////////////////////////////////////
encoderHandle = SsbSipH264EncodeInit(width, height, frame_rate, bitrate, gop_num, intraqp, qpmax, gamma);
RETAILMSG(1,(L"\n HANDLE = 0x%X.\n", (DWORD) encoderHandle));
if (encoderHandle == NULL) {
return ;
}
////////////////////////////////////////////////////////////////////
/// 2. Set some configuration parameter for initialization ///
/// (SsbSipH264EncodeExe) ///
////////////////////////////////////////////////////////////////////
num_slices = 4;
// SsbSipH264EncodeSetConfig(handle, H264_ENC_SETCONF_NUM_SLICES, &num_slices);
////////////////////////////////////////////////
/// 3. Initialize the Encoder Instance ///
/// (SsbSipH264EncodeExe) ///
////////////////////////////////////////////////
if (SsbSipH264EncodeExe(encoderHandle) != SSBSIP_H264_ENC_RET_OK) {
RETAILMSG(1,(L"H.264 Encoder Instance Initialization Failed.\n"));
return ;
}
p_inbuf = (unsigned char *)SsbSipH264EncodeGetInBuf(encoderHandle, 0);
if (p_inbuf == NULL) {
RETAILMSG(1,(L"\n (ERROR)Input buffer is NULL\n"));
return ;
}
//填充满H264流buffer //fill all H264 stream buffers
encoderFrameBufCounter=inYUVbufCounter;
for (nLoop=0; nLoop
if(encoderFrameBufCounter!=inYUVbufCounter)
{
memcpy(p_inbuf,inYUVbuf[encoderFrameBufCounter],BUFF_SIZE);
ret = SsbSipH264EncodeExe(encoderHandle);
p_outbuf = (unsigned char *)SsbSipH264EncodeGetOutBuf(encoderHandle, &sizef);
memcpy(streamBufferInfo[encoderFrameBufCounter].strmBuf,p_outbuf,sizef);
streamBufferInfo[encoderFrameBufCounter].size=sizef;
nLoop++;
if(++encoderFrameBufCounter==MAX_STREAM_BUFFER_NUM)encoderFrameBufCounter=0;
}
Sleep(5);
}
//RETAILMSG(1,(L"\n Filled Frame buffer\n"));
//==========================================================================================
//Decoder
//初始化解码器
delimiter = delimiter_h264;
delimiter_leng = sizeof(delimiter_h264);
///////////////////////////////////
// FrameExtractor Initialization //
///////////////////////////////////
pFrameExCtx = FrameExtractorInit(FRAMEX_IN_TYPE_MEM, delimiter, delimiter_leng, 1);
//////////////////////////////////////
/// 1. Create new instance ///
//////////////////////////////////////
decoderHandle = SsbSipH264DecodeInit();
if (decoderHandle == NULL) {
RETAILMSG(1,(L"Decoder Init Failed.\n"));
return ;
}
/////////////////////////////////////////////
/// 2. Obtaining the Input Buffer ///
/// (SsbSipH264DecodeGetInBuf) ///
/////////////////////////////////////////////
pStrmBuf = (unsigned char *) SsbSipH264DecodeGetInBuf(decoderHandle, 204800);
if (pStrmBuf == NULL) {
RETAILMSG(1,(L"SsbSipH264DecodeGetInBuf Failed.\n"));
SsbSipH264DecodeDeInit(decoderHandle);
return ;
}
//copy first frame to decoder
memcpy(pStrmBuf,streamBufferInfo[encoderFrameBufCounter].strmBuf,streamBufferInfo[encoderFrameBufCounter].size);
nFrameLeng=streamBufferInfo[encoderFrameBufCounter].size;
////////////////////////////////////////////////////////////////
/// 3. Configuring the instance with the config stream ///
/// (SsbSipH264DecodeExe) ///
////////////////////////////////////////////////////////////////
if (SsbSipH264DecodeExe(decoderHandle, nFrameLeng) != SSBSIP_H264_DEC_RET_OK) {
RETAILMSG(1,(L"H.264 Decoder Configuration Failed.\n"));
return ;
}
/////////////////////////////////////
/// 4. Get stream information ///
/////////////////////////////////////
SsbSipH264DecodeGetConfig(decoderHandle, H264_DEC_GETCONF_STREAMINFO, &(stream_info));
//RETAILMSG(1,(L"\n\t width=%d height=%d.\n", stream_info[pip].width, stream_info[pip].height));
// Performance display interval setting
if ((stream_info.width == 320) && (stream_info.height == 240)) {
size_img_idx = SIZE_IMG_QVGA;
perf_disp_period = 200;
}
else if ((stream_info.width == 640) && (stream_info.height == 480)) {
size_img_idx = SIZE_IMG_VGA;
perf_disp_period = 100;
}
else if ((stream_info.width == 720) && (stream_info.height == 480)) {
size_img_idx = SIZE_IMG_SD;
perf_disp_period = 60;
}
else if ((stream_info.width == 720) && (stream_info.height == 576)) {
size_img_idx = SIZE_IMG_SD;
perf_disp_period = 60;
}
else {
size_img_idx = SIZE_IMG_UNDEF;
perf_disp_period = 100;
}
decoderBufCounter = 0;
//===========================================================================================
t1 = GetTickCount();
for (nLoop=0; ; ) {
//wait for camera one yuv stream buffer
if (WaitForSingleObject(hDecoderEvent, INFINITE) == WAIT_OBJECT_0) //等待送camera 一帧数据
{
memcpy(p_inbuf,inYUVbuf[encoderFrameBufCounter],BUFF_SIZE); //送camera一帧YUV 数据到编码器 //send yuv frame to encoder
ret = SsbSipH264EncodeExe(encoderHandle);//编码
p_outbuf = (unsigned char *)SsbSipH264EncodeGetOutBuf(encoderHandle, &sizef);
memcpy(streamBufferInfo[encoderFrameBufCounter].strmBuf,p_outbuf,sizef); //copy编码后的H264数据流到解码buffer //get stream to decoder buffer
streamBufferInfo[encoderFrameBufCounter].size=sizef;//保留H264数据流
//直接copy到显示buffer //show camera yuv buffer to display
//memcpy(decoderOutBuf[decoderBufCounter],inYUVbuf[encoderFrameBufCounter],BUFF_SIZE);
//if(++decoderBufCounter==MAX_STREAM_BUFFER_NUM)decoderBufCounter=0;
#ifdef DECODER_FLAG
//////////////////////////////////
/// 5. DECODE ///
/// (SsbSipH264DecodeExe) ///
//////////////////////////////////
if (SsbSipH264DecodeExe(decoderHandle, nFrameLeng) != SSBSIP_H264_DEC_RET_OK) {
// sprintf(msg, "\n\t Error in decoding -th video, %d-th frame\n", nLoop);
RETAILMSG(1,(L"DECODE ERROR\n"));
continue;
}
//////////////////////////////////////////////
/// 6. Obtaining the Output Buffer ///
/// (SsbSipH264DecodeGetOutBuf) ///
//////////////////////////////////////////////
pYUVBuf = (unsigned char *) SsbSipH264DecodeGetOutBuf(decoderHandle, (long *) &(nYUVLeng));
//copy到显示buffer 获得解码后的yuv buffer到显示缓冲区 //copy decoder output yuv buffer to display buffer
memcpy(decoderOutBuf[decoderBufCounter],pYUVBuf,nYUVLeng);
if(++decoderBufCounter==MAX_STREAM_BUFFER_NUM)decoderBufCounter=0;
///////////////////////
// Next VIDEO stream //
///////////////////////
//将解码流数据buffer送入解码器 //copy next stream frame to decoder
memcpy(pStrmBuf,streamBufferInfo[encoderFrameBufCounter].strmBuf,streamBufferInfo[encoderFrameBufCounter].size);
nFrameLeng=streamBufferInfo[encoderFrameBufCounter].size;
#endif
//下一帧数据指针 //point++
if(++encoderFrameBufCounter==MAX_STREAM_BUFFER_NUM)encoderFrameBufCounter=0;//=((cameraFrameBufCounter+2)%MAX_CAMERA_BUFFER_NUM);
//RETAILMSG(1,(L"H.264 Encoder finish %x. %x\n",encoderFrameBufCounter,sizef));
nLoop++;
}
//计算帧率 //count frame rate
if (nLoop == perf_disp_period) {
t2 = GetTickCount();
t_diff = t2 - t1;
fps = (float)(1000 * nLoop) / t_diff;
wsprintf(str_performance, L"%3.1f", fps);
RETAILMSG(1,(L"Decoder =%s fps\n", str_performance));
nLoop = 0;
t1 = GetTickCount();
}
}
}
同时编解码附件是个从camera -> yuv -> encoder -> stream buffer -> decoder -> yuv buffer -> display buffer的一个函数,里面都是按demo程序设计。
问题:目前显示的没有马赛克,但图像显示会看到一帧一帧的不连贯(计算显示还是25帧)。
如果单编码的话(不执行解码)图像更可以非常流畅;甚至参数可以降低到:
{
width = 640;
height = 480;
frame_rate = 25;
bitrate = 800;
gop_num = 50;
intraqp = 1;
qpmax = 32;//32;//50;
gamma = 0.75;
}
也一样流畅,没有马赛克。这组参数放到同时编解码的话会运动图像有马赛克。
请帮看看参数设置不对还是流程不对,非常感谢。