在高版本的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});新聞熱點
疑難解答