[FFmpeg-devel] [PATCH] avformat: correct avg_frame_rate for telecine

Michael Niedermayer michaelni at gmx.at
Wed Feb 27 02:16:26 CET 2013


Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 libavformat/avformat.h |    2 +-
 libavformat/utils.c    |   21 ++++++++++++++++++---
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 9b72279..1185dd9 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -756,7 +756,7 @@ typedef struct AVStream {
         int duration_count;
         double (*duration_error)[2][MAX_STD_TIMEBASES];
         int64_t codec_info_duration;
-        int64_t codec_info_duration_fields;
+        int64_t codec_info_duration_fields[6];
         int found_decoder;
 
         /**
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 9bd2d0c..fd8e929 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2878,8 +2878,10 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 break;
             }
             if (pkt->duration) {
+                int repeat = st->parser && st->codec->ticks_per_frame==2 ? st->parser->repeat_pict : 1;
                 st->info->codec_info_duration        += pkt->duration;
-                st->info->codec_info_duration_fields += st->parser && st->codec->ticks_per_frame==2 ? st->parser->repeat_pict + 1 : 2;
+                av_assert0(repeat >= 0 && repeat<6);
+                st->info->codec_info_duration_fields[repeat]++;
             }
         }
 #if FF_API_R_FRAME_RATE
@@ -2995,14 +2997,27 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             }
 
             /* estimate average framerate if not set by demuxer */
-            if (st->info->codec_info_duration_fields && !st->avg_frame_rate.num && st->info->codec_info_duration) {
+            if (!st->avg_frame_rate.num && st->info->codec_info_duration) {
                 int      best_fps = 0;
                 double best_error = 0.01;
+                int duration_fields = 0;
+
+                for (j=0; j<FF_ARRAY_ELEMS(st->info->codec_info_duration_fields); j++)
+                    duration_fields += st->info->codec_info_duration_fields[j] * (j+1);
 
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
-                          st->info->codec_info_duration_fields*(int64_t)st->time_base.den,
+                          duration_fields*(int64_t)st->time_base.den,
                           st->info->codec_info_duration*2*(int64_t)st->time_base.num, 60000);
 
+                if (   FFABS(st->info->codec_info_duration_fields[1] - st->info->codec_info_duration_fields[2]) <= 1
+                    && 2*st->info->codec_info_duration_fields[1] + 3*st->info->codec_info_duration_fields[2] == duration_fields) {
+                    av_log(ic, AV_LOG_DEBUG, "3/2 pulldown detected, compensating fps\n");
+
+                    av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
+                              duration_fields*(int64_t)st->time_base.den * 4,
+                              st->info->codec_info_duration*(int64_t)st->time_base.num*10, 60000);
+                }
+
                 /* round guessed framerate to a "standard" framerate if it's
                  * within 1% of the original estimate*/
                 for (j = 1; j < MAX_STD_TIMEBASES; j++) {
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list