package com.castlabs.dash.helpers; import com.googlecode.mp4parser.authoring.Track; import com.googlecode.mp4parser.authoring.builder.Fragmenter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Created by sannies on 05.02.2015. */ public class SoundIntersectionFinderImpl implements Fragmenter { long timscale = 1; private List<Long> syncPoints; /** * Creates an intersection finder for sound tracks. This finder will not take sync samples * into consideration but makes that all intersects for all tracks are at the same times. * * @param tracks all sound tracks * @param desiredFragmentDuration desired fragment duration in seconds */ public SoundIntersectionFinderImpl(List<Track> tracks, double desiredFragmentDuration) { for (Track track : tracks) { timscale = lcmcal(timscale, track.getTrackMetaData().getTimescale()); } long[] commonTimes = null; for (Track track : tracks) { long trackTimeScale = track.getTrackMetaData().getTimescale(); long[] sampleTimes = new long[track.getSamples().size()]; long[] sampleDurations = track.getSampleDurations(); for (int i = 1; i < sampleDurations.length; i++) { sampleTimes[i] = sampleTimes[i - 1] + sampleDurations[i] * timscale / trackTimeScale; } if (commonTimes == null) { commonTimes = sampleTimes; } else { long[] nuCommonTimes = new long[0]; for (long timeStamp : commonTimes) { if (Arrays.binarySearch(sampleTimes, timeStamp) >= 0) { nuCommonTimes = Arrays.copyOf(nuCommonTimes, nuCommonTimes.length + 1); nuCommonTimes[nuCommonTimes.length - 1] = timeStamp; } } } } syncPoints = new ArrayList<Long>(); for (long timestamp : commonTimes) { if (timestamp >= desiredFragmentDuration * timscale * syncPoints.size() ) { syncPoints.add(timestamp); } } } /** * {@inheritDoc} */ public long[] sampleNumbers(Track track) { long time = 0; long[] sampleNums = new long[0]; long[] sampleDurations = track.getSampleDurations(); long trackTimeScale = track.getTrackMetaData().getTimescale(); for (int i = 0; i < sampleDurations.length; i++) { if (syncPoints.contains(time)) { sampleNums = Arrays.copyOf(sampleNums, sampleNums.length + 1); sampleNums[sampleNums.length - 1] = i + 1; } time += sampleDurations[i] * timscale / trackTimeScale; } return sampleNums; } long lcmcal(long x1, long x2) { long max,min; if (x1>x2) { max = x1; min = x2; } else { max = x2; min = x1; } for(int i=1; i<=min; i++) { if( (max*i)%min == 0 ) { return i*max; } } throw new Error("Cannot find the least common multiple of numbers "+ x1+" and "+x2); } }