1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/* 2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright 2012 Sebastian Annies, Hamburg 3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the License); 5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * you may not use this file except in compliance with the License. 6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * You may obtain a copy of the License at 7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * http://www.apache.org/licenses/LICENSE-2.0 9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software 11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * distributed under the License is distributed on an AS IS BASIS, 12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * See the License for the specific language governing permissions and 14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * limitations under the License. 15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.googlecode.mp4parser.authoring.tracks; 17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.boxes.*; 19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.authoring.Track; 20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.authoring.TrackMetaData; 21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer; 23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayList; 24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Arrays; 25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.LinkedList; 26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List; 27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Queue; 28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.logging.Logger; 29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/** 31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Changes the timescale of a track by wrapping the track. 32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class ChangeTimeScaleTrack implements Track { 34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu private static final Logger LOG = Logger.getLogger(ChangeTimeScaleTrack.class.getName()); 35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu Track source; 37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<CompositionTimeToSample.Entry> ctts; 38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<TimeToSampleBox.Entry> tts; 39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long timeScale; 40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu /** 42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Changes the time scale of the source track to the target time scale and makes sure 43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * that any rounding errors that may have summed are corrected exactly before the syncSamples. 44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param source the source track 46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param targetTimeScale the resulting time scale of this track. 47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param syncSamples at these sync points where rounding error are corrected. 48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public ChangeTimeScaleTrack(Track source, long targetTimeScale, long[] syncSamples) { 50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.source = source; 51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.timeScale = targetTimeScale; 52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu double timeScaleFactor = (double) targetTimeScale / source.getTrackMetaData().getTimescale(); 53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ctts = adjustCtts(source.getCompositionTimeEntries(), timeScaleFactor); 54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu tts = adjustTts(source.getDecodingTimeEntries(), timeScaleFactor, syncSamples, getTimes(source, syncSamples, targetTimeScale)); 55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu private static long[] getTimes(Track track, long[] syncSamples, long targetTimeScale) { 58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long[] syncSampleTimes = new long[syncSamples.length]; 59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu Queue<TimeToSampleBox.Entry> timeQueue = new LinkedList<TimeToSampleBox.Entry>(track.getDecodingTimeEntries()); 60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int currentSample = 1; // first syncsample is 1 62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long currentDuration = 0; 63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long currentDelta = 0; 64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int currentSyncSampleIndex = 0; 65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long left = 0; 66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu while (currentSample <= syncSamples[syncSamples.length - 1]) { 69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (currentSample++ == syncSamples[currentSyncSampleIndex]) { 70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu syncSampleTimes[currentSyncSampleIndex++] = (currentDuration * targetTimeScale) / track.getTrackMetaData().getTimescale(); 71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (left-- == 0) { 73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu TimeToSampleBox.Entry entry = timeQueue.poll(); 74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu left = entry.getCount() - 1; 75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu currentDelta = entry.getDelta(); 76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu currentDuration += currentDelta; 78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return syncSampleTimes; 80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public SampleDescriptionBox getSampleDescriptionBox() { 84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getSampleDescriptionBox(); 85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { 88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return tts; 89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { 92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return ctts; 93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long[] getSyncSamples() { 96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getSyncSamples(); 97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { 100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getSampleDependencies(); 101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public TrackMetaData getTrackMetaData() { 104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu TrackMetaData trackMetaData = (TrackMetaData) source.getTrackMetaData().clone(); 105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu trackMetaData.setTimescale(timeScale); 106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return trackMetaData; 107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String getHandler() { 110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getHandler(); 111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public boolean isEnabled() { 114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.isEnabled(); 115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public boolean isInMovie() { 118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.isInMovie(); 119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public boolean isInPreview() { 122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.isInPreview(); 123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public boolean isInPoster() { 126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.isInPoster(); 127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<ByteBuffer> getSamples() { 130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getSamples(); 131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu /** 135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Adjusting the composition times is easy. Just scale it by the factor - that's it. There is no rounding 136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * error summing up. 137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param source 139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param timeScaleFactor 140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @return 141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu static List<CompositionTimeToSample.Entry> adjustCtts(List<CompositionTimeToSample.Entry> source, double timeScaleFactor) { 143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (source != null) { 144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<CompositionTimeToSample.Entry> entries2 = new ArrayList<CompositionTimeToSample.Entry>(source.size()); 145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (CompositionTimeToSample.Entry entry : source) { 146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries2.add(new CompositionTimeToSample.Entry(entry.getCount(), (int) Math.round(timeScaleFactor * entry.getOffset()))); 147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 148dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return entries2; 149dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } else { 150dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return null; 151dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 152dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 153dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 154dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu static List<TimeToSampleBox.Entry> adjustTts(List<TimeToSampleBox.Entry> source, double timeScaleFactor, long[] syncSample, long[] syncSampleTimes) { 155dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 156dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long[] sourceArray = TimeToSampleBox.blowupTimeToSamples(source); 157dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long summedDurations = 0; 158dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 159dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu LinkedList<TimeToSampleBox.Entry> entries2 = new LinkedList<TimeToSampleBox.Entry>(); 160dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = 1; i <= sourceArray.length; i++) { 161dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long duration = sourceArray[i - 1]; 162dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 163dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long x = Math.round(timeScaleFactor * duration); 164dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 165dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 166dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu TimeToSampleBox.Entry last = entries2.peekLast(); 167dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int ssIndex; 168dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if ((ssIndex = Arrays.binarySearch(syncSample, i + 1)) >= 0) { 169dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu // we are at the sample before sync point 170dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (syncSampleTimes[ssIndex] != summedDurations) { 171dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long correction = syncSampleTimes[ssIndex] - (summedDurations + x); 172dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu LOG.finest(String.format("Sample %d %d / %d - correct by %d", i, summedDurations, syncSampleTimes[ssIndex], correction)); 173dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu x += correction; 174dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 175dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 176dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu summedDurations += x; 177dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (last == null) { 178dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries2.add(new TimeToSampleBox.Entry(1, x)); 179dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } else if (last.getDelta() != x) { 180dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries2.add(new TimeToSampleBox.Entry(1, x)); 181dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } else { 182dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu last.setCount(last.getCount() + 1); 183dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 184dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 185dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 186dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return entries2; 187dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 188dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 189dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public Box getMediaHeaderBox() { 190dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getMediaHeaderBox(); 191dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 192dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 193dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public SubSampleInformationBox getSubsampleInformationBox() { 194dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return source.getSubsampleInformationBox(); 195dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 196dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 197dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 198dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String toString() { 199dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return "ChangeTimeScaleTrack{" + 200dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu "source=" + source + 201dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu '}'; 202dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 203dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu}