ffmpeg 编码器AVCodecContext 的配置参数

转自:http://blog.csdn.net/chance_yin/article/details/16335625


1、先说一些基本的API

[cpp]  view plain copy
  1. AVFormatContex * pFormatCtxEnc;  
  2. AVCodecContext * pCodecCtxEnc;  
  3.   
  4. AVStream * video_st;  
  5. AVOutputFormat * pOutputFormat;  
  6.   
  7. pOutputFormat = av_guess_format(NULL,/*文件名*/,NULL); //根据文件后缀来猜测文件的格式  
  8.   
  9. pFormatCtxEnc = avformat_alloc_context();  
  10.   
  11. pFormatCtxEnc->oformat = pOutputFormat;  
  12. video_st = avformat_new_stream(pFormatCtxEnc,0);  

2、开始配置编码器上下文的参数

[cpp]  view plain copy
  1. /*AVCodecContext 相当于虚基类,需要用具体的编码器实现来给他赋值*/  
  2. pCodecCtxEnc = video_st->codec;   
  3.   
  4. //编码器的ID号,这里我们自行指定为264编码器,实际上也可以根据video_st里的codecID 参数赋值  
  5. pCodecCtxEnc->codec_id = AV_CODEC_ID_H264;  
  6.   
  7. //编码器编码的数据类型  
  8. pCodecCtxEnc->codec_type = AVMEDIA_TYPE_VIDEO;  
  9.   
  10. //目标的码率,即采样的码率;显然,采样码率越大,视频大小越大  
  11. pCodecCtxEnc->bit_rate = 200000;  
  12.   
  13. //固定允许的码率误差,数值越大,视频越小  
  14. pCodecCtxEnc->bit_rate_tolerance = 4000000;  
  15.   
  16. //编码目标的视频帧大小,以像素为单位  
  17. pCodecCtxEnc->width = 640;  
  18. pCodecCtxEnc->height = 480;  
  19.   
  20. //帧率的基本单位,我们用分数来表示,  
  21. //用分数来表示的原因是,有很多视频的帧率是带小数的eg:NTSC 使用的帧率是29.97  
  22. pCodecCtxEnc->time_base.den = 30;  
  23. pCodecCtxEnc->time_base = (AVRational){1,25};  
  24. pCodecCtxEnc->time_base.num = 1;  
  25.   
  26. //像素的格式,也就是说采用什么样的色彩空间来表明一个像素点  
  27. pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;  
  28.   
  29. //每250帧插入1个I帧,I帧越少,视频越小  
[cpp]  view plain copy
  1. pCodecCtxEnc->gop_size = 250;  
  2.   
  3. //两个非B帧之间允许出现多少个B帧数  
  4. //设置0表示不使用B帧  
  5. //b 帧越多,图片越小  
  6. pCodecCtxEnc->max_b_frames = 0;  
  7.   
  8. //运动估计  
  9. pCodecCtxEnc->pre_me = 2;  
  10.   
  11. //设置最小和最大拉格朗日乘数  
  12. //拉格朗日乘数 是统计学用来检测瞬间平均值的一种方法  
  13. pCodecCtxEnc->lmin = 1;  
  14. pCodecCtxEnc->lmax = 5;  
  15.   
  16. //最大和最小量化系数  
  17. pCodecCtxEnc->qmin = 10;  
  18. pCodecCtxEnc->qmax = 50;  
  19.   
  20. //因为我们的量化系数q是在qmin和qmax之间浮动的,  
  21. //qblur表示这种浮动变化的变化程度,取值范围0.0~1.0,取0表示不削减  
  22. pCodecCtxEnc->qblur = 0.0;  
  23.   
  24. //空间复杂度的masking力度,取值范围 0.0-1.0  
  25. pCodecCtxEnc->spatial_cplx_masking = 0.3;  
  26.   
  27. //运动场景预判功能的力度,数值越大编码时间越长  
  28. pCodecCtxEnc->me_pre_cmp = 2;  
  29.   
  30. //采用(qmin/qmax的比值来控制码率,1表示局部采用此方法,)  
  31. pCodecCtxEnc->rc_qsquish = 1;  
  32.   
  33. //设置 i帧、p帧与B帧之间的量化系数q比例因子,这个值越大,B帧越不清楚  
  34. //B帧量化系数 = 前一个P帧的量化系数q * b_quant_factor + b_quant_offset  
  35. pCodecCtxEnc->b_quant_factor = 1.25;  
  36.   
  37. //i帧、p帧与B帧的量化系数便宜量,便宜越大,B帧越不清楚  
  38. pCodecCtxEnc->b_quant_offset = 1.25;  
  39.   
  40. //p和i的量化系数比例因子,越接近1,P帧越清楚  
  41. //p的量化系数 = I帧的量化系数 * i_quant_factor + i_quant_offset  
  42. pCodecCtxEnc->i_quant_factor = 0.8;  
  43. pCodecCtxEnc->i_quant_offset = 0.0;  
  44.   
  45. //码率控制测率,宏定义,查API  
  46. pCodecCtxEnc->rc_strategy = 2;  
  47.   
  48. //b帧的生成策略  
  49. pCodecCtxEnc->b_frame_strategy = 0;  
  50.   
  51. //消除亮度和色度门限  
  52. pCodecCtxEnc->luma_elim_threshold = 0;  
  53. pCodecCtxEnc->chroma_elim_threshold = 0;  
  54.   
  55. //DCT变换算法的设置,有7种设置,这个算法的设置是根据不同的CPU指令集来优化的取值范围在0-7之间  
  56. pCodecCtxEnc->dct_algo = 0;  
  57.   
  58. //这两个参数表示对过亮或过暗的场景作masking的力度,0表示不作  
  59. pCodecCtxEnc->lumi_masking = 0.0;  
  60. pCodecCtxEnc->dark_masking = 0.0;  

3、一些针对具体要求进行的配置

(1)x264编码时延问题

方法一:

[cpp]  view plain copy
  1. vcodec_encode_video2函数输出的延时仅仅跟max_b_frames的设置有关,  
  2. 想进行实时编码,将max_b_frames设置为0便没有编码延时了  

方法二:

[cpp]  view plain copy
  1. 1、使用264的API设置编码速度   
  2. /** 
  3.  * ultrafast,superfast, veryfast, faster, fast, medium 
  4.  * slow, slower, veryslow, placebo. 这是x264编码速度的选项 
  5.  */  
  6.  av_opt_set(m_context->priv_data,"preset","ultrafast",0);  
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将YUV和PCM数据编码成视频和音频文件需要使用FFmpeg库,具体的实现步骤如下: 1. 初始化FFmpeg库 在使用FFmpeg库之前,需要先进行初始化。使用av_register_all函数可以注册FFmpeg库中的所有编解码器、格式器和协议等。 ``` av_register_all(); ``` 2. 打开输出文件 使用avformat_alloc_output_context2和avio_open2函数打开输出文件,创建AVFormatContext结构体并分配内存,将输出文件与该结构体关联。 ``` AVFormatContext *out_ctx = NULL; int ret = avformat_alloc_output_context2(&out_ctx, NULL, NULL, output_file); if (ret < 0) { // 创建AVFormatContext失败 return; } if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) { ret = avio_open2(&out_ctx->pb, output_file, AVIO_FLAG_WRITE, NULL, NULL); if (ret < 0) { // 打开输出文件失败 return; } } ``` 3. 创建音视频流 使用avformat_new_stream函数创建音视频流,并设置音视频流的相关参数,如编码器率、码率、采样率等。 ``` AVStream *video_stream = avformat_new_stream(out_ctx, NULL); if (video_stream == NULL) { // 创建视频流失败 return; } AVCodecParameters *codecpar = video_stream->codecpar; codecpar->codec_type = AVMEDIA_TYPE_VIDEO; codecpar->width = width; codecpar->height = height; codecpar->format = AV_PIX_FMT_YUV420P; codecpar->codec_id = AV_CODEC_ID_H264; codecpar->bit_rate = bit_rate; codecpar->framerate = {fps, 1}; AVStream *audio_stream = avformat_new_stream(out_ctx, NULL); if (audio_stream == NULL) { // 创建音频流失败 return; } codecpar = audio_stream->codecpar; codecpar->codec_type = AVMEDIA_TYPE_AUDIO; codecpar->sample_rate = sample_rate; codecpar->format = AV_SAMPLE_FMT_S16; codecpar->channels = channels; codecpar->channel_layout = av_get_default_channel_layout(channels); codecpar->codec_id = AV_CODEC_ID_AAC; codecpar->bit_rate = bit_rate; ``` 4. 打开视频和音频编码器 使用avcodec_find_encoder函数查找视频和音频编码器,并使用avcodec_open2打开编码器。 ``` AVCodec *video_codec = avcodec_find_encoder(video_stream->codecpar->codec_id); if (video_codec == NULL) { // 查找视频编码器失败 return; } AVCodecContext *video_cctx = avcodec_alloc_context3(video_codec); if (video_cctx == NULL) { // 创建视频编码器上下文失败 return; } ret = avcodec_open2(video_cctx, video_codec, NULL); if (ret < 0) { // 打开视频编码器失败 return; } AVCodec *audio_codec = avcodec_find_encoder(audio_stream->codecpar->codec_id); if (audio_codec == NULL) { // 查找音频编码器失败 return; } AVCodecContext *audio_cctx = avcodec_alloc_context3(audio_codec); if (audio_cctx == NULL) { // 创建音频编码器上下文失败 return; } ret = avcodec_open2(audio_cctx, audio_codec, NULL); if (ret < 0) { // 打开音频编码器失败 return; } ``` 5. 写入视频和音频数据 使用av_frame_alloc函数创建AVFrame结构体,填充YUV和PCM数据,并使用avcodec_send_frame和avcodec_receive_packet函数将数据编码成视频和音频包,最后使用av_write_frame函数将包写入输出文件。 ``` AVFrame *video_frame = av_frame_alloc(); // 填充YUV数据到video_frame中 AVPacket *video_packet = av_packet_alloc(); ret = avcodec_send_frame(video_cctx, video_frame); if (ret < 0) { // 向视频编码器发送数据失败 return; } while (ret >= 0) { ret = avcodec_receive_packet(video_cctx, video_packet); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } if (ret < 0) { // 从视频编码器接收数据失败 return; } av_packet_rescale_ts(video_packet, video_cctx->time_base, video_stream->time_base); video_packet->stream_index = video_stream->index; ret = av_write_frame(out_ctx, video_packet); if (ret < 0) { // 写入视频数据失败 return; } } AVFrame *audio_frame = av_frame_alloc(); // 填充PCM数据到audio_frame中 AVPacket *audio_packet = av_packet_alloc(); ret = avcodec_send_frame(audio_cctx, audio_frame); if (ret < 0) { // 向音频编码器发送数据失败 return; } while (ret >= 0) { ret = avcodec_receive_packet(audio_cctx, audio_packet); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } if (ret < 0) { // 从音频编码器接收数据失败 return; } av_packet_rescale_ts(audio_packet, audio_cctx->time_base, audio_stream->time_base); audio_packet->stream_index = audio_stream->index; ret = av_write_frame(out_ctx, audio_packet); if (ret < 0) { // 写入音频数据失败 return; } } ``` 6. 关闭编码器和输出文件 使用av_write_trailer、avcodec_free_context和avformat_free_context函数释放资源并关闭编码器和输出文件。 ``` av_write_trailer(out_ctx); avcodec_free_context(&video_cctx); avcodec_free_context(&audio_cctx); avformat_free_context(out_ctx); ``` 以上是将YUV和PCM数据编码成视频和音频文件的基本流程,需要注意的是各项参数设置和数据的填充。如果需要进行更详细的配置和处理,可以参考FFmpeg库的官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值