• error:无法从“AVCodecParameters ”转换为“AVCodecContext

从提示来看,需要使用AVStream.codecpar代替AVStream.codec,前者的类型是AVCodecParameters,后者的类型是AVCodecContext。事实上,AVCodecContext结构体仍然是编解码时不可或缺的结构体。换言之,AVCodecContext结构体的重要成员仍然需要设置,才能使用(特别是编码),比如bit_rate。
之所以使用AVStream.codec,是因为解码时很容易获得源视频的一些基本信息。

  1. const char *filename = "a.mp4";
  2. AVFormatContext fmt_ctx = nullptr;
  3. avformat_open_input(&fmt_ctx, filename, nullptr, nullptr);//打开一个视频
  4. avformat_find_stream_info(fmt_ctx, nullptr);//读取视频,然后得到流和码率等信息
  5. for(size_t i = 0; i < fmt_ctx->nb_streams; ++i)
  6. {
  7. AVStream *stream = m_fmt_ctx->streams[i];
  8. AVCodecContext *codec_ctx = stream->codec;
  9. //此时就可以通过stream和codec_ctx的结构体成员获取流的绝大部分信息,相当方便
  10. }

上面的代码十分简洁,又能获取大部分流相关的信息。编码时直接从源视频的AVCodecContext中复制成员值,并作简单的修改即可。
但是,无论是编解码,使用AVCodecParameters的代码都相当简洁。

解码

  1. const char *filename = "a.mp4";
  2. AVFormatContext fmt_ctx = nullptr;
  3. avformat_open_input(&fmt_ctx, filename, nullptr, nullptr);//打开一个视频
  4. avformat_find_stream_info(fmt_ctx, nullptr);//读取视频,然后得到流和码率等信息
  5. for(size_t i = 0; i < fmt_ctx->nb_streams; ++i)
  6. {
  7. AVStream *stream = fmt_ctx->streams[i];
  8. AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id);
  9. AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);//需要使用avcodec_free_context释放
  10. //事实上codecpar包含了大部分解码器相关的信息,这里是直接从AVCodecParameters复制到AVCodecContext
  11. avcodec_parameters_to_context(codec_ctx, stream->codecpar);
  12. av_codec_set_pkt_timebase(codec_ctx, stream->time_base);
  13. avcodec_open2(codec_ctx, codec, nullptr);
  14. }

视频的帧率,应该从AVStream结构的avg_frame_rate成员获取,而非AVCodecContext结构体。如果avg_frame_rate为{0, 1},那么再尝试从r_frame_rate成员获取。

  • error:av_codec_set_pkt_timebase声明已被否决

关闭SDL检查。
image.png

编码

编码时,需要分配一个AVCodecContext,然后为成员变量设置适当的值,最后将设置值复制到AVCodecParameters。

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

来自
https://blog.csdn.net/luotuo44/article/details/54981809?utm_source=blogxgwz4