/* * 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.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; /** * Appends two or more <code>Tracks</code> of the same type. No only that the type must be equal * also the decoder settings must be the same. */ public class AppendTrack extends AbstractTrack { Track[] tracks; public AppendTrack(Track... tracks) throws IOException { this.tracks = tracks; byte[] referenceSampleDescriptionBox = null; for (Track track : tracks) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); track.getSampleDescriptionBox().getBox(Channels.newChannel(baos)); if (referenceSampleDescriptionBox == null) { referenceSampleDescriptionBox = baos.toByteArray(); } else if (!Arrays.equals(referenceSampleDescriptionBox, baos.toByteArray())) { throw new IOException("Cannot append " + track + " to " + tracks[0] + " since their Sample Description Boxes differ"); } } } public List<ByteBuffer> getSamples() { ArrayList<ByteBuffer> lists = new ArrayList<ByteBuffer>(); for (Track track : tracks) { lists.addAll(track.getSamples()); } return lists; } public SampleDescriptionBox getSampleDescriptionBox() { return tracks[0].getSampleDescriptionBox(); } public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { if (tracks[0].getDecodingTimeEntries() != null && !tracks[0].getDecodingTimeEntries().isEmpty()) { List<long[]> lists = new LinkedList<long[]>(); for (Track track : tracks) { lists.add(TimeToSampleBox.blowupTimeToSamples(track.getDecodingTimeEntries())); } LinkedList<TimeToSampleBox.Entry> returnDecodingEntries = new LinkedList<TimeToSampleBox.Entry>(); for (long[] list : lists) { for (long nuDecodingTime : list) { 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 (tracks[0].getCompositionTimeEntries() != null && !tracks[0].getCompositionTimeEntries().isEmpty()) { List<int[]> lists = new LinkedList<int[]>(); for (Track track : tracks) { lists.add(CompositionTimeToSample.blowupCompositionTimes(track.getCompositionTimeEntries())); } LinkedList<CompositionTimeToSample.Entry> compositionTimeEntries = new LinkedList<CompositionTimeToSample.Entry>(); for (int[] list : lists) { for (int compositionTime : list) { if (compositionTimeEntries.isEmpty() || compositionTimeEntries.getLast().getOffset() != compositionTime) { CompositionTimeToSample.Entry e = new CompositionTimeToSample.Entry(1, compositionTime); compositionTimeEntries.add(e); } else { CompositionTimeToSample.Entry e = compositionTimeEntries.getLast(); e.setCount(e.getCount() + 1); } } } return compositionTimeEntries; } else { return null; } } public long[] getSyncSamples() { if (tracks[0].getSyncSamples() != null && tracks[0].getSyncSamples().length > 0) { int numSyncSamples = 0; for (Track track : tracks) { numSyncSamples += track.getSyncSamples().length; } long[] returnSyncSamples = new long[numSyncSamples]; int pos = 0; long samplesBefore = 0; for (Track track : tracks) { for (long l : track.getSyncSamples()) { returnSyncSamples[pos++] = samplesBefore + l; } samplesBefore += track.getSamples().size(); } return returnSyncSamples; } else { return null; } } public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { if (tracks[0].getSampleDependencies() != null && !tracks[0].getSampleDependencies().isEmpty()) { List<SampleDependencyTypeBox.Entry> list = new LinkedList<SampleDependencyTypeBox.Entry>(); for (Track track : tracks) { list.addAll(track.getSampleDependencies()); } return list; } else { return null; } } public TrackMetaData getTrackMetaData() { return tracks[0].getTrackMetaData(); } public String getHandler() { return tracks[0].getHandler(); } public AbstractMediaHeaderBox getMediaHeaderBox() { return tracks[0].getMediaHeaderBox(); } public SubSampleInformationBox getSubsampleInformationBox() { return tracks[0].getSubsampleInformationBox(); } }