Use FFmpeg's own `av_guess_frame_rate()` function instead of guessing ourselves
authorSybren A. Stüvel <sybren@blender.org>
Thu, 19 Sep 2019 11:46:12 +0000 (13:46 +0200)
committerSybren A. Stüvel <sybren@blender.org>
Thu, 19 Sep 2019 13:12:53 +0000 (15:12 +0200)
This was introduced in FFmpeg lavf 55.1.100 in 2013. For systems that are
still on LibAV or older FFmpeg there is a fallback implementation that
performs the same guess as we did before in `av_get_r_frame_rate_compat()`.

intern/ffmpeg/ffmpeg_compat.h
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/indexer.c

index d254fa76ba99f236bd8d56b1731f9448f4cc109d..123e18430a9543f7289f2e17fd0259eb9a37aee0 100644 (file)
@@ -528,35 +528,21 @@ bool av_check_encoded_with_ffmpeg(AVFormatContext *ctx)
   return false;
 }
 
-FFMPEG_INLINE
-AVRational av_get_r_frame_rate_compat(AVFormatContext *ctx, const AVStream *stream)
+/* Libav doesn't have av_guess_frame_rate().
+ * It was introduced in FFmpeg's lavf 55.1.100. */
+#ifdef AV_USING_LIBAV
+AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame)
 {
-  /* If the video is encoded with FFmpeg and we are decoding with FFmpeg
-   * as well it seems to be more reliable to use r_frame_rate (tbr).
-   *
-   * For other cases we fall back to avg_frame_rate (fps) when possible.
-   */
-#ifdef AV_USING_FFMPEG
-  if (av_check_encoded_with_ffmpeg(ctx)) {
-    return stream->r_frame_rate;
-  }
-#endif
-
-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 23, 1)
-  /* For until r_frame_rate was deprecated use it. */
+  (void)ctx;
+  (void)frame;
+#  if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 23, 1)
+  /* For until r_frame_rate was deprecated (in Libav) use it. */
   return stream->r_frame_rate;
-#else
-#  ifdef AV_USING_FFMPEG
-  /* Some of the videos might have average frame rate set to, while the
-   * r_frame_rate will show a correct value. This happens, for example, for
-   * OGG video files saved with Blender. */
-  if (stream->avg_frame_rate.den == 0) {
-    return stream->r_frame_rate;
-  }
-#  endif
+#  else
   return stream->avg_frame_rate;
-#endif
+#  endif
 }
+#endif
 
 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0)
 #  define AV_OPT_SEARCH_FAKE_OBJ 0
index da7dcc543436f7d98ab3166199914bab74109282..5bfcca22faee66696347795aa87eb3370610af11 100644 (file)
@@ -569,7 +569,7 @@ static int startffmpeg(struct anim *anim)
     return -1;
   }
 
-  frame_rate = av_get_r_frame_rate_compat(pFormatCtx, video_stream);
+  frame_rate = av_guess_frame_rate(pFormatCtx, video_stream, NULL);
   if (video_stream->nb_frames != 0) {
     anim->duration = video_stream->nb_frames;
   }
@@ -1040,7 +1040,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
 
   v_st = anim->pFormatCtx->streams[anim->videoStream];
 
-  frame_rate = av_q2d(av_get_r_frame_rate_compat(anim->pFormatCtx, v_st));
+  frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL));
 
   st_time = anim->pFormatCtx->start_time;
   pts_time_base = av_q2d(v_st->time_base);
index 66e0a681f8f7c8b3114f4a2af3b7f8b78794525a..97a0cc85301b5d9d0909a9b20cb0d8b520e3647f 100644 (file)
@@ -900,7 +900,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
 
   stream_size = avio_size(context->iFormatCtx->pb);
 
-  context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iFormatCtx, context->iStream));
+  context->frame_rate = av_q2d(av_guess_frame_rate(context->iFormatCtx, context->iStream, NULL));
   context->pts_time_base = av_q2d(context->iStream->time_base);
 
   while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {