在高版本的ffmpeg库中使用AVStream::codec成员时,编译和运行时都出现一堆警告:
main.cpp:151: warning: ‘AVStream::codec’ is dePRecated (declared at ……/Other_libs/ffmpeg3.2/include/libavformat/avformat.h:893)
和
Using AVStream.codec … deprecated, use AVStream.codecpar instead
从提示来看,需要使用AVStream.codecpar代替AVStream.codec,前者的类型是AVCodecParameters,后者的类型是AVCodecContext。事实上,AVCodecContext结构体仍然是编解码时不可或缺的结构体。换言之,AVCodecContext结构体的重要成员仍然需要设置,才能使用(特别是编码),比如bit_rate。
之所以使用AVStream.codec,是因为解码时很容易获得源视频的一些基本信息。
const char *filename = "a.mp4";AVFormatContext fmt_ctx = nullptr;avformat_open_input(&fmt_ctx, filename, nullptr, nullptr);//打开一个视频avformat_find_stream_info(fmt_ctx, nullptr);//读取视频,然后得到流和码率等信息for(size_t i = 0; i < fmt_ctx->nb_streams; ++i){ AVStream *stream = m_fmt_ctx->streams[i]; AVCodecContext *codec_ctx = stream->codec; //此时就可以通过stream和codec_ctx的结构体成员获取流的绝大部分信息,相当方便}上面的代码十分简洁,又能获取大部分流相关的信息。编码时直接从源视频的AVCodecContext中复制成员值,并作简单的修改即可。也正因为如此,多数人不肯离开这温床。
事实上,无论是编解码,使用AVCodecParameters的代码都相当简洁。
视频的帧率,应该从AVStream结构的avg_frame_rate成员获取,而非AVCodecContext结构体。
编码时,需要分配一个AVCodecContext,然后为成员变量设置适当的值,最后将设置值复制到AVCodecParameters。
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_codecAVCodecContext *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});新闻热点
疑难解答