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.
This commit is contained in:
Sam Edwards 2018-03-31 01:36:39 -06:00
parent cc77c5dbe2
commit 9596095294
2 changed files with 91 additions and 17 deletions

View File

@ -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;

View File

@ -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;