Merge commit '00431bf874e1044b01e09a2266ef85d4ff8d44cc'
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 15 Sep 2014 20:31:43 +0000 (22:31 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 15 Sep 2014 20:39:31 +0000 (22:39 +0200)
* commit '00431bf874e1044b01e09a2266ef85d4ff8d44cc':
  ismindex: handle time discontinuities and nonzero start time

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
tools/ismindex.c

diff --combined tools/ismindex.c
index d66a389e0ec49d7fc726b141a24f0e0087a36cf4,6ed31ac2935eeeff15d8fe045bd5da172fffda8a..734419b1c95c4a5c9c20be33576cdcef36449c2d
@@@ -1,26 -1,26 +1,26 @@@
  /*
   * Copyright (c) 2012 Martin Storsjo
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  /*
   * To create a simple file for smooth streaming:
 - * avconv <normal input/transcoding options> -movflags frag_keyframe foo.ismv
 + * ffmpeg <normal input/transcoding options> -movflags frag_keyframe foo.ismv
   * ismindex -n foo foo.ismv
   * This step creates foo.ism and foo.ismc that is required by IIS for
   * serving it.
@@@ -47,8 -47,6 +47,8 @@@
  #include <stdio.h>
  #include <string.h>
  
 +#include "cmdutils.h"
 +
  #include "libavformat/avformat.h"
  #include "libavformat/os_support.h"
  #include "libavutil/intreadwrite.h"
@@@ -249,11 -247,18 +249,18 @@@ static int read_tfra(struct Tracks *tra
      }
      fieldlength = avio_rb32(f);
      track->chunks  = avio_rb32(f);
 -    track->offsets = av_mallocz(sizeof(*track->offsets) * track->chunks);
 +    track->offsets = av_mallocz_array(track->chunks, sizeof(*track->offsets));
      if (!track->offsets) {
          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);
              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:
@@@ -526,6 -552,7 +554,7 @@@ static void print_track_chunks(FILE *ou
                                 const char *type)
  {
      int i, j;
+     int64_t pos = 0;
      struct Track *track = tracks->tracks[main];
      int should_print_time_mismatch = 1;
  
                  }
              }
          }
-         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");
      }
  }