[FFmpeg-cvslog] ismindex: handle time discontinuities and nonzero start time

Mika Raento git at videolan.org
Mon Sep 15 22:40:19 CEST 2014


ffmpeg | branch: master | Mika Raento <mika.raento at elisa.fi> | Sun Sep 14 19:00:56 2014 +0300| [00431bf874e1044b01e09a2266ef85d4ff8d44cc] | committer: Martin Storsjö

ismindex: handle time discontinuities and nonzero start time

The input file may not have consistent start times, stream durations and
chunk durations. This patch at least removes negative durations that
make chromecast unhappy, and correctly sets starting time on chunks so
that the split (or .ismf) outputs match the manifest.

Signed-off-by: Martin Storsjö <martin at martin.st>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=00431bf874e1044b01e09a2266ef85d4ff8d44cc
---

 tools/ismindex.c |   45 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/tools/ismindex.c b/tools/ismindex.c
index aa862f8..6ed31ac 100644
--- a/tools/ismindex.c
+++ b/tools/ismindex.c
@@ -252,6 +252,13 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
         ret = AVERROR(ENOMEM);
         goto fail;
     }
+    // The duration here is always the difference between consecutive
+    // start times and doesn't even try to read the actual duration of the
+    // media fragments. This is what other smooth streaming tools tend to
+    // do too, but cannot express missing fragments, and the start times
+    // may not match the stream metadata we get from libavformat. Correct
+    // calculation would require parsing the tfxd atom (if present, it's
+    // not mandatory) or parsing the full moof atoms separately.
     for (i = 0; i < track->chunks; i++) {
         if (version == 1) {
             track->offsets[i].time   = avio_rb64(f);
@@ -270,9 +277,30 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
             track->offsets[i - 1].duration = track->offsets[i].time -
                                              track->offsets[i - 1].time;
     }
-    if (track->chunks > 0)
-        track->offsets[track->chunks - 1].duration = track->duration -
+    if (track->chunks > 0) {
+        track->offsets[track->chunks - 1].duration = track->offsets[0].time +
+                                                     track->duration -
                                                      track->offsets[track->chunks - 1].time;
+        if (track->offsets[track->chunks - 1].duration <= 0) {
+            fprintf(stderr, "Calculated last chunk duration for track %d "
+                    "was non-positive (%"PRId64"), probably due to missing "
+                    "fragments ", track->track_id,
+                    track->offsets[track->chunks - 1].duration);
+            if (track->chunks > 1) {
+                track->offsets[track->chunks - 1].duration =
+                    track->offsets[track->chunks - 2].duration;
+            } else {
+                track->offsets[track->chunks - 1].duration = 1;
+            }
+            fprintf(stderr, "corrected to %"PRId64"\n",
+                    track->offsets[track->chunks - 1].duration);
+            track->duration = track->offsets[track->chunks - 1].time +
+                              track->offsets[track->chunks - 1].duration -
+                              track->offsets[0].time;
+            fprintf(stderr, "Track duration corrected to %"PRId64"\n",
+                    track->duration);
+        }
+    }
     ret = 0;
 
 fail:
@@ -524,6 +552,7 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main,
                                const char *type)
 {
     int i, j;
+    int64_t pos = 0;
     struct Track *track = tracks->tracks[main];
     int should_print_time_mismatch = 1;
 
@@ -543,8 +572,18 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main,
                 }
             }
         }
-        fprintf(out, "\t\t<c n=\"%d\" d=\"%"PRId64"\" />\n",
+        fprintf(out, "\t\t<c n=\"%d\" d=\"%"PRId64"\" ",
                 i, track->offsets[i].duration);
+        if (pos != track->offsets[i].time) {
+            // With the current logic for calculation of durations from
+            // chunk start times, this branch can only be hit on the first
+            // chunk - but that's still useful and this will keep working
+            // if the duration calculation is improved.
+            fprintf(out, "t=\"%"PRId64"\" ", track->offsets[i].time);
+            pos = track->offsets[i].time;
+        }
+        pos += track->offsets[i].duration;
+        fprintf(out, "/>\n");
     }
 }
 



More information about the ffmpeg-cvslog mailing list