AVCodec *pCodec = NULL;//编码器
AVCodecContext *pCodecCtx;
AVFrame *pFrame = NULL;
AVPacket *pPkt = NULL;
AVDictionary *dictParam = 0;
do
{
pCodec = avcodec_find_encoder_by_name(编码器名称);//libx264 libx265 h264_amf h264_qsv h264_nvenc hevc_nvenc hevc_amf hevc_qsv
if (!pCodec)
{
break;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx)
{
break;
}
pPkt = av_packet_alloc();
if (!pPkt)
{
break;
}
pCodecCtx->width = w;
pCodecCtx->height = h;
pCodecCtx->time_base = { 1, 30 };
pCodecCtx->framerate = { 30, 1 };
pCodecCtx->gop_size =30; //I帧间隔
pCodecCtx->max_b_frames = 0;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->thread_count = 1;
pCodecCtx->refs = 1;//设置参考帧个数
//这边不同的编码器的设置参数不一样,需要区别设置下,且每个人想要使用的方式也不一样,比如CQP,CBR,VBR,ABR,CRF等,大家根据自己的想法来
av_dict_set(&dictParam, "tune", "zerolatency", 0);
av_opt_set_int(pCodecCtx->priv_data, "qp", 17, 0);
int ret = 0;
try
{
ret = avcodec_open2(pCodecCtx, pCodec, &dictParam);
if (ret < 0)
{
break;
}
}
catch (...)
{
break;
}
pFrame = av_frame_alloc();
if (!pFrame)
{
break;
}
pFrame->format = AV_PIX_FMT_YUV420P;
pFrame->width = w;
pFrame->height = h;
if (pCodec->id == AV_CODEC_ID_H264) {
ret = av_frame_get_buffer(pFrame, 8);
}
else if (pCodec->id == AV_CODEC_ID_H265 || pCodec->id == AV_CODEC_ID_HEVC) {
ret = av_frame_get_buffer(pFrame, 32);
}
if (ret < 0)
{
break;
}
if (dictParam)
{
av_dict_free(&dictParam);
dictParam = NULL;
}
bool bFirst = true;
//开始编码
while(1)
{
//传入一帧YUV420P数据
memcpy(pFrame->data[0], Y数据, Y长度);
memcpy(pFrame->data[1], U数据, U长度);
memcpy(pFrame->data[2], V数据, V长度);
if(bFirst)//首帧编译为I帧,其他P帧
{
pFrame->pict_type = AV_PICTURE_TYPE_I;
pFrame->key_frame = 1;
bFirst = false;
}else{
pFrame->pict_type = AV_PICTURE_TYPE_P;
pFrame->key_frame = 0;
}
avcodec_send_frame(pCodecCtx,pFrame);
while(1)
{
ret = avcodec_receive_packet(pCodecCtx, pPkt);//获取编码后的数据
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0) {
av_packet_unref(pPkt);
break;
}
//编码成功
av_packet_unref(pPkt);
}
}
} while (false);
if (dictParam)
{
av_dict_free(&dictParam);
dictParam = NULL;
}
if (pCodecCtx) {
avcodec_free_context(&pCodecCtx);
}
if (pPkt) {
av_packet_free(&pPkt);
}
if (pFrame)
{
av_frame_free(&pFrame);
}
return 0;