blob: 2389961f06130b5632f5bdad8a70afc74c5e6d92 [file] [log] [blame]
/*
* 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.tracks;
import com.coremedia.iso.boxes.*;
import com.googlecode.mp4parser.authoring.AbstractTrack;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.TrackMetaData;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
/**
* Generates a Track that starts at fromSample and ends at toSample (exclusive). The user of this class
* has to make sure that the fromSample is a random access sample.
* <ul>
* <li>In AAC this is every single sample</li>
* <li>In H264 this is every sample that is marked in the SyncSampleBox</li>
* </ul>
*/
public class CroppedTrack extends AbstractTrack {
Track origTrack;
private int fromSample;
private int toSample;
private long[] syncSampleArray;
public CroppedTrack(Track origTrack, long fromSample, long toSample) {
this.origTrack = origTrack;
assert fromSample <= Integer.MAX_VALUE;
assert toSample <= Integer.MAX_VALUE;
this.fromSample = (int) fromSample;
this.toSample = (int) toSample;
}
public List<ByteBuffer> getSamples() {
return origTrack.getSamples().subList(fromSample, toSample);
}
public SampleDescriptionBox getSampleDescriptionBox() {
return origTrack.getSampleDescriptionBox();
}
public List<TimeToSampleBox.Entry> getDecodingTimeEntries() {
if (origTrack.getDecodingTimeEntries() != null && !origTrack.getDecodingTimeEntries().isEmpty()) {
// todo optimize! too much long is allocated but then not used
long[] decodingTimes = TimeToSampleBox.blowupTimeToSamples(origTrack.getDecodingTimeEntries());
long[] nuDecodingTimes = new long[toSample - fromSample];
System.arraycopy(decodingTimes, fromSample, nuDecodingTimes, 0, toSample - fromSample);
LinkedList<TimeToSampleBox.Entry> returnDecodingEntries = new LinkedList<TimeToSampleBox.Entry>();
for (long nuDecodingTime : nuDecodingTimes) {
if (returnDecodingEntries.isEmpty() || returnDecodingEntries.getLast().getDelta() != nuDecodingTime) {
TimeToSampleBox.Entry e = new TimeToSampleBox.Entry(1, nuDecodingTime);
returnDecodingEntries.add(e);
} else {
TimeToSampleBox.Entry e = returnDecodingEntries.getLast();
e.setCount(e.getCount() + 1);
}
}
return returnDecodingEntries;
} else {
return null;
}
}
public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() {
if (origTrack.getCompositionTimeEntries() != null && !origTrack.getCompositionTimeEntries().isEmpty()) {
int[] compositionTime = CompositionTimeToSample.blowupCompositionTimes(origTrack.getCompositionTimeEntries());
int[] nuCompositionTimes = new int[toSample - fromSample];
System.arraycopy(compositionTime, fromSample, nuCompositionTimes, 0, toSample - fromSample);
LinkedList<CompositionTimeToSample.Entry> returnDecodingEntries = new LinkedList<CompositionTimeToSample.Entry>();
for (int nuDecodingTime : nuCompositionTimes) {
if (returnDecodingEntries.isEmpty() || returnDecodingEntries.getLast().getOffset() != nuDecodingTime) {
CompositionTimeToSample.Entry e = new CompositionTimeToSample.Entry(1, nuDecodingTime);
returnDecodingEntries.add(e);
} else {
CompositionTimeToSample.Entry e = returnDecodingEntries.getLast();
e.setCount(e.getCount() + 1);
}
}
return returnDecodingEntries;
} else {
return null;
}
}
synchronized public long[] getSyncSamples() {
if (this.syncSampleArray == null) {
if (origTrack.getSyncSamples() != null && origTrack.getSyncSamples().length > 0) {
List<Long> syncSamples = new LinkedList<Long>();
for (long l : origTrack.getSyncSamples()) {
if (l >= fromSample && l < toSample) {
syncSamples.add(l - fromSample);
}
}
syncSampleArray = new long[syncSamples.size()];
for (int i = 0; i < syncSampleArray.length; i++) {
syncSampleArray[i] = syncSamples.get(i);
}
return syncSampleArray;
} else {
return null;
}
} else {
return this.syncSampleArray;
}
}
public List<SampleDependencyTypeBox.Entry> getSampleDependencies() {
if (origTrack.getSampleDependencies() != null && !origTrack.getSampleDependencies().isEmpty()) {
return origTrack.getSampleDependencies().subList(fromSample, toSample);
} else {
return null;
}
}
public TrackMetaData getTrackMetaData() {
return origTrack.getTrackMetaData();
}
public String getHandler() {
return origTrack.getHandler();
}
public Box getMediaHeaderBox() {
return origTrack.getMediaHeaderBox();
}
public SubSampleInformationBox getSubsampleInformationBox() {
return origTrack.getSubsampleInformationBox();
}
}