使用的是FFMpeg SDKv3的库。
使用步骤很简单:(不含对象创建/释放)
1、初始化
2、编码/解码
3、释放资源
希望熟悉H264的高手提供一下建议设置,公网传输10%的丢包率下,在QCIF的分辨率下我的Bitrate、GOP、MaxBFrames、FrameRate是否合理?
BTW:编译不过的问题请自己解决吧
[XVCodecObj.h]
#include "stdafx.h"
class CXVEncodeObj
{
private:
AVCodec * m_Codec;
AVCodecContext * m_CodecCtx;
int m_inbufMaxSize;
void * m_OutBuffer;
AVFrame * m_YUVFrame;
AVFrame * m_RGBFrame;
SwsContext * m_ConvertCtx;
public:
CXVEncodeObj():
m_Codec(NULL),
m_CodecCtx(NULL),
m_inbufMaxSize(0),
m_OutBuffer(NULL),
m_YUVFrame(NULL),
m_RGBFrame(NULL),
m_ConvertCtx(NULL)
{
//构造函数
}
~CXVEncodeObj()
{
//析构函数
}
int InitCodec();
int EncodeYUV420P(void * inbuf, int inbufsize, void * outbuf, int outbufsize);
int EncodeRGB24(void * inbuf, int inbufsize, void * outbuf, int outbufsize, int * IsKey);
void FinalCodec();
};
//
class CXVDecodeObj
{
private:
AVCodec * m_Codec;
AVCodecContext * m_CodecCtx;
AVFrame * m_DecodeFrame;
AVFrame * m_RGBFrame;
SwsContext * m_ConvertCtx;
public:
CXVDecodeObj():
m_Codec(NULL),
m_CodecCtx(NULL),
m_DecodeFrame(NULL),
m_RGBFrame(NULL),
m_ConvertCtx(NULL)
{
//
}
~CXVDecodeObj()
{
}
int InitCodec();
int DecodeVideo(void * inbuf, int inbufsize, void * outbuf, int outbufsize);
void FinalCodec();
};
[XVCodecObj.cpp]
#include "stdafx.h"
#include "XVCodecObj.h"
#define CVIDEO_BITRATE 5000
#define CVIDEO_WIDTH 176
#define CVIDEO_HEIGHT 144
#define CVIDEO_FRAMERATE 15
#define CVIDEO_GOP 10
#define CVIDEO_MAXBFRAME 0
#define CVIDEO_OUTBUFFERSIZE 100000
#define CVIDEO_CODEC CODEC_ID_H264
static AVFrame *alloc_picture(int pix_fmt, int width, int height)
{
AVFrame *picture;
uint8_t *picture_buf;
int size;
picture = avcodec_alloc_frame();
if (!picture)
return NULL;
size = avpicture_get_size(pix_fmt, width, height);
picture_buf = (uint8_t *)av_malloc(size);
if (!picture_buf) {
av_free(picture);
return NULL;
}
avpicture_fill((AVPicture *)picture, picture_buf,
pix_fmt, width, height);
return picture;
}
int CXVEncodeObj::InitCodec()
{
m_Codec = avcodec_find_encoder(CVIDEO_CODEC);
if (!m_Codec)
return 1;//not support this codec
m_CodecCtx = avcodec_alloc_context();
if (!m_CodecCtx)
return 2;//maybe not enough memory
m_CodecCtx->bit_rate = CVIDEO_BITRATE;
m_CodecCtx->width = CVIDEO_WIDTH;
m_CodecCtx->height = CVIDEO_HEIGHT;
m_CodecCtx->time_base.den = CVIDEO_FRAMERATE;
m_CodecCtx->time_base.num = 1;
m_CodecCtx->gop_size = CVIDEO_GOP;
m_CodecCtx->max_b_frames = CVIDEO_MAXBFRAME;
m_CodecCtx->pix_fmt = PIX_FMT_YUV420P;
if (avcodec_open(m_CodecCtx,m_Codec)<0)
return 3;//codec open failed
m_inbufMaxSize = (m_CodecCtx->width * m_CodecCtx->height * 3) / 2;
m_OutBuffer = av_malloc(CVIDEO_OUTBUFFERSIZE);
if (!m_OutBuffer)
return 4;//maybe not enough memory
m_YUVFrame = alloc_picture(m_CodecCtx->pix_fmt,m_CodecCtx->width,m_CodecCtx->height);
if (!m_YUVFrame)
return 5;//maybe not enough memory
m_RGBFrame = alloc_picture(PIX_FMT_BGR24,m_CodecCtx->width,m_CodecCtx->height);
if (!m_RGBFrame)
return 6;//maybe not enough memory
m_ConvertCtx = sws_getContext(m_CodecCtx->width,m_CodecCtx->height,PIX_FMT_BGR24,
m_CodecCtx->width,m_CodecCtx->height,PIX_FMT_YUV420P,SWS_BICUBIC,NULL,
NULL,NULL);
if (!m_ConvertCtx)
return 7;//error
return 0;
}
int CXVEncodeObj::EncodeYUV420P(void * inbuf, int inbufsize, void * outbuf, int outbufsize)
{
if (inbufsize!=m_inbufMaxSize)
return -1;
memcpy(m_YUVFrame->data[0],inbuf,inbufsize);
int outsize = avcodec_encode_video(m_CodecCtx,(uint8_t *)m_OutBuffer,CVIDEO_OUTBUFFERSIZE,m_YUVFrame);
memcpy(outbuf,m_OutBuffer,(outbufsize>outsize ? outsize : outbufsize));
return outsize;
}
int CXVEncodeObj::EncodeRGB24(void * inbuf, int inbufsize, void * outbuf, int outbufsize, int * IsKey)
{
if (inbufsize!=m_inbufMaxSize*2)
return -1;
memcpy(m_RGBFrame->data[0],inbuf,inbufsize);
sws_scale(
m_ConvertCtx,
m_RGBFrame->data,
m_RGBFrame->linesize,
0,
m_CodecCtx->height,
m_YUVFrame->data,
m_YUVFrame->linesize);
int outsize = avcodec_encode_video(m_CodecCtx,(uint8_t *)m_OutBuffer,CVIDEO_OUTBUFFERSIZE,m_YUVFrame);
memcpy(outbuf,m_OutBuffer,(outbufsize>=outsize ? outsize : outbufsize));
*IsKey = m_CodecCtx->coded_frame->key_frame;
return outsize;
}
void CXVEncodeObj::FinalCodec()
{
if (m_ConvertCtx)
{
sws_freeContext(m_ConvertCtx);
m_ConvertCtx = NULL;
}
if (m_RGBFrame)
{
av_free(m_RGBFrame->data[0]);
av_free(m_RGBFrame);
m_RGBFrame = NULL;
}
if (m_YUVFrame)
{
av_free(m_YUVFrame->data[0]);
av_free(m_YUVFrame);
m_YUVFrame = NULL;
}
if (m_OutBuffer)
{
av_free(m_OutBuffer);
m_OutBuffer = NULL;
}
if (m_CodecCtx)
{
if (m_CodecCtx->codec)
avcodec_close(m_CodecCtx);
av_free(m_CodecCtx);
m_CodecCtx = NULL;
}
}
/
int CXVDecodeObj::InitCodec()
{
m_Codec = avcodec_find_decoder(CVIDEO_CODEC);
if (!m_Codec)
return 1;//not support this codec
m_CodecCtx = avcodec_alloc_context();
if (!m_CodecCtx)
return 2;//maybe not enough memory
m_CodecCtx->width = CVIDEO_WIDTH;
m_CodecCtx->height = CVIDEO_HEIGHT;
//if(m_Codec->capabilities&CODEC_CAP_TRUNCATED)
// m_CodecCtx->flags|= CODEC_FLAG_TRUNCATED;
if (avcodec_open(m_CodecCtx,m_Codec)<0)
return 3;//codec open failed
m_DecodeFrame = avcodec_alloc_frame();
if (!m_DecodeFrame)
return 4;//maybe not enough memory
m_RGBFrame = alloc_picture(PIX_FMT_BGR24,m_CodecCtx->width,m_CodecCtx->height);
if (!m_RGBFrame)
return 5;//maybe not enough memory
m_ConvertCtx = sws_getContext(m_CodecCtx->width,m_CodecCtx->height,PIX_FMT_YUV420P,
m_CodecCtx->width,m_CodecCtx->height,PIX_FMT_BGR24,SWS_BICUBIC,NULL,
NULL,NULL);
if (!m_ConvertCtx)
return 6;//error
return 0;
}
int CXVDecodeObj:ecodeVideo(void * inbuf, int inbufsize, void * outbuf, int outbufsize)
{
uint8_t * inptr = (uint8_t *)inbuf;
int size = inbufsize;
int got_picture = 0;
while (size>0)
{
int len = avcodec_decode_video(m_CodecCtx,m_DecodeFrame,&got_picture,inptr,size);
if (len<0)
return -1;//error
if (got_picture)
{
sws_scale(
m_ConvertCtx,
m_DecodeFrame->data,
m_DecodeFrame->linesize,
0,
m_CodecCtx->height,
m_RGBFrame->data,
m_RGBFrame->linesize);
int outlen = (m_RGBFrame->linesize[0]*m_CodecCtx->height>=outbufsize ? outbufsize : m_RGBFrame->linesize[0]*m_CodecCtx->height);
memcpy(outbuf, m_RGBFrame->data[0],outlen);
return outlen;
}
size -= len;
inptr += len;
}
return 0;
}
void CXVDecodeObj::FinalCodec()
{
if (m_ConvertCtx)
{
sws_freeContext(m_ConvertCtx);
m_ConvertCtx = NULL;
}
if (m_RGBFrame)
{
av_free(m_RGBFrame->data[0]);
av_free(m_RGBFrame);
m_RGBFrame = NULL;
}
if (m_DecodeFrame)
{
av_free(m_DecodeFrame);
m_DecodeFrame = NULL;
}
if (m_CodecCtx)
{
if (m_CodecCtx->codec)
avcodec_close(m_CodecCtx);
av_free(m_CodecCtx);
}
}
转载于:https://www.cnblogs.com/li-baibo/archive/2012/12/03/2799794.html