From 95960952945f79f1a5acc458570703e1c9250b4e Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Sat, 31 Mar 2018 01:36:39 -0600 Subject: [PATCH] ffmpeg: Use AVStream.codecpar AVStream.codec is deprecated as of libavformat version 57.41.100, so if this version is detected, we switch to AVStream.codecpar instead. Note this also makes it necessary to construct and use our own codec context - but doing that is a cleaner approach anyway. --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 49 ++++++++++++++++++--- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 59 +++++++++++++++++++++----- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 83ae9dcf28..2a94dd25b9 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -68,28 +68,58 @@ FfmpegAudioCursor(FfmpegAudio *src) : return; } + // As of libavformat version 57.41.100, AVStream.codec is deprecated in favor + // of AVStream.codecpar. Fortunately, the two structures have + // similarly-named members, so we can just switch out the declaration. +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + AVCodecParameters *codecpar; +#else + AVCodecContext *codecpar; +#endif + // Find the audio stream + AVStream *stream = nullptr; for (int i = 0; i < (int)_format_ctx->nb_streams; i++) { - if (_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + codecpar = _format_ctx->streams[i]->codecpar; +#else + codecpar = _format_ctx->streams[i]->codec; +#endif + if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { _audio_index = i; - _audio_ctx = _format_ctx->streams[i]->codec; - _audio_timebase = av_q2d(_format_ctx->streams[i]->time_base); - _audio_rate = _audio_ctx->sample_rate; - _audio_channels = _audio_ctx->channels; + stream = _format_ctx->streams[i]; + break; } } - if (_audio_ctx == 0) { + if (stream == nullptr) { cleanup(); return; } - AVCodec *pAudioCodec = avcodec_find_decoder(_audio_ctx->codec_id); + _audio_timebase = av_q2d(stream->time_base); + _audio_rate = codecpar->sample_rate; + _audio_channels = codecpar->channels; + + AVCodec *pAudioCodec = avcodec_find_decoder(codecpar->codec_id); if (pAudioCodec == 0) { cleanup(); return; } + _audio_ctx = avcodec_alloc_context3(pAudioCodec); + + if (_audio_ctx == nullptr) { + cleanup(); + return; + } + +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + avcodec_parameters_to_context(_audio_ctx, codecpar); +#else + avcodec_copy_context(_audio_ctx, codecpar); +#endif + AVDictionary *opts = NULL; av_dict_set(&opts, "request_sample_fmt", "s16", 0); if (avcodec_open2(_audio_ctx, pAudioCodec, NULL) < 0) { @@ -202,6 +232,11 @@ cleanup() { if ((_audio_ctx)&&(_audio_ctx->codec)) { avcodec_close(_audio_ctx); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) + avcodec_free_context(&_audio_ctx); +#else + delete _audio_ctx; +#endif } _audio_ctx = NULL; diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index ff3f46a538..33d0a1d411 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -482,37 +482,55 @@ open_stream() { return false; } - // Find the video stream nassertr(_video_ctx == NULL, false); + + // As of libavformat version 57.41.100, AVStream.codec is deprecated in favor + // of AVStream.codecpar. Fortunately, the two structures have + // similarly-named members, so we can just switch out the declaration. +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + AVCodecParameters *codecpar; +#else + AVCodecContext *codecpar; +#endif + + // Find the video stream + AVStream *stream = nullptr; for (int i = 0; i < (int)_format_ctx->nb_streams; ++i) { - if (_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + codecpar = _format_ctx->streams[i]->codecpar; +#else + codecpar = _format_ctx->streams[i]->codec; +#endif + if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { _video_index = i; - _video_ctx = _format_ctx->streams[i]->codec; - _video_timebase = av_q2d(_format_ctx->streams[i]->time_base); - _min_fseek = (int)(3.0 / _video_timebase); + stream = _format_ctx->streams[i]; + break; } } - if (_video_ctx == NULL) { + if (stream == nullptr) { ffmpeg_cat.info() - << "Couldn't find video_ctx\n"; + << "Couldn't find stream\n"; close_stream(); return false; } + _video_timebase = av_q2d(stream->time_base); + _min_fseek = (int)(3.0 / _video_timebase); + AVCodec *pVideoCodec = NULL; if (ffmpeg_prefer_libvpx) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 0, 0) - if (_video_ctx->codec_id == AV_CODEC_ID_VP9) { + if (codecpar->codec_id == AV_CODEC_ID_VP9) { pVideoCodec = avcodec_find_decoder_by_name("libvpx-vp9"); } else #endif - if (_video_ctx->codec_id == AV_CODEC_ID_VP8) { + if (codecpar->codec_id == AV_CODEC_ID_VP8) { pVideoCodec = avcodec_find_decoder_by_name("libvpx"); } } if (pVideoCodec == NULL) { - pVideoCodec = avcodec_find_decoder(_video_ctx->codec_id); + pVideoCodec = avcodec_find_decoder(codecpar->codec_id); } if (pVideoCodec == NULL) { ffmpeg_cat.info() @@ -520,6 +538,22 @@ open_stream() { close_stream(); return false; } + + _video_ctx = avcodec_alloc_context3(pVideoCodec); + + if (_video_ctx == nullptr) { + ffmpeg_cat.info() + << "Couldn't allocate _video_ctx\n"; + close_stream(); + return false; + } + +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 41, 100) + avcodec_parameters_to_context(_video_ctx, codecpar); +#else + avcodec_copy_context(_video_ctx, codecpar); +#endif + if (avcodec_open2(_video_ctx, pVideoCodec, NULL) < 0) { ffmpeg_cat.info() << "Couldn't open codec\n"; @@ -547,6 +581,11 @@ close_stream() { if ((_video_ctx)&&(_video_ctx->codec)) { avcodec_close(_video_ctx); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) + avcodec_free_context(&_video_ctx); +#else + delete _video_ctx; +#endif } _video_ctx = NULL;