一 ffmpeg不包含h264编码部分,要做h264编码需要额外引入x264库。
二 最简单的h264 编码代码以及设置的一些基本参数
int EncodeH264(const AVPacket *srcpkt,AVPacket *out_pkt)
{
if(srcpkt == NULL || out_pkt == NULL)
{
srs_error("pkt is null here ##\n");
return -1;
}
AVFrame *frame = av_frame_alloc();
if(frame == NULL)
{
srs_error("av_frame_alloc failed ##\n");
return -2;
}
int GetFrame = 0;
int ret = avcodec_decode_video2(f_SrcCodecCtx_,frame,&GetFrame,srcpkt);
if(ret < 0 || GetFrame == 0)
{
srs_error("avcodec_decode_video2 failed ##\n");
return -3;
}
EncodeParam encode_param = {0};
encode_param.widht = frame->width;
encode_param.height = frame->height;
if(InitEncoder(encode_param) != 0)
{
srs_error("InitEncoder failed ##\n");
return -4;
}
int got_packet = 0;
if(f_DstCodecCtx_ == NULL)
{
if(InitEncoder(encode_param) != 0)
{
srs_error("f_DstCodecCtx_ NULL InitEncoder failed ##\n");
return -6;
}
}
ret = avcodec_encode_video2(f_DstCodecCtx_,out_pkt,frame,&got_packet);
if(ret < 0 || got_packet == 0)
{
srs_error("avcodec_encode_video2 failed ##\n");
return -5;
}
return 0;
}
int InitEncoder(EncodeParam encode_param)
{
if(encode_param == param_)
{
return 0;
}
//printf("InitEncoder param reInit OK ###\n");
f_DstCodec_ = avcodec_find_encoder((enum AVCodecID)dst_code_type_);
if(f_DstCodec_ == NULL)
{
srs_error("avcodec_find_encoder failed ##\n");
return -2;
}
if(f_DstCodecCtx_)
{
avcodec_flush_buffers(f_DstCodecCtx_);
avcodec_close(f_DstCodecCtx_);
avcodec_free_context(&f_DstCodecCtx_);
f_DstCodecCtx_ = NULL;
}
f_DstCodecCtx_ = avcodec_alloc_context3(f_DstCodec_);
if(f_DstCodecCtx_ == NULL)
{
srs_error("avcodec_alloc_context3 failed ##\n");
return -4;
}
av_dict_set(&m_encode_dic, "profile", "main", 0);//profile类型
av_dict_set(&m_encode_dic, "preset", "veryslow", 0);//预设值,
av_dict_set(&m_encode_dic, "tune", "zerolatency", 0);
av_opt_set(f_DstCodecCtx_->priv_data, "x264opts", "rc-lookahead=30", 0);
f_DstCodecCtx_->width = encode_param.widht;
f_DstCodecCtx_->height = encode_param.height;
f_DstCodecCtx_->gop_size = 25;
f_DstCodecCtx_->has_b_frames = false;
f_DstCodecCtx_->pix_fmt = AV_PIX_FMT_YUV420P;
f_DstCodecCtx_->max_b_frames = 0;
f_DstCodecCtx_->thread_count = 1;
f_DstCodecCtx_->qmin = 1;
f_DstCodecCtx_->qmax = 40;
f_DstCodecCtx_->max_qdiff = 4;
f_DstCodecCtx_->keyint_min = 1;
f_DstCodecCtx_->me_subpel_quality = 4;
f_DstCodecCtx_->refs = 1;
f_DstCodecCtx_->bit_rate = 1000000; // use cbr instead
f_DstCodecCtx_->rc_max_rate = 1000000;
f_DstCodecCtx_->rc_buffer_size = 1000000;
f_DstCodecCtx_->bit_rate_tolerance = 300000;
f_DstCodecCtx_->rc_initial_buffer_occupancy = 0;
f_DstCodecCtx_->time_base.num = 1;
f_DstCodecCtx_->time_base.den = 20;
if(avcodec_open2(f_DstCodecCtx_,f_DstCodec_,&m_encode_dic) != 0)
{
srs_error("avcodec_open2 failed ##\n");
return -6;
}
param_ = encode_param;
return 0;
二 最简单的h264 编码代码以及设置的一些基本参数
int EncodeH264(const AVPacket *srcpkt,AVPacket *out_pkt)
{
if(srcpkt == NULL || out_pkt == NULL)
{
srs_error("pkt is null here ##\n");
return -1;
}
AVFrame *frame = av_frame_alloc();
if(frame == NULL)
{
srs_error("av_frame_alloc failed ##\n");
return -2;
}
int GetFrame = 0;
int ret = avcodec_decode_video2(f_SrcCodecCtx_,frame,&GetFrame,srcpkt);
if(ret < 0 || GetFrame == 0)
{
srs_error("avcodec_decode_video2 failed ##\n");
return -3;
}
EncodeParam encode_param = {0};
encode_param.widht = frame->width;
encode_param.height = frame->height;
if(InitEncoder(encode_param) != 0)
{
srs_error("InitEncoder failed ##\n");
return -4;
}
int got_packet = 0;
if(f_DstCodecCtx_ == NULL)
{
if(InitEncoder(encode_param) != 0)
{
srs_error("f_DstCodecCtx_ NULL InitEncoder failed ##\n");
return -6;
}
}
ret = avcodec_encode_video2(f_DstCodecCtx_,out_pkt,frame,&got_packet);
if(ret < 0 || got_packet == 0)
{
srs_error("avcodec_encode_video2 failed ##\n");
return -5;
}
return 0;
}
int InitEncoder(EncodeParam encode_param)
{
if(encode_param == param_)
{
return 0;
}
//printf("InitEncoder param reInit OK ###\n");
f_DstCodec_ = avcodec_find_encoder((enum AVCodecID)dst_code_type_);
if(f_DstCodec_ == NULL)
{
srs_error("avcodec_find_encoder failed ##\n");
return -2;
}
if(f_DstCodecCtx_)
{
avcodec_flush_buffers(f_DstCodecCtx_);
avcodec_close(f_DstCodecCtx_);
avcodec_free_context(&f_DstCodecCtx_);
f_DstCodecCtx_ = NULL;
}
f_DstCodecCtx_ = avcodec_alloc_context3(f_DstCodec_);
if(f_DstCodecCtx_ == NULL)
{
srs_error("avcodec_alloc_context3 failed ##\n");
return -4;
}
av_dict_set(&m_encode_dic, "profile", "main", 0);//profile类型
av_dict_set(&m_encode_dic, "preset", "veryslow", 0);//预设值,
av_dict_set(&m_encode_dic, "tune", "zerolatency", 0);
av_opt_set(f_DstCodecCtx_->priv_data, "x264opts", "rc-lookahead=30", 0);
f_DstCodecCtx_->width = encode_param.widht;
f_DstCodecCtx_->height = encode_param.height;
f_DstCodecCtx_->gop_size = 25;
f_DstCodecCtx_->has_b_frames = false;
f_DstCodecCtx_->pix_fmt = AV_PIX_FMT_YUV420P;
f_DstCodecCtx_->max_b_frames = 0;
f_DstCodecCtx_->thread_count = 1;
f_DstCodecCtx_->qmin = 1;
f_DstCodecCtx_->qmax = 40;
f_DstCodecCtx_->max_qdiff = 4;
f_DstCodecCtx_->keyint_min = 1;
f_DstCodecCtx_->me_subpel_quality = 4;
f_DstCodecCtx_->refs = 1;
f_DstCodecCtx_->bit_rate = 1000000; // use cbr instead
f_DstCodecCtx_->rc_max_rate = 1000000;
f_DstCodecCtx_->rc_buffer_size = 1000000;
f_DstCodecCtx_->bit_rate_tolerance = 300000;
f_DstCodecCtx_->rc_initial_buffer_occupancy = 0;
f_DstCodecCtx_->time_base.num = 1;
f_DstCodecCtx_->time_base.den = 20;
if(avcodec_open2(f_DstCodecCtx_,f_DstCodec_,&m_encode_dic) != 0)
{
srs_error("avcodec_open2 failed ##\n");
return -6;
}
param_ = encode_param;
return 0;
}