/*
* 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;
import com.coremedia.iso.boxes.*;
import com.coremedia.iso.boxes.fragment.*;
import com.coremedia.iso.boxes.mdat.SampleList;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static com.googlecode.mp4parser.util.CastUtils.l2i;
/**
* Represents a single track of an MP4 file.
*/
public class Mp4TrackImpl extends AbstractTrack {
private List<ByteBuffer> samples;
private SampleDescriptionBox sampleDescriptionBox;
private List<TimeToSampleBox.Entry> decodingTimeEntries;
private List<CompositionTimeToSample.Entry> compositionTimeEntries;
private long[] syncSamples = new long[0];
private List<SampleDependencyTypeBox.Entry> sampleDependencies;
private TrackMetaData trackMetaData = new TrackMetaData();
private String handler;
private AbstractMediaHeaderBox mihd;
public Mp4TrackImpl(TrackBox trackBox) {
final long trackId = trackBox.getTrackHeaderBox().getTrackId();
samples = new SampleList(trackBox);
SampleTableBox stbl = trackBox.getMediaBox().getMediaInformationBox().getSampleTableBox();
handler = trackBox.getMediaBox().getHandlerBox().getHandlerType();
mihd = trackBox.getMediaBox().getMediaInformationBox().getMediaHeaderBox();
decodingTimeEntries = new ArrayList<TimeToSampleBox.Entry>();
compositionTimeEntries = new ArrayList<CompositionTimeToSample.Entry>();
sampleDependencies = new ArrayList<SampleDependencyTypeBox.Entry>();
decodingTimeEntries.addAll(stbl.getTimeToSampleBox().getEntries());
if (stbl.getCompositionTimeToSample() != null) {
compositionTimeEntries.addAll(stbl.getCompositionTimeToSample().getEntries());
}
if (stbl.getSampleDependencyTypeBox() != null) {
sampleDependencies.addAll(stbl.getSampleDependencyTypeBox().getEntries());
}
if (stbl.getSyncSampleBox() != null) {
syncSamples = stbl.getSyncSampleBox().getSampleNumber();
}
sampleDescriptionBox = stbl.getSampleDescriptionBox();
final List<MovieExtendsBox> movieExtendsBoxes = trackBox.getParent().getBoxes(MovieExtendsBox.class);
if (movieExtendsBoxes.size() > 0) {
for (MovieExtendsBox mvex : movieExtendsBoxes) {
final List<TrackExtendsBox> trackExtendsBoxes = mvex.getBoxes(TrackExtendsBox.class);
for (TrackExtendsBox trex : trackExtendsBoxes) {
if (trex.getTrackId() == trackId) {
List<Long> syncSampleList = new LinkedList<Long>();
long sampleNumber = 1;
for (MovieFragmentBox movieFragmentBox : trackBox.getIsoFile().getBoxes(MovieFragmentBox.class)) {
List<TrackFragmentBox> trafs = movieFragmentBox.getBoxes(TrackFragmentBox.class);
for (TrackFragmentBox traf : trafs) {
if (traf.getTrackFragmentHeaderBox().getTrackId() == trackId) {
List<TrackRunBox> truns = traf.getBoxes(TrackRunBox.class);
for (TrackRunBox trun : truns) {
final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) trun.getParent()).getTrackFragmentHeaderBox();
boolean first = true;
for (TrackRunBox.Entry entry : trun.getEntries()) {
if (trun.isSampleDurationPresent()) {
if (decodingTimeEntries.size() == 0 ||
decodingTimeEntries.get(decodingTimeEntries.size() - 1).getDelta() != entry.getSampleDuration()) {
decodingTimeEntries.add(new TimeToSampleBox.Entry(1, entry.getSampleDuration()));
} else {
TimeToSampleBox.Entry e = decodingTimeEntries.get(decodingTimeEntries.size() - 1);
e.setCount(e.getCount() + 1);
}
} else {
if (tfhd.hasDefaultSampleDuration()) {
decodingTimeEntries.add(new TimeToSampleBox.Entry(1, tfhd.getDefaultSampleDuration()));
} else {
decodingTimeEntries.add(new TimeToSampleBox.Entry(1, trex.getDefaultSampleDuration()));
}
}
if (trun.isSampleCompositionTimeOffsetPresent()) {
if (compositionTimeEntries.size() == 0 ||
compositionTimeEntries.get(compositionTimeEntries.size() - 1).getOffset() != entry.getSampleCompositionTimeOffset()) {
compositionTimeEntries.add(new CompositionTimeToSample.Entry(1, l2i(entry.getSampleCompositionTimeOffset())));
} else {
CompositionTimeToSample.Entry e = compositionTimeEntries.get(compositionTimeEntries.size() - 1);
e.setCount(e.getCount() + 1);
}
}
final SampleFlags sampleFlags;
if (trun.isSampleFlagsPresent()) {
sampleFlags = entry.getSampleFlags();
} else {
if (first && trun.isFirstSampleFlagsPresent()) {
sampleFlags = trun.getFirstSampleFlags();
} else {
if (tfhd.hasDefaultSampleFlags()) {
sampleFlags = tfhd.getDefaultSampleFlags();
} else {
sampleFlags = trex.getDefaultSampleFlags();
}
}
}
if (sampleFlags != null && !sampleFlags.isSampleIsDifferenceSample()) {
//iframe
syncSampleList.add(sampleNumber);
}
sampleNumber++;
first = false;
}
}
}
}
}
// Warning: Crappy code
long[] oldSS = syncSamples;
syncSamples = new long[syncSamples.length + syncSampleList.size()];
System.arraycopy(oldSS, 0, syncSamples, 0, oldSS.length);
final Iterator<Long> iterator = syncSampleList.iterator();
int i = oldSS.length;
while (iterator.hasNext()) {
Long syncSampleNumber = iterator.next();
syncSamples[i++] = syncSampleNumber;
}
}
}
}
}
MediaHeaderBox mdhd = trackBox.getMediaBox().getMediaHeaderBox();
TrackHeaderBox tkhd = trackBox.getTrackHeaderBox();
setEnabled(tkhd.isEnabled());
setInMovie(tkhd.isInMovie());
setInPoster(tkhd.isInPoster());
setInPreview(tkhd.isInPreview());
trackMetaData.setTrackId(tkhd.getTrackId());
trackMetaData.setCreationTime(DateHelper.convert(mdhd.getCreationTime()));
trackMetaData.setLanguage(mdhd.getLanguage());
/* System.err.println(mdhd.getModificationTime());
System.err.println(DateHelper.convert(mdhd.getModificationTime()));
System.err.println(DateHelper.convert(DateHelper.convert(mdhd.getModificationTime())));
System.err.println(DateHelper.convert(DateHelper.convert(DateHelper.convert(mdhd.getModificationTime()))));*/
trackMetaData.setModificationTime(DateHelper.convert(mdhd.getModificationTime()));
trackMetaData.setTimescale(mdhd.getTimescale());
trackMetaData.setHeight(tkhd.getHeight());
trackMetaData.setWidth(tkhd.getWidth());
trackMetaData.setLayer(tkhd.getLayer());
}
public List<ByteBuffer> getSamples() {
return samples;
}
public SampleDescriptionBox getSampleDescriptionBox() {
return sampleDescriptionBox;
}
public List<TimeToSampleBox.Entry> getDecodingTimeEntries() {
return decodingTimeEntries;
}
public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() {
return compositionTimeEntries;
}
public long[] getSyncSamples() {
return syncSamples;
}
public List<SampleDependencyTypeBox.Entry> getSampleDependencies() {
return sampleDependencies;
}
public TrackMetaData getTrackMetaData() {
return trackMetaData;
}
public String getHandler() {
return handler;
}
public AbstractMediaHeaderBox getMediaHeaderBox() {
return mihd;
}
public SubSampleInformationBox getSubsampleInformationBox() {
return null;
}
@Override
public String toString() {
return "Mp4TrackImpl{" +
"handler='" + handler + '\'' +
'}';
}
}
|