Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead

ffmpeg读取h264报错:

Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead

 ffmpeg新版本中(封装流)AVStream的codec参数要被codecpar参数所替代,这样替代我们要注意什么,为什么要替代,我们先来看下ffmpeg的代码。
 
 代码分析和新参数优势

 typedef struct AVStream {
 
 #if FF_API_LAVF_AVCTX
 
 /**
 
 * @deprecated use the codecpar struct instead
 
 */
 
 attribute_deprecated
 
 AVCodecContext *codec;
 
 #endif
 
 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
 
 /*
 
 * Codec parameters associated with this stream. Allocated and freed by
 
 * libavformat in avformat_new_stream() and avformat_free_context()
 
 * respectively.
 
 *
 
 * - demuxing: filled by libavformat on stream creation or in
 
 * avformat_find_stream_info()
 
 * - muxing: filled by the caller before avformat_write_header()
 
 */
 
 AVCodecParameters *codecpar;

 }


 
 从代码中我们可以看出codec参数在58版本及之后就不会支持了,需要由codecpar参数所替代。这样做的目的我想主要是将编码和封装彻底分离,之前封装和编码使用的参数都是存放在codec中,这样的好处是代码简洁,不需要额外给封装传递参数,但坏处是把编码和封装的代码融合在一块耦合性较大,有很多需求,我们只需要编码并不需要做封装,比如我们做自己的推流协议,直接吧编码后h264数据通过自定义的协议发送。
 
 再比如直播推流中我们编码和封装推流会在不同的线程中处理,如果共用一个上下文肯定还需要处理互斥问题,分开就不会存在这个问题。
 
 既然必须要替换我们如何处理;
 
 比如原来的视频播放处理方式是这样(错误处理省略):
 
 //打开多媒体文件,我们假定视频流索引为0
 
 AVFormatContext *ic = NULL;
 
 avformat_open_input(&ic, "test.mp4", 0, 0);
 
 //找到视频解码器,比如H264

   AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codec->codecid);

   //打开视频解码器,打开音频解码器用的也是同一个函数

 avcodec_open2(enc, ic->streams[0]->codec, NULL);
 
 看代码我们知道avformat_open_input之后音视频的配置信息已经被写在了codec中,解封装和解码用同一套参数。但是如果替换为
 codecpar ,那解码器是独立创建的,那是否还要手动填写一遍解码参数,理论上是需要的,不过还好ffmpeg提供给我们一个函数做参数复制
 
 int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);

 那我们
 codec参数替换为codecpar 代码就可以这样写了(错误处理省略)
 
 //打开多媒体文件,我们假定视频流索引为0
 
 AVFormatContext *ic = NULL;
 
 avformat_open_input(&ic, "test.mp4", 0, 0);
 
 //找到视频解码器,比如H264

   AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codecpar->codec_id);
 
 //独立的解码上下文
 
 AVCodecContext * vc = avcodec_alloc_context3(codec);
 
 avcodec_parameters_to_context(vc, ic->streams[0]->codecpar);
 
 avcodec_open2(vc, codec, NULL);
 
 代码改变后解码上下文就是独立的,后面解码也不需要与解封装上下文关联,包括清理。
 
 解码器的ID号也变为从codecpar->codec_id成员获取。

原文链接:https://blog.csdn.net/jiedichina/article/details/77524920

解决方法:

AVStream *out_stream = avformat_new_stream(ofmt_ctx, pCodecH264);

if (!out_stream) {

printf("Failed allocating output stream\n");

ret = AVERROR_UNKNOWN;

return NULL;

}

out_stream->time_base = rate;

 

avcodec_parameters_from_context(out_stream->codecpar, c);

 

av_stream_set_r_frame_rate(out_stream, { 1, 25 });

c是:AVCodecContext *c;

也可以参考: http://blog.csdn.net/luotuo44/article/details/54981809 

const char *filename = "b.mp4";
AVFormatContext *fmt_ctx = nullptr;
avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, filename); //需要调用avformat_free_context释放
 
//new一个流并挂到fmt_ctx名下,调用avformat_free_context时会释放该流
AVStream *stream = avformat_new_stream(fmt_ctx, nullptr);
AVCodec *codec = avcodec_find_encoder(fmt_ctx->oformat->video_codec);//音频为audio_codec
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
 
codec_ctx->video_type = AVMEDIA_TYPE_VIDEO;
codec_ctx->codec_id = m_fmt_ctx->oformat->video_codec;
 
codec_ctx->width = 1280;//你想要的宽度
codec_ctx->height = 720;//你想要的高度
codec_ctx->format = AV_PIX_FMT_YUV420P;//受codec->pix_fmts数组限制
 
codec_ctx->gop_size = 12;
 
codec_ctx->time_base = AVRational{1, 25};//应该根据帧率设置
codec_ctx->bit_rate = 1400 * 1000;
 
avcodec_open2(codec_ctx, codec, nullptr);
//将AVCodecContext的成员复制到AVCodecParameters结构体。前后两行不能调换顺序
avcodec_parameters_from_context(stream->codecpar, codec_ctx);
 
av_stream_set_r_frame_rate(stream, {1, 25});

 以上只是它使用的顺序问题,但是你发现你的录制处理的MP4文件的码率,帧率还是很大。和自己设置的完全不一样。


为甚么会y偶这个原因,是因为新版本中该了很多东西,下面请参考这个文章。
http://blog.csdn.net/mj1523/article/details/50434977?locationNum=14


    AVDictionary* opt = NULL;
    av_dict_set_int(&opt, "video_track_timescale", 25, 0);
    avformat_write_header(m_pFormatCtx, &opt);

原文链接:https://blog.csdn.net/ILOVEYOULEEHUIJIE/article/details/72778650

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值