title: Clipping mp4s with mp4parser. Can't get past timeCorrected with SyncSample
body: <p>I am writing an Android app and I have a bunch of 5-15 second .mp4 files that I want to clip.  I have been trying to use Sebastian Annies' <a href="https://code.google.com/p/mp4parser/" rel="noreferrer">mp4parser</a> to do so, following the example code given here: <a href="https://mp4parser.googlecode.com/svn/trunk/examples/src/main/java/com/googlecode/mp4parser/ShortenExample.java" rel="noreferrer">ShortenExample</a>. </p>
  
  <p>Here is the code I am using (heavily resembles the example code above):</p>
  
  <pre><code>    public static void clip(Sprinkle sprinkle, double start, double end) throws IOException {
      Movie movie = MovieCreator.build(sprinkle.getLocalVideoPath());
  
      // Save all tracks then remove them from movie
      List&lt;Track&gt; tracks = movie.getTracks();
      movie.setTracks(new LinkedList&lt;Track&gt;());
  
      boolean timeCorrected = false;
  
      // Here we try to find a track that has sync samples. Since we can only start decoding
      // at such a sample we SHOULD make sure that the start of the new fragment is exactly
      // such a frame
      for (Track track : tracks) {
          if (track.getSyncSamples() != null &amp;&amp; track.getSyncSamples().length &gt; 0) {
              if (timeCorrected) {
                  // This exception here could be a false positive in case we have multiple tracks
                  // with sync samples at exactly the same positions. E.g. a single movie containing
                  // multiple qualities of the same video (Microsoft Smooth Streaming file)
                  Log.v("clip", "track.getSyncSamples().length: " + track.getSyncSamples().length);
                  throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
              }
              Log.v("syncSample", "start before: " + start);
              Log.v("syncSample", "end before: " + end);
              start = correctTimeToSyncSample(track, start, false);
              end = correctTimeToSyncSample(track, end, true);
              Log.v("syncSample", "start after: " + start);
              Log.v("syncSample", "end after: " + end);
              timeCorrected = true;
          }
      }
  
      for (Track track : tracks) {
          long currentSample = 0;
          double currentTime = 0;
          double lastTime = 0;
          long startSample = -1;
          long endSample = -1;
  
          for (int i = 0; i &lt; track.getDecodingTimeEntries().size(); i++) {
              TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
              for (int j = 0; j &lt; entry.getCount(); j++) {
                  if (currentTime &gt; lastTime &amp;&amp; currentTime &lt;= start) {
                      // current sample is still before the new starttime
                      startSample = currentSample;
                  }
                  if (currentTime &gt; lastTime &amp;&amp; currentTime &lt;= end) {
                      // current sample is after the new start time and still before the new endtime
                      endSample = currentSample;
                  }
                  lastTime = currentTime;
                  currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
                  currentSample++;
              }
          }
          movie.addTrack(new AppendTrack(new CroppedTrack(track, startSample, endSample)));
      }
  
      long start1 = System.currentTimeMillis();
      Container out = new DefaultMp4Builder().build(movie);
      long start2 = System.currentTimeMillis();
      File file = Constants.getEditsDir();
      FileOutputStream fos = new FileOutputStream(file.getPath() + String.format("output-%f-%f.mp4", start, end));
      FileChannel fc = fos.getChannel();
      out.writeContainer(fc);
      fc.close();
      fos.close();
      long start3 = System.currentTimeMillis();
      System.err.println("Building IsoFile took : " + (start2 - start1) + "ms");
      System.err.println("Writing IsoFile took  : " + (start3 - start2) + "ms");
      System.err.println("Writing IsoFile speed : " + (new File(String.format("output-%f-%f.mp4", start, end)).length() / (start3 - start2) / 1000) + "MB/s");
  
  }
  
  private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
      double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
      long currentSample = 0;
      double currentTime = 0;
      for (int i = 0; i &lt; track.getDecodingTimeEntries().size(); i++) {
          TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
          for (int j = 0; j &lt; entry.getCount(); j++) {
              if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) &gt;= 0) {
                  // samples always start with 1 but we start with zero therefore +1
                  timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
              }
              currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
              currentSample++;
          }
      }
      double previous = 0;
      for (double timeOfSyncSample : timeOfSyncSamples) {
          if (timeOfSyncSample &gt; cutHere) {
              if (next) {
                  return timeOfSyncSample;
              } else {
                  return previous;
              }
          }
          previous = timeOfSyncSample;
      }
      return timeOfSyncSamples[timeOfSyncSamples.length - 1];
  }
  </code></pre>
  
  <p>I can't seem to prevent the error "The startTime has already been corrected by another track with SyncSample. Not Supported." from occurring.  When I log the tracks that I am looping through, getHandler() returns "vide", "soun", and then crashes when it comes to "hint".  If I comment this part out: </p>
  
  <pre><code>    if (timeCorrected) {
              // This exception here could be a false positive in case we have multiple tracks
              // with sync samples at exactly the same positions. E.g. a single movie containing
              // multiple qualities of the same video (Microsoft Smooth Streaming file)
              Log.v("clip", "track.getSyncSamples().length: " + track.getSyncSamples().length);
              throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
          }
  </code></pre>
  
  <p>then the program just crashes with an index out of bounds error when it gets to the line </p>
  
  <pre><code>    Container out = new DefaultMp4Builder().build(movie);
  </code></pre>
  
  <p>What am I doing wrong?</p>