Browse Source

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.
Sam Edwards 7 years ago
parent
commit
9596095294
2 changed files with 91 additions and 17 deletions
  1. 42 7
      panda/src/ffmpeg/ffmpegAudioCursor.cxx
  2. 49 10
      panda/src/ffmpeg/ffmpegVideoCursor.cxx

+ 42 - 7
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;
 

+ 49 - 10
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;