[FFmpeg-devel] [PATCH] MPEG-TS/-PS : better probing for duration and start-time for all streams in a container

Gaullier Nicolas nicolas.gaullier at arkena.com
Wed May 14 18:25:13 CEST 2014


Carl,
Here below is a newly formated patch : it now passes tools/patcheck and I have git-applied it successfully. Hope it suits your requirements now.
Nicolas Gaullier
---
diff --git a/libavformat/utils.c b/libavformat/utils.c
index d84d605..7630501 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1028,6 +1028,13 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
     int64_t shift;
     int i, delay;
 
+    if (pts != AV_NOPTS_VALUE) {
+        if (st->start_time == AV_NOPTS_VALUE) {
+            st->start_time = pts;
+        } else {
+            st->start_time = FFMIN(pts,st->start_time);
+        }
+    }
     if (st->first_dts != AV_NOPTS_VALUE ||
         dts           == AV_NOPTS_VALUE ||
         st->cur_dts   == AV_NOPTS_VALUE ||
@@ -1065,9 +1072,6 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
             pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
         }
     }
-
-    if (st->start_time == AV_NOPTS_VALUE)
-        st->start_time = pts;
 }
 
 static void update_initial_durations(AVFormatContext *s, AVStream *st,
@@ -2469,7 +2473,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
     AVPacket pkt1, *pkt = &pkt1;
     AVStream *st;
     int read_size, i, ret;
-    int64_t end_time;
+    int all_duration_valid = 0;
     int64_t filesize, offset, duration;
     int retry = 0;
 
@@ -2488,12 +2492,12 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
             av_parser_close(st->parser);
             st->parser = NULL;
         }
+        st->info->last_duration = AV_NOPTS_VALUE;
     }
 
-    /* estimate the end time (duration) */
+    /* estimate the end time (duration) for all streams */
     /* XXX: may need to support wrapping */
     filesize = ic->pb ? avio_size(ic->pb) : 0;
-    end_time = AV_NOPTS_VALUE;
     do {
         offset = filesize - (DURATION_MAX_READ_SIZE << retry);
         if (offset < 0)
@@ -2502,11 +2506,11 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
         avio_seek(ic->pb, offset, SEEK_SET);
         read_size = 0;
         for (;;) {
-            if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0)))
+            if (read_size >= DURATION_MAX_READ_SIZE << retry)
                 break;
 
             do {
-                ret = ff_read_packet(ic, pkt);
+                ret = read_frame_internal(ic,pkt);
             } while (ret == AVERROR(EAGAIN));
             if (ret != 0)
                 break;
@@ -2515,7 +2519,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
             if (pkt->pts != AV_NOPTS_VALUE &&
                 (st->start_time != AV_NOPTS_VALUE ||
                  st->first_dts  != AV_NOPTS_VALUE)) {
-                duration = end_time = pkt->pts;
+                duration = pkt->pts + pkt->duration;
                 if (st->start_time != AV_NOPTS_VALUE)
                     duration -= st->start_time;
                 else
@@ -2529,10 +2533,32 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
             }
             av_free_packet(pkt);
         }
-    } while (end_time == AV_NOPTS_VALUE &&
-             filesize > (DURATION_MAX_READ_SIZE << retry) &&
+        /* check if all audio/video streams have valid duration */
+        all_duration_valid = 1;
+        for (i = 0; i < ic->nb_streams; i++) {
+            st = ic->streams[i];
+            switch (st->codec->codec_type) {
+                case AVMEDIA_TYPE_VIDEO:
+                case AVMEDIA_TYPE_AUDIO:
+                    if (st->info->last_duration == AV_NOPTS_VALUE)
+                        all_duration_valid = 0;
+            }
+        }
+    } while (!all_duration_valid &&
+             filesize > (DURATION_MAX_READ_SIZE << (retry+1)) &&
              ++retry <= DURATION_MAX_RETRY);
 
+    /* warn about audio/video streams which duration could not be estimated */
+    for (i = 0; i < ic->nb_streams; i++) {
+        st = ic->streams[i];
+        if (st->duration == AV_NOPTS_VALUE) {
+            switch (st->codec->codec_type) {
+                case AVMEDIA_TYPE_VIDEO:
+                case AVMEDIA_TYPE_AUDIO:
+                    av_log(ic, AV_LOG_WARNING, "stream %d : no PTS found at end of file, duration not set\n", i);
+            }
+        }
+    }
     fill_all_stream_timings(ic);
 
     avio_seek(ic->pb, old_offset, SEEK_SET);


More information about the ffmpeg-devel mailing list