http://blog.csdn.net/luotuo44/article/details/54981809
在高版本的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.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的代碼都相當簡潔。
-
解碼
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 = fmt_ctx->streams[i]; AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id); AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);//需要使用avcodec_free_context釋放 //事實上codecpar包含了大部分解碼器相關的信息,這里是直接從AVCodecParameters復制到AVCodecContext avcodec_parameters_to_context(codec_ctx, stream->codecpar); av_codec_set_pkt_timebase(codec_ctx, stream->time_base); avcodec_open2(codec_ctx, codec, nullptr); }
視頻的幀率,應該從AVStream結構的avg_frame_rate成員獲取,而非AVCodecContext結構體。如果avg_frame_rate為{0, 1},那么再嘗試從r_frame_rate成員獲取。
-
編碼
編碼時,需要分配一個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_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});