diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2012-09-23 14:06:01 -0700 |
---|---|---|
committer | Teng-Hui Zhu <ztenghui@google.com> | 2012-09-23 14:07:00 -0700 |
commit | d6072f0a479bb3bb6fe1ef2825b9ee6187827d96 (patch) | |
tree | 045d208ea840d3ee0821f0666c773e4e31affe7d /isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base | |
parent | dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf (diff) | |
download | mp4parser-d6072f0a479bb3bb6fe1ef2825b9ee6187827d96.tar.gz |
Remove all the .svn directory
bug:7093055
Change-Id: Iea526bdda3ba27736440daf17ff8b25ff4fb3660
Diffstat (limited to 'isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base')
-rw-r--r-- | isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base | 334 |
1 files changed, 0 insertions, 334 deletions
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base deleted file mode 100644 index 2766c5e..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2012 Sebastian Annies, Hamburg - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.googlecode.mp4parser.authoring.builder; - -import com.coremedia.iso.boxes.TimeToSampleBox; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -import static com.googlecode.mp4parser.util.Math.lcm; - -/** - * This <code>FragmentIntersectionFinder</code> cuts the input movie video tracks in - * fragments of the same length exactly before the sync samples. Audio tracks are cut - * into pieces of similar length. - */ -public class SyncSampleIntersectFinderImpl implements FragmentIntersectionFinder { - - private static Logger LOG = Logger.getLogger(SyncSampleIntersectFinderImpl.class.getName()); - private static Map<CacheTuple, long[]> getTimesCache = new ConcurrentHashMap<CacheTuple, long[]>(); - private static Map<CacheTuple, long[]> getSampleNumbersCache = new ConcurrentHashMap<CacheTuple, long[]>(); - - private final int minFragmentDurationSeconds; - - public SyncSampleIntersectFinderImpl() { - minFragmentDurationSeconds = 0; - } - - /** - * Creates a <code>SyncSampleIntersectFinderImpl</code> that will not create any fragment - * smaller than the given <code>minFragmentDurationSeconds</code> - * - * @param minFragmentDurationSeconds the smallest allowable duration of a fragment. - */ - public SyncSampleIntersectFinderImpl(int minFragmentDurationSeconds) { - this.minFragmentDurationSeconds = minFragmentDurationSeconds; - } - - /** - * Gets an array of sample numbers that are meant to be the first sample of each - * chunk or fragment. - * - * @param track concerned track - * @param movie the context of the track - * @return an array containing the ordinal of each fragment's first sample - */ - public long[] sampleNumbers(Track track, Movie movie) { - final CacheTuple key = new CacheTuple(track, movie); - final long[] result = getSampleNumbersCache.get(key); - if (result != null) { - return result; - } - - if ("vide".equals(track.getHandler())) { - if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { - List<long[]> times = getSyncSamplesTimestamps(movie, track); - final long[] commonIndices = getCommonIndices(track.getSyncSamples(), getTimes(track, movie), track.getTrackMetaData().getTimescale(), times.toArray(new long[times.size()][])); - getSampleNumbersCache.put(key, commonIndices); - return commonIndices; - } else { - throw new RuntimeException("Video Tracks need sync samples. Only tracks other than video may have no sync samples."); - } - } else if ("soun".equals(track.getHandler())) { - Track referenceTrack = null; - for (Track candidate : movie.getTracks()) { - if (candidate.getSyncSamples() != null && "vide".equals(candidate.getHandler()) && candidate.getSyncSamples().length > 0) { - referenceTrack = candidate; - } - } - if (referenceTrack != null) { - - // Gets the reference track's fra - long[] refSyncSamples = sampleNumbers(referenceTrack, movie); - - int refSampleCount = referenceTrack.getSamples().size(); - - long[] syncSamples = new long[refSyncSamples.length]; - long minSampleRate = 192000; - for (Track testTrack : movie.getTracks()) { - if ("soun".equals(testTrack.getHandler())) { - AudioSampleEntry ase = (AudioSampleEntry) testTrack.getSampleDescriptionBox().getSampleEntry(); - if (ase.getSampleRate() < minSampleRate) { - minSampleRate = ase.getSampleRate(); - long sc = testTrack.getSamples().size(); - double stretch = (double) sc / refSampleCount; - TimeToSampleBox.Entry sttsEntry = testTrack.getDecodingTimeEntries().get(0); - long samplesPerFrame = sttsEntry.getDelta(); // Assuming all audio tracks have the same number of samples per frame, which they do for all known types - - for (int i = 0; i < syncSamples.length; i++) { - long start = (long) Math.ceil(stretch * (refSyncSamples[i] - 1) * samplesPerFrame); - syncSamples[i] = start; - // The Stretch makes sure that there are as much audio and video chunks! - } - break; - } - } - } - AudioSampleEntry ase = (AudioSampleEntry) track.getSampleDescriptionBox().getSampleEntry(); - TimeToSampleBox.Entry sttsEntry = track.getDecodingTimeEntries().get(0); - long samplesPerFrame = sttsEntry.getDelta(); // Assuming all audio tracks have the same number of samples per frame, which they do for all known types - double factor = (double) ase.getSampleRate() / (double) minSampleRate; - if (factor != Math.rint(factor)) { // Not an integer - throw new RuntimeException("Sample rates must be a multiple of the lowest sample rate to create a correct file!"); - } - for (int i = 0; i < syncSamples.length; i++) { - syncSamples[i] = (long) (1 + syncSamples[i] * factor / (double) samplesPerFrame); - } - getSampleNumbersCache.put(key, syncSamples); - return syncSamples; - } - throw new RuntimeException("There was absolutely no Track with sync samples. I can't work with that!"); - } else { - // Ok, my track has no sync samples - let's find one with sync samples. - for (Track candidate : movie.getTracks()) { - if (candidate.getSyncSamples() != null && candidate.getSyncSamples().length > 0) { - long[] refSyncSamples = sampleNumbers(candidate, movie); - int refSampleCount = candidate.getSamples().size(); - - long[] syncSamples = new long[refSyncSamples.length]; - long sc = track.getSamples().size(); - double stretch = (double) sc / refSampleCount; - - for (int i = 0; i < syncSamples.length; i++) { - long start = (long) Math.ceil(stretch * (refSyncSamples[i] - 1)) + 1; - syncSamples[i] = start; - // The Stretch makes sure that there are as much audio and video chunks! - } - getSampleNumbersCache.put(key, syncSamples); - return syncSamples; - } - } - throw new RuntimeException("There was absolutely no Track with sync samples. I can't work with that!"); - } - - - } - - /** - * Calculates the timestamp of all tracks' sync samples. - * - * @param movie - * @param track - * @return - */ - public static List<long[]> getSyncSamplesTimestamps(Movie movie, Track track) { - List<long[]> times = new LinkedList<long[]>(); - for (Track currentTrack : movie.getTracks()) { - if (currentTrack.getHandler().equals(track.getHandler())) { - long[] currentTrackSyncSamples = currentTrack.getSyncSamples(); - if (currentTrackSyncSamples != null && currentTrackSyncSamples.length > 0) { - final long[] currentTrackTimes = getTimes(currentTrack, movie); - times.add(currentTrackTimes); - } - } - } - return times; - } - - public long[] getCommonIndices(long[] syncSamples, long[] syncSampleTimes, long timeScale, long[]... otherTracksTimes) { - List<Long> nuSyncSamples = new LinkedList<Long>(); - List<Long> nuSyncSampleTimes = new LinkedList<Long>(); - - - for (int i = 0; i < syncSampleTimes.length; i++) { - boolean foundInEveryRef = true; - for (long[] times : otherTracksTimes) { - foundInEveryRef &= (Arrays.binarySearch(times, syncSampleTimes[i]) >= 0); - } - - if (foundInEveryRef) { - // use sample only if found in every other track. - nuSyncSamples.add(syncSamples[i]); - nuSyncSampleTimes.add(syncSampleTimes[i]); - } - } - // We have two arrays now: - // nuSyncSamples: Contains all common sync samples - // nuSyncSampleTimes: Contains the times of all sync samples - - // Start: Warn user if samples are not matching! - if (nuSyncSamples.size() < (syncSamples.length * 0.25)) { - String log = ""; - log += String.format("%5d - Common: [", nuSyncSamples.size()); - for (long l : nuSyncSamples) { - log += (String.format("%10d,", l)); - } - log += ("]"); - LOG.warning(log); - log = ""; - - log += String.format("%5d - In : [", syncSamples.length); - for (long l : syncSamples) { - log += (String.format("%10d,", l)); - } - log += ("]"); - LOG.warning(log); - LOG.warning("There are less than 25% of common sync samples in the given track."); - throw new RuntimeException("There are less than 25% of common sync samples in the given track."); - } else if (nuSyncSamples.size() < (syncSamples.length * 0.5)) { - LOG.fine("There are less than 50% of common sync samples in the given track. This is implausible but I'm ok to continue."); - } else if (nuSyncSamples.size() < syncSamples.length) { - LOG.finest("Common SyncSample positions vs. this tracks SyncSample positions: " + nuSyncSamples.size() + " vs. " + syncSamples.length); - } - // End: Warn user if samples are not matching! - - - - - List<Long> finalSampleList = new LinkedList<Long>(); - - if (minFragmentDurationSeconds > 0) { - // if minFragmentDurationSeconds is greater 0 - // we need to throw away certain samples. - long lastSyncSampleTime = -1; - Iterator<Long> nuSyncSamplesIterator = nuSyncSamples.iterator(); - Iterator<Long> nuSyncSampleTimesIterator = nuSyncSampleTimes.iterator(); - while (nuSyncSamplesIterator.hasNext() && nuSyncSampleTimesIterator.hasNext()) { - long curSyncSample = nuSyncSamplesIterator.next(); - long curSyncSampleTime = nuSyncSampleTimesIterator.next(); - if (lastSyncSampleTime == -1 || (curSyncSampleTime - lastSyncSampleTime) / timeScale >= minFragmentDurationSeconds) { - finalSampleList.add(curSyncSample); - lastSyncSampleTime = curSyncSampleTime; - } - } - } else { - // the list of all samples is the final list of samples - // since minFragmentDurationSeconds ist not used. - finalSampleList = nuSyncSamples; - } - - - // transform the list to an array - long[] finalSampleArray = new long[finalSampleList.size()]; - for (int i = 0; i < finalSampleArray.length; i++) { - finalSampleArray[i] = finalSampleList.get(i); - } - return finalSampleArray; - - } - - - private static long[] getTimes(Track track, Movie m) { - final CacheTuple key = new CacheTuple(track, m); - final long[] result = getTimesCache.get(key); - if (result != null) { - return result; - } - - long[] syncSamples = track.getSyncSamples(); - long[] syncSampleTimes = new long[syncSamples.length]; - Queue<TimeToSampleBox.Entry> timeQueue = new LinkedList<TimeToSampleBox.Entry>(track.getDecodingTimeEntries()); - - int currentSample = 1; // first syncsample is 1 - long currentDuration = 0; - long currentDelta = 0; - int currentSyncSampleIndex = 0; - long left = 0; - - final long scalingFactor = calculateTracktimesScalingFactor(m, track); - - while (currentSample <= syncSamples[syncSamples.length - 1]) { - if (currentSample++ == syncSamples[currentSyncSampleIndex]) { - syncSampleTimes[currentSyncSampleIndex++] = currentDuration * scalingFactor; - } - if (left-- == 0) { - TimeToSampleBox.Entry entry = timeQueue.poll(); - left = entry.getCount() - 1; - currentDelta = entry.getDelta(); - } - currentDuration += currentDelta; - } - getTimesCache.put(key, syncSampleTimes); - return syncSampleTimes; - } - - private static long calculateTracktimesScalingFactor(Movie m, Track track) { - long timeScale = 1; - for (Track track1 : m.getTracks()) { - if (track1.getHandler().equals(track.getHandler())) { - if (track1.getTrackMetaData().getTimescale() != track.getTrackMetaData().getTimescale()) { - timeScale = lcm(timeScale, track1.getTrackMetaData().getTimescale()); - } - } - } - return timeScale; - } - - public static class CacheTuple { - Track track; - Movie movie; - - public CacheTuple(Track track, Movie movie) { - this.track = track; - this.movie = movie; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - CacheTuple that = (CacheTuple) o; - - if (movie != null ? !movie.equals(that.movie) : that.movie != null) return false; - if (track != null ? !track.equals(that.track) : that.track != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = track != null ? track.hashCode() : 0; - result = 31 * result + (movie != null ? movie.hashCode() : 0); - return result; - } - } -} |