From 4a7342e7ee9efc76892018c517ab367d39b930ec Mon Sep 17 00:00:00 2001
From: Karl Dietz <dekarl@mythtv.org>
Date: Sun, 27 Apr 2014 02:19:55 +0200
Subject: [PATCH 1/3] divide framerate by number of ticks (fields) per frame

Inspired by av_guess_frame_rate, see
https://www.ffmpeg.org/doxygen/trunk/group__lavf__misc.html#ga12c049178414cc221dfafd4e7f836dea
Why don't we just use that?

Fixes #12047
---
 mythtv/libs/libmythtv/avformatdecoder.cpp |   54 ++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 5 deletions(-)

diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 552d3fe..e176d09 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -1337,11 +1337,50 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
     return recordingHasPositionMap;
 }
 
+/* FIXME remove after updating FFmpeg past 2.0 */
+/**
+ * Guess the frame rate, based on both the container and codec information.
+ *
+ * @param ctx the format context which the stream is part of
+ * @param stream the stream which the frame is part of
+ * @param frame the frame for which the frame rate should be determined, may be NULL
+ * @return the guessed (valid) frame rate, 0/1 if no idea
+ */
+
+AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);
+
+AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
+{
+    AVRational fr = st->r_frame_rate;
+    AVRational codec_fr = av_inv_q(st->codec->time_base);
+    AVRational avg_fr = st->avg_frame_rate;
+
+    if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 &&
+        av_q2d(avg_fr) < 70 && av_q2d(fr) > 210) {
+        fr = avg_fr;
+    }
+
+
+    if (st->codec->ticks_per_frame > 1) {
+        codec_fr.den *= st->codec->ticks_per_frame;
+        if ( codec_fr.num > 0 && codec_fr.den > 0 && av_q2d(codec_fr) < av_q2d(fr)*0.7
+            && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)
+            fr = codec_fr;
+    }
+
+    return fr;
+}
+
 float AvFormatDecoder::normalized_fps(AVStream *stream, AVCodecContext *enc)
 {
-    float fps, avg_fps, codec_fps, container_fps, estimated_fps;
-    avg_fps = codec_fps = container_fps = estimated_fps = 0.0f;
+    float fps, avg_fps, codec_fps, container_fps, estimated_fps, guess_fps;
+    avg_fps = codec_fps = container_fps = estimated_fps = guess_fps = 0.0f;
+
+    guess_fps = av_q2d(av_guess_frame_rate(ic, stream, NULL));
 
+    /* this is not a good source for FPS according to
+     * https://trac.bunkus.org/wiki/FAQ:WrongFrameRateDisplayed
+     */
     if (stream->avg_frame_rate.den && stream->avg_frame_rate.num)
         avg_fps = av_q2d(stream->avg_frame_rate); // MKV default_duration
 
@@ -1360,9 +1399,13 @@ float AvFormatDecoder::normalized_fps(AVStream *stream, AVCodecContext *enc)
     if (stream->r_frame_rate.den && stream->r_frame_rate.num) // tbr
         estimated_fps = av_q2d(stream->r_frame_rate);
 
+    if (guess_fps > 3.0f)
+    {
+       fps = guess_fps;
+    }
     // matroska demuxer sets the default_duration to avg_frame_rate
     // mov,mp4,m4a,3gp,3g2,mj2 demuxer sets avg_frame_rate
-    if ((QString(ic->iformat->name).contains("matroska") ||
+    else if ((QString(ic->iformat->name).contains("matroska") ||
         QString(ic->iformat->name).contains("mov")) &&
         avg_fps < 121.0f && avg_fps > 3.0f)
         fps = avg_fps;
@@ -1383,9 +1426,10 @@ float AvFormatDecoder::normalized_fps(AVStream *stream, AVCodecContext *enc)
     if (fps != m_fps)
     {
         LOG(VB_PLAYBACK, LOG_INFO, LOC +
-            QString("Selected FPS is %1 (avg %2 codec %3 "
+            QString("Selected FPS is %1 (guess %6 avg %2 codec %3 "
                     "container %4 estimated %5)").arg(fps).arg(avg_fps)
-                .arg(codec_fps).arg(container_fps).arg(estimated_fps));
+                .arg(codec_fps).arg(container_fps).arg(estimated_fps)
+                .arg(guess_fps));
         m_fps = fps;
     }
 
-- 
1.7.9.5

