CroppedTrack.java revision dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf
1/*
2 * Copyright 2012 Sebastian Annies, Hamburg
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.googlecode.mp4parser.authoring.tracks;
17
18import com.coremedia.iso.boxes.*;
19import com.googlecode.mp4parser.authoring.AbstractTrack;
20import com.googlecode.mp4parser.authoring.Track;
21import com.googlecode.mp4parser.authoring.TrackMetaData;
22
23import java.nio.ByteBuffer;
24import java.util.LinkedList;
25import java.util.List;
26
27/**
28 * Generates a Track that starts at fromSample and ends at toSample (exclusive). The user of this class
29 * has to make sure that the fromSample is a random access sample.
30 * <ul>
31 * <li>In AAC this is every single sample</li>
32 * <li>In H264 this is every sample that is marked in the SyncSampleBox</li>
33 * </ul>
34 */
35public class CroppedTrack extends AbstractTrack {
36    Track origTrack;
37    private int fromSample;
38    private int toSample;
39    private long[] syncSampleArray;
40
41    public CroppedTrack(Track origTrack, long fromSample, long toSample) {
42        this.origTrack = origTrack;
43        assert fromSample <= Integer.MAX_VALUE;
44        assert toSample <= Integer.MAX_VALUE;
45        this.fromSample = (int) fromSample;
46        this.toSample = (int) toSample;
47    }
48
49    public List<ByteBuffer> getSamples() {
50        return origTrack.getSamples().subList(fromSample, toSample);
51    }
52
53    public SampleDescriptionBox getSampleDescriptionBox() {
54        return origTrack.getSampleDescriptionBox();
55    }
56
57    public List<TimeToSampleBox.Entry> getDecodingTimeEntries() {
58        if (origTrack.getDecodingTimeEntries() != null && !origTrack.getDecodingTimeEntries().isEmpty()) {
59            // todo optimize! too much long is allocated but then not used
60            long[] decodingTimes = TimeToSampleBox.blowupTimeToSamples(origTrack.getDecodingTimeEntries());
61            long[] nuDecodingTimes = new long[toSample - fromSample];
62            System.arraycopy(decodingTimes, fromSample, nuDecodingTimes, 0, toSample - fromSample);
63
64            LinkedList<TimeToSampleBox.Entry> returnDecodingEntries = new LinkedList<TimeToSampleBox.Entry>();
65
66            for (long nuDecodingTime : nuDecodingTimes) {
67                if (returnDecodingEntries.isEmpty() || returnDecodingEntries.getLast().getDelta() != nuDecodingTime) {
68                    TimeToSampleBox.Entry e = new TimeToSampleBox.Entry(1, nuDecodingTime);
69                    returnDecodingEntries.add(e);
70                } else {
71                    TimeToSampleBox.Entry e = returnDecodingEntries.getLast();
72                    e.setCount(e.getCount() + 1);
73                }
74            }
75            return returnDecodingEntries;
76        } else {
77            return null;
78        }
79    }
80
81    public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() {
82        if (origTrack.getCompositionTimeEntries() != null && !origTrack.getCompositionTimeEntries().isEmpty()) {
83            int[] compositionTime = CompositionTimeToSample.blowupCompositionTimes(origTrack.getCompositionTimeEntries());
84            int[] nuCompositionTimes = new int[toSample - fromSample];
85            System.arraycopy(compositionTime, fromSample, nuCompositionTimes, 0, toSample - fromSample);
86
87            LinkedList<CompositionTimeToSample.Entry> returnDecodingEntries = new LinkedList<CompositionTimeToSample.Entry>();
88
89            for (int nuDecodingTime : nuCompositionTimes) {
90                if (returnDecodingEntries.isEmpty() || returnDecodingEntries.getLast().getOffset() != nuDecodingTime) {
91                    CompositionTimeToSample.Entry e = new CompositionTimeToSample.Entry(1, nuDecodingTime);
92                    returnDecodingEntries.add(e);
93                } else {
94                    CompositionTimeToSample.Entry e = returnDecodingEntries.getLast();
95                    e.setCount(e.getCount() + 1);
96                }
97            }
98            return returnDecodingEntries;
99        } else {
100            return null;
101        }
102    }
103
104    synchronized public long[] getSyncSamples() {
105        if (this.syncSampleArray == null) {
106            if (origTrack.getSyncSamples() != null && origTrack.getSyncSamples().length > 0) {
107                List<Long> syncSamples = new LinkedList<Long>();
108                for (long l : origTrack.getSyncSamples()) {
109                    if (l >= fromSample && l < toSample) {
110                        syncSamples.add(l - fromSample);
111                    }
112                }
113                syncSampleArray = new long[syncSamples.size()];
114                for (int i = 0; i < syncSampleArray.length; i++) {
115                    syncSampleArray[i] = syncSamples.get(i);
116
117                }
118                return syncSampleArray;
119            } else {
120                return null;
121            }
122        } else {
123            return this.syncSampleArray;
124        }
125    }
126
127    public List<SampleDependencyTypeBox.Entry> getSampleDependencies() {
128        if (origTrack.getSampleDependencies() != null && !origTrack.getSampleDependencies().isEmpty()) {
129            return origTrack.getSampleDependencies().subList(fromSample, toSample);
130        } else {
131            return null;
132        }
133    }
134
135    public TrackMetaData getTrackMetaData() {
136        return origTrack.getTrackMetaData();
137    }
138
139    public String getHandler() {
140        return origTrack.getHandler();
141    }
142
143    public Box getMediaHeaderBox() {
144        return origTrack.getMediaHeaderBox();
145    }
146
147    public SubSampleInformationBox getSubsampleInformationBox() {
148        return origTrack.getSubsampleInformationBox();
149    }
150
151}