AVPacket.duration is mostly made up and thus completely useless, this is
especially true for video streams.
---
 libavformat/avformat.h |    9 +++++++++
 libavformat/utils.c    |   22 +++++++++++++++++++---
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index e292206..55cbc9e 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -721,6 +721,15 @@ typedef struct AVStream {
         int64_t codec_info_duration;
         int nb_decoded_frames;
         int found_decoder;
+
+        /**
+         * Those are used for average framerate estimation.
+         */
+        int64_t fps_first_dts;
+        int     fps_first_dts_idx;
+        int64_t fps_last_dts;
+        int     fps_last_dts_idx;
+
     } *info;
 
     int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) 
*/
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 8dbf1e5..2a43645 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2287,6 +2287,8 @@ int avformat_find_stream_info(AVFormatContext *ic, 
AVDictionary **options)
 
     for (i=0; i<ic->nb_streams; i++) {
         ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
+        ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;
+        ic->streams[i]->info->fps_last_dts  = AV_NOPTS_VALUE;
     }
 
     count = 0;
@@ -2395,6 +2397,15 @@ int avformat_find_stream_info(AVFormatContext *ic, 
AVDictionary **options)
                 break;
             }
             st->info->codec_info_duration += pkt->duration;
+            if (pkt->dts != AV_NOPTS_VALUE) {
+                if (st->info->fps_first_dts == AV_NOPTS_VALUE) {
+                    st->info->fps_first_dts  = pkt->dts;
+                    st->info->fps_first_dts_idx = st->codec_info_nb_frames;
+                } else if (pkt->dts > st->info->fps_first_dts) {
+                    st->info->fps_last_dts = pkt->dts;
+                    st->info->fps_last_dts_idx = st->codec_info_nb_frames;
+                }
+            }
         }
         {
             int64_t last = st->info->last_dts;
@@ -2454,10 +2465,15 @@ int avformat_find_stream_info(AVFormatContext *ic, 
AVDictionary **options)
     for(i=0;i<ic->nb_streams;i++) {
         st = ic->streams[i];
         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && 
st->info->codec_info_duration)
+            /* estimate average framerate if not set by demuxer */
+            if (!st->avg_frame_rate.num && st->info->fps_last_dts != 
AV_NOPTS_VALUE) {
+                int64_t delta_dts = st->info->fps_last_dts - 
st->info->fps_first_dts;
+                int delta_packets = st->info->fps_last_dts_idx - 
st->info->fps_first_dts_idx;
+
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
-                          
(st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
-                          
st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
+                          delta_packets*(int64_t)st->time_base.den,
+                          delta_dts*(int64_t)st->time_base.num, 60000);
+            }
             // the check for tb_unreliable() is not completely correct, since 
this is not about handling
             // a unreliable/inexact time base, but a time base that is finer 
than necessary, as e.g.
             // ipmovie.c produces.
-- 
1.7.10.4

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to