summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn
diff options
context:
space:
mode:
Diffstat (limited to 'isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn')
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/all-wcprops47
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/entries266
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/ByteBufferHelper.java.svn-base50
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/DefaultMp4Builder.java.svn-base576
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentIntersectionFinder.java.svn-base34
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentedMp4Builder.java.svn-base742
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/Mp4Builder.java.svn-base35
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base334
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/TwoSecondIntersectionFinder.java.svn-base86
9 files changed, 0 insertions, 2170 deletions
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/all-wcprops
deleted file mode 100644
index 9204edf..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/all-wcprops
+++ /dev/null
@@ -1,47 +0,0 @@
-K 25
-svn:wc:ra_dav:version-url
-V 90
-/svn/!svn/ver/776/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder
-END
-FragmentIntersectionFinder.java
-K 25
-svn:wc:ra_dav:version-url
-V 122
-/svn/!svn/ver/455/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/FragmentIntersectionFinder.java
-END
-TwoSecondIntersectionFinder.java
-K 25
-svn:wc:ra_dav:version-url
-V 123
-/svn/!svn/ver/658/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/TwoSecondIntersectionFinder.java
-END
-FragmentedMp4Builder.java
-K 25
-svn:wc:ra_dav:version-url
-V 116
-/svn/!svn/ver/707/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/FragmentedMp4Builder.java
-END
-Mp4Builder.java
-K 25
-svn:wc:ra_dav:version-url
-V 106
-/svn/!svn/ver/672/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/Mp4Builder.java
-END
-SyncSampleIntersectFinderImpl.java
-K 25
-svn:wc:ra_dav:version-url
-V 125
-/svn/!svn/ver/774/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/SyncSampleIntersectFinderImpl.java
-END
-DefaultMp4Builder.java
-K 25
-svn:wc:ra_dav:version-url
-V 113
-/svn/!svn/ver/776/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/DefaultMp4Builder.java
-END
-ByteBufferHelper.java
-K 25
-svn:wc:ra_dav:version-url
-V 112
-/svn/!svn/ver/530/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/ByteBufferHelper.java
-END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/entries
deleted file mode 100644
index 2c6e266..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/entries
+++ /dev/null
@@ -1,266 +0,0 @@
-10
-
-dir
-778
-http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder
-http://mp4parser.googlecode.com/svn
-
-
-
-2012-09-10T14:34:23.574807Z
-776
-sebastian.annies@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7decde4b-c250-0410-a0da-51896bc88be6
-
-FragmentIntersectionFinder.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-979df582987d3797c42ae315b3d2555a
-2012-04-10T10:20:46.357991Z
-455
-Sebastian.Annies@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1160
-
-TwoSecondIntersectionFinder.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-47aa683919ce24da51b82236e8f27426
-2012-06-06T10:36:10.590512Z
-658
-Sebastian.Annies@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2817
-
-FragmentedMp4Builder.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-f81cbeb22aee5ab0405ad38e67b9e4e1
-2012-07-10T16:32:53.757675Z
-707
-michael.stattmann@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-31005
-
-Mp4Builder.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-ea548a5ace2a4480472b90d9f820bceb
-2012-06-11T22:10:18.183835Z
-672
-michael.stattmann@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1156
-
-SyncSampleIntersectFinderImpl.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-d49823bb95a5920f2df6899195c28a72
-2012-09-06T12:33:39.419429Z
-774
-michael.stattmann@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-14915
-
-DefaultMp4Builder.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-15d93ea29e24e257604301ad5e73d623
-2012-09-10T14:34:23.574807Z
-776
-sebastian.annies@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-22096
-
-ByteBufferHelper.java
-file
-
-
-
-
-2012-09-14T17:27:50.237215Z
-a103511eeddf1e0d1962704ae23ba4a5
-2012-04-27T09:17:25.544414Z
-530
-hoemmagnus@gmail.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2344
-
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/ByteBufferHelper.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/ByteBufferHelper.java.svn-base
deleted file mode 100644
index ad21b11..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/ByteBufferHelper.java.svn-base
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.builder;
-
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Used to merge adjacent byte buffers.
- */
-public class ByteBufferHelper {
- public static List<ByteBuffer> mergeAdjacentBuffers(List<ByteBuffer> samples) {
- ArrayList<ByteBuffer> nuSamples = new ArrayList<ByteBuffer>(samples.size());
- for (ByteBuffer buffer : samples) {
- int lastIndex = nuSamples.size() - 1;
- if (lastIndex >= 0 && buffer.hasArray() && nuSamples.get(lastIndex).hasArray() && buffer.array() == nuSamples.get(lastIndex).array() &&
- nuSamples.get(lastIndex).arrayOffset() + nuSamples.get(lastIndex).limit() == buffer.arrayOffset()) {
- ByteBuffer oldBuffer = nuSamples.remove(lastIndex);
- ByteBuffer nu = ByteBuffer.wrap(buffer.array(), oldBuffer.arrayOffset(), oldBuffer.limit() + buffer.limit()).slice();
- // We need to slice here since wrap([], offset, length) just sets position and not the arrayOffset.
- nuSamples.add(nu);
- } else if (lastIndex >= 0 &&
- buffer instanceof MappedByteBuffer && nuSamples.get(lastIndex) instanceof MappedByteBuffer &&
- nuSamples.get(lastIndex).limit() == nuSamples.get(lastIndex).capacity() - buffer.capacity()) {
- // This can go wrong - but will it?
- ByteBuffer oldBuffer = nuSamples.get(lastIndex);
- oldBuffer.limit(buffer.limit() + oldBuffer.limit());
- } else {
- buffer.rewind();
- nuSamples.add(buffer);
- }
- }
- return nuSamples;
- }
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/DefaultMp4Builder.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/DefaultMp4Builder.java.svn-base
deleted file mode 100644
index 9bd1ca6..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/DefaultMp4Builder.java.svn-base
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * 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.builder;
-
-import com.coremedia.iso.BoxParser;
-import com.coremedia.iso.IsoFile;
-import com.coremedia.iso.IsoTypeWriter;
-import com.coremedia.iso.boxes.Box;
-import com.coremedia.iso.boxes.CompositionTimeToSample;
-import com.coremedia.iso.boxes.ContainerBox;
-import com.coremedia.iso.boxes.DataEntryUrlBox;
-import com.coremedia.iso.boxes.DataInformationBox;
-import com.coremedia.iso.boxes.DataReferenceBox;
-import com.coremedia.iso.boxes.FileTypeBox;
-import com.coremedia.iso.boxes.HandlerBox;
-import com.coremedia.iso.boxes.MediaBox;
-import com.coremedia.iso.boxes.MediaHeaderBox;
-import com.coremedia.iso.boxes.MediaInformationBox;
-import com.coremedia.iso.boxes.MovieBox;
-import com.coremedia.iso.boxes.MovieHeaderBox;
-import com.coremedia.iso.boxes.SampleDependencyTypeBox;
-import com.coremedia.iso.boxes.SampleSizeBox;
-import com.coremedia.iso.boxes.SampleTableBox;
-import com.coremedia.iso.boxes.SampleToChunkBox;
-import com.coremedia.iso.boxes.StaticChunkOffsetBox;
-import com.coremedia.iso.boxes.SyncSampleBox;
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.coremedia.iso.boxes.TrackBox;
-import com.coremedia.iso.boxes.TrackHeaderBox;
-import com.googlecode.mp4parser.authoring.DateHelper;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.GatheringByteChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.googlecode.mp4parser.util.CastUtils.l2i;
-
-/**
- * Creates a plain MP4 file from a video. Plain as plain can be.
- */
-public class DefaultMp4Builder implements Mp4Builder {
-
- public int STEPSIZE = 64;
- Set<StaticChunkOffsetBox> chunkOffsetBoxes = new HashSet<StaticChunkOffsetBox>();
- private static Logger LOG = Logger.getLogger(DefaultMp4Builder.class.getName());
-
- HashMap<Track, List<ByteBuffer>> track2Sample = new HashMap<Track, List<ByteBuffer>>();
- HashMap<Track, long[]> track2SampleSizes = new HashMap<Track, long[]>();
- private FragmentIntersectionFinder intersectionFinder = new TwoSecondIntersectionFinder();
-
- public void setIntersectionFinder(FragmentIntersectionFinder intersectionFinder) {
- this.intersectionFinder = intersectionFinder;
- }
-
- /**
- * {@inheritDoc}
- */
- public IsoFile build(Movie movie) {
- LOG.fine("Creating movie " + movie);
- for (Track track : movie.getTracks()) {
- // getting the samples may be a time consuming activity
- List<ByteBuffer> samples = track.getSamples();
- putSamples(track, samples);
- long[] sizes = new long[samples.size()];
- for (int i = 0; i < sizes.length; i++) {
- sizes[i] = samples.get(i).limit();
- }
- putSampleSizes(track, sizes);
- }
-
- IsoFile isoFile = new IsoFile();
- // ouch that is ugly but I don't know how to do it else
- List<String> minorBrands = new LinkedList<String>();
- minorBrands.add("isom");
- minorBrands.add("iso2");
- minorBrands.add("avc1");
-
- isoFile.addBox(new FileTypeBox("isom", 0, minorBrands));
- isoFile.addBox(createMovieBox(movie));
- InterleaveChunkMdat mdat = new InterleaveChunkMdat(movie);
- isoFile.addBox(mdat);
-
- /*
- dataOffset is where the first sample starts. In this special mdat the samples always start
- at offset 16 so that we can use the same offset for large boxes and small boxes
- */
- long dataOffset = mdat.getDataOffset();
- for (StaticChunkOffsetBox chunkOffsetBox : chunkOffsetBoxes) {
- long[] offsets = chunkOffsetBox.getChunkOffsets();
- for (int i = 0; i < offsets.length; i++) {
- offsets[i] += dataOffset;
- }
- }
-
-
- return isoFile;
- }
-
- public FragmentIntersectionFinder getFragmentIntersectionFinder() {
- throw new UnsupportedOperationException("No fragment intersection finder in default MP4 builder!");
- }
-
- protected long[] putSampleSizes(Track track, long[] sizes) {
- return track2SampleSizes.put(track, sizes);
- }
-
- protected List<ByteBuffer> putSamples(Track track, List<ByteBuffer> samples) {
- return track2Sample.put(track, samples);
- }
-
- private MovieBox createMovieBox(Movie movie) {
- MovieBox movieBox = new MovieBox();
- MovieHeaderBox mvhd = new MovieHeaderBox();
-
- mvhd.setCreationTime(DateHelper.convert(new Date()));
- mvhd.setModificationTime(DateHelper.convert(new Date()));
-
- long movieTimeScale = getTimescale(movie);
- long duration = 0;
-
- for (Track track : movie.getTracks()) {
- long tracksDuration = getDuration(track) * movieTimeScale / track.getTrackMetaData().getTimescale();
- if (tracksDuration > duration) {
- duration = tracksDuration;
- }
-
-
- }
-
- mvhd.setDuration(duration);
- mvhd.setTimescale(movieTimeScale);
- // find the next available trackId
- long nextTrackId = 0;
- for (Track track : movie.getTracks()) {
- nextTrackId = nextTrackId < track.getTrackMetaData().getTrackId() ? track.getTrackMetaData().getTrackId() : nextTrackId;
- }
- mvhd.setNextTrackId(++nextTrackId);
- if (mvhd.getCreationTime() >= 1l << 32 ||
- mvhd.getModificationTime() >= 1l << 32 ||
- mvhd.getDuration() >= 1l << 32) {
- mvhd.setVersion(1);
- }
-
- movieBox.addBox(mvhd);
- for (Track track : movie.getTracks()) {
- movieBox.addBox(createTrackBox(track, movie));
- }
- // metadata here
- Box udta = createUdta(movie);
- if (udta != null) {
- movieBox.addBox(udta);
- }
- return movieBox;
-
- }
-
- /**
- * Override to create a user data box that may contain metadata.
- *
- * @return a 'udta' box or <code>null</code> if none provided
- */
- protected Box createUdta(Movie movie) {
- return null;
- }
-
- private TrackBox createTrackBox(Track track, Movie movie) {
-
- LOG.info("Creating Mp4TrackImpl " + track);
- TrackBox trackBox = new TrackBox();
- TrackHeaderBox tkhd = new TrackHeaderBox();
- int flags = 0;
- if (track.isEnabled()) {
- flags += 1;
- }
-
- if (track.isInMovie()) {
- flags += 2;
- }
-
- if (track.isInPreview()) {
- flags += 4;
- }
-
- if (track.isInPoster()) {
- flags += 8;
- }
- tkhd.setFlags(flags);
-
- tkhd.setAlternateGroup(track.getTrackMetaData().getGroup());
- tkhd.setCreationTime(DateHelper.convert(track.getTrackMetaData().getCreationTime()));
- // We need to take edit list box into account in trackheader duration
- // but as long as I don't support edit list boxes it is sufficient to
- // just translate media duration to movie timescale
- tkhd.setDuration(getDuration(track) * getTimescale(movie) / track.getTrackMetaData().getTimescale());
- tkhd.setHeight(track.getTrackMetaData().getHeight());
- tkhd.setWidth(track.getTrackMetaData().getWidth());
- tkhd.setLayer(track.getTrackMetaData().getLayer());
- tkhd.setModificationTime(DateHelper.convert(new Date()));
- tkhd.setTrackId(track.getTrackMetaData().getTrackId());
- tkhd.setVolume(track.getTrackMetaData().getVolume());
- if (tkhd.getCreationTime() >= 1l << 32 ||
- tkhd.getModificationTime() >= 1l << 32 ||
- tkhd.getDuration() >= 1l << 32) {
- tkhd.setVersion(1);
- }
-
- trackBox.addBox(tkhd);
-
-/*
- EditBox edit = new EditBox();
- EditListBox editListBox = new EditListBox();
- editListBox.setEntries(Collections.singletonList(
- new EditListBox.Entry(editListBox, (long) (track.getTrackMetaData().getStartTime() * getTimescale(movie)), -1, 1)));
- edit.addBox(editListBox);
- trackBox.addBox(edit);
-*/
-
- MediaBox mdia = new MediaBox();
- trackBox.addBox(mdia);
- MediaHeaderBox mdhd = new MediaHeaderBox();
- mdhd.setCreationTime(DateHelper.convert(track.getTrackMetaData().getCreationTime()));
- mdhd.setDuration(getDuration(track));
- mdhd.setTimescale(track.getTrackMetaData().getTimescale());
- mdhd.setLanguage(track.getTrackMetaData().getLanguage());
- mdia.addBox(mdhd);
- HandlerBox hdlr = new HandlerBox();
- mdia.addBox(hdlr);
-
- hdlr.setHandlerType(track.getHandler());
-
- MediaInformationBox minf = new MediaInformationBox();
- minf.addBox(track.getMediaHeaderBox());
-
- // dinf: all these three boxes tell us is that the actual
- // data is in the current file and not somewhere external
- DataInformationBox dinf = new DataInformationBox();
- DataReferenceBox dref = new DataReferenceBox();
- dinf.addBox(dref);
- DataEntryUrlBox url = new DataEntryUrlBox();
- url.setFlags(1);
- dref.addBox(url);
- minf.addBox(dinf);
- //
-
- SampleTableBox stbl = new SampleTableBox();
-
- stbl.addBox(track.getSampleDescriptionBox());
-
- List<TimeToSampleBox.Entry> decodingTimeToSampleEntries = track.getDecodingTimeEntries();
- if (decodingTimeToSampleEntries != null && !track.getDecodingTimeEntries().isEmpty()) {
- TimeToSampleBox stts = new TimeToSampleBox();
- stts.setEntries(track.getDecodingTimeEntries());
- stbl.addBox(stts);
- }
-
- List<CompositionTimeToSample.Entry> compositionTimeToSampleEntries = track.getCompositionTimeEntries();
- if (compositionTimeToSampleEntries != null && !compositionTimeToSampleEntries.isEmpty()) {
- CompositionTimeToSample ctts = new CompositionTimeToSample();
- ctts.setEntries(compositionTimeToSampleEntries);
- stbl.addBox(ctts);
- }
-
- long[] syncSamples = track.getSyncSamples();
- if (syncSamples != null && syncSamples.length > 0) {
- SyncSampleBox stss = new SyncSampleBox();
- stss.setSampleNumber(syncSamples);
- stbl.addBox(stss);
- }
-
- if (track.getSampleDependencies() != null && !track.getSampleDependencies().isEmpty()) {
- SampleDependencyTypeBox sdtp = new SampleDependencyTypeBox();
- sdtp.setEntries(track.getSampleDependencies());
- stbl.addBox(sdtp);
- }
- HashMap<Track, int[]> track2ChunkSizes = new HashMap<Track, int[]>();
- for (Track current : movie.getTracks()) {
- track2ChunkSizes.put(current, getChunkSizes(current, movie));
- }
- int[] tracksChunkSizes = track2ChunkSizes.get(track);
-
- SampleToChunkBox stsc = new SampleToChunkBox();
- stsc.setEntries(new LinkedList<SampleToChunkBox.Entry>());
- long lastChunkSize = Integer.MIN_VALUE; // to be sure the first chunks hasn't got the same size
- for (int i = 0; i < tracksChunkSizes.length; i++) {
- // The sample description index references the sample description box
- // that describes the samples of this chunk. My Tracks cannot have more
- // than one sample description box. Therefore 1 is always right
- // the first chunk has the number '1'
- if (lastChunkSize != tracksChunkSizes[i]) {
- stsc.getEntries().add(new SampleToChunkBox.Entry(i + 1, tracksChunkSizes[i], 1));
- lastChunkSize = tracksChunkSizes[i];
- }
- }
- stbl.addBox(stsc);
-
- SampleSizeBox stsz = new SampleSizeBox();
- stsz.setSampleSizes(track2SampleSizes.get(track));
-
- stbl.addBox(stsz);
- // The ChunkOffsetBox we create here is just a stub
- // since we haven't created the whole structure we can't tell where the
- // first chunk starts (mdat box). So I just let the chunk offset
- // start at zero and I will add the mdat offset later.
- StaticChunkOffsetBox stco = new StaticChunkOffsetBox();
- this.chunkOffsetBoxes.add(stco);
- long offset = 0;
- long[] chunkOffset = new long[tracksChunkSizes.length];
- // all tracks have the same number of chunks
- if (LOG.isLoggable(Level.FINE)) {
- LOG.fine("Calculating chunk offsets for track_" + track.getTrackMetaData().getTrackId());
- }
-
-
- for (int i = 0; i < tracksChunkSizes.length; i++) {
- // The filelayout will be:
- // chunk_1_track_1,... ,chunk_1_track_n, chunk_2_track_1,... ,chunk_2_track_n, ... , chunk_m_track_1,... ,chunk_m_track_n
- // calculating the offsets
- if (LOG.isLoggable(Level.FINER)) {
- LOG.finer("Calculating chunk offsets for track_" + track.getTrackMetaData().getTrackId() + " chunk " + i);
- }
- for (Track current : movie.getTracks()) {
- if (LOG.isLoggable(Level.FINEST)) {
- LOG.finest("Adding offsets of track_" + current.getTrackMetaData().getTrackId());
- }
- int[] chunkSizes = track2ChunkSizes.get(current);
- long firstSampleOfChunk = 0;
- for (int j = 0; j < i; j++) {
- firstSampleOfChunk += chunkSizes[j];
- }
- if (current == track) {
- chunkOffset[i] = offset;
- }
- for (int j = l2i(firstSampleOfChunk); j < firstSampleOfChunk + chunkSizes[i]; j++) {
- offset += track2SampleSizes.get(current)[j];
- }
- }
- }
- stco.setChunkOffsets(chunkOffset);
- stbl.addBox(stco);
- minf.addBox(stbl);
- mdia.addBox(minf);
-
- return trackBox;
- }
-
- private class InterleaveChunkMdat implements Box {
- List<Track> tracks;
- List<ByteBuffer> samples = new ArrayList<ByteBuffer>();
- ContainerBox parent;
-
- long contentSize = 0;
-
- public ContainerBox getParent() {
- return parent;
- }
-
- public void setParent(ContainerBox parent) {
- this.parent = parent;
- }
-
- public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
- }
-
- private InterleaveChunkMdat(Movie movie) {
-
- tracks = movie.getTracks();
- Map<Track, int[]> chunks = new HashMap<Track, int[]>();
- for (Track track : movie.getTracks()) {
- chunks.put(track, getChunkSizes(track, movie));
- }
-
- for (int i = 0; i < chunks.values().iterator().next().length; i++) {
- for (Track track : tracks) {
-
- int[] chunkSizes = chunks.get(track);
- long firstSampleOfChunk = 0;
- for (int j = 0; j < i; j++) {
- firstSampleOfChunk += chunkSizes[j];
- }
-
- for (int j = l2i(firstSampleOfChunk); j < firstSampleOfChunk + chunkSizes[i]; j++) {
-
- ByteBuffer s = DefaultMp4Builder.this.track2Sample.get(track).get(j);
- contentSize += s.limit();
- samples.add((ByteBuffer) s.rewind());
- }
-
- }
-
- }
-
- }
-
- public long getDataOffset() {
- Box b = this;
- long offset = 16;
- while (b.getParent() != null) {
- for (Box box : b.getParent().getBoxes()) {
- if (b == box) {
- break;
- }
- offset += box.getSize();
- }
- b = b.getParent();
- }
- return offset;
- }
-
-
- public String getType() {
- return "mdat";
- }
-
- public long getSize() {
- return 16 + contentSize;
- }
-
- private boolean isSmallBox(long contentSize) {
- return (contentSize + 8) < 4294967296L;
- }
-
-
- public void getBox(WritableByteChannel writableByteChannel) throws IOException {
- ByteBuffer bb = ByteBuffer.allocate(16);
- long size = getSize();
- if (isSmallBox(size)) {
- IsoTypeWriter.writeUInt32(bb, size);
- } else {
- IsoTypeWriter.writeUInt32(bb, 1);
- }
- bb.put(IsoFile.fourCCtoBytes("mdat"));
- if (isSmallBox(size)) {
- bb.put(new byte[8]);
- } else {
- IsoTypeWriter.writeUInt64(bb, size);
- }
- bb.rewind();
- writableByteChannel.write(bb);
- if (writableByteChannel instanceof GatheringByteChannel) {
- List<ByteBuffer> nuSamples = unifyAdjacentBuffers(samples);
-
-
- for (int i = 0; i < Math.ceil((double) nuSamples.size() / STEPSIZE); i++) {
- List<ByteBuffer> sublist = nuSamples.subList(
- i * STEPSIZE, // start
- (i + 1) * STEPSIZE < nuSamples.size() ? (i + 1) * STEPSIZE : nuSamples.size()); // end
- ByteBuffer sampleArray[] = sublist.toArray(new ByteBuffer[sublist.size()]);
- do {
- ((GatheringByteChannel) writableByteChannel).write(sampleArray);
- } while (sampleArray[sampleArray.length - 1].remaining() > 0);
- }
- //System.err.println(bytesWritten);
- } else {
- for (ByteBuffer sample : samples) {
- sample.rewind();
- writableByteChannel.write(sample);
- }
- }
- }
-
- }
-
- /**
- * Gets the chunk sizes for the given track.
- *
- * @param track
- * @param movie
- * @return
- */
- int[] getChunkSizes(Track track, Movie movie) {
-
- long[] referenceChunkStarts = intersectionFinder.sampleNumbers(track, movie);
- int[] chunkSizes = new int[referenceChunkStarts.length];
-
-
- for (int i = 0; i < referenceChunkStarts.length; i++) {
- long start = referenceChunkStarts[i] - 1;
- long end;
- if (referenceChunkStarts.length == i + 1) {
- end = track.getSamples().size();
- } else {
- end = referenceChunkStarts[i + 1] - 1;
- }
-
- chunkSizes[i] = l2i(end - start);
- // The Stretch makes sure that there are as much audio and video chunks!
- }
- assert DefaultMp4Builder.this.track2Sample.get(track).size() == sum(chunkSizes) : "The number of samples and the sum of all chunk lengths must be equal";
- return chunkSizes;
-
-
- }
-
-
- private static long sum(int[] ls) {
- long rc = 0;
- for (long l : ls) {
- rc += l;
- }
- return rc;
- }
-
- protected static long getDuration(Track track) {
- long duration = 0;
- for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
- duration += entry.getCount() * entry.getDelta();
- }
- return duration;
- }
-
- public long getTimescale(Movie movie) {
- long timescale = movie.getTracks().iterator().next().getTrackMetaData().getTimescale();
- for (Track track : movie.getTracks()) {
- timescale = gcd(track.getTrackMetaData().getTimescale(), timescale);
- }
- return timescale;
- }
-
- public static long gcd(long a, long b) {
- if (b == 0) {
- return a;
- }
- return gcd(b, a % b);
- }
-
- public List<ByteBuffer> unifyAdjacentBuffers(List<ByteBuffer> samples) {
- ArrayList<ByteBuffer> nuSamples = new ArrayList<ByteBuffer>(samples.size());
- for (ByteBuffer buffer : samples) {
- int lastIndex = nuSamples.size() - 1;
- if (lastIndex >= 0 && buffer.hasArray() && nuSamples.get(lastIndex).hasArray() && buffer.array() == nuSamples.get(lastIndex).array() &&
- nuSamples.get(lastIndex).arrayOffset() + nuSamples.get(lastIndex).limit() == buffer.arrayOffset()) {
- ByteBuffer oldBuffer = nuSamples.remove(lastIndex);
- ByteBuffer nu = ByteBuffer.wrap(buffer.array(), oldBuffer.arrayOffset(), oldBuffer.limit() + buffer.limit()).slice();
- // We need to slice here since wrap([], offset, length) just sets position and not the arrayOffset.
- nuSamples.add(nu);
- } else if (lastIndex >= 0 &&
- buffer instanceof MappedByteBuffer && nuSamples.get(lastIndex) instanceof MappedByteBuffer &&
- nuSamples.get(lastIndex).limit() == nuSamples.get(lastIndex).capacity() - buffer.capacity()) {
- // This can go wrong - but will it?
- ByteBuffer oldBuffer = nuSamples.get(lastIndex);
- oldBuffer.limit(buffer.limit() + oldBuffer.limit());
- } else {
- nuSamples.add(buffer);
- }
- }
- return nuSamples;
- }
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentIntersectionFinder.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentIntersectionFinder.java.svn-base
deleted file mode 100644
index 1224bbf..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentIntersectionFinder.java.svn-base
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.builder;
-
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-
-/**
- *
- */
-public interface FragmentIntersectionFinder {
- /**
- * Gets the ordinal number of the samples which will be the first sample
- * in each fragment.
- *
- * @param track concerned track
- * @param movie the context of the track
- * @return an array containing the ordinal of each fragment's first sample
- */
- public long[] sampleNumbers(Track track, Movie movie);
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentedMp4Builder.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentedMp4Builder.java.svn-base
deleted file mode 100644
index c65ff1c..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/FragmentedMp4Builder.java.svn-base
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * 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.builder;
-
-import com.coremedia.iso.BoxParser;
-import com.coremedia.iso.IsoFile;
-import com.coremedia.iso.IsoTypeWriter;
-import com.coremedia.iso.boxes.*;
-import com.coremedia.iso.boxes.fragment.*;
-import com.googlecode.mp4parser.authoring.DateHelper;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.GatheringByteChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.*;
-import java.util.logging.Logger;
-
-import static com.googlecode.mp4parser.util.CastUtils.l2i;
-
-/**
- * Creates a fragmented MP4 file.
- */
-public class FragmentedMp4Builder implements Mp4Builder {
- private static final Logger LOG = Logger.getLogger(FragmentedMp4Builder.class.getName());
-
- protected FragmentIntersectionFinder intersectionFinder;
-
- public FragmentedMp4Builder() {
- this.intersectionFinder = new SyncSampleIntersectFinderImpl();
- }
-
- public List<String> getAllowedHandlers() {
- return Arrays.asList("soun", "vide");
- }
-
- public Box createFtyp(Movie movie) {
- List<String> minorBrands = new LinkedList<String>();
- minorBrands.add("isom");
- minorBrands.add("iso2");
- minorBrands.add("avc1");
- return new FileTypeBox("isom", 0, minorBrands);
- }
-
- /**
- * Some formats require sorting of the fragments. E.g. Ultraviolet CFF files are required
- * to contain the fragments size sort:
- * <ul>
- * <li>video[1].getBytes().length < audio[1].getBytes().length < subs[1].getBytes().length</li>
- * <li> audio[2].getBytes().length < video[2].getBytes().length < subs[2].getBytes().length</li>
- * </ul>
- *
- * make this fragment:
- *
- * <ol>
- * <li>video[1]</li>
- * <li>audio[1]</li>
- * <li>subs[1]</li>
- * <li>audio[2]</li>
- * <li>video[2]</li>
- * <li>subs[2]</li>
- * </ol>
- *
- * @param tracks the list of tracks to returned sorted
- * @param cycle current fragment (sorting may vary between the fragments)
- * @param intersectionMap a map from tracks to their fragments' first samples.
- * @return the list of tracks in order of appearance in the fragment
- */
- protected List<Track> sortTracksInSequence(List<Track> tracks, final int cycle, final Map<Track, long[]> intersectionMap) {
- tracks = new LinkedList<Track>(tracks);
- Collections.sort(tracks, new Comparator<Track>() {
- public int compare(Track o1, Track o2) {
- long[] startSamples1 = intersectionMap.get(o1);
- long startSample1 = startSamples1[cycle];
- // one based sample numbers - the first sample is 1
- long endSample1 = cycle + 1 < startSamples1.length ? startSamples1[cycle + 1] : o1.getSamples().size() + 1;
- long[] startSamples2 = intersectionMap.get(o2);
- long startSample2 = startSamples2[cycle];
- // one based sample numbers - the first sample is 1
- long endSample2 = cycle + 1 < startSamples2.length ? startSamples2[cycle + 1] : o2.getSamples().size() + 1;
- List<ByteBuffer> samples1 = o1.getSamples().subList(l2i(startSample1) - 1, l2i(endSample1) - 1);
- List<ByteBuffer> samples2 = o2.getSamples().subList(l2i(startSample2) - 1, l2i(endSample2) - 1);
- int size1 = 0;
- for (ByteBuffer byteBuffer : samples1) {
- size1 += byteBuffer.limit();
- }
- int size2 = 0;
- for (ByteBuffer byteBuffer : samples2) {
- size2 += byteBuffer.limit();
- }
- return size1 - size2;
- }
- });
- return tracks;
- }
-
- protected List<Box> createMoofMdat(final Movie movie) {
- List<Box> boxes = new LinkedList<Box>();
- HashMap<Track, long[]> intersectionMap = new HashMap<Track, long[]>();
- int maxNumberOfFragments = 0;
- for (Track track : movie.getTracks()) {
- long[] intersects = intersectionFinder.sampleNumbers(track, movie);
- intersectionMap.put(track, intersects);
- maxNumberOfFragments = Math.max(maxNumberOfFragments, intersects.length);
- }
-
-
- int sequence = 1;
- // this loop has two indices:
-
- for (int cycle = 0; cycle < maxNumberOfFragments; cycle++) {
-
- final List<Track> sortedTracks = sortTracksInSequence(movie.getTracks(), cycle, intersectionMap);
-
- for (Track track : sortedTracks) {
- if (getAllowedHandlers().isEmpty() || getAllowedHandlers().contains(track.getHandler())) {
- long[] startSamples = intersectionMap.get(track);
- //some tracks may have less fragments -> skip them
- if (cycle < startSamples.length) {
-
- long startSample = startSamples[cycle];
- // one based sample numbers - the first sample is 1
- long endSample = cycle + 1 < startSamples.length ? startSamples[cycle + 1] : track.getSamples().size() + 1;
-
- // if startSample == endSample the cycle is empty!
- if (startSample != endSample) {
- boxes.add(createMoof(startSample, endSample, track, sequence));
- boxes.add(createMdat(startSample, endSample, track, sequence++));
- }
- }
- }
- }
- }
- return boxes;
- }
-
- /**
- * {@inheritDoc}
- */
- public IsoFile build(Movie movie) {
- LOG.fine("Creating movie " + movie);
- IsoFile isoFile = new IsoFile();
-
-
- isoFile.addBox(createFtyp(movie));
- isoFile.addBox(createMoov(movie));
-
- for (Box box : createMoofMdat(movie)) {
- isoFile.addBox(box);
- }
- isoFile.addBox(createMfra(movie, isoFile));
-
- return isoFile;
- }
-
- protected Box createMdat(final long startSample, final long endSample, final Track track, final int i) {
-
- class Mdat implements Box {
- ContainerBox parent;
-
- public ContainerBox getParent() {
- return parent;
- }
-
- public void setParent(ContainerBox parent) {
- this.parent = parent;
- }
-
- public long getSize() {
- long size = 8; // I don't expect 2gig fragments
- for (ByteBuffer sample : getSamples(startSample, endSample, track, i)) {
- size += sample.limit();
- }
- return size;
- }
-
- public String getType() {
- return "mdat";
- }
-
- public void getBox(WritableByteChannel writableByteChannel) throws IOException {
- List<ByteBuffer> bbs = getSamples(startSample, endSample, track, i);
- final List<ByteBuffer> samples = ByteBufferHelper.mergeAdjacentBuffers(bbs);
- ByteBuffer header = ByteBuffer.allocate(8);
- IsoTypeWriter.writeUInt32(header, l2i(getSize()));
- header.put(IsoFile.fourCCtoBytes(getType()));
- header.rewind();
- writableByteChannel.write(header);
- if (writableByteChannel instanceof GatheringByteChannel) {
-
- int STEPSIZE = 1024;
- // This is required to prevent android from crashing
- // it seems that {@link GatheringByteChannel#write(java.nio.ByteBuffer[])}
- // just handles up to 1024 buffers
- for (int i = 0; i < Math.ceil((double) samples.size() / STEPSIZE); i++) {
- List<ByteBuffer> sublist = samples.subList(
- i * STEPSIZE, // start
- (i + 1) * STEPSIZE < samples.size() ? (i + 1) * STEPSIZE : samples.size()); // end
- ByteBuffer sampleArray[] = sublist.toArray(new ByteBuffer[sublist.size()]);
- do {
- ((GatheringByteChannel) writableByteChannel).write(sampleArray);
- } while (sampleArray[sampleArray.length - 1].remaining() > 0);
- }
- //System.err.println(bytesWritten);
- } else {
- for (ByteBuffer sample : samples) {
- sample.rewind();
- writableByteChannel.write(sample);
- }
- }
-
- }
-
- public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
-
- }
- }
-
- return new Mdat();
- }
-
- protected Box createTfhd(long startSample, long endSample, Track track, int sequenceNumber) {
- TrackFragmentHeaderBox tfhd = new TrackFragmentHeaderBox();
- SampleFlags sf = new SampleFlags();
-
- tfhd.setDefaultSampleFlags(sf);
- tfhd.setBaseDataOffset(-1);
- tfhd.setTrackId(track.getTrackMetaData().getTrackId());
- return tfhd;
- }
-
- protected Box createMfhd(long startSample, long endSample, Track track, int sequenceNumber) {
- MovieFragmentHeaderBox mfhd = new MovieFragmentHeaderBox();
- mfhd.setSequenceNumber(sequenceNumber);
- return mfhd;
- }
-
- protected Box createTraf(long startSample, long endSample, Track track, int sequenceNumber) {
- TrackFragmentBox traf = new TrackFragmentBox();
- traf.addBox(createTfhd(startSample, endSample, track, sequenceNumber));
- for (Box trun : createTruns(startSample, endSample, track, sequenceNumber)) {
- traf.addBox(trun);
- }
-
- return traf;
- }
-
-
- /**
- * Gets the all samples starting with <code>startSample</code> (one based -> one is the first) and
- * ending with <code>endSample</code> (exclusive).
- *
- * @param startSample low endpoint (inclusive) of the sample sequence
- * @param endSample high endpoint (exclusive) of the sample sequence
- * @param track source of the samples
- * @param sequenceNumber the fragment index of the requested list of samples
- * @return a <code>List&lt;ByteBuffer></code> of raw samples
- */
- protected List<ByteBuffer> getSamples(long startSample, long endSample, Track track, int sequenceNumber) {
- // since startSample and endSample are one-based substract 1 before addressing list elements
- return track.getSamples().subList(l2i(startSample) - 1, l2i(endSample) - 1);
- }
-
- /**
- * Gets the sizes of a sequence of samples-
- *
- * @param startSample low endpoint (inclusive) of the sample sequence
- * @param endSample high endpoint (exclusive) of the sample sequence
- * @param track source of the samples
- * @param sequenceNumber the fragment index of the requested list of samples
- * @return
- */
- protected long[] getSampleSizes(long startSample, long endSample, Track track, int sequenceNumber) {
- List<ByteBuffer> samples = getSamples(startSample, endSample, track, sequenceNumber);
-
- long[] sampleSizes = new long[samples.size()];
- for (int i = 0; i < sampleSizes.length; i++) {
- sampleSizes[i] = samples.get(i).limit();
- }
- return sampleSizes;
- }
-
- /**
- * Creates one or more track run boxes for a given sequence.
- *
- * @param startSample low endpoint (inclusive) of the sample sequence
- * @param endSample high endpoint (exclusive) of the sample sequence
- * @param track source of the samples
- * @param sequenceNumber the fragment index of the requested list of samples
- * @return the list of TrackRun boxes.
- */
- protected List<? extends Box> createTruns(long startSample, long endSample, Track track, int sequenceNumber) {
- TrackRunBox trun = new TrackRunBox();
- long[] sampleSizes = getSampleSizes(startSample, endSample, track, sequenceNumber);
-
- trun.setSampleDurationPresent(true);
- trun.setSampleSizePresent(true);
- List<TrackRunBox.Entry> entries = new ArrayList<TrackRunBox.Entry>(l2i(endSample - startSample));
-
-
- Queue<TimeToSampleBox.Entry> timeQueue = new LinkedList<TimeToSampleBox.Entry>(track.getDecodingTimeEntries());
- long left = startSample - 1;
- long curEntryLeft = timeQueue.peek().getCount();
- while (left > curEntryLeft) {
- left -= curEntryLeft;
- timeQueue.remove();
- curEntryLeft = timeQueue.peek().getCount();
- }
- curEntryLeft -= left;
-
-
- Queue<CompositionTimeToSample.Entry> compositionTimeQueue =
- track.getCompositionTimeEntries() != null && track.getCompositionTimeEntries().size() > 0 ?
- new LinkedList<CompositionTimeToSample.Entry>(track.getCompositionTimeEntries()) : null;
- long compositionTimeEntriesLeft = compositionTimeQueue != null ? compositionTimeQueue.peek().getCount() : -1;
-
-
- trun.setSampleCompositionTimeOffsetPresent(compositionTimeEntriesLeft > 0);
-
- // fast forward composition stuff
- for (long i = 1; i < startSample; i++) {
- if (compositionTimeQueue != null) {
- //trun.setSampleCompositionTimeOffsetPresent(true);
- if (--compositionTimeEntriesLeft == 0 && compositionTimeQueue.size() > 1) {
- compositionTimeQueue.remove();
- compositionTimeEntriesLeft = compositionTimeQueue.element().getCount();
- }
- }
- }
-
- boolean sampleFlagsRequired = (track.getSampleDependencies() != null && !track.getSampleDependencies().isEmpty() ||
- track.getSyncSamples() != null && track.getSyncSamples().length != 0);
-
- trun.setSampleFlagsPresent(sampleFlagsRequired);
-
- for (int i = 0; i < sampleSizes.length; i++) {
- TrackRunBox.Entry entry = new TrackRunBox.Entry();
- entry.setSampleSize(sampleSizes[i]);
- if (sampleFlagsRequired) {
- //if (false) {
- SampleFlags sflags = new SampleFlags();
-
- if (track.getSampleDependencies() != null && !track.getSampleDependencies().isEmpty()) {
- SampleDependencyTypeBox.Entry e = track.getSampleDependencies().get(i);
- sflags.setSampleDependsOn(e.getSampleDependsOn());
- sflags.setSampleIsDependedOn(e.getSampleIsDependentOn());
- sflags.setSampleHasRedundancy(e.getSampleHasRedundancy());
- }
- if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
- // we have to mark non-sync samples!
- if (Arrays.binarySearch(track.getSyncSamples(), startSample + i) >= 0) {
- sflags.setSampleIsDifferenceSample(false);
- sflags.setSampleDependsOn(2);
- } else {
- sflags.setSampleIsDifferenceSample(true);
- sflags.setSampleDependsOn(1);
- }
- }
- // i don't have sample degradation
- entry.setSampleFlags(sflags);
-
- }
-
- entry.setSampleDuration(timeQueue.peek().getDelta());
- if (--curEntryLeft == 0 && timeQueue.size() > 1) {
- timeQueue.remove();
- curEntryLeft = timeQueue.peek().getCount();
- }
-
- if (compositionTimeQueue != null) {
- entry.setSampleCompositionTimeOffset(compositionTimeQueue.peek().getOffset());
- if (--compositionTimeEntriesLeft == 0 && compositionTimeQueue.size() > 1) {
- compositionTimeQueue.remove();
- compositionTimeEntriesLeft = compositionTimeQueue.element().getCount();
- }
- }
- entries.add(entry);
- }
-
- trun.setEntries(entries);
-
- return Collections.singletonList(trun);
- }
-
- /**
- * Creates a 'moof' box for a given sequence of samples.
- *
- * @param startSample low endpoint (inclusive) of the sample sequence
- * @param endSample high endpoint (exclusive) of the sample sequence
- * @param track source of the samples
- * @param sequenceNumber the fragment index of the requested list of samples
- * @return the list of TrackRun boxes.
- */
- protected Box createMoof(long startSample, long endSample, Track track, int sequenceNumber) {
- MovieFragmentBox moof = new MovieFragmentBox();
- moof.addBox(createMfhd(startSample, endSample, track, sequenceNumber));
- moof.addBox(createTraf(startSample, endSample, track, sequenceNumber));
-
- TrackRunBox firstTrun = moof.getTrackRunBoxes().get(0);
- firstTrun.setDataOffset(1); // dummy to make size correct
- firstTrun.setDataOffset((int) (8 + moof.getSize())); // mdat header + moof size
-
- return moof;
- }
-
- /**
- * Creates a single 'mvhd' movie header box for a given movie.
- *
- * @param movie the concerned movie
- * @return an 'mvhd' box
- */
- protected Box createMvhd(Movie movie) {
- MovieHeaderBox mvhd = new MovieHeaderBox();
- mvhd.setVersion(1);
- mvhd.setCreationTime(DateHelper.convert(new Date()));
- mvhd.setModificationTime(DateHelper.convert(new Date()));
- long movieTimeScale = movie.getTimescale();
- long duration = 0;
-
- for (Track track : movie.getTracks()) {
- long tracksDuration = getDuration(track) * movieTimeScale / track.getTrackMetaData().getTimescale();
- if (tracksDuration > duration) {
- duration = tracksDuration;
- }
-
-
- }
-
- mvhd.setDuration(duration);
- mvhd.setTimescale(movieTimeScale);
- // find the next available trackId
- long nextTrackId = 0;
- for (Track track : movie.getTracks()) {
- nextTrackId = nextTrackId < track.getTrackMetaData().getTrackId() ? track.getTrackMetaData().getTrackId() : nextTrackId;
- }
- mvhd.setNextTrackId(++nextTrackId);
- return mvhd;
- }
-
- /**
- * Creates a fully populated 'moov' box with all child boxes. Child boxes are:
- * <ul>
- * <li>{@link #createMvhd(com.googlecode.mp4parser.authoring.Movie) mvhd}</li>
- * <li>{@link #createMvex(com.googlecode.mp4parser.authoring.Movie) mvex}</li>
- * <li>a {@link #createTrak(com.googlecode.mp4parser.authoring.Track, com.googlecode.mp4parser.authoring.Movie) trak} for every track</li>
- * </ul>
- *
- * @param movie the concerned movie
- * @return fully populated 'moov'
- */
- protected Box createMoov(Movie movie) {
- MovieBox movieBox = new MovieBox();
-
- movieBox.addBox(createMvhd(movie));
- movieBox.addBox(createMvex(movie));
-
- for (Track track : movie.getTracks()) {
- movieBox.addBox(createTrak(track, movie));
- }
- // metadata here
- return movieBox;
-
- }
-
- /**
- * Creates a 'tfra' - track fragment random access box for the given track with the isoFile.
- * The tfra contains a map of random access points with time as key and offset within the isofile
- * as value.
- *
- * @param track the concerned track
- * @param isoFile the track is contained in
- * @return a track fragment random access box.
- */
- protected Box createTfra(Track track, IsoFile isoFile) {
- TrackFragmentRandomAccessBox tfra = new TrackFragmentRandomAccessBox();
- tfra.setVersion(1); // use long offsets and times
- List<TrackFragmentRandomAccessBox.Entry> offset2timeEntries = new LinkedList<TrackFragmentRandomAccessBox.Entry>();
- List<Box> boxes = isoFile.getBoxes();
- long offset = 0;
- long duration = 0;
- for (Box box : boxes) {
- if (box instanceof MovieFragmentBox) {
- List<TrackFragmentBox> trafs = ((MovieFragmentBox) box).getBoxes(TrackFragmentBox.class);
- for (int i = 0; i < trafs.size(); i++) {
- TrackFragmentBox traf = trafs.get(i);
- if (traf.getTrackFragmentHeaderBox().getTrackId() == track.getTrackMetaData().getTrackId()) {
- // here we are at the offset required for the current entry.
- List<TrackRunBox> truns = traf.getBoxes(TrackRunBox.class);
- for (int j = 0; j < truns.size(); j++) {
- List<TrackFragmentRandomAccessBox.Entry> offset2timeEntriesThisTrun = new LinkedList<TrackFragmentRandomAccessBox.Entry>();
- TrackRunBox trun = truns.get(j);
- for (int k = 0; k < trun.getEntries().size(); k++) {
- TrackRunBox.Entry trunEntry = trun.getEntries().get(k);
- SampleFlags sf = null;
- if (k == 0 && trun.isFirstSampleFlagsPresent()) {
- sf = trun.getFirstSampleFlags();
- } else if (trun.isSampleFlagsPresent()) {
- sf = trunEntry.getSampleFlags();
- } else {
- List<MovieExtendsBox> mvexs = isoFile.getMovieBox().getBoxes(MovieExtendsBox.class);
- for (MovieExtendsBox mvex : mvexs) {
- List<TrackExtendsBox> trexs = mvex.getBoxes(TrackExtendsBox.class);
- for (TrackExtendsBox trex : trexs) {
- if (trex.getTrackId() == track.getTrackMetaData().getTrackId()) {
- sf = trex.getDefaultSampleFlags();
- }
- }
- }
-
- }
- if (sf == null) {
- throw new RuntimeException("Could not find any SampleFlags to indicate random access or not");
- }
- if (sf.getSampleDependsOn() == 2) {
- offset2timeEntriesThisTrun.add(new TrackFragmentRandomAccessBox.Entry(
- duration,
- offset,
- i + 1, j + 1, k + 1));
- }
- duration += trunEntry.getSampleDuration();
- }
- if (offset2timeEntriesThisTrun.size() == trun.getEntries().size() && trun.getEntries().size() > 0) {
- // Oooops every sample seems to be random access sample
- // is this an audio track? I don't care.
- // I just use the first for trun sample for tfra random access
- offset2timeEntries.add(offset2timeEntriesThisTrun.get(0));
- } else {
- offset2timeEntries.addAll(offset2timeEntriesThisTrun);
- }
- }
- }
- }
- }
-
-
- offset += box.getSize();
- }
- tfra.setEntries(offset2timeEntries);
- tfra.setTrackId(track.getTrackMetaData().getTrackId());
- return tfra;
- }
-
- /**
- * Creates a 'mfra' - movie fragment random access box for the given movie in the given
- * isofile. Uses {@link #createTfra(com.googlecode.mp4parser.authoring.Track, com.coremedia.iso.IsoFile)}
- * to generate the child boxes.
- *
- * @param movie concerned movie
- * @param isoFile concerned isofile
- * @return a complete 'mfra' box
- */
- protected Box createMfra(Movie movie, IsoFile isoFile) {
- MovieFragmentRandomAccessBox mfra = new MovieFragmentRandomAccessBox();
- for (Track track : movie.getTracks()) {
- mfra.addBox(createTfra(track, isoFile));
- }
-
- MovieFragmentRandomAccessOffsetBox mfro = new MovieFragmentRandomAccessOffsetBox();
- mfra.addBox(mfro);
- mfro.setMfraSize(mfra.getSize());
- return mfra;
- }
-
- protected Box createTrex(Movie movie, Track track) {
- TrackExtendsBox trex = new TrackExtendsBox();
- trex.setTrackId(track.getTrackMetaData().getTrackId());
- trex.setDefaultSampleDescriptionIndex(1);
- trex.setDefaultSampleDuration(0);
- trex.setDefaultSampleSize(0);
- SampleFlags sf = new SampleFlags();
- if ("soun".equals(track.getHandler())) {
- // as far as I know there is no audio encoding
- // where the sample are not self contained.
- sf.setSampleDependsOn(2);
- sf.setSampleIsDependedOn(2);
- }
- trex.setDefaultSampleFlags(sf);
- return trex;
- }
-
- /**
- * Creates a 'mvex' - movie extends box and populates it with 'trex' boxes
- * by calling {@link #createTrex(com.googlecode.mp4parser.authoring.Movie, com.googlecode.mp4parser.authoring.Track)}
- * for each track to generate them
- *
- * @param movie the source movie
- * @return a complete 'mvex'
- */
- protected Box createMvex(Movie movie) {
- MovieExtendsBox mvex = new MovieExtendsBox();
- final MovieExtendsHeaderBox mved = new MovieExtendsHeaderBox();
- for (Track track : movie.getTracks()) {
- final long trackDuration = getTrackDuration(movie, track);
- if (mved.getFragmentDuration() < trackDuration) {
- mved.setFragmentDuration(trackDuration);
- }
- }
- mvex.addBox(mved);
-
- for (Track track : movie.getTracks()) {
- mvex.addBox(createTrex(movie, track));
- }
- return mvex;
- }
-
- protected Box createTkhd(Movie movie, Track track) {
- TrackHeaderBox tkhd = new TrackHeaderBox();
- tkhd.setVersion(1);
- int flags = 0;
- if (track.isEnabled()) {
- flags += 1;
- }
-
- if (track.isInMovie()) {
- flags += 2;
- }
-
- if (track.isInPreview()) {
- flags += 4;
- }
-
- if (track.isInPoster()) {
- flags += 8;
- }
- tkhd.setFlags(flags);
-
- tkhd.setAlternateGroup(track.getTrackMetaData().getGroup());
- tkhd.setCreationTime(DateHelper.convert(track.getTrackMetaData().getCreationTime()));
- // We need to take edit list box into account in trackheader duration
- // but as long as I don't support edit list boxes it is sufficient to
- // just translate media duration to movie timescale
- tkhd.setDuration(getTrackDuration(movie, track));
- tkhd.setHeight(track.getTrackMetaData().getHeight());
- tkhd.setWidth(track.getTrackMetaData().getWidth());
- tkhd.setLayer(track.getTrackMetaData().getLayer());
- tkhd.setModificationTime(DateHelper.convert(new Date()));
- tkhd.setTrackId(track.getTrackMetaData().getTrackId());
- tkhd.setVolume(track.getTrackMetaData().getVolume());
- return tkhd;
- }
-
- private long getTrackDuration(Movie movie, Track track) {
- return getDuration(track) * movie.getTimescale() / track.getTrackMetaData().getTimescale();
- }
-
- protected Box createMdhd(Movie movie, Track track) {
- MediaHeaderBox mdhd = new MediaHeaderBox();
- mdhd.setCreationTime(DateHelper.convert(track.getTrackMetaData().getCreationTime()));
- mdhd.setDuration(getDuration(track));
- mdhd.setTimescale(track.getTrackMetaData().getTimescale());
- mdhd.setLanguage(track.getTrackMetaData().getLanguage());
- return mdhd;
- }
-
- protected Box createStbl(Movie movie, Track track) {
- SampleTableBox stbl = new SampleTableBox();
-
- stbl.addBox(track.getSampleDescriptionBox());
- stbl.addBox(new TimeToSampleBox());
- //stbl.addBox(new SampleToChunkBox());
- stbl.addBox(new StaticChunkOffsetBox());
- return stbl;
- }
-
- protected Box createMinf(Track track, Movie movie) {
- MediaInformationBox minf = new MediaInformationBox();
- minf.addBox(track.getMediaHeaderBox());
- minf.addBox(createDinf(movie, track));
- minf.addBox(createStbl(movie, track));
- return minf;
- }
-
- protected Box createMdiaHdlr(Track track, Movie movie) {
- HandlerBox hdlr = new HandlerBox();
- hdlr.setHandlerType(track.getHandler());
- return hdlr;
- }
-
- protected Box createMdia(Track track, Movie movie) {
- MediaBox mdia = new MediaBox();
- mdia.addBox(createMdhd(movie, track));
-
-
- mdia.addBox(createMdiaHdlr(track, movie));
-
-
- mdia.addBox(createMinf(track, movie));
- return mdia;
- }
-
- protected Box createTrak(Track track, Movie movie) {
- LOG.fine("Creating Track " + track);
- TrackBox trackBox = new TrackBox();
- trackBox.addBox(createTkhd(movie, track));
- trackBox.addBox(createMdia(track, movie));
- return trackBox;
- }
-
- protected DataInformationBox createDinf(Movie movie, Track track) {
- DataInformationBox dinf = new DataInformationBox();
- DataReferenceBox dref = new DataReferenceBox();
- dinf.addBox(dref);
- DataEntryUrlBox url = new DataEntryUrlBox();
- url.setFlags(1);
- dref.addBox(url);
- return dinf;
- }
-
- public FragmentIntersectionFinder getFragmentIntersectionFinder() {
- return intersectionFinder;
- }
-
- public void setIntersectionFinder(FragmentIntersectionFinder intersectionFinder) {
- this.intersectionFinder = intersectionFinder;
- }
-
- protected long getDuration(Track track) {
- long duration = 0;
- for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
- duration += entry.getCount() * entry.getDelta();
- }
- return duration;
- }
-
-
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/Mp4Builder.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/Mp4Builder.java.svn-base
deleted file mode 100644
index 725745e..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/Mp4Builder.java.svn-base
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.builder;
-
-import com.coremedia.iso.IsoFile;
-import com.googlecode.mp4parser.authoring.Movie;
-
-/**
- * Transforms a <code>Movie</code> object to an IsoFile. Implementations can
- * determine the specific format: Fragmented MP4, MP4, MP4 with Apple Metadata,
- * MP4 with 3GPP Metadata, MOV.
- */
-public interface Mp4Builder {
- /**
- * Builds the actual IsoFile from the Movie.
- *
- * @param movie data source
- * @return the freshly built IsoFile
- */
- public IsoFile build(Movie movie);
-
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base
deleted file mode 100644
index 2766c5e..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/SyncSampleIntersectFinderImpl.java.svn-base
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.builder;
-
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
-
-import static com.googlecode.mp4parser.util.Math.lcm;
-
-/**
- * This <code>FragmentIntersectionFinder</code> cuts the input movie video tracks in
- * fragments of the same length exactly before the sync samples. Audio tracks are cut
- * into pieces of similar length.
- */
-public class SyncSampleIntersectFinderImpl implements FragmentIntersectionFinder {
-
- private static Logger LOG = Logger.getLogger(SyncSampleIntersectFinderImpl.class.getName());
- private static Map<CacheTuple, long[]> getTimesCache = new ConcurrentHashMap<CacheTuple, long[]>();
- private static Map<CacheTuple, long[]> getSampleNumbersCache = new ConcurrentHashMap<CacheTuple, long[]>();
-
- private final int minFragmentDurationSeconds;
-
- public SyncSampleIntersectFinderImpl() {
- minFragmentDurationSeconds = 0;
- }
-
- /**
- * Creates a <code>SyncSampleIntersectFinderImpl</code> that will not create any fragment
- * smaller than the given <code>minFragmentDurationSeconds</code>
- *
- * @param minFragmentDurationSeconds the smallest allowable duration of a fragment.
- */
- public SyncSampleIntersectFinderImpl(int minFragmentDurationSeconds) {
- this.minFragmentDurationSeconds = minFragmentDurationSeconds;
- }
-
- /**
- * Gets an array of sample numbers that are meant to be the first sample of each
- * chunk or fragment.
- *
- * @param track concerned track
- * @param movie the context of the track
- * @return an array containing the ordinal of each fragment's first sample
- */
- public long[] sampleNumbers(Track track, Movie movie) {
- final CacheTuple key = new CacheTuple(track, movie);
- final long[] result = getSampleNumbersCache.get(key);
- if (result != null) {
- return result;
- }
-
- if ("vide".equals(track.getHandler())) {
- if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
- List<long[]> times = getSyncSamplesTimestamps(movie, track);
- final long[] commonIndices = getCommonIndices(track.getSyncSamples(), getTimes(track, movie), track.getTrackMetaData().getTimescale(), times.toArray(new long[times.size()][]));
- getSampleNumbersCache.put(key, commonIndices);
- return commonIndices;
- } else {
- throw new RuntimeException("Video Tracks need sync samples. Only tracks other than video may have no sync samples.");
- }
- } else if ("soun".equals(track.getHandler())) {
- Track referenceTrack = null;
- for (Track candidate : movie.getTracks()) {
- if (candidate.getSyncSamples() != null && "vide".equals(candidate.getHandler()) && candidate.getSyncSamples().length > 0) {
- referenceTrack = candidate;
- }
- }
- if (referenceTrack != null) {
-
- // Gets the reference track's fra
- long[] refSyncSamples = sampleNumbers(referenceTrack, movie);
-
- int refSampleCount = referenceTrack.getSamples().size();
-
- long[] syncSamples = new long[refSyncSamples.length];
- long minSampleRate = 192000;
- for (Track testTrack : movie.getTracks()) {
- if ("soun".equals(testTrack.getHandler())) {
- AudioSampleEntry ase = (AudioSampleEntry) testTrack.getSampleDescriptionBox().getSampleEntry();
- if (ase.getSampleRate() < minSampleRate) {
- minSampleRate = ase.getSampleRate();
- long sc = testTrack.getSamples().size();
- double stretch = (double) sc / refSampleCount;
- TimeToSampleBox.Entry sttsEntry = testTrack.getDecodingTimeEntries().get(0);
- long samplesPerFrame = sttsEntry.getDelta(); // Assuming all audio tracks have the same number of samples per frame, which they do for all known types
-
- for (int i = 0; i < syncSamples.length; i++) {
- long start = (long) Math.ceil(stretch * (refSyncSamples[i] - 1) * samplesPerFrame);
- syncSamples[i] = start;
- // The Stretch makes sure that there are as much audio and video chunks!
- }
- break;
- }
- }
- }
- AudioSampleEntry ase = (AudioSampleEntry) track.getSampleDescriptionBox().getSampleEntry();
- TimeToSampleBox.Entry sttsEntry = track.getDecodingTimeEntries().get(0);
- long samplesPerFrame = sttsEntry.getDelta(); // Assuming all audio tracks have the same number of samples per frame, which they do for all known types
- double factor = (double) ase.getSampleRate() / (double) minSampleRate;
- if (factor != Math.rint(factor)) { // Not an integer
- throw new RuntimeException("Sample rates must be a multiple of the lowest sample rate to create a correct file!");
- }
- for (int i = 0; i < syncSamples.length; i++) {
- syncSamples[i] = (long) (1 + syncSamples[i] * factor / (double) samplesPerFrame);
- }
- getSampleNumbersCache.put(key, syncSamples);
- return syncSamples;
- }
- throw new RuntimeException("There was absolutely no Track with sync samples. I can't work with that!");
- } else {
- // Ok, my track has no sync samples - let's find one with sync samples.
- for (Track candidate : movie.getTracks()) {
- if (candidate.getSyncSamples() != null && candidate.getSyncSamples().length > 0) {
- long[] refSyncSamples = sampleNumbers(candidate, movie);
- int refSampleCount = candidate.getSamples().size();
-
- long[] syncSamples = new long[refSyncSamples.length];
- long sc = track.getSamples().size();
- double stretch = (double) sc / refSampleCount;
-
- for (int i = 0; i < syncSamples.length; i++) {
- long start = (long) Math.ceil(stretch * (refSyncSamples[i] - 1)) + 1;
- syncSamples[i] = start;
- // The Stretch makes sure that there are as much audio and video chunks!
- }
- getSampleNumbersCache.put(key, syncSamples);
- return syncSamples;
- }
- }
- throw new RuntimeException("There was absolutely no Track with sync samples. I can't work with that!");
- }
-
-
- }
-
- /**
- * Calculates the timestamp of all tracks' sync samples.
- *
- * @param movie
- * @param track
- * @return
- */
- public static List<long[]> getSyncSamplesTimestamps(Movie movie, Track track) {
- List<long[]> times = new LinkedList<long[]>();
- for (Track currentTrack : movie.getTracks()) {
- if (currentTrack.getHandler().equals(track.getHandler())) {
- long[] currentTrackSyncSamples = currentTrack.getSyncSamples();
- if (currentTrackSyncSamples != null && currentTrackSyncSamples.length > 0) {
- final long[] currentTrackTimes = getTimes(currentTrack, movie);
- times.add(currentTrackTimes);
- }
- }
- }
- return times;
- }
-
- public long[] getCommonIndices(long[] syncSamples, long[] syncSampleTimes, long timeScale, long[]... otherTracksTimes) {
- List<Long> nuSyncSamples = new LinkedList<Long>();
- List<Long> nuSyncSampleTimes = new LinkedList<Long>();
-
-
- for (int i = 0; i < syncSampleTimes.length; i++) {
- boolean foundInEveryRef = true;
- for (long[] times : otherTracksTimes) {
- foundInEveryRef &= (Arrays.binarySearch(times, syncSampleTimes[i]) >= 0);
- }
-
- if (foundInEveryRef) {
- // use sample only if found in every other track.
- nuSyncSamples.add(syncSamples[i]);
- nuSyncSampleTimes.add(syncSampleTimes[i]);
- }
- }
- // We have two arrays now:
- // nuSyncSamples: Contains all common sync samples
- // nuSyncSampleTimes: Contains the times of all sync samples
-
- // Start: Warn user if samples are not matching!
- if (nuSyncSamples.size() < (syncSamples.length * 0.25)) {
- String log = "";
- log += String.format("%5d - Common: [", nuSyncSamples.size());
- for (long l : nuSyncSamples) {
- log += (String.format("%10d,", l));
- }
- log += ("]");
- LOG.warning(log);
- log = "";
-
- log += String.format("%5d - In : [", syncSamples.length);
- for (long l : syncSamples) {
- log += (String.format("%10d,", l));
- }
- log += ("]");
- LOG.warning(log);
- LOG.warning("There are less than 25% of common sync samples in the given track.");
- throw new RuntimeException("There are less than 25% of common sync samples in the given track.");
- } else if (nuSyncSamples.size() < (syncSamples.length * 0.5)) {
- LOG.fine("There are less than 50% of common sync samples in the given track. This is implausible but I'm ok to continue.");
- } else if (nuSyncSamples.size() < syncSamples.length) {
- LOG.finest("Common SyncSample positions vs. this tracks SyncSample positions: " + nuSyncSamples.size() + " vs. " + syncSamples.length);
- }
- // End: Warn user if samples are not matching!
-
-
-
-
- List<Long> finalSampleList = new LinkedList<Long>();
-
- if (minFragmentDurationSeconds > 0) {
- // if minFragmentDurationSeconds is greater 0
- // we need to throw away certain samples.
- long lastSyncSampleTime = -1;
- Iterator<Long> nuSyncSamplesIterator = nuSyncSamples.iterator();
- Iterator<Long> nuSyncSampleTimesIterator = nuSyncSampleTimes.iterator();
- while (nuSyncSamplesIterator.hasNext() && nuSyncSampleTimesIterator.hasNext()) {
- long curSyncSample = nuSyncSamplesIterator.next();
- long curSyncSampleTime = nuSyncSampleTimesIterator.next();
- if (lastSyncSampleTime == -1 || (curSyncSampleTime - lastSyncSampleTime) / timeScale >= minFragmentDurationSeconds) {
- finalSampleList.add(curSyncSample);
- lastSyncSampleTime = curSyncSampleTime;
- }
- }
- } else {
- // the list of all samples is the final list of samples
- // since minFragmentDurationSeconds ist not used.
- finalSampleList = nuSyncSamples;
- }
-
-
- // transform the list to an array
- long[] finalSampleArray = new long[finalSampleList.size()];
- for (int i = 0; i < finalSampleArray.length; i++) {
- finalSampleArray[i] = finalSampleList.get(i);
- }
- return finalSampleArray;
-
- }
-
-
- private static long[] getTimes(Track track, Movie m) {
- final CacheTuple key = new CacheTuple(track, m);
- final long[] result = getTimesCache.get(key);
- if (result != null) {
- return result;
- }
-
- long[] syncSamples = track.getSyncSamples();
- long[] syncSampleTimes = new long[syncSamples.length];
- Queue<TimeToSampleBox.Entry> timeQueue = new LinkedList<TimeToSampleBox.Entry>(track.getDecodingTimeEntries());
-
- int currentSample = 1; // first syncsample is 1
- long currentDuration = 0;
- long currentDelta = 0;
- int currentSyncSampleIndex = 0;
- long left = 0;
-
- final long scalingFactor = calculateTracktimesScalingFactor(m, track);
-
- while (currentSample <= syncSamples[syncSamples.length - 1]) {
- if (currentSample++ == syncSamples[currentSyncSampleIndex]) {
- syncSampleTimes[currentSyncSampleIndex++] = currentDuration * scalingFactor;
- }
- if (left-- == 0) {
- TimeToSampleBox.Entry entry = timeQueue.poll();
- left = entry.getCount() - 1;
- currentDelta = entry.getDelta();
- }
- currentDuration += currentDelta;
- }
- getTimesCache.put(key, syncSampleTimes);
- return syncSampleTimes;
- }
-
- private static long calculateTracktimesScalingFactor(Movie m, Track track) {
- long timeScale = 1;
- for (Track track1 : m.getTracks()) {
- if (track1.getHandler().equals(track.getHandler())) {
- if (track1.getTrackMetaData().getTimescale() != track.getTrackMetaData().getTimescale()) {
- timeScale = lcm(timeScale, track1.getTrackMetaData().getTimescale());
- }
- }
- }
- return timeScale;
- }
-
- public static class CacheTuple {
- Track track;
- Movie movie;
-
- public CacheTuple(Track track, Movie movie) {
- this.track = track;
- this.movie = movie;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- CacheTuple that = (CacheTuple) o;
-
- if (movie != null ? !movie.equals(that.movie) : that.movie != null) return false;
- if (track != null ? !track.equals(that.track) : that.track != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = track != null ? track.hashCode() : 0;
- result = 31 * result + (movie != null ? movie.hashCode() : 0);
- return result;
- }
- }
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/TwoSecondIntersectionFinder.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/TwoSecondIntersectionFinder.java.svn-base
deleted file mode 100644
index 88aa4ab..0000000
--- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/builder/.svn/text-base/TwoSecondIntersectionFinder.java.svn-base
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.builder;
-
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * This <code>FragmentIntersectionFinder</code> cuts the input movie in 2 second
- * snippets.
- */
-public class TwoSecondIntersectionFinder implements FragmentIntersectionFinder {
-
- protected long getDuration(Track track) {
- long duration = 0;
- for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
- duration += entry.getCount() * entry.getDelta();
- }
- return duration;
- }
-
- /**
- * {@inheritDoc}
- */
- public long[] sampleNumbers(Track track, Movie movie) {
- List<TimeToSampleBox.Entry> entries = track.getDecodingTimeEntries();
-
- double trackLength = 0;
- for (Track thisTrack : movie.getTracks()) {
- double thisTracksLength = getDuration(thisTrack) / thisTrack.getTrackMetaData().getTimescale();
- if (trackLength < thisTracksLength) {
- trackLength = thisTracksLength;
- }
- }
-
- int fragmentCount = (int)Math.ceil(trackLength / 2) - 1;
- if (fragmentCount < 1) {
- fragmentCount = 1;
- }
-
- long fragments[] = new long[fragmentCount];
- Arrays.fill(fragments, -1);
- fragments[0] = 1;
-
- long time = 0;
- int samples = 0;
- for (TimeToSampleBox.Entry entry : entries) {
- for (int i = 0; i < entry.getCount(); i++) {
- int currentFragment = (int) (time / track.getTrackMetaData().getTimescale() / 2) + 1;
- if (currentFragment >= fragments.length) {
- break;
- }
- fragments[currentFragment] = samples++ + 1;
- time += entry.getDelta();
- }
- }
- long last = samples + 1;
- // fill all -1 ones.
- for (int i = fragments.length - 1; i >= 0; i--) {
- if (fragments[i] == -1) {
- fragments[i] = last ;
- }
- last = fragments[i];
- }
- return fragments;
-
- }
-
-}