private InterleaveChunkMdat(Movie movie, Map<Track, int[]> chunks, long contentSize) { this.contentSize = contentSize; this.tracks = movie.getTracks(); List<Track> tracks = new ArrayList<Track>(chunks.keySet()); Collections.sort( tracks, new Comparator<Track>() { public int compare(Track o1, Track o2) { return l2i(o1.getTrackMetaData().getTrackId() - o2.getTrackMetaData().getTrackId()); } }); Map<Track, Integer> trackToChunk = new HashMap<Track, Integer>(); Map<Track, Integer> trackToSample = new HashMap<Track, Integer>(); Map<Track, Double> trackToTime = new HashMap<Track, Double>(); for (Track track : tracks) { trackToChunk.put(track, 0); trackToSample.put(track, 0); trackToTime.put(track, 0.0); } while (true) { Track nextChunksTrack = null; for (Track track : tracks) { if ((nextChunksTrack == null || trackToTime.get(track) < trackToTime.get(nextChunksTrack)) && // either first OR track's next chunk's starttime is smaller than nextTrack's next // chunks starttime // AND their need to be chunks left! (trackToChunk.get(track) < chunks.get(track).length)) { nextChunksTrack = track; } } if (nextChunksTrack == null) { break; } // found the next one int nextChunksIndex = trackToChunk.get(nextChunksTrack); int numberOfSampleInNextChunk = chunks.get(nextChunksTrack)[nextChunksIndex]; int startSample = trackToSample.get(nextChunksTrack); double time = trackToTime.get(nextChunksTrack); for (int j = startSample; j < startSample + numberOfSampleInNextChunk; j++) { time += (double) nextChunksTrack.getSampleDurations()[j] / nextChunksTrack.getTrackMetaData().getTimescale(); } chunkList.add( nextChunksTrack .getSamples() .subList(startSample, startSample + numberOfSampleInNextChunk)); trackToChunk.put(nextChunksTrack, nextChunksIndex + 1); trackToSample.put(nextChunksTrack, startSample + numberOfSampleInNextChunk); trackToTime.put(nextChunksTrack, time); } }
protected void createStco( Track targetTrack, Movie movie, Map<Track, int[]> chunks, SampleTableBox stbl) { if (chunkOffsetBoxes.get(targetTrack) == null) { // The ChunkOffsetBox we create here is just a stub // since we haven't created the whole structure we can't tell where the // first chunk starts (mdat box). So I just let the chunk offset // start at zero and I will add the mdat offset later. long offset = 0; // all tracks have the same number of chunks if (LOG.isLoggable(Level.FINE)) { LOG.fine( "Calculating chunk offsets for track_" + targetTrack.getTrackMetaData().getTrackId()); } List<Track> tracks = new ArrayList<Track>(chunks.keySet()); Collections.sort( tracks, new Comparator<Track>() { public int compare(Track o1, Track o2) { return l2i(o1.getTrackMetaData().getTrackId() - o2.getTrackMetaData().getTrackId()); } }); Map<Track, Integer> trackToChunk = new HashMap<Track, Integer>(); Map<Track, Integer> trackToSample = new HashMap<Track, Integer>(); Map<Track, Double> trackToTime = new HashMap<Track, Double>(); for (Track track : tracks) { trackToChunk.put(track, 0); trackToSample.put(track, 0); trackToTime.put(track, 0.0); chunkOffsetBoxes.put(track, new StaticChunkOffsetBox()); } while (true) { Track nextChunksTrack = null; for (Track track : tracks) { // This always chooses the least progressed track if ((nextChunksTrack == null || trackToTime.get(track) < trackToTime.get(nextChunksTrack)) && // either first OR track's next chunk's starttime is smaller than nextTrack's next // chunks starttime // AND their need to be chunks left! (trackToChunk.get(track) < chunks.get(track).length)) { nextChunksTrack = track; } } if (nextChunksTrack == null) { break; // no next } // found the next one ChunkOffsetBox chunkOffsetBox = chunkOffsetBoxes.get(nextChunksTrack); chunkOffsetBox.setChunkOffsets( Mp4Arrays.copyOfAndAppend(chunkOffsetBox.getChunkOffsets(), offset)); int nextChunksIndex = trackToChunk.get(nextChunksTrack); int numberOfSampleInNextChunk = chunks.get(nextChunksTrack)[nextChunksIndex]; int startSample = trackToSample.get(nextChunksTrack); double time = trackToTime.get(nextChunksTrack); for (int j = startSample; j < startSample + numberOfSampleInNextChunk; j++) { offset += track2SampleSizes.get(nextChunksTrack)[j]; time += (double) nextChunksTrack.getSampleDurations()[j] / nextChunksTrack.getTrackMetaData().getTimescale(); } trackToChunk.put(nextChunksTrack, nextChunksIndex + 1); trackToSample.put(nextChunksTrack, startSample + numberOfSampleInNextChunk); trackToTime.put(nextChunksTrack, time); } } stbl.addBox(chunkOffsetBoxes.get(targetTrack)); }