diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2012-09-23 14:06:01 -0700 |
---|---|---|
committer | Teng-Hui Zhu <ztenghui@google.com> | 2012-09-23 14:07:00 -0700 |
commit | d6072f0a479bb3bb6fe1ef2825b9ee6187827d96 (patch) | |
tree | 045d208ea840d3ee0821f0666c773e4e31affe7d /isoparser/src/main/java/com/googlecode/mp4parser/authoring | |
parent | dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf (diff) | |
download | mp4parser-d6072f0a479bb3bb6fe1ef2825b9ee6187827d96.tar.gz |
Remove all the .svn directory
bug:7093055
Change-Id: Iea526bdda3ba27736440daf17ff8b25ff4fb3660
Diffstat (limited to 'isoparser/src/main/java/com/googlecode/mp4parser/authoring')
47 files changed, 0 insertions, 8779 deletions
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/all-wcprops deleted file mode 100644 index 89054c9..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/all-wcprops +++ /dev/null @@ -1,41 +0,0 @@ -K 25 -svn:wc:ra_dav:version-url -V 82 -/svn/!svn/ver/776/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring -END -Movie.java -K 25 -svn:wc:ra_dav:version-url -V 93 -/svn/!svn/ver/514/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/Movie.java -END -Track.java -K 25 -svn:wc:ra_dav:version-url -V 93 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/Track.java -END -TrackMetaData.java -K 25 -svn:wc:ra_dav:version-url -V 101 -/svn/!svn/ver/745/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/TrackMetaData.java -END -Mp4TrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 100 -/svn/!svn/ver/765/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/Mp4TrackImpl.java -END -AbstractTrack.java -K 25 -svn:wc:ra_dav:version-url -V 101 -/svn/!svn/ver/418/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/AbstractTrack.java -END -DateHelper.java -K 25 -svn:wc:ra_dav:version-url -V 98 -/svn/!svn/ver/418/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/DateHelper.java -END diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/entries deleted file mode 100644 index 7d2b29e..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/entries +++ /dev/null @@ -1,244 +0,0 @@ -10 - -dir -778 -http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring -http://mp4parser.googlecode.com/svn - - - -2012-09-10T14:34:23.574807Z -776 -sebastian.annies@gmail.com - - - - - - - - - - - - - - -7decde4b-c250-0410-a0da-51896bc88be6 - -Movie.java -file - - - - -2012-09-14T17:27:50.517219Z -e3a56133cfdfacb92ed0a54177e847b4 -2012-04-22T10:09:06.632613Z -514 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -2558 - -container -dir - -Track.java -file - - - - -2012-09-14T17:27:50.517219Z -9537fa79b71fe26727e56e84e94bbdb8 -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -1607 - -TrackMetaData.java -file - - - - -2012-09-14T17:27:50.527219Z -cbb770cca0ee421026eec0a2f40d2376 -2012-08-14T19:18:50.777750Z -745 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -2948 - -builder -dir - -adaptivestreaming -dir - -tracks -dir - -Mp4TrackImpl.java -file - - - - -2012-09-14T17:27:50.527219Z -c57930172e9d0da9e881d8dc8ecf2924 -2012-08-29T08:26:56.932482Z -765 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -10958 - -AbstractTrack.java -file - - - - -2012-09-14T17:27:50.527219Z -973f4f354fb6f575dd1a0c8a68d54653 -2012-03-11T20:54:45.638478Z -418 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -1481 - -DateHelper.java -file - - - - -2012-09-14T17:27:50.527219Z -765e3f37d7bb369f569aa91e326a90b8 -2012-03-11T20:54:45.638478Z -418 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -1349 - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/AbstractTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/AbstractTrack.java.svn-base deleted file mode 100644 index fb0e224..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/AbstractTrack.java.svn-base +++ /dev/null @@ -1,60 +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; - -/** - * - */ -public abstract class AbstractTrack implements Track { - private boolean enabled = true; - private boolean inMovie = true; - private boolean inPreview = true; - private boolean inPoster = true; - - public boolean isEnabled() { - return enabled; - } - - public boolean isInMovie() { - return inMovie; - } - - public boolean isInPreview() { - return inPreview; - } - - public boolean isInPoster() { - return inPoster; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public void setInMovie(boolean inMovie) { - this.inMovie = inMovie; - } - - public void setInPreview(boolean inPreview) { - this.inPreview = inPreview; - } - - public void setInPoster(boolean inPoster) { - this.inPoster = inPoster; - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/DateHelper.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/DateHelper.java.svn-base deleted file mode 100644 index 0252859..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/DateHelper.java.svn-base +++ /dev/null @@ -1,44 +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; - -import java.util.Date; - -/** - * Converts ISO Dates (seconds since 1/1/1904) to Date and vice versa. - */ -public class DateHelper { - /** - * Converts a long value with seconds since 1/1/1904 to Date. - * - * @param secondsSince seconds since 1/1/1904 - * @return date the corresponding <code>Date</code> - */ - static public Date convert(long secondsSince) { - return new Date((secondsSince - 2082844800L) * 1000L); - } - - - /** - * Converts a date as long to a mac date as long - * - * @param date date to convert - * @return date in mac format - */ - static public long convert(Date date) { - return (date.getTime() / 1000L) + 2082844800L; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Movie.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Movie.java.svn-base deleted file mode 100644 index 0658682..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Movie.java.svn-base +++ /dev/null @@ -1,91 +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; - -import java.util.LinkedList; -import java.util.List; - -/** - * - */ -public class Movie { - List<Track> tracks = new LinkedList<Track>(); - - public List<Track> getTracks() { - return tracks; - } - - public void setTracks(List<Track> tracks) { - this.tracks = tracks; - } - - public void addTrack(Track nuTrack) { - // do some checking - // perhaps the movie needs to get longer! - if (getTrackByTrackId(nuTrack.getTrackMetaData().getTrackId()) != null) { - // We already have a track with that trackId. Create a new one - nuTrack.getTrackMetaData().setTrackId(getNextTrackId()); - } - tracks.add(nuTrack); - } - - - @Override - public String toString() { - String s = "Movie{ "; - for (Track track : tracks) { - s += "track_" + track.getTrackMetaData().getTrackId() + " (" + track.getHandler() + ") "; - } - - s += '}'; - return s; - } - - public long getNextTrackId() { - long nextTrackId = 0; - for (Track track : tracks) { - nextTrackId = nextTrackId < track.getTrackMetaData().getTrackId() ? track.getTrackMetaData().getTrackId() : nextTrackId; - } - return ++nextTrackId; - } - - - public Track getTrackByTrackId(long trackId) { - for (Track track : tracks) { - if (track.getTrackMetaData().getTrackId() == trackId) { - return track; - } - } - return null; - } - - - public long getTimescale() { - long timescale = this.getTracks().iterator().next().getTrackMetaData().getTimescale(); - for (Track track : this.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); - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Mp4TrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Mp4TrackImpl.java.svn-base deleted file mode 100644 index 3bff1a5..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Mp4TrackImpl.java.svn-base +++ /dev/null @@ -1,219 +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; - -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.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 LinkedList<TimeToSampleBox.Entry>(); - compositionTimeEntries = new LinkedList<CompositionTimeToSample.Entry>(); - sampleDependencies = new LinkedList<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 + '\'' + - '}'; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Track.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Track.java.svn-base deleted file mode 100644 index 1f4b363..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/Track.java.svn-base +++ /dev/null @@ -1,60 +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; - -import com.coremedia.iso.boxes.*; - -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Represents a Track. A track is a timed sequence of related samples. - * <p/> - * <b>NOTE: </b><br/ - * For media data, a track corresponds to a sequence of images or sampled audio; for hint tracks, a track - * corresponds to a streaming channel. - */ -public interface Track { - - SampleDescriptionBox getSampleDescriptionBox(); - - List<TimeToSampleBox.Entry> getDecodingTimeEntries(); - - List<CompositionTimeToSample.Entry> getCompositionTimeEntries(); - - long[] getSyncSamples(); - - List<SampleDependencyTypeBox.Entry> getSampleDependencies(); - - TrackMetaData getTrackMetaData(); - - String getHandler(); - - boolean isEnabled(); - - boolean isInMovie(); - - boolean isInPreview(); - - boolean isInPoster(); - - List<ByteBuffer> getSamples(); - - public Box getMediaHeaderBox(); - - public SubSampleInformationBox getSubsampleInformationBox(); - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/TrackMetaData.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/TrackMetaData.java.svn-base deleted file mode 100644 index c262309..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/.svn/text-base/TrackMetaData.java.svn-base +++ /dev/null @@ -1,130 +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; - -import java.util.Date; - -/** - * - */ -public class TrackMetaData implements Cloneable { - private String language; - private long timescale; - private Date modificationTime = new Date(); - private Date creationTime = new Date(); - private double width; - private double height; - private float volume; - private long trackId = 1; // zero is not allowed - private int group = 0; - - - /** - * specifies the front-to-back ordering of video tracks; tracks with lower - * numbers are closer to the viewer. 0 is the normal value, and -1 would be - * in front of track 0, and so on. - */ - int layer; - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public long getTimescale() { - return timescale; - } - - public void setTimescale(long timescale) { - this.timescale = timescale; - } - - public Date getModificationTime() { - return modificationTime; - } - - public void setModificationTime(Date modificationTime) { - this.modificationTime = modificationTime; - } - - public Date getCreationTime() { - return creationTime; - } - - public void setCreationTime(Date creationTime) { - this.creationTime = creationTime; - } - - public double getWidth() { - return width; - } - - public void setWidth(double width) { - this.width = width; - } - - public double getHeight() { - return height; - } - - public void setHeight(double height) { - this.height = height; - } - - public long getTrackId() { - return trackId; - } - - public void setTrackId(long trackId) { - this.trackId = trackId; - } - - public int getLayer() { - return layer; - } - - public void setLayer(int layer) { - this.layer = layer; - } - - public float getVolume() { - return volume; - } - - public void setVolume(float volume) { - this.volume = volume; - } - - public int getGroup() { - return group; - } - - public void setGroup(int group) { - this.group = group; - } - - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/all-wcprops deleted file mode 100644 index 7d70c40..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/all-wcprops +++ /dev/null @@ -1,47 +0,0 @@ -K 25 -svn:wc:ra_dav:version-url -V 100 -/svn/!svn/ver/773/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming -END -VideoQuality.java -K 25 -svn:wc:ra_dav:version-url -V 118 -/svn/!svn/ver/760/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/VideoQuality.java -END -FlatPackageWriterImpl.java -K 25 -svn:wc:ra_dav:version-url -V 127 -/svn/!svn/ver/760/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/FlatPackageWriterImpl.java -END -ManifestWriter.java -K 25 -svn:wc:ra_dav:version-url -V 120 -/svn/!svn/ver/755/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/ManifestWriter.java -END -AbstractManifestWriter.java -K 25 -svn:wc:ra_dav:version-url -V 128 -/svn/!svn/ver/757/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/AbstractManifestWriter.java -END -PackageWriter.java -K 25 -svn:wc:ra_dav:version-url -V 119 -/svn/!svn/ver/755/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/PackageWriter.java -END -AudioQuality.java -K 25 -svn:wc:ra_dav:version-url -V 118 -/svn/!svn/ver/760/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/AudioQuality.java -END -FlatManifestWriterImpl.java -K 25 -svn:wc:ra_dav:version-url -V 128 -/svn/!svn/ver/773/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/FlatManifestWriterImpl.java -END diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/entries deleted file mode 100644 index 619b17c..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.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/adaptivestreaming -http://mp4parser.googlecode.com/svn - - - -2012-09-01T21:55:19.768646Z -773 -michael.stattmann@gmail.com - - - - - - - - - - - - - - -7decde4b-c250-0410-a0da-51896bc88be6 - -VideoQuality.java -file - - - - -2012-09-14T17:27:50.317216Z -356fcadf80f684d83b5f30afd5cb26e4 -2012-08-17T15:20:10.783404Z -760 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -807 - -FlatPackageWriterImpl.java -file - - - - -2012-09-14T17:27:50.317216Z -f38a8b91e1b8abd48e1ae26b23b060fa -2012-08-17T15:20:10.783404Z -760 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -8285 - -ManifestWriter.java -file - - - - -2012-09-14T17:27:50.317216Z -4fc006c7919c1ab4ed498340dfa133b3 -2012-08-17T01:13:17.213046Z -755 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -992 - -AbstractManifestWriter.java -file - - - - -2012-09-14T17:27:50.317216Z -1ce766c781ae825fb0620a61eb2b2e1c -2012-08-17T05:55:12.215481Z -757 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -5030 - -PackageWriter.java -file - - - - -2012-09-14T17:27:50.317216Z -ffdb02efc14eeadf6c1ba9c5e500e76c -2012-08-17T01:13:17.213046Z -755 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -878 - -AudioQuality.java -file - - - - -2012-09-14T17:27:50.317216Z -c2b5ada192ff228aac261452067773fd -2012-08-17T15:20:10.783404Z -760 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -887 - -FlatManifestWriterImpl.java -file - - - - -2012-09-14T17:27:50.317216Z -d45a45107db5f4c43765d95708382310 -2012-09-01T21:55:19.768646Z -773 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -30095 - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AbstractManifestWriter.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AbstractManifestWriter.java.svn-base deleted file mode 100644 index 6ee4ffa..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AbstractManifestWriter.java.svn-base +++ /dev/null @@ -1,126 +0,0 @@ -package com.googlecode.mp4parser.authoring.adaptivestreaming;
-
-import com.coremedia.iso.boxes.OriginalFormatBox;
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.coremedia.iso.boxes.sampleentry.SampleEntry;
-import com.googlecode.mp4parser.authoring.Movie;
-import com.googlecode.mp4parser.authoring.Track;
-import com.googlecode.mp4parser.authoring.builder.FragmentIntersectionFinder;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.logging.Logger;
-
-import static com.googlecode.mp4parser.util.CastUtils.l2i;
-
-/**
- * Created with IntelliJ IDEA.
- * User: mstattma
- * Date: 17.08.12
- * Time: 02:51
- * To change this template use File | Settings | File Templates.
- */
-public abstract class AbstractManifestWriter implements ManifestWriter {
- private static final Logger LOG = Logger.getLogger(AbstractManifestWriter.class.getName());
-
- private FragmentIntersectionFinder intersectionFinder;
- protected long[] audioFragmentsDurations;
- protected long[] videoFragmentsDurations;
-
- protected AbstractManifestWriter(FragmentIntersectionFinder intersectionFinder) {
- this.intersectionFinder = intersectionFinder;
- }
-
- /**
- * Calculates the length of each fragment in the given <code>track</code> (as part of <code>movie</code>).
- *
- * @param track target of calculation
- * @param movie the <code>track</code> must be part of this <code>movie</code>
- * @return the duration of each fragment in track timescale
- */
- public long[] calculateFragmentDurations(Track track, Movie movie) {
- long[] startSamples = intersectionFinder.sampleNumbers(track, movie);
- long[] durations = new long[startSamples.length];
- int currentFragment = 0;
- int currentSample = 1; // sync samples start with 1 !
-
- for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
- for (int max = currentSample + l2i(entry.getCount()); currentSample < max; currentSample++) {
- // in this loop we go through the entry.getCount() samples starting from current sample.
- // the next entry.getCount() samples have the same decoding time.
- if (currentFragment != startSamples.length - 1 && currentSample == startSamples[currentFragment + 1]) {
- // we are not in the last fragment && the current sample is the start sample of the next fragment
- currentFragment++;
- }
- durations[currentFragment] += entry.getDelta();
-
-
- }
- }
- return durations;
-
- }
-
- public long getBitrate(Track track) {
- long bitrate = 0;
- for (ByteBuffer sample : track.getSamples()) {
- bitrate += sample.limit();
- }
- bitrate *= 8; // from bytes to bits
- bitrate /= ((double) getDuration(track)) / track.getTrackMetaData().getTimescale(); // per second
- return bitrate;
- }
-
- protected static long getDuration(Track track) {
- long duration = 0;
- for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
- duration += entry.getCount() * entry.getDelta();
- }
- return duration;
- }
-
- protected long[] checkFragmentsAlign(long[] referenceTimes, long[] checkTimes) throws IOException {
-
- if (referenceTimes == null || referenceTimes.length == 0) {
- return checkTimes;
- }
- long[] referenceTimesMinusLast = new long[referenceTimes.length - 1];
- System.arraycopy(referenceTimes, 0, referenceTimesMinusLast, 0, referenceTimes.length - 1);
- long[] checkTimesMinusLast = new long[checkTimes.length - 1];
- System.arraycopy(checkTimes, 0, checkTimesMinusLast, 0, checkTimes.length - 1);
-
- if (!Arrays.equals(checkTimesMinusLast, referenceTimesMinusLast)) {
- String log = "";
- log += (referenceTimes.length);
- log += ("Reference : [");
- for (long l : referenceTimes) {
- log += (String.format("%10d,", l));
- }
- log += ("]");
- LOG.warning(log);
- log = "";
-
- log += (checkTimes.length);
- log += ("Current : [");
- for (long l : checkTimes) {
- log += (String.format("%10d,", l));
- }
- log += ("]");
- LOG.warning(log);
- throw new IOException("Track does not have the same fragment borders as its predecessor.");
-
- } else {
- return checkTimes;
- }
- }
-
- protected String getFormat(SampleEntry se) {
- String type = se.getType();
- if (type.equals("encv") || type.equals("enca") || type.equals("encv")) {
- OriginalFormatBox frma = se.getBoxes(OriginalFormatBox.class, true).get(0);
- type = frma.getDataFormat();
- }
- return type;
- }
-}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AudioQuality.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AudioQuality.java.svn-base deleted file mode 100644 index 39e115f..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/AudioQuality.java.svn-base +++ /dev/null @@ -1,29 +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.adaptivestreaming; - - -public class AudioQuality { - String fourCC; - long bitrate; - int audioTag; - long samplingRate; - int channels; - int bitPerSample; - int packetSize; - String language; - String codecPrivateData; -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatManifestWriterImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatManifestWriterImpl.java.svn-base deleted file mode 100644 index 5cc9be9..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatManifestWriterImpl.java.svn-base +++ /dev/null @@ -1,643 +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.adaptivestreaming; - -import com.coremedia.iso.Hex; -import com.coremedia.iso.boxes.SampleDescriptionBox; -import com.coremedia.iso.boxes.SoundMediaHeaderBox; -import com.coremedia.iso.boxes.VideoMediaHeaderBox; -import com.coremedia.iso.boxes.h264.AvcConfigurationBox; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.coremedia.iso.boxes.sampleentry.VisualSampleEntry; -import com.googlecode.mp4parser.Version; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.builder.FragmentIntersectionFinder; -import com.googlecode.mp4parser.boxes.DTSSpecificBox; -import com.googlecode.mp4parser.boxes.EC3SpecificBox; -import com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.AudioSpecificConfig; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.*; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.StringWriter; -import java.nio.ByteBuffer; -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Logger; - -public class FlatManifestWriterImpl extends AbstractManifestWriter { - private static final Logger LOG = Logger.getLogger(FlatManifestWriterImpl.class.getName()); - - protected FlatManifestWriterImpl(FragmentIntersectionFinder intersectionFinder) { - super(intersectionFinder); - } - - /** - * Overwrite this method in subclasses to add your specialities. - * - * @param manifest the original manifest - * @return your customized version of the manifest - */ - protected Document customizeManifest(Document manifest) { - return manifest; - } - - public String getManifest(Movie movie) throws IOException { - - LinkedList<VideoQuality> videoQualities = new LinkedList<VideoQuality>(); - long videoTimescale = -1; - - LinkedList<AudioQuality> audioQualities = new LinkedList<AudioQuality>(); - long audioTimescale = -1; - - for (Track track : movie.getTracks()) { - if (track.getMediaHeaderBox() instanceof VideoMediaHeaderBox) { - videoFragmentsDurations = checkFragmentsAlign(videoFragmentsDurations, calculateFragmentDurations(track, movie)); - SampleDescriptionBox stsd = track.getSampleDescriptionBox(); - videoQualities.add(getVideoQuality(track, (VisualSampleEntry) stsd.getSampleEntry())); - if (videoTimescale == -1) { - videoTimescale = track.getTrackMetaData().getTimescale(); - } else { - assert videoTimescale == track.getTrackMetaData().getTimescale(); - } - } - if (track.getMediaHeaderBox() instanceof SoundMediaHeaderBox) { - audioFragmentsDurations = checkFragmentsAlign(audioFragmentsDurations, calculateFragmentDurations(track, movie)); - SampleDescriptionBox stsd = track.getSampleDescriptionBox(); - audioQualities.add(getAudioQuality(track, (AudioSampleEntry) stsd.getSampleEntry())); - if (audioTimescale == -1) { - audioTimescale = track.getTrackMetaData().getTimescale(); - } else { - assert audioTimescale == track.getTrackMetaData().getTimescale(); - } - - } - } - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder; - try { - documentBuilder = documentBuilderFactory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new IOException(e); - } - Document document = documentBuilder.newDocument(); - - - Element smoothStreamingMedia = document.createElement("SmoothStreamingMedia"); - document.appendChild(smoothStreamingMedia); - smoothStreamingMedia.setAttribute("MajorVersion", "2"); - smoothStreamingMedia.setAttribute("MinorVersion", "1"); -// silverlight ignores the timescale attr smoothStreamingMedia.addAttribute(new Attribute("TimeScale", Long.toString(movieTimeScale))); - smoothStreamingMedia.setAttribute("Duration", "0"); - - smoothStreamingMedia.appendChild(document.createComment(Version.VERSION)); - Element videoStreamIndex = document.createElement("StreamIndex"); - videoStreamIndex.setAttribute("Type", "video"); - videoStreamIndex.setAttribute("TimeScale", Long.toString(videoTimescale)); // silverlight ignores the timescale attr - videoStreamIndex.setAttribute("Chunks", Integer.toString(videoFragmentsDurations.length)); - videoStreamIndex.setAttribute("Url", "video/{bitrate}/{start time}"); - videoStreamIndex.setAttribute("QualityLevels", Integer.toString(videoQualities.size())); - smoothStreamingMedia.appendChild(videoStreamIndex); - - for (int i = 0; i < videoQualities.size(); i++) { - VideoQuality vq = videoQualities.get(i); - Element qualityLevel = document.createElement("QualityLevel"); - qualityLevel.setAttribute("Index", Integer.toString(i)); - qualityLevel.setAttribute("Bitrate", Long.toString(vq.bitrate)); - qualityLevel.setAttribute("FourCC", vq.fourCC); - qualityLevel.setAttribute("MaxWidth", Long.toString(vq.width)); - qualityLevel.setAttribute("MaxHeight", Long.toString(vq.height)); - qualityLevel.setAttribute("CodecPrivateData", vq.codecPrivateData); - qualityLevel.setAttribute("NALUnitLengthField", Integer.toString(vq.nalLength)); - videoStreamIndex.appendChild(qualityLevel); - } - - for (int i = 0; i < videoFragmentsDurations.length; i++) { - Element c = document.createElement("c"); - c.setAttribute("n", Integer.toString(i)); - c.setAttribute("d", Long.toString(videoFragmentsDurations[i])); - videoStreamIndex.appendChild(c); - } - - if (audioFragmentsDurations != null) { - Element audioStreamIndex = document.createElement("StreamIndex"); - audioStreamIndex.setAttribute("Type", "audio"); - audioStreamIndex.setAttribute("TimeScale", Long.toString(audioTimescale)); // silverlight ignores the timescale attr - audioStreamIndex.setAttribute("Chunks", Integer.toString(audioFragmentsDurations.length)); - audioStreamIndex.setAttribute("Url", "audio/{bitrate}/{start time}"); - audioStreamIndex.setAttribute("QualityLevels", Integer.toString(audioQualities.size())); - smoothStreamingMedia.appendChild(audioStreamIndex); - - for (int i = 0; i < audioQualities.size(); i++) { - AudioQuality aq = audioQualities.get(i); - Element qualityLevel = document.createElement("QualityLevel"); - qualityLevel.setAttribute("Index", Integer.toString(i)); - qualityLevel.setAttribute("FourCC", aq.fourCC); - qualityLevel.setAttribute("Bitrate", Long.toString(aq.bitrate)); - qualityLevel.setAttribute("AudioTag", Integer.toString(aq.audioTag)); - qualityLevel.setAttribute("SamplingRate", Long.toString(aq.samplingRate)); - qualityLevel.setAttribute("Channels", Integer.toString(aq.channels)); - qualityLevel.setAttribute("BitsPerSample", Integer.toString(aq.bitPerSample)); - qualityLevel.setAttribute("PacketSize", Integer.toString(aq.packetSize)); - qualityLevel.setAttribute("CodecPrivateData", aq.codecPrivateData); - audioStreamIndex.appendChild(qualityLevel); - } - for (int i = 0; i < audioFragmentsDurations.length; i++) { - Element c = document.createElement("c"); - c.setAttribute("n", Integer.toString(i)); - c.setAttribute("d", Long.toString(audioFragmentsDurations[i])); - audioStreamIndex.appendChild(c); - } - } - - document.setXmlStandalone(true); - Source source = new DOMSource(document); - StringWriter stringWriter = new StringWriter(); - Result result = new StreamResult(stringWriter); - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer; - try { - transformer = factory.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.transform(source, result); - } catch (TransformerConfigurationException e) { - throw new IOException(e); - } catch (TransformerException e) { - throw new IOException(e); - } - return stringWriter.getBuffer().toString(); - - - } - - private AudioQuality getAudioQuality(Track track, AudioSampleEntry ase) { - if (getFormat(ase).equals("mp4a")) { - return getAacAudioQuality(track, ase); - } else if (getFormat(ase).equals("ec-3")) { - return getEc3AudioQuality(track, ase); - } else if (getFormat(ase).startsWith("dts")) { - return getDtsAudioQuality(track, ase); - } else { - throw new InternalError("I don't know what to do with audio of type " + getFormat(ase)); - } - - } - - private AudioQuality getAacAudioQuality(Track track, AudioSampleEntry ase) { - AudioQuality l = new AudioQuality(); - final ESDescriptorBox esDescriptorBox = ase.getBoxes(ESDescriptorBox.class).get(0); - final AudioSpecificConfig audioSpecificConfig = esDescriptorBox.getEsDescriptor().getDecoderConfigDescriptor().getAudioSpecificInfo(); - if (audioSpecificConfig.getSbrPresentFlag() == 1) { - l.fourCC = "AACH"; - } else if (audioSpecificConfig.getPsPresentFlag() == 1) { - l.fourCC = "AACP"; //I'm not sure if that's what MS considers as AAC+ - because actually AAC+ and AAC-HE should be the same... - } else { - l.fourCC = "AACL"; - } - l.bitrate = getBitrate(track); - l.audioTag = 255; - l.samplingRate = ase.getSampleRate(); - l.channels = ase.getChannelCount(); - l.bitPerSample = ase.getSampleSize(); - l.packetSize = 4; - l.codecPrivateData = getAudioCodecPrivateData(audioSpecificConfig); - //Index="0" Bitrate="103000" AudioTag="255" SamplingRate="44100" Channels="2" BitsPerSample="16" packetSize="4" CodecPrivateData="" - return l; - } - - private AudioQuality getEc3AudioQuality(Track track, AudioSampleEntry ase) { - final EC3SpecificBox ec3SpecificBox = ase.getBoxes(EC3SpecificBox.class).get(0); - if (ec3SpecificBox == null) { - throw new RuntimeException("EC-3 track misses EC3SpecificBox!"); - } - - short nfchans = 0; //full bandwidth channels - short lfechans = 0; - byte dWChannelMaskFirstByte = 0; - byte dWChannelMaskSecondByte = 0; - for (EC3SpecificBox.Entry entry : ec3SpecificBox.getEntries()) { - /* - Table 4.3: Audio coding mode - acmod Audio coding mode Nfchans Channel array ordering - 000 1 + 1 2 Ch1, Ch2 - 001 1/0 1 C - 010 2/0 2 L, R - 011 3/0 3 L, C, R - 100 2/1 3 L, R, S - 101 3/1 4 L, C, R, S - 110 2/2 4 L, R, SL, SR - 111 3/2 5 L, C, R, SL, SR - - Table F.2: Chan_loc field bit assignments - Bit Location - 0 Lc/Rc pair - 1 Lrs/Rrs pair - 2 Cs - 3 Ts - 4 Lsd/Rsd pair - 5 Lw/Rw pair - 6 Lvh/Rvh pair - 7 Cvh - 8 LFE2 - */ - switch (entry.acmod) { - case 0: //1+1; Ch1, Ch2 - nfchans += 2; - throw new RuntimeException("Smooth Streaming doesn't support DDP 1+1 mode"); - case 1: //1/0; C - nfchans += 1; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0x20; - } - break; - case 2: //2/0; L, R - nfchans += 2; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xC0; - } - break; - case 3: //3/0; L, C, R - nfchans += 3; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xE0; - } - break; - case 4: //2/1; L, R, S - nfchans += 3; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xC0; - dWChannelMaskSecondByte |= 0x80; - } - break; - case 5: //3/1; L, C, R, S - nfchans += 4; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xE0; - dWChannelMaskSecondByte |= 0x80; - } - break; - case 6: //2/2; L, R, SL, SR - nfchans += 4; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xCC; - } - break; - case 7: //3/2; L, C, R, SL, SR - nfchans += 5; - if (entry.num_dep_sub > 0) { - DependentSubstreamMask dependentSubstreamMask = new DependentSubstreamMask(dWChannelMaskFirstByte, dWChannelMaskSecondByte, entry).process(); - dWChannelMaskFirstByte |= dependentSubstreamMask.getdWChannelMaskFirstByte(); - dWChannelMaskSecondByte |= dependentSubstreamMask.getdWChannelMaskSecondByte(); - } else { - dWChannelMaskFirstByte |= 0xEC; - } - break; - } - if (entry.lfeon == 1) { - lfechans ++; - dWChannelMaskFirstByte |= 0x10; - } - } - - final ByteBuffer waveformatex = ByteBuffer.allocate(22); - waveformatex.put(new byte[]{0x00, 0x06}); //1536 wSamplesPerBlock - little endian - waveformatex.put(dWChannelMaskFirstByte); - waveformatex.put(dWChannelMaskSecondByte); - waveformatex.put(new byte[]{0x00, 0x00}); //pad dwChannelMask to 32bit - waveformatex.put(new byte[]{(byte)0xAF, (byte)0x87, (byte)0xFB, (byte)0xA7, 0x02, 0x2D, (byte)0xFB, 0x42, (byte)0xA4, (byte)0xD4, 0x05, (byte)0xCD, (byte)0x93, (byte)0x84, 0x3B, (byte)0xDD}); //SubFormat - Dolby Digital Plus GUID - - final ByteBuffer dec3Content = ByteBuffer.allocate((int) ec3SpecificBox.getContentSize()); - ec3SpecificBox.getContent(dec3Content); - - AudioQuality l = new AudioQuality(); - l.fourCC = "EC-3"; - l.bitrate = getBitrate(track); - l.audioTag = 65534; - l.samplingRate = ase.getSampleRate(); - l.channels = nfchans + lfechans; - l.bitPerSample = 16; - l.packetSize = track.getSamples().get(0).limit(); //assuming all are same size - l.codecPrivateData = Hex.encodeHex(waveformatex.array()) + Hex.encodeHex(dec3Content.array()); //append EC3SpecificBox (big endian) at the end of waveformatex - return l; - } - - private AudioQuality getDtsAudioQuality(Track track, AudioSampleEntry ase) { - final DTSSpecificBox dtsSpecificBox = ase.getBoxes(DTSSpecificBox.class).get(0); - if (dtsSpecificBox == null) { - throw new RuntimeException("DTS track misses DTSSpecificBox!"); - } - - final ByteBuffer waveformatex = ByteBuffer.allocate(22); - final int frameDuration = dtsSpecificBox.getFrameDuration(); - short samplesPerBlock = 0; - switch (frameDuration) { - case 0: - samplesPerBlock = 512; - break; - case 1: - samplesPerBlock = 1024; - break; - case 2: - samplesPerBlock = 2048; - break; - case 3: - samplesPerBlock = 4096; - break; - } - waveformatex.put((byte) (samplesPerBlock & 0xff)); - waveformatex.put((byte) (samplesPerBlock >>> 8)); - final int dwChannelMask = getNumChannelsAndMask(dtsSpecificBox)[1]; - waveformatex.put((byte) (dwChannelMask & 0xff)); - waveformatex.put((byte) (dwChannelMask >>> 8)); - waveformatex.put((byte) (dwChannelMask >>> 16)); - waveformatex.put((byte) (dwChannelMask >>> 24)); - waveformatex.put(new byte[]{(byte)0xAE, (byte)0xE4, (byte)0xBF, (byte)0x5E, (byte)0x61, (byte)0x5E, (byte)0x41, (byte)0x87, (byte)0x92, (byte)0xFC, (byte)0xA4, (byte)0x81, (byte)0x26, (byte)0x99, (byte)0x02, (byte)0x11}); //DTS-HD GUID - - final ByteBuffer dtsCodecPrivateData = ByteBuffer.allocate(8); - dtsCodecPrivateData.put((byte) dtsSpecificBox.getStreamConstruction()); - - final int channelLayout = dtsSpecificBox.getChannelLayout(); - dtsCodecPrivateData.put((byte) (channelLayout & 0xff)); - dtsCodecPrivateData.put((byte) (channelLayout >>> 8)); - dtsCodecPrivateData.put((byte) (channelLayout >>> 16)); - dtsCodecPrivateData.put((byte) (channelLayout >>> 24)); - - byte dtsFlags = (byte) (dtsSpecificBox.getMultiAssetFlag() << 1); - dtsFlags |= dtsSpecificBox.getLBRDurationMod(); - dtsCodecPrivateData.put(dtsFlags); - dtsCodecPrivateData.put(new byte[]{0x00, 0x00}); //reserved - - AudioQuality l = new AudioQuality(); - l.fourCC = getFormat(ase); - l.bitrate = dtsSpecificBox.getAvgBitRate(); - l.audioTag = 65534; - l.samplingRate = dtsSpecificBox.getDTSSamplingFrequency(); - l.channels = getNumChannelsAndMask(dtsSpecificBox)[0]; - l.bitPerSample = 16; - l.packetSize = track.getSamples().get(0).limit(); //assuming all are same size - l.codecPrivateData = Hex.encodeHex(waveformatex.array()) + Hex.encodeHex(dtsCodecPrivateData.array()); - return l; - - } - - /* dwChannelMask - L SPEAKER_FRONT_LEFT 0x00000001 - R SPEAKER_FRONT_RIGHT 0x00000002 - C SPEAKER_FRONT_CENTER 0x00000004 - LFE1 SPEAKER_LOW_FREQUENCY 0x00000008 - Ls or Lsr* SPEAKER_BACK_LEFT 0x00000010 - Rs or Rsr* SPEAKER_BACK_RIGHT 0x00000020 - Lc SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040 - Rc SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080 - Cs SPEAKER_BACK_CENTER 0x00000100 - Lss SPEAKER_SIDE_LEFT 0x00000200 - Rss SPEAKER_SIDE_RIGHT 0x00000400 - Oh SPEAKER_TOP_CENTER 0x00000800 - Lh SPEAKER_TOP_FRONT_LEFT 0x00001000 - Ch SPEAKER_TOP_FRONT_CENTER 0x00002000 - Rh SPEAKER_TOP_FRONT_RIGHT 0x00004000 - Lhr SPEAKER_TOP_BACK_LEFT 0x00008000 - Chf SPEAKER_TOP_BACK_CENTER 0x00010000 - Rhr SPEAKER_TOP_BACK_RIGHT 0x00020000 - SPEAKER_RESERVED 0x80000000 - - * if Lss, Rss exist, then this position is equivalent to Lsr, Rsr respectively - */ - private int[] getNumChannelsAndMask(DTSSpecificBox dtsSpecificBox) { - final int channelLayout = dtsSpecificBox.getChannelLayout(); - int numChannels = 0; - int dwChannelMask = 0; - if ((channelLayout & 0x0001) == 0x0001) { - //0001h Center in front of listener 1 - numChannels += 1; - dwChannelMask |= 0x00000004; //SPEAKER_FRONT_CENTER - } - if ((channelLayout & 0x0002) == 0x0002) { - //0002h Left/Right in front 2 - numChannels += 2; - dwChannelMask |= 0x00000001; //SPEAKER_FRONT_LEFT - dwChannelMask |= 0x00000002; //SPEAKER_FRONT_RIGHT - } - if ((channelLayout & 0x0004) == 0x0004) { - //0004h Left/Right surround on side in rear 2 - numChannels += 2; - //* if Lss, Rss exist, then this position is equivalent to Lsr, Rsr respectively - dwChannelMask |= 0x00000010; //SPEAKER_BACK_LEFT - dwChannelMask |= 0x00000020; //SPEAKER_BACK_RIGHT - } - if ((channelLayout & 0x0008) == 0x0008) { - //0008h Low frequency effects subwoofer 1 - numChannels += 1; - dwChannelMask |= 0x00000008; //SPEAKER_LOW_FREQUENCY - } - if ((channelLayout & 0x0010) == 0x0010) { - //0010h Center surround in rear 1 - numChannels += 1; - dwChannelMask |= 0x00000100; //SPEAKER_BACK_CENTER - } - if ((channelLayout & 0x0020) == 0x0020) { - //0020h Left/Right height in front 2 - numChannels += 2; - dwChannelMask |= 0x00001000; //SPEAKER_TOP_FRONT_LEFT - dwChannelMask |= 0x00004000; //SPEAKER_TOP_FRONT_RIGHT - } - if ((channelLayout & 0x0040) == 0x0040) { - //0040h Left/Right surround in rear 2 - numChannels += 2; - dwChannelMask |= 0x00000010; //SPEAKER_BACK_LEFT - dwChannelMask |= 0x00000020; //SPEAKER_BACK_RIGHT - } - if ((channelLayout & 0x0080) == 0x0080) { - //0080h Center Height in front 1 - numChannels += 1; - dwChannelMask |= 0x00002000; //SPEAKER_TOP_FRONT_CENTER - } - if ((channelLayout & 0x0100) == 0x0100) { - //0100h Over the listener’s head 1 - numChannels += 1; - dwChannelMask |= 0x00000800; //SPEAKER_TOP_CENTER - } - if ((channelLayout & 0x0200) == 0x0200) { - //0200h Between left/right and center in front 2 - numChannels += 2; - dwChannelMask |= 0x00000040; //SPEAKER_FRONT_LEFT_OF_CENTER - dwChannelMask |= 0x00000080; //SPEAKER_FRONT_RIGHT_OF_CENTER - } - if ((channelLayout & 0x0400) == 0x0400) { - //0400h Left/Right on side in front 2 - numChannels += 2; - dwChannelMask |= 0x00000200; //SPEAKER_SIDE_LEFT - dwChannelMask |= 0x00000400; //SPEAKER_SIDE_RIGHT - } - if ((channelLayout & 0x0800) == 0x0800) { - //0800h Left/Right surround on side 2 - numChannels += 2; - //* if Lss, Rss exist, then this position is equivalent to Lsr, Rsr respectively - dwChannelMask |= 0x00000010; //SPEAKER_BACK_LEFT - dwChannelMask |= 0x00000020; //SPEAKER_BACK_RIGHT - } - if ((channelLayout & 0x1000) == 0x1000) { - //1000h Second low frequency effects subwoofer 1 - numChannels += 1; - dwChannelMask |= 0x00000008; //SPEAKER_LOW_FREQUENCY - } - if ((channelLayout & 0x2000) == 0x2000) { - //2000h Left/Right height on side 2 - numChannels += 2; - dwChannelMask |= 0x00000010; //SPEAKER_BACK_LEFT - dwChannelMask |= 0x00000020; //SPEAKER_BACK_RIGHT - } - if ((channelLayout & 0x4000) == 0x4000) { - //4000h Center height in rear 1 - numChannels += 1; - dwChannelMask |= 0x00010000; //SPEAKER_TOP_BACK_CENTER - } - if ((channelLayout & 0x8000) == 0x8000) { - //8000h Left/Right height in rear 2 - numChannels += 2; - dwChannelMask |= 0x00008000; //SPEAKER_TOP_BACK_LEFT - dwChannelMask |= 0x00020000; //SPEAKER_TOP_BACK_RIGHT - } - if ((channelLayout & 0x10000) == 0x10000) { - //10000h Center below in front - numChannels += 1; - } - if ((channelLayout & 0x20000) == 0x20000) { - //20000h Left/Right below in front - numChannels += 2; - } - return new int[]{numChannels, dwChannelMask}; - } - - private String getAudioCodecPrivateData(AudioSpecificConfig audioSpecificConfig) { - byte[] configByteArray = audioSpecificConfig.getConfigBytes(); - return Hex.encodeHex(configByteArray); - } - - private VideoQuality getVideoQuality(Track track, VisualSampleEntry vse) { - VideoQuality l; - if ("avc1".equals(getFormat(vse))) { - AvcConfigurationBox avcConfigurationBox = vse.getBoxes(AvcConfigurationBox.class).get(0); - l = new VideoQuality(); - l.bitrate = getBitrate(track); - l.codecPrivateData = Hex.encodeHex(getAvcCodecPrivateData(avcConfigurationBox)); - l.fourCC = "AVC1"; - l.width = vse.getWidth(); - l.height = vse.getHeight(); - l.nalLength = avcConfigurationBox.getLengthSizeMinusOne() + 1; - } else { - throw new InternalError("I don't know how to handle video of type " + getFormat(vse)); - } - return l; - } - - private byte[] getAvcCodecPrivateData(AvcConfigurationBox avcConfigurationBox) { - List<byte[]> sps = avcConfigurationBox.getSequenceParameterSets(); - List<byte[]> pps = avcConfigurationBox.getPictureParameterSets(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - baos.write(new byte[]{0, 0, 0, 1}); - - for (byte[] sp : sps) { - baos.write(sp); - } - baos.write(new byte[]{0, 0, 0, 1}); - for (byte[] pp : pps) { - baos.write(pp); - } - } catch (IOException ex) { - throw new RuntimeException("ByteArrayOutputStream do not throw IOException ?!?!?"); - } - return baos.toByteArray(); - } - - private class DependentSubstreamMask { - private byte dWChannelMaskFirstByte; - private byte dWChannelMaskSecondByte; - private EC3SpecificBox.Entry entry; - - public DependentSubstreamMask(byte dWChannelMaskFirstByte, byte dWChannelMaskSecondByte, EC3SpecificBox.Entry entry) { - this.dWChannelMaskFirstByte = dWChannelMaskFirstByte; - this.dWChannelMaskSecondByte = dWChannelMaskSecondByte; - this.entry = entry; - } - - public byte getdWChannelMaskFirstByte() { - return dWChannelMaskFirstByte; - } - - public byte getdWChannelMaskSecondByte() { - return dWChannelMaskSecondByte; - } - - public DependentSubstreamMask process() { - switch (entry.chan_loc) { - case 0: - dWChannelMaskFirstByte |= 0x3; - break; - case 1: - dWChannelMaskFirstByte |= 0xC; - break; - case 2: - dWChannelMaskSecondByte |= 0x80; - break; - case 3: - dWChannelMaskSecondByte |= 0x8; - break; - case 6: - dWChannelMaskSecondByte |= 0x5; - break; - case 7: - dWChannelMaskSecondByte |= 0x2; - break; - } - return this; - } - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatPackageWriterImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatPackageWriterImpl.java.svn-base deleted file mode 100644 index 3e3847c..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/FlatPackageWriterImpl.java.svn-base +++ /dev/null @@ -1,197 +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.adaptivestreaming; - -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.Box; -import com.coremedia.iso.boxes.SoundMediaHeaderBox; -import com.coremedia.iso.boxes.VideoMediaHeaderBox; -import com.coremedia.iso.boxes.fragment.MovieFragmentBox; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.builder.*; -import com.googlecode.mp4parser.authoring.tracks.ChangeTimeScaleTrack; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.util.Iterator; -import java.util.logging.Logger; - -public class FlatPackageWriterImpl implements PackageWriter { - private static Logger LOG = Logger.getLogger(FlatPackageWriterImpl.class.getName()); - long timeScale = 10000000; - - private File outputDirectory; - private boolean debugOutput; - private FragmentedMp4Builder ismvBuilder; - ManifestWriter manifestWriter; - - public FlatPackageWriterImpl() { - ismvBuilder = new FragmentedMp4Builder(); - FragmentIntersectionFinder intersectionFinder = new SyncSampleIntersectFinderImpl(); - ismvBuilder.setIntersectionFinder(intersectionFinder); - manifestWriter = new FlatManifestWriterImpl(intersectionFinder); - } - - /** - * Creates a factory for a smooth streaming package. A smooth streaming package is - * a collection of files that can be served by a webserver as a smooth streaming - * stream. - * @param minFragmentDuration the smallest allowable duration of a fragment (0 == no restriction). - */ - public FlatPackageWriterImpl(int minFragmentDuration) { - ismvBuilder = new FragmentedMp4Builder(); - FragmentIntersectionFinder intersectionFinder = new SyncSampleIntersectFinderImpl(minFragmentDuration); - ismvBuilder.setIntersectionFinder(intersectionFinder); - manifestWriter = new FlatManifestWriterImpl(intersectionFinder); - } - - public void setOutputDirectory(File outputDirectory) { - assert outputDirectory.isDirectory(); - this.outputDirectory = outputDirectory; - - } - - public void setDebugOutput(boolean debugOutput) { - this.debugOutput = debugOutput; - } - - public void setIsmvBuilder(FragmentedMp4Builder ismvBuilder) { - this.ismvBuilder = ismvBuilder; - this.manifestWriter = new FlatManifestWriterImpl(ismvBuilder.getFragmentIntersectionFinder()); - } - - public void setManifestWriter(ManifestWriter manifestWriter) { - this.manifestWriter = manifestWriter; - } - - /** - * Writes the movie given as <code>qualities</code> flattened into the - * <code>outputDirectory</code>. - * - * @param source the source movie with all qualities - * @throws IOException - */ - public void write(Movie source) throws IOException { - - if (debugOutput) { - outputDirectory.mkdirs(); - DefaultMp4Builder defaultMp4Builder = new DefaultMp4Builder(); - IsoFile muxed = defaultMp4Builder.build(source); - File muxedFile = new File(outputDirectory, "debug_1_muxed.mp4"); - FileOutputStream muxedFileOutputStream = new FileOutputStream(muxedFile); - muxed.getBox(muxedFileOutputStream.getChannel()); - muxedFileOutputStream.close(); - } - Movie cleanedSource = removeUnknownTracks(source); - Movie movieWithAdjustedTimescale = correctTimescale(cleanedSource); - - if (debugOutput) { - DefaultMp4Builder defaultMp4Builder = new DefaultMp4Builder(); - IsoFile muxed = defaultMp4Builder.build(movieWithAdjustedTimescale); - File muxedFile = new File(outputDirectory, "debug_2_timescale.mp4"); - FileOutputStream muxedFileOutputStream = new FileOutputStream(muxedFile); - muxed.getBox(muxedFileOutputStream.getChannel()); - muxedFileOutputStream.close(); - } - IsoFile isoFile = ismvBuilder.build(movieWithAdjustedTimescale); - if (debugOutput) { - File allQualities = new File(outputDirectory, "debug_3_fragmented.mp4"); - FileOutputStream allQualis = new FileOutputStream(allQualities); - isoFile.getBox(allQualis.getChannel()); - allQualis.close(); - } - - - for (Track track : movieWithAdjustedTimescale.getTracks()) { - String bitrate = Long.toString(manifestWriter.getBitrate(track)); - long trackId = track.getTrackMetaData().getTrackId(); - Iterator<Box> boxIt = isoFile.getBoxes().iterator(); - File mediaOutDir; - if (track.getMediaHeaderBox() instanceof SoundMediaHeaderBox) { - mediaOutDir = new File(outputDirectory, "audio"); - - } else if (track.getMediaHeaderBox() instanceof VideoMediaHeaderBox) { - mediaOutDir = new File(outputDirectory, "video"); - } else { - System.err.println("Skipping Track with handler " + track.getHandler() + " and " + track.getMediaHeaderBox().getClass().getSimpleName()); - continue; - } - File bitRateOutputDir = new File(mediaOutDir, bitrate); - bitRateOutputDir.mkdirs(); - LOG.finer("Created : " + bitRateOutputDir.getCanonicalPath()); - - long[] fragmentTimes = manifestWriter.calculateFragmentDurations(track, movieWithAdjustedTimescale); - long startTime = 0; - int currentFragment = 0; - while (boxIt.hasNext()) { - Box b = boxIt.next(); - if (b instanceof MovieFragmentBox) { - assert ((MovieFragmentBox) b).getTrackCount() == 1; - if (((MovieFragmentBox) b).getTrackNumbers()[0] == trackId) { - FileOutputStream fos = new FileOutputStream(new File(bitRateOutputDir, Long.toString(startTime))); - startTime += fragmentTimes[currentFragment++]; - FileChannel fc = fos.getChannel(); - Box mdat = boxIt.next(); - assert mdat.getType().equals("mdat"); - b.getBox(fc); // moof - mdat.getBox(fc); // mdat - fc.truncate(fc.position()); - fc.close(); - } - } - - } - } - FileWriter fw = new FileWriter(new File(outputDirectory, "Manifest")); - fw.write(manifestWriter.getManifest(movieWithAdjustedTimescale)); - fw.close(); - - } - - private Movie removeUnknownTracks(Movie source) { - Movie nuMovie = new Movie(); - for (Track track : source.getTracks()) { - if ("vide".equals(track.getHandler()) || "soun".equals(track.getHandler())) { - nuMovie.addTrack(track); - } else { - LOG.fine("Removed track " + track); - } - } - return nuMovie; - } - - - /** - * Returns a new <code>Movie</code> in that all tracks have the timescale 10000000. CTS & DTS are modified - * in a way that even with more than one framerate the fragments exactly begin at the same time. - * - * @param movie - * @return a movie with timescales suitable for smooth streaming manifests - */ - public Movie correctTimescale(Movie movie) { - Movie nuMovie = new Movie(); - for (Track track : movie.getTracks()) { - nuMovie.addTrack(new ChangeTimeScaleTrack(track, timeScale, ismvBuilder.getFragmentIntersectionFinder().sampleNumbers(track, movie))); - } - return nuMovie; - - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/ManifestWriter.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/ManifestWriter.java.svn-base deleted file mode 100644 index 2b2ba7d..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/ManifestWriter.java.svn-base +++ /dev/null @@ -1,31 +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.adaptivestreaming; - - -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; - -import java.io.IOException; - -public interface ManifestWriter { - String getManifest(Movie inputs) throws IOException; - - long getBitrate(Track track); - - long[] calculateFragmentDurations(Track track, Movie movie); - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/PackageWriter.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/PackageWriter.java.svn-base deleted file mode 100644 index 0d97fc5..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/PackageWriter.java.svn-base +++ /dev/null @@ -1,27 +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.adaptivestreaming; - -import com.googlecode.mp4parser.authoring.Movie; - -import java.io.IOException; - -/** - * Writes the whole package. - */ -public interface PackageWriter { - public void write(Movie qualities) throws IOException; -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/VideoQuality.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/VideoQuality.java.svn-base deleted file mode 100644 index 4a70e47..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/adaptivestreaming/.svn/text-base/VideoQuality.java.svn-base +++ /dev/null @@ -1,25 +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.adaptivestreaming; - -class VideoQuality { - long bitrate; - String fourCC; - int width; - int height; - String codecPrivateData; - int nalLength; -} 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<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; - - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/all-wcprops deleted file mode 100644 index a7245be..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/all-wcprops +++ /dev/null @@ -1,5 +0,0 @@ -K 25 -svn:wc:ra_dav:version-url -V 92 -/svn/!svn/ver/418/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container -END diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/entries deleted file mode 100644 index bde4d0e..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/.svn/entries +++ /dev/null @@ -1,31 +0,0 @@ -10 - -dir -778 -http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container -http://mp4parser.googlecode.com/svn - - - -2012-03-11T20:54:45.638478Z -418 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - -7decde4b-c250-0410-a0da-51896bc88be6 - -mp4 -dir - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/all-wcprops deleted file mode 100644 index ec2a4f9..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/all-wcprops +++ /dev/null @@ -1,11 +0,0 @@ -K 25 -svn:wc:ra_dav:version-url -V 96 -/svn/!svn/ver/418/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4 -END -MovieCreator.java -K 25 -svn:wc:ra_dav:version-url -V 114 -/svn/!svn/ver/418/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/MovieCreator.java -END diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/entries deleted file mode 100644 index d7d7f30..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/entries +++ /dev/null @@ -1,62 +0,0 @@ -10 - -dir -778 -http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4 -http://mp4parser.googlecode.com/svn - - - -2012-03-11T20:54:45.638478Z -418 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - -7decde4b-c250-0410-a0da-51896bc88be6 - -MovieCreator.java -file - - - - -2012-09-14T17:27:49.987212Z -ecb22de8d79473683de67e40f494641d -2012-03-11T20:54:45.638478Z -418 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -1404 - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/text-base/MovieCreator.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/text-base/MovieCreator.java.svn-base deleted file mode 100644 index ed9d15f..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/container/mp4/.svn/text-base/MovieCreator.java.svn-base +++ /dev/null @@ -1,40 +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.container.mp4; - -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.TrackBox; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Mp4TrackImpl; - -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.util.List; - -/** - * Shortcut to build a movie from an MP4 file. - */ -public class MovieCreator { - public static Movie build(ReadableByteChannel channel) throws IOException { - IsoFile isoFile = new IsoFile(channel); - Movie m = new Movie(); - List<TrackBox> trackBoxes = isoFile.getMovieBox().getBoxes(TrackBox.class); - for (TrackBox trackBox : trackBoxes) { - m.addTrack(new Mp4TrackImpl(trackBox)); - } - return m; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/all-wcprops deleted file mode 100644 index 496d7bb..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/all-wcprops +++ /dev/null @@ -1,89 +0,0 @@ -K 25 -svn:wc:ra_dav:version-url -V 89 -/svn/!svn/ver/756/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks -END -DivideTimeScaleTrack.java -K 25 -svn:wc:ra_dav:version-url -V 115 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/DivideTimeScaleTrack.java -END -CroppedTrack.java -K 25 -svn:wc:ra_dav:version-url -V 107 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/CroppedTrack.java -END -ChangeTimeScaleTrack.java -K 25 -svn:wc:ra_dav:version-url -V 115 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/ChangeTimeScaleTrack.java -END -EC3TrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 107 -/svn/!svn/ver/756/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/EC3TrackImpl.java -END -ReplaceSampleTrack.java -K 25 -svn:wc:ra_dav:version-url -V 113 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/ReplaceSampleTrack.java -END -QuicktimeTextTrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 117 -/svn/!svn/ver/691/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/QuicktimeTextTrackImpl.java -END -Amf0Track.java -K 25 -svn:wc:ra_dav:version-url -V 104 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/Amf0Track.java -END -SilenceTrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 111 -/svn/!svn/ver/698/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/SilenceTrackImpl.java -END -H264TrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 108 -/svn/!svn/ver/756/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/H264TrackImpl.java -END -TextTrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 108 -/svn/!svn/ver/684/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/TextTrackImpl.java -END -AACTrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 107 -/svn/!svn/ver/756/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/AACTrackImpl.java -END -MultiplyTimeScaleTrack.java -K 25 -svn:wc:ra_dav:version-url -V 117 -/svn/!svn/ver/686/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/MultiplyTimeScaleTrack.java -END -AppendTrack.java -K 25 -svn:wc:ra_dav:version-url -V 106 -/svn/!svn/ver/714/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/AppendTrack.java -END -AC3TrackImpl.java -K 25 -svn:wc:ra_dav:version-url -V 107 -/svn/!svn/ver/756/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/AC3TrackImpl.java -END diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/entries deleted file mode 100644 index dbe8ae3..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/entries +++ /dev/null @@ -1,504 +0,0 @@ -10 - -dir -778 -http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks -http://mp4parser.googlecode.com/svn - - - -2012-08-17T01:19:11.953078Z -756 -michael.stattmann@gmail.com - - - - - - - - - - - - - - -7decde4b-c250-0410-a0da-51896bc88be6 - -DivideTimeScaleTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -6aa41cdb7489e16e879ddebd68b7ac52 -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -3893 - -CroppedTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -5d9c65d9aac52a26372aa3fdf6f1b7ea -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -6025 - -ChangeTimeScaleTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -ba01d30ac4b7c4fa9a2c6538ee537594 -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -7152 - -EC3TrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -1d568bfaa0f41c3771986a7790347072 -2012-08-17T01:19:11.953078Z -756 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -13623 - -ReplaceSampleTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -f6846b7a262ab0e530da46f4d7e34850 -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -3139 - -QuicktimeTextTrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -7ccd01a58545fb02b507b57892eb53e5 -2012-06-24T21:35:59.546504Z -691 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -5128 - -Amf0Track.java -file - - - - -2012-09-14T17:27:50.507219Z -4718a34bc271adf4517de9829ac74a9d -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -3858 - -SilenceTrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -a897677e602dfa0d64af1b0d33a04ca8 -2012-06-26T08:37:32.910396Z -698 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -2623 - -H264TrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -76abb4b21c13d11215a2ac4cb0c7e461 -2012-08-17T01:19:11.953078Z -756 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -28816 - -TextTrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -5a643c876754eb5c7bcf75b4b71114a1 -2012-06-24T14:45:45.932648Z -684 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -4963 - -AACTrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -ece8d364a9a5aeabf6a281f6d428e3cf -2012-08-17T01:19:11.953078Z -756 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -10097 - -MultiplyTimeScaleTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -b0ea53239c124607a26a181f594f82a1 -2012-06-24T19:52:05.961412Z -686 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -4192 - -AppendTrack.java -file - - - - -2012-09-14T17:27:50.507219Z -e7814aebc4500724771fd0582455a7ca -2012-07-18T23:22:45.506793Z -714 -Sebastian.Annies@gmail.com - - - - - - - - - - - - - - - - - - - - - -15783 - -AC3TrackImpl.java -file - - - - -2012-09-14T17:27:50.507219Z -fbd724739cd9a5f2b28f16b412b27309 -2012-08-17T01:19:11.953078Z -756 -michael.stattmann@gmail.com - - - - - - - - - - - - - - - - - - - - - -19303 - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AACTrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AACTrackImpl.java.svn-base deleted file mode 100644 index df51a1a..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AACTrackImpl.java.svn-base +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2012 castLabs GmbH, Berlin - * - * 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.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.AC3SpecificBox; -import com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.*; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.*; - -/** - */ -public class AACTrackImpl extends AbstractTrack { - public static Map<Integer, Integer> samplingFrequencyIndexMap = new HashMap<Integer, Integer>(); - - static { - samplingFrequencyIndexMap.put(96000, 0); - samplingFrequencyIndexMap.put(88200, 1); - samplingFrequencyIndexMap.put(64000, 2); - samplingFrequencyIndexMap.put(48000, 3); - samplingFrequencyIndexMap.put(44100, 4); - samplingFrequencyIndexMap.put(32000, 5); - samplingFrequencyIndexMap.put(24000, 6); - samplingFrequencyIndexMap.put(22050, 7); - samplingFrequencyIndexMap.put(16000, 8); - samplingFrequencyIndexMap.put(12000, 9); - samplingFrequencyIndexMap.put(11025, 10); - samplingFrequencyIndexMap.put(8000, 11); - samplingFrequencyIndexMap.put(0x0, 96000); - samplingFrequencyIndexMap.put(0x1, 88200); - samplingFrequencyIndexMap.put(0x2, 64000); - samplingFrequencyIndexMap.put(0x3, 48000); - samplingFrequencyIndexMap.put(0x4, 44100); - samplingFrequencyIndexMap.put(0x5, 32000); - samplingFrequencyIndexMap.put(0x6, 24000); - samplingFrequencyIndexMap.put(0x7, 22050); - samplingFrequencyIndexMap.put(0x8, 16000); - samplingFrequencyIndexMap.put(0x9, 12000); - samplingFrequencyIndexMap.put(0xa, 11025); - samplingFrequencyIndexMap.put(0xb, 8000); - } - - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - - int samplerate; - int bitrate; - int channelCount; - int channelconfig; - - int bufferSizeDB; - long maxBitRate; - long avgBitRate; - - private BufferedInputStream inputStream; - private List<ByteBuffer> samples; - boolean readSamples = false; - List<TimeToSampleBox.Entry> stts; - private String lang = "und"; - - - public AACTrackImpl(InputStream inputStream, String lang) throws IOException { - this.lang = lang; - parse(inputStream); - } - - public AACTrackImpl(InputStream inputStream) throws IOException { - parse(inputStream); - } - - private void parse(InputStream inputStream) throws IOException { - this.inputStream = new BufferedInputStream(inputStream); - stts = new LinkedList<TimeToSampleBox.Entry>(); - - if (!readVariables()) { - throw new IOException(); - } - - samples = new LinkedList<ByteBuffer>(); - if (!readSamples()) { - throw new IOException(); - } - - double packetsPerSecond = (double)samplerate / 1024.0; - double duration = samples.size() / packetsPerSecond; - - long dataSize = 0; - LinkedList<Integer> queue = new LinkedList<Integer>(); - for (int i = 0; i < samples.size(); i++) { - int size = samples.get(i).capacity(); - dataSize += size; - queue.add(size); - while (queue.size() > packetsPerSecond) { - queue.pop(); - } - if (queue.size() == (int) packetsPerSecond) { - int currSize = 0; - for (int j = 0 ; j < queue.size(); j++) { - currSize += queue.get(j); - } - double currBitrate = 8.0 * currSize / queue.size() * packetsPerSecond; - if (currBitrate > maxBitRate) { - maxBitRate = (int)currBitrate; - } - } - } - - avgBitRate = (int) (8 * dataSize / duration); - - bufferSizeDB = 1536; /* TODO: Calcultate this somehow! */ - - sampleDescriptionBox = new SampleDescriptionBox(); - AudioSampleEntry audioSampleEntry = new AudioSampleEntry("mp4a"); - audioSampleEntry.setChannelCount(2); - audioSampleEntry.setSampleRate(samplerate); - audioSampleEntry.setDataReferenceIndex(1); - audioSampleEntry.setSampleSize(16); - - - ESDescriptorBox esds = new ESDescriptorBox(); - ESDescriptor descriptor = new ESDescriptor(); - descriptor.setEsId(0); - - SLConfigDescriptor slConfigDescriptor = new SLConfigDescriptor(); - slConfigDescriptor.setPredefined(2); - descriptor.setSlConfigDescriptor(slConfigDescriptor); - - DecoderConfigDescriptor decoderConfigDescriptor = new DecoderConfigDescriptor(); - decoderConfigDescriptor.setObjectTypeIndication(0x40); - decoderConfigDescriptor.setStreamType(5); - decoderConfigDescriptor.setBufferSizeDB(bufferSizeDB); - decoderConfigDescriptor.setMaxBitRate(maxBitRate); - decoderConfigDescriptor.setAvgBitRate(avgBitRate); - - AudioSpecificConfig audioSpecificConfig = new AudioSpecificConfig(); - audioSpecificConfig.setAudioObjectType(2); // AAC LC - audioSpecificConfig.setSamplingFrequencyIndex(samplingFrequencyIndexMap.get(samplerate)); - audioSpecificConfig.setChannelConfiguration(channelconfig); - decoderConfigDescriptor.setAudioSpecificInfo(audioSpecificConfig); - - descriptor.setDecoderConfigDescriptor(decoderConfigDescriptor); - - ByteBuffer data = descriptor.serialize(); - esds.setData(data); - audioSampleEntry.addBox(esds); - sampleDescriptionBox.addBox(audioSampleEntry); - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setLanguage(lang); - trackMetaData.setTimescale(samplerate); // Audio tracks always use samplerate as timescale - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "soun"; - } - - public List<ByteBuffer> getSamples() { - return samples; - } - - public Box getMediaHeaderBox() { - return new SoundMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - - private boolean readVariables() throws IOException { - byte[] data = new byte[100]; - inputStream.mark(100); - if (100 != inputStream.read(data, 0, 100)) { - return false; - } - inputStream.reset(); // Rewind - ByteBuffer bb = ByteBuffer.wrap(data); - BitReaderBuffer brb = new BitReaderBuffer(bb); - int syncword = brb.readBits(12); - if (syncword != 0xfff) { - return false; - } - int id = brb.readBits(1); - int layer = brb.readBits(2); - int protectionAbsent = brb.readBits(1); - int profile = brb.readBits(2); - samplerate = samplingFrequencyIndexMap.get(brb.readBits(4)); - brb.readBits(1); - channelconfig = brb.readBits(3); - int original = brb.readBits(1); - int home = brb.readBits(1); - int emphasis = brb.readBits(2); - - return true; - } - - private boolean readSamples() throws IOException { - if (readSamples) { - return true; - } - - readSamples = true; - byte[] header = new byte[15]; - boolean ret = false; - inputStream.mark(15); - while (-1 != inputStream.read(header)) { - ret = true; - ByteBuffer bb = ByteBuffer.wrap(header); - inputStream.reset(); - BitReaderBuffer brb = new BitReaderBuffer(bb); - int syncword = brb.readBits(12); - if (syncword != 0xfff) { - return false; - } - brb.readBits(3); - int protectionAbsent = brb.readBits(1); - brb.readBits(14); - int frameSize = brb.readBits(13); - int bufferFullness = brb.readBits(11); - int noBlocks = brb.readBits(2); - int used = (int) Math.ceil(brb.getPosition() / 8.0); - if (protectionAbsent == 0) { - used += 2; - } - inputStream.skip(used); - frameSize -= used; -// System.out.println("Size: " + frameSize + " fullness: " + bufferFullness + " no blocks: " + noBlocks); - byte[] data = new byte[frameSize]; - inputStream.read(data); - samples.add(ByteBuffer.wrap(data)); - stts.add(new TimeToSampleBox.Entry(1, 1024)); - inputStream.mark(15); - } - return ret; - } - - @Override - public String toString() { - return "AACTrackImpl{" + - "samplerate=" + samplerate + - ", bitrate=" + bitrate + - ", channelCount=" + channelCount + - ", channelconfig=" + channelconfig + - '}'; - } -} - diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AC3TrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AC3TrackImpl.java.svn-base deleted file mode 100644 index 5e5b2cd..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AC3TrackImpl.java.svn-base +++ /dev/null @@ -1,513 +0,0 @@ -package com.googlecode.mp4parser.authoring.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.AC3SpecificBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; - -import java.io.InputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -public class AC3TrackImpl extends AbstractTrack { - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - - int samplerate; - int bitrate; - int channelCount; - - int fscod; - int bsid; - int bsmod; - int acmod; - int lfeon; - int frmsizecod; - - int frameSize; - int[][][][] bitRateAndFrameSizeTable; - - private InputStream inputStream; - private List<ByteBuffer> samples; - boolean readSamples = false; - List<TimeToSampleBox.Entry> stts; - private String lang = "und"; - - public AC3TrackImpl(InputStream fin, String lang) throws IOException { - this.lang = lang; - parse(fin); - } - - public AC3TrackImpl(InputStream fin) throws IOException { - parse(fin); - } - - private void parse(InputStream fin) throws IOException { - inputStream = fin; - bitRateAndFrameSizeTable = new int[19][2][3][2]; - stts = new LinkedList<TimeToSampleBox.Entry>(); - initBitRateAndFrameSizeTable(); - if (!readVariables()) { - throw new IOException(); - } - - sampleDescriptionBox = new SampleDescriptionBox(); - AudioSampleEntry audioSampleEntry = new AudioSampleEntry("ac-3"); - audioSampleEntry.setChannelCount(2); // According to ETSI TS 102 366 Annex F - audioSampleEntry.setSampleRate(samplerate); - audioSampleEntry.setDataReferenceIndex(1); - audioSampleEntry.setSampleSize(16); - - AC3SpecificBox ac3 = new AC3SpecificBox(); - ac3.setAcmod(acmod); - ac3.setBitRateCode(frmsizecod >> 1); - ac3.setBsid(bsid); - ac3.setBsmod(bsmod); - ac3.setFscod(fscod); - ac3.setLfeon(lfeon); - ac3.setReserved(0); - - audioSampleEntry.addBox(ac3); - sampleDescriptionBox.addBox(audioSampleEntry); - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setLanguage(lang); - trackMetaData.setTimescale(samplerate); // Audio tracks always use samplerate as timescale - - samples = new LinkedList<ByteBuffer>(); - if (!readSamples()) { - throw new IOException(); - } - } - - - public List<ByteBuffer> getSamples() { - - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "soun"; - } - - public Box getMediaHeaderBox() { - return new SoundMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - - private boolean readVariables() throws IOException { - byte[] data = new byte[100]; - inputStream.mark(100); - if (100 != inputStream.read(data, 0, 100)) { - return false; - } - inputStream.reset(); // Rewind - ByteBuffer bb = ByteBuffer.wrap(data); - BitReaderBuffer brb = new BitReaderBuffer(bb); - int syncword = brb.readBits(16); - if (syncword != 0xb77) { - return false; - } - brb.readBits(16); // CRC-1 - fscod = brb.readBits(2); - - switch (fscod) { - case 0: - samplerate = 48000; - break; - - case 1: - samplerate = 44100; - break; - - case 2: - samplerate = 32000; - break; - - case 3: - samplerate = 0; - break; - - } - if (samplerate == 0) { - return false; - } - - frmsizecod = brb.readBits(6); - - if (!calcBitrateAndFrameSize(frmsizecod)) { - return false; - } - - if (frameSize == 0) { - return false; - } - bsid = brb.readBits(5); - bsmod = brb.readBits(3); - acmod = brb.readBits(3); - - if (bsid == 9) { - samplerate /= 2; - } else if (bsid != 8 && bsid != 6) { - return false; - } - - if ((acmod != 1) && ((acmod & 1) == 1)) { - brb.readBits(2); - } - - if (0 != (acmod & 4)) { - brb.readBits(2); - } - - if (acmod == 2) { - brb.readBits(2); - } - - switch (acmod) { - case 0: - channelCount = 2; - break; - - case 1: - channelCount = 1; - break; - - case 2: - channelCount = 2; - break; - - case 3: - channelCount = 3; - break; - - case 4: - channelCount = 3; - break; - - case 5: - channelCount = 4; - break; - - case 6: - channelCount = 4; - break; - - case 7: - channelCount = 5; - break; - - } - - lfeon = brb.readBits(1); - - if (lfeon == 1) { - channelCount++; - } - return true; - } - - private boolean calcBitrateAndFrameSize(int code) { - int frmsizecode = code >>> 1; - int flag = code & 1; - if (frmsizecode > 18 || flag > 1 || fscod > 2) { - return false; - } - bitrate = bitRateAndFrameSizeTable[frmsizecode][flag][fscod][0]; - frameSize = 2 * bitRateAndFrameSizeTable[frmsizecode][flag][fscod][1]; - return true; - } - - private boolean readSamples() throws IOException { - if (readSamples) { - return true; - } - readSamples = true; - byte[] header = new byte[5]; - boolean ret = false; - inputStream.mark(5); - while (-1 != inputStream.read(header)) { - ret = true; - int frmsizecode = header[4] & 63; - calcBitrateAndFrameSize(frmsizecode); - inputStream.reset(); - byte[] data = new byte[frameSize]; - inputStream.read(data); - samples.add(ByteBuffer.wrap(data)); - stts.add(new TimeToSampleBox.Entry(1, 1536)); - inputStream.mark(5); - } - return ret; - } - - private void initBitRateAndFrameSizeTable() { - // ETSI 102 366 Table 4.13, in frmsizecod, flag, fscod, bitrate/size order. Note that all sizes are in words, and all bitrates in kbps - - // 48kHz - bitRateAndFrameSizeTable[0][0][0][0] = 32; - bitRateAndFrameSizeTable[0][1][0][0] = 32; - bitRateAndFrameSizeTable[0][0][0][1] = 64; - bitRateAndFrameSizeTable[0][1][0][1] = 64; - bitRateAndFrameSizeTable[1][0][0][0] = 40; - bitRateAndFrameSizeTable[1][1][0][0] = 40; - bitRateAndFrameSizeTable[1][0][0][1] = 80; - bitRateAndFrameSizeTable[1][1][0][1] = 80; - bitRateAndFrameSizeTable[2][0][0][0] = 48; - bitRateAndFrameSizeTable[2][1][0][0] = 48; - bitRateAndFrameSizeTable[2][0][0][1] = 96; - bitRateAndFrameSizeTable[2][1][0][1] = 96; - bitRateAndFrameSizeTable[3][0][0][0] = 56; - bitRateAndFrameSizeTable[3][1][0][0] = 56; - bitRateAndFrameSizeTable[3][0][0][1] = 112; - bitRateAndFrameSizeTable[3][1][0][1] = 112; - bitRateAndFrameSizeTable[4][0][0][0] = 64; - bitRateAndFrameSizeTable[4][1][0][0] = 64; - bitRateAndFrameSizeTable[4][0][0][1] = 128; - bitRateAndFrameSizeTable[4][1][0][1] = 128; - bitRateAndFrameSizeTable[5][0][0][0] = 80; - bitRateAndFrameSizeTable[5][1][0][0] = 80; - bitRateAndFrameSizeTable[5][0][0][1] = 160; - bitRateAndFrameSizeTable[5][1][0][1] = 160; - bitRateAndFrameSizeTable[6][0][0][0] = 96; - bitRateAndFrameSizeTable[6][1][0][0] = 96; - bitRateAndFrameSizeTable[6][0][0][1] = 192; - bitRateAndFrameSizeTable[6][1][0][1] = 192; - bitRateAndFrameSizeTable[7][0][0][0] = 112; - bitRateAndFrameSizeTable[7][1][0][0] = 112; - bitRateAndFrameSizeTable[7][0][0][1] = 224; - bitRateAndFrameSizeTable[7][1][0][1] = 224; - bitRateAndFrameSizeTable[8][0][0][0] = 128; - bitRateAndFrameSizeTable[8][1][0][0] = 128; - bitRateAndFrameSizeTable[8][0][0][1] = 256; - bitRateAndFrameSizeTable[8][1][0][1] = 256; - bitRateAndFrameSizeTable[9][0][0][0] = 160; - bitRateAndFrameSizeTable[9][1][0][0] = 160; - bitRateAndFrameSizeTable[9][0][0][1] = 320; - bitRateAndFrameSizeTable[9][1][0][1] = 320; - bitRateAndFrameSizeTable[10][0][0][0] = 192; - bitRateAndFrameSizeTable[10][1][0][0] = 192; - bitRateAndFrameSizeTable[10][0][0][1] = 384; - bitRateAndFrameSizeTable[10][1][0][1] = 384; - bitRateAndFrameSizeTable[11][0][0][0] = 224; - bitRateAndFrameSizeTable[11][1][0][0] = 224; - bitRateAndFrameSizeTable[11][0][0][1] = 448; - bitRateAndFrameSizeTable[11][1][0][1] = 448; - bitRateAndFrameSizeTable[12][0][0][0] = 256; - bitRateAndFrameSizeTable[12][1][0][0] = 256; - bitRateAndFrameSizeTable[12][0][0][1] = 512; - bitRateAndFrameSizeTable[12][1][0][1] = 512; - bitRateAndFrameSizeTable[13][0][0][0] = 320; - bitRateAndFrameSizeTable[13][1][0][0] = 320; - bitRateAndFrameSizeTable[13][0][0][1] = 640; - bitRateAndFrameSizeTable[13][1][0][1] = 640; - bitRateAndFrameSizeTable[14][0][0][0] = 384; - bitRateAndFrameSizeTable[14][1][0][0] = 384; - bitRateAndFrameSizeTable[14][0][0][1] = 768; - bitRateAndFrameSizeTable[14][1][0][1] = 768; - bitRateAndFrameSizeTable[15][0][0][0] = 448; - bitRateAndFrameSizeTable[15][1][0][0] = 448; - bitRateAndFrameSizeTable[15][0][0][1] = 896; - bitRateAndFrameSizeTable[15][1][0][1] = 896; - bitRateAndFrameSizeTable[16][0][0][0] = 512; - bitRateAndFrameSizeTable[16][1][0][0] = 512; - bitRateAndFrameSizeTable[16][0][0][1] = 1024; - bitRateAndFrameSizeTable[16][1][0][1] = 1024; - bitRateAndFrameSizeTable[17][0][0][0] = 576; - bitRateAndFrameSizeTable[17][1][0][0] = 576; - bitRateAndFrameSizeTable[17][0][0][1] = 1152; - bitRateAndFrameSizeTable[17][1][0][1] = 1152; - bitRateAndFrameSizeTable[18][0][0][0] = 640; - bitRateAndFrameSizeTable[18][1][0][0] = 640; - bitRateAndFrameSizeTable[18][0][0][1] = 1280; - bitRateAndFrameSizeTable[18][1][0][1] = 1280; - - // 44.1 kHz - bitRateAndFrameSizeTable[0][0][1][0] = 32; - bitRateAndFrameSizeTable[0][1][1][0] = 32; - bitRateAndFrameSizeTable[0][0][1][1] = 69; - bitRateAndFrameSizeTable[0][1][1][1] = 70; - bitRateAndFrameSizeTable[1][0][1][0] = 40; - bitRateAndFrameSizeTable[1][1][1][0] = 40; - bitRateAndFrameSizeTable[1][0][1][1] = 87; - bitRateAndFrameSizeTable[1][1][1][1] = 88; - bitRateAndFrameSizeTable[2][0][1][0] = 48; - bitRateAndFrameSizeTable[2][1][1][0] = 48; - bitRateAndFrameSizeTable[2][0][1][1] = 104; - bitRateAndFrameSizeTable[2][1][1][1] = 105; - bitRateAndFrameSizeTable[3][0][1][0] = 56; - bitRateAndFrameSizeTable[3][1][1][0] = 56; - bitRateAndFrameSizeTable[3][0][1][1] = 121; - bitRateAndFrameSizeTable[3][1][1][1] = 122; - bitRateAndFrameSizeTable[4][0][1][0] = 64; - bitRateAndFrameSizeTable[4][1][1][0] = 64; - bitRateAndFrameSizeTable[4][0][1][1] = 139; - bitRateAndFrameSizeTable[4][1][1][1] = 140; - bitRateAndFrameSizeTable[5][0][1][0] = 80; - bitRateAndFrameSizeTable[5][1][1][0] = 80; - bitRateAndFrameSizeTable[5][0][1][1] = 174; - bitRateAndFrameSizeTable[5][1][1][1] = 175; - bitRateAndFrameSizeTable[6][0][1][0] = 96; - bitRateAndFrameSizeTable[6][1][1][0] = 96; - bitRateAndFrameSizeTable[6][0][1][1] = 208; - bitRateAndFrameSizeTable[6][1][1][1] = 209; - bitRateAndFrameSizeTable[7][0][1][0] = 112; - bitRateAndFrameSizeTable[7][1][1][0] = 112; - bitRateAndFrameSizeTable[7][0][1][1] = 243; - bitRateAndFrameSizeTable[7][1][1][1] = 244; - bitRateAndFrameSizeTable[8][0][1][0] = 128; - bitRateAndFrameSizeTable[8][1][1][0] = 128; - bitRateAndFrameSizeTable[8][0][1][1] = 278; - bitRateAndFrameSizeTable[8][1][1][1] = 279; - bitRateAndFrameSizeTable[9][0][1][0] = 160; - bitRateAndFrameSizeTable[9][1][1][0] = 160; - bitRateAndFrameSizeTable[9][0][1][1] = 348; - bitRateAndFrameSizeTable[9][1][1][1] = 349; - bitRateAndFrameSizeTable[10][0][1][0] = 192; - bitRateAndFrameSizeTable[10][1][1][0] = 192; - bitRateAndFrameSizeTable[10][0][1][1] = 417; - bitRateAndFrameSizeTable[10][1][1][1] = 418; - bitRateAndFrameSizeTable[11][0][1][0] = 224; - bitRateAndFrameSizeTable[11][1][1][0] = 224; - bitRateAndFrameSizeTable[11][0][1][1] = 487; - bitRateAndFrameSizeTable[11][1][1][1] = 488; - bitRateAndFrameSizeTable[12][0][1][0] = 256; - bitRateAndFrameSizeTable[12][1][1][0] = 256; - bitRateAndFrameSizeTable[12][0][1][1] = 557; - bitRateAndFrameSizeTable[12][1][1][1] = 558; - bitRateAndFrameSizeTable[13][0][1][0] = 320; - bitRateAndFrameSizeTable[13][1][1][0] = 320; - bitRateAndFrameSizeTable[13][0][1][1] = 696; - bitRateAndFrameSizeTable[13][1][1][1] = 697; - bitRateAndFrameSizeTable[14][0][1][0] = 384; - bitRateAndFrameSizeTable[14][1][1][0] = 384; - bitRateAndFrameSizeTable[14][0][1][1] = 835; - bitRateAndFrameSizeTable[14][1][1][1] = 836; - bitRateAndFrameSizeTable[15][0][1][0] = 448; - bitRateAndFrameSizeTable[15][1][1][0] = 448; - bitRateAndFrameSizeTable[15][0][1][1] = 975; - bitRateAndFrameSizeTable[15][1][1][1] = 975; - bitRateAndFrameSizeTable[16][0][1][0] = 512; - bitRateAndFrameSizeTable[16][1][1][0] = 512; - bitRateAndFrameSizeTable[16][0][1][1] = 1114; - bitRateAndFrameSizeTable[16][1][1][1] = 1115; - bitRateAndFrameSizeTable[17][0][1][0] = 576; - bitRateAndFrameSizeTable[17][1][1][0] = 576; - bitRateAndFrameSizeTable[17][0][1][1] = 1253; - bitRateAndFrameSizeTable[17][1][1][1] = 1254; - bitRateAndFrameSizeTable[18][0][1][0] = 640; - bitRateAndFrameSizeTable[18][1][1][0] = 640; - bitRateAndFrameSizeTable[18][0][1][1] = 1393; - bitRateAndFrameSizeTable[18][1][1][1] = 1394; - - // 32kHz - bitRateAndFrameSizeTable[0][0][2][0] = 32; - bitRateAndFrameSizeTable[0][1][2][0] = 32; - bitRateAndFrameSizeTable[0][0][2][1] = 96; - bitRateAndFrameSizeTable[0][1][2][1] = 96; - bitRateAndFrameSizeTable[1][0][2][0] = 40; - bitRateAndFrameSizeTable[1][1][2][0] = 40; - bitRateAndFrameSizeTable[1][0][2][1] = 120; - bitRateAndFrameSizeTable[1][1][2][1] = 120; - bitRateAndFrameSizeTable[2][0][2][0] = 48; - bitRateAndFrameSizeTable[2][1][2][0] = 48; - bitRateAndFrameSizeTable[2][0][2][1] = 144; - bitRateAndFrameSizeTable[2][1][2][1] = 144; - bitRateAndFrameSizeTable[3][0][2][0] = 56; - bitRateAndFrameSizeTable[3][1][2][0] = 56; - bitRateAndFrameSizeTable[3][0][2][1] = 168; - bitRateAndFrameSizeTable[3][1][2][1] = 168; - bitRateAndFrameSizeTable[4][0][2][0] = 64; - bitRateAndFrameSizeTable[4][1][2][0] = 64; - bitRateAndFrameSizeTable[4][0][2][1] = 192; - bitRateAndFrameSizeTable[4][1][2][1] = 192; - bitRateAndFrameSizeTable[5][0][2][0] = 80; - bitRateAndFrameSizeTable[5][1][2][0] = 80; - bitRateAndFrameSizeTable[5][0][2][1] = 240; - bitRateAndFrameSizeTable[5][1][2][1] = 240; - bitRateAndFrameSizeTable[6][0][2][0] = 96; - bitRateAndFrameSizeTable[6][1][2][0] = 96; - bitRateAndFrameSizeTable[6][0][2][1] = 288; - bitRateAndFrameSizeTable[6][1][2][1] = 288; - bitRateAndFrameSizeTable[7][0][2][0] = 112; - bitRateAndFrameSizeTable[7][1][2][0] = 112; - bitRateAndFrameSizeTable[7][0][2][1] = 336; - bitRateAndFrameSizeTable[7][1][2][1] = 336; - bitRateAndFrameSizeTable[8][0][2][0] = 128; - bitRateAndFrameSizeTable[8][1][2][0] = 128; - bitRateAndFrameSizeTable[8][0][2][1] = 384; - bitRateAndFrameSizeTable[8][1][2][1] = 384; - bitRateAndFrameSizeTable[9][0][2][0] = 160; - bitRateAndFrameSizeTable[9][1][2][0] = 160; - bitRateAndFrameSizeTable[9][0][2][1] = 480; - bitRateAndFrameSizeTable[9][1][2][1] = 480; - bitRateAndFrameSizeTable[10][0][2][0] = 192; - bitRateAndFrameSizeTable[10][1][2][0] = 192; - bitRateAndFrameSizeTable[10][0][2][1] = 576; - bitRateAndFrameSizeTable[10][1][2][1] = 576; - bitRateAndFrameSizeTable[11][0][2][0] = 224; - bitRateAndFrameSizeTable[11][1][2][0] = 224; - bitRateAndFrameSizeTable[11][0][2][1] = 672; - bitRateAndFrameSizeTable[11][1][2][1] = 672; - bitRateAndFrameSizeTable[12][0][2][0] = 256; - bitRateAndFrameSizeTable[12][1][2][0] = 256; - bitRateAndFrameSizeTable[12][0][2][1] = 768; - bitRateAndFrameSizeTable[12][1][2][1] = 768; - bitRateAndFrameSizeTable[13][0][2][0] = 320; - bitRateAndFrameSizeTable[13][1][2][0] = 320; - bitRateAndFrameSizeTable[13][0][2][1] = 960; - bitRateAndFrameSizeTable[13][1][2][1] = 960; - bitRateAndFrameSizeTable[14][0][2][0] = 384; - bitRateAndFrameSizeTable[14][1][2][0] = 384; - bitRateAndFrameSizeTable[14][0][2][1] = 1152; - bitRateAndFrameSizeTable[14][1][2][1] = 1152; - bitRateAndFrameSizeTable[15][0][2][0] = 448; - bitRateAndFrameSizeTable[15][1][2][0] = 448; - bitRateAndFrameSizeTable[15][0][2][1] = 1344; - bitRateAndFrameSizeTable[15][1][2][1] = 1344; - bitRateAndFrameSizeTable[16][0][2][0] = 512; - bitRateAndFrameSizeTable[16][1][2][0] = 512; - bitRateAndFrameSizeTable[16][0][2][1] = 1536; - bitRateAndFrameSizeTable[16][1][2][1] = 1536; - bitRateAndFrameSizeTable[17][0][2][0] = 576; - bitRateAndFrameSizeTable[17][1][2][0] = 576; - bitRateAndFrameSizeTable[17][0][2][1] = 1728; - bitRateAndFrameSizeTable[17][1][2][1] = 1728; - bitRateAndFrameSizeTable[18][0][2][0] = 640; - bitRateAndFrameSizeTable[18][1][2][0] = 640; - bitRateAndFrameSizeTable[18][0][2][1] = 1920; - bitRateAndFrameSizeTable[18][1][2][1] = 1920; - } -}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/Amf0Track.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/Amf0Track.java.svn-base deleted file mode 100644 index 0917767..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/Amf0Track.java.svn-base +++ /dev/null @@ -1,116 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.adobe.ActionMessageFormat0SampleEntryBox; - -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -public class Amf0Track extends AbstractTrack { - SortedMap<Long, byte[]> rawSamples = new TreeMap<Long, byte[]>() { - }; - private TrackMetaData trackMetaData = new TrackMetaData(); - - - /** - * Creates a new AMF0 track from - * - * @param rawSamples - */ - public Amf0Track(Map<Long, byte[]> rawSamples) { - this.rawSamples = new TreeMap<Long, byte[]>(rawSamples); - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setTimescale(1000); // Text tracks use millieseconds - trackMetaData.setLanguage("eng"); - } - - public List<ByteBuffer> getSamples() { - LinkedList<ByteBuffer> samples = new LinkedList<ByteBuffer>(); - for (byte[] bytes : rawSamples.values()) { - samples.add(ByteBuffer.wrap(bytes)); - } - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - SampleDescriptionBox stsd = new SampleDescriptionBox(); - ActionMessageFormat0SampleEntryBox amf0 = new ActionMessageFormat0SampleEntryBox(); - amf0.setDataReferenceIndex(1); - stsd.addBox(amf0); - return stsd; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - LinkedList<TimeToSampleBox.Entry> timesToSample = new LinkedList<TimeToSampleBox.Entry>(); - LinkedList<Long> keys = new LinkedList<Long>(rawSamples.keySet()); - Collections.sort(keys); - long lastTimeStamp = 0; - for (Long key : keys) { - long delta = key - lastTimeStamp; - if (timesToSample.size() > 0 && timesToSample.peek().getDelta() == delta) { - timesToSample.peek().setCount(timesToSample.peek().getCount() + 1); - } else { - timesToSample.add(new TimeToSampleBox.Entry(1, delta)); - } - lastTimeStamp = key; - } - return timesToSample; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - // AMF0 tracks do not have Composition Time - return null; - } - - public long[] getSyncSamples() { - // AMF0 tracks do not have Sync Samples - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - // AMF0 tracks do not have Sample Dependencies - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; //To change body of implemented methods use File | Settings | File Templates. - } - - public String getHandler() { - return "data"; - } - - public Box getMediaHeaderBox() { - return new NullMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AppendTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AppendTrack.java.svn-base deleted file mode 100644 index 93ee0cd..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/AppendTrack.java.svn-base +++ /dev/null @@ -1,348 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.DecoderConfigDescriptor; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.util.*; - -/** - * 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; - SampleDescriptionBox stsd; - - public AppendTrack(Track... tracks) throws IOException { - this.tracks = tracks; - - for (Track track : tracks) { - - if (stsd == null) { - stsd = track.getSampleDescriptionBox(); - } else { - ByteArrayOutputStream curBaos = new ByteArrayOutputStream(); - ByteArrayOutputStream refBaos = new ByteArrayOutputStream(); - track.getSampleDescriptionBox().getBox(Channels.newChannel(curBaos)); - stsd.getBox(Channels.newChannel(refBaos)); - byte[] cur = curBaos.toByteArray(); - byte[] ref = refBaos.toByteArray(); - - if (!Arrays.equals(ref, cur)) { - SampleDescriptionBox curStsd = track.getSampleDescriptionBox(); - if (stsd.getBoxes().size() == 1 && curStsd.getBoxes().size() == 1) { - if (stsd.getBoxes().get(0) instanceof AudioSampleEntry && curStsd.getBoxes().get(0) instanceof AudioSampleEntry) { - AudioSampleEntry aseResult = mergeAudioSampleEntries((AudioSampleEntry) stsd.getBoxes().get(0), (AudioSampleEntry) curStsd.getBoxes().get(0)); - if (aseResult != null) { - stsd.setBoxes(Collections.<Box>singletonList(aseResult)); - return; - } - } - } - throw new IOException("Cannot append " + track + " to " + tracks[0] + " since their Sample Description Boxes differ: \n" + track.getSampleDescriptionBox() + "\n vs. \n" + tracks[0].getSampleDescriptionBox()); - } - } - } - } - - private AudioSampleEntry mergeAudioSampleEntries(AudioSampleEntry ase1, AudioSampleEntry ase2) throws IOException { - if (ase1.getType().equals(ase2.getType())) { - AudioSampleEntry ase = new AudioSampleEntry(ase2.getType()); - if (ase1.getBytesPerFrame() == ase2.getBytesPerFrame()) { - ase.setBytesPerFrame(ase1.getBytesPerFrame()); - } else { - return null; - } - if (ase1.getBytesPerPacket() == ase2.getBytesPerPacket()) { - ase.setBytesPerPacket(ase1.getBytesPerPacket()); - } else { - return null; - } - if (ase1.getBytesPerSample() == ase2.getBytesPerSample()) { - ase.setBytesPerSample(ase1.getBytesPerSample()); - } else { - return null; - } - if (ase1.getChannelCount() == ase2.getChannelCount()) { - ase.setChannelCount(ase1.getChannelCount()); - } else { - return null; - } - if (ase1.getPacketSize() == ase2.getPacketSize()) { - ase.setPacketSize(ase1.getPacketSize()); - } else { - return null; - } - if (ase1.getCompressionId() == ase2.getCompressionId()) { - ase.setCompressionId(ase1.getCompressionId()); - } else { - return null; - } - if (ase1.getSampleRate() == ase2.getSampleRate()) { - ase.setSampleRate(ase1.getSampleRate()); - } else { - return null; - } - if (ase1.getSampleSize() == ase2.getSampleSize()) { - ase.setSampleSize(ase1.getSampleSize()); - } else { - return null; - } - if (ase1.getSamplesPerPacket() == ase2.getSamplesPerPacket()) { - ase.setSamplesPerPacket(ase1.getSamplesPerPacket()); - } else { - return null; - } - if (ase1.getSoundVersion() == ase2.getSoundVersion()) { - ase.setSoundVersion(ase1.getSoundVersion()); - } else { - return null; - } - if (Arrays.equals(ase1.getSoundVersion2Data(), ase2.getSoundVersion2Data())) { - ase.setSoundVersion2Data(ase1.getSoundVersion2Data()); - } else { - return null; - } - if (ase1.getBoxes().size() == ase2.getBoxes().size()) { - Iterator<Box> bxs1 = ase1.getBoxes().iterator(); - Iterator<Box> bxs2 = ase2.getBoxes().iterator(); - while (bxs1.hasNext()) { - Box cur1 = bxs1.next(); - Box cur2 = bxs2.next(); - ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - cur1.getBox(Channels.newChannel(baos1)); - cur2.getBox(Channels.newChannel(baos2)); - if (Arrays.equals(baos1.toByteArray(), baos2.toByteArray())) { - ase.addBox(cur1); - } else { - if (ESDescriptorBox.TYPE.equals(cur1.getType()) && ESDescriptorBox.TYPE.equals(cur2.getType())) { - ESDescriptorBox esdsBox1 = (ESDescriptorBox) cur1; - ESDescriptorBox esdsBox2 = (ESDescriptorBox) cur2; - ESDescriptor esds1 = esdsBox1.getEsDescriptor(); - ESDescriptor esds2 = esdsBox2.getEsDescriptor(); - if (esds1.getURLFlag() != esds2.getURLFlag()) { - return null; - } - if (esds1.getURLLength() != esds2.getURLLength()) { - return null; - } - if (esds1.getDependsOnEsId() != esds2.getDependsOnEsId()) { - return null; - } - if (esds1.getEsId() != esds2.getEsId()) { - return null; - } - if (esds1.getoCREsId() != esds2.getoCREsId()) { - return null; - } - if (esds1.getoCRstreamFlag() != esds2.getoCRstreamFlag()) { - return null; - } - if (esds1.getRemoteODFlag() != esds2.getRemoteODFlag()) { - return null; - } - if (esds1.getStreamDependenceFlag() != esds2.getStreamDependenceFlag()) { - return null; - } - if (esds1.getStreamPriority() != esds2.getStreamPriority()) { - return null; - } - if (esds1.getURLString() != null ? !esds1.getURLString().equals(esds2.getURLString()) : esds2.getURLString() != null) { - return null; - } - if (esds1.getDecoderConfigDescriptor() != null ? !esds1.getDecoderConfigDescriptor().equals(esds2.getDecoderConfigDescriptor()) : esds2.getDecoderConfigDescriptor() != null) { - DecoderConfigDescriptor dcd1 = esds1.getDecoderConfigDescriptor(); - DecoderConfigDescriptor dcd2 = esds2.getDecoderConfigDescriptor(); - if (!dcd1.getAudioSpecificInfo().equals(dcd2.getAudioSpecificInfo())) { - return null; - } - if (dcd1.getAvgBitRate() != dcd2.getAvgBitRate()) { - // I don't care - } - if (dcd1.getBufferSizeDB() != dcd2.getBufferSizeDB()) { - // I don't care - } - - if (dcd1.getDecoderSpecificInfo() != null ? !dcd1.getDecoderSpecificInfo().equals(dcd2.getDecoderSpecificInfo()) : dcd2.getDecoderSpecificInfo() != null) { - return null; - } - - if (dcd1.getMaxBitRate() != dcd2.getMaxBitRate()) { - // I don't care - } - if (!dcd1.getProfileLevelIndicationDescriptors().equals(dcd2.getProfileLevelIndicationDescriptors())) { - return null; - } - - if (dcd1.getObjectTypeIndication() != dcd2.getObjectTypeIndication()) { - return null; - } - if (dcd1.getStreamType() != dcd2.getStreamType()) { - return null; - } - if (dcd1.getUpStream() != dcd2.getUpStream()) { - return null; - } - - - } - if (esds1.getOtherDescriptors() != null ? !esds1.getOtherDescriptors().equals(esds2.getOtherDescriptors()) : esds2.getOtherDescriptors() != null) { - return null; - } - if (esds1.getSlConfigDescriptor() != null ? !esds1.getSlConfigDescriptor().equals(esds2.getSlConfigDescriptor()) : esds2.getSlConfigDescriptor() != null) { - return null; - } - ase.addBox(cur1); - } - } - } - } - return ase; - } else { - return null; - } - - - } - - - public List<ByteBuffer> getSamples() { - ArrayList<ByteBuffer> lists = new ArrayList<ByteBuffer>(); - - for (Track track : tracks) { - lists.addAll(track.getSamples()); - } - - return lists; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return stsd; - } - - 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 Box getMediaHeaderBox() { - return tracks[0].getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return tracks[0].getSubsampleInformationBox(); - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ChangeTimeScaleTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ChangeTimeScaleTrack.java.svn-base deleted file mode 100644 index 50f76c2..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ChangeTimeScaleTrack.java.svn-base +++ /dev/null @@ -1,203 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.TrackMetaData; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.logging.Logger; - -/** - * Changes the timescale of a track by wrapping the track. - */ -public class ChangeTimeScaleTrack implements Track { - private static final Logger LOG = Logger.getLogger(ChangeTimeScaleTrack.class.getName()); - - Track source; - List<CompositionTimeToSample.Entry> ctts; - List<TimeToSampleBox.Entry> tts; - long timeScale; - - /** - * Changes the time scale of the source track to the target time scale and makes sure - * that any rounding errors that may have summed are corrected exactly before the syncSamples. - * - * @param source the source track - * @param targetTimeScale the resulting time scale of this track. - * @param syncSamples at these sync points where rounding error are corrected. - */ - public ChangeTimeScaleTrack(Track source, long targetTimeScale, long[] syncSamples) { - this.source = source; - this.timeScale = targetTimeScale; - double timeScaleFactor = (double) targetTimeScale / source.getTrackMetaData().getTimescale(); - ctts = adjustCtts(source.getCompositionTimeEntries(), timeScaleFactor); - tts = adjustTts(source.getDecodingTimeEntries(), timeScaleFactor, syncSamples, getTimes(source, syncSamples, targetTimeScale)); - } - - private static long[] getTimes(Track track, long[] syncSamples, long targetTimeScale) { - 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; - - - while (currentSample <= syncSamples[syncSamples.length - 1]) { - if (currentSample++ == syncSamples[currentSyncSampleIndex]) { - syncSampleTimes[currentSyncSampleIndex++] = (currentDuration * targetTimeScale) / track.getTrackMetaData().getTimescale(); - } - if (left-- == 0) { - TimeToSampleBox.Entry entry = timeQueue.poll(); - left = entry.getCount() - 1; - currentDelta = entry.getDelta(); - } - currentDuration += currentDelta; - } - return syncSampleTimes; - - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return source.getSampleDescriptionBox(); - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return tts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return ctts; - } - - public long[] getSyncSamples() { - return source.getSyncSamples(); - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return source.getSampleDependencies(); - } - - public TrackMetaData getTrackMetaData() { - TrackMetaData trackMetaData = (TrackMetaData) source.getTrackMetaData().clone(); - trackMetaData.setTimescale(timeScale); - return trackMetaData; - } - - public String getHandler() { - return source.getHandler(); - } - - public boolean isEnabled() { - return source.isEnabled(); - } - - public boolean isInMovie() { - return source.isInMovie(); - } - - public boolean isInPreview() { - return source.isInPreview(); - } - - public boolean isInPoster() { - return source.isInPoster(); - } - - public List<ByteBuffer> getSamples() { - return source.getSamples(); - } - - - /** - * Adjusting the composition times is easy. Just scale it by the factor - that's it. There is no rounding - * error summing up. - * - * @param source - * @param timeScaleFactor - * @return - */ - static List<CompositionTimeToSample.Entry> adjustCtts(List<CompositionTimeToSample.Entry> source, double timeScaleFactor) { - if (source != null) { - List<CompositionTimeToSample.Entry> entries2 = new ArrayList<CompositionTimeToSample.Entry>(source.size()); - for (CompositionTimeToSample.Entry entry : source) { - entries2.add(new CompositionTimeToSample.Entry(entry.getCount(), (int) Math.round(timeScaleFactor * entry.getOffset()))); - } - return entries2; - } else { - return null; - } - } - - static List<TimeToSampleBox.Entry> adjustTts(List<TimeToSampleBox.Entry> source, double timeScaleFactor, long[] syncSample, long[] syncSampleTimes) { - - long[] sourceArray = TimeToSampleBox.blowupTimeToSamples(source); - long summedDurations = 0; - - LinkedList<TimeToSampleBox.Entry> entries2 = new LinkedList<TimeToSampleBox.Entry>(); - for (int i = 1; i <= sourceArray.length; i++) { - long duration = sourceArray[i - 1]; - - long x = Math.round(timeScaleFactor * duration); - - - TimeToSampleBox.Entry last = entries2.peekLast(); - int ssIndex; - if ((ssIndex = Arrays.binarySearch(syncSample, i + 1)) >= 0) { - // we are at the sample before sync point - if (syncSampleTimes[ssIndex] != summedDurations) { - long correction = syncSampleTimes[ssIndex] - (summedDurations + x); - LOG.finest(String.format("Sample %d %d / %d - correct by %d", i, summedDurations, syncSampleTimes[ssIndex], correction)); - x += correction; - } - } - summedDurations += x; - if (last == null) { - entries2.add(new TimeToSampleBox.Entry(1, x)); - } else if (last.getDelta() != x) { - entries2.add(new TimeToSampleBox.Entry(1, x)); - } else { - last.setCount(last.getCount() + 1); - } - - } - return entries2; - } - - public Box getMediaHeaderBox() { - return source.getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return source.getSubsampleInformationBox(); - } - - @Override - public String toString() { - return "ChangeTimeScaleTrack{" + - "source=" + source + - '}'; - } -}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/CroppedTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/CroppedTrack.java.svn-base deleted file mode 100644 index 2389961..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/CroppedTrack.java.svn-base +++ /dev/null @@ -1,151 +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.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(); - } - -}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/DivideTimeScaleTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/DivideTimeScaleTrack.java.svn-base deleted file mode 100644 index c51e8e0..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/DivideTimeScaleTrack.java.svn-base +++ /dev/null @@ -1,126 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.TrackMetaData; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -/** - * Changes the timescale of a track by wrapping the track. - */ -public class DivideTimeScaleTrack implements Track { - Track source; - private int timeScaleDivisor; - - public DivideTimeScaleTrack(Track source, int timeScaleDivisor) { - this.source = source; - this.timeScaleDivisor = timeScaleDivisor; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return source.getSampleDescriptionBox(); - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return adjustTts(); - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return adjustCtts(); - } - - public long[] getSyncSamples() { - return source.getSyncSamples(); - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return source.getSampleDependencies(); - } - - public TrackMetaData getTrackMetaData() { - TrackMetaData trackMetaData = (TrackMetaData) source.getTrackMetaData().clone(); - trackMetaData.setTimescale(source.getTrackMetaData().getTimescale() / this.timeScaleDivisor); - return trackMetaData; - } - - public String getHandler() { - return source.getHandler(); - } - - public boolean isEnabled() { - return source.isEnabled(); - } - - public boolean isInMovie() { - return source.isInMovie(); - } - - public boolean isInPreview() { - return source.isInPreview(); - } - - public boolean isInPoster() { - return source.isInPoster(); - } - - public List<ByteBuffer> getSamples() { - return source.getSamples(); - } - - - List<CompositionTimeToSample.Entry> adjustCtts() { - List<CompositionTimeToSample.Entry> origCtts = this.source.getCompositionTimeEntries(); - if (origCtts != null) { - List<CompositionTimeToSample.Entry> entries2 = new ArrayList<CompositionTimeToSample.Entry>(origCtts.size()); - for (CompositionTimeToSample.Entry entry : origCtts) { - entries2.add(new CompositionTimeToSample.Entry(entry.getCount(), entry.getOffset() / timeScaleDivisor)); - } - return entries2; - } else { - return null; - } - } - - List<TimeToSampleBox.Entry> adjustTts() { - List<TimeToSampleBox.Entry> origTts = source.getDecodingTimeEntries(); - LinkedList<TimeToSampleBox.Entry> entries2 = new LinkedList<TimeToSampleBox.Entry>(); - for (TimeToSampleBox.Entry e : origTts) { - entries2.add(new TimeToSampleBox.Entry(e.getCount(), e.getDelta() / timeScaleDivisor)); - } - return entries2; - } - - public Box getMediaHeaderBox() { - return source.getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return source.getSubsampleInformationBox(); - } - - @Override - public String toString() { - return "MultiplyTimeScaleTrack{" + - "source=" + source + - '}'; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/EC3TrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/EC3TrackImpl.java.svn-base deleted file mode 100644 index d0b2d76..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/EC3TrackImpl.java.svn-base +++ /dev/null @@ -1,436 +0,0 @@ -package com.googlecode.mp4parser.authoring.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.EC3SpecificBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -/** - * Created by IntelliJ IDEA. - * User: magnus - * Date: 2012-03-14 - * Time: 10:39 - * To change this template use File | Settings | File Templates. - */ -public class EC3TrackImpl extends AbstractTrack { - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - - int samplerate; - int bitrate; - int frameSize; - - List<BitStreamInfo> entries = new LinkedList<BitStreamInfo>(); - - private BufferedInputStream inputStream; - private List<ByteBuffer> samples; - List<TimeToSampleBox.Entry> stts = new LinkedList<TimeToSampleBox.Entry>(); - private String lang = "und"; - - public EC3TrackImpl(InputStream fin, String lang) throws IOException { - this.lang = lang; - parse(fin); - } - - public EC3TrackImpl(InputStream fin) throws IOException { - parse(fin); - } - - private void parse(InputStream fin) throws IOException { - inputStream = new BufferedInputStream(fin); - - boolean done = false; - inputStream.mark(10000); - while (!done) { - BitStreamInfo bsi = readVariables(); - if (bsi == null) { - throw new IOException(); - } - for (BitStreamInfo entry : entries) { - if (bsi.strmtyp != 1 && entry.substreamid == bsi.substreamid) { - done = true; - } - } - if (!done) { - entries.add(bsi); - long skipped = inputStream.skip(bsi.frameSize); - assert skipped == bsi.frameSize; - } - } - - inputStream.reset(); - - if (entries.size() == 0) { - throw new IOException(); - } - samplerate = entries.get(0).samplerate; - - sampleDescriptionBox = new SampleDescriptionBox(); - AudioSampleEntry audioSampleEntry = new AudioSampleEntry("ec-3"); - audioSampleEntry.setChannelCount(2); // According to ETSI TS 102 366 Annex F - audioSampleEntry.setSampleRate(samplerate); - audioSampleEntry.setDataReferenceIndex(1); - audioSampleEntry.setSampleSize(16); - - EC3SpecificBox ec3 = new EC3SpecificBox(); - int[] deps = new int[entries.size()]; - int[] chan_locs = new int[entries.size()]; - for (BitStreamInfo bsi : entries) { - if (bsi.strmtyp == 1) { - deps[bsi.substreamid]++; - chan_locs[bsi.substreamid] = ((bsi.chanmap >> 6) & 0x100) | ((bsi.chanmap >> 5) & 0xff); - } - } - for (BitStreamInfo bsi : entries) { - if (bsi.strmtyp != 1) { - EC3SpecificBox.Entry e = new EC3SpecificBox.Entry(); - e.fscod = bsi.fscod; - e.bsid = bsi.bsid; - e.bsmod = bsi.bsmod; - e.acmod = bsi.acmod; - e.lfeon = bsi.lfeon; - e.reserved = 0; - e.num_dep_sub = deps[bsi.substreamid]; - e.chan_loc = chan_locs[bsi.substreamid]; - e.reserved2 = 0; - ec3.addEntry(e); - } - bitrate += bsi.bitrate; - frameSize += bsi.frameSize; - } - - ec3.setDataRate(bitrate / 1000); - audioSampleEntry.addBox(ec3); - sampleDescriptionBox.addBox(audioSampleEntry); - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setLanguage(lang); - trackMetaData.setTimescale(samplerate); // Audio tracks always use samplerate as timescale - - samples = new LinkedList<ByteBuffer>(); - if (!readSamples()) { - throw new IOException(); - } - } - - - public List<ByteBuffer> getSamples() { - - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "soun"; - } - - public AbstractMediaHeaderBox getMediaHeaderBox() { - return new SoundMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - - private BitStreamInfo readVariables() throws IOException { - byte[] data = new byte[200]; - inputStream.mark(200); - if (200 != inputStream.read(data, 0, 200)) { - return null; - } - inputStream.reset(); // Rewind - ByteBuffer bb = ByteBuffer.wrap(data); - BitReaderBuffer brb = new BitReaderBuffer(bb); - int syncword = brb.readBits(16); - if (syncword != 0xb77) { - return null; - } - - BitStreamInfo entry = new BitStreamInfo(); - - entry.strmtyp = brb.readBits(2); - entry.substreamid = brb.readBits(3); - int frmsiz = brb.readBits(11); - entry.frameSize = 2 * (frmsiz + 1); - - entry.fscod = brb.readBits(2); - int fscod2 = -1; - int numblkscod; - if (entry.fscod == 3) { - fscod2 = brb.readBits(2); - numblkscod = 3; - } else { - numblkscod = brb.readBits(2); - } - int numberOfBlocksPerSyncFrame = 0; - switch (numblkscod) { - case 0: - numberOfBlocksPerSyncFrame = 1; - break; - - case 1: - numberOfBlocksPerSyncFrame = 2; - break; - - case 2: - numberOfBlocksPerSyncFrame = 3; - break; - - case 3: - numberOfBlocksPerSyncFrame = 6; - break; - - } - entry.frameSize *= (6 / numberOfBlocksPerSyncFrame); - - entry.acmod = brb.readBits(3); - entry.lfeon = brb.readBits(1); - entry.bsid = brb.readBits(5); - brb.readBits(5); - if (1 == brb.readBits(1)) { - brb.readBits(8); // compr - } - if (0 == entry.acmod) { - brb.readBits(5); - if (1 == brb.readBits(1)) { - brb.readBits(8); - } - } - if (1 == entry.strmtyp) { - if (1 == brb.readBits(1)) { - entry.chanmap = brb.readBits(16); - } - } - if (1 == brb.readBits(1)) { // mixing metadata - if (entry.acmod > 2) { - brb.readBits(2); - } - if (1 == (entry.acmod & 1) && entry.acmod > 2) { - brb.readBits(3); - brb.readBits(3); - } - if (0 < (entry.acmod & 4)) { - brb.readBits(3); - brb.readBits(3); - } - if (1 == entry.lfeon) { - if (1 == brb.readBits(1)) { - brb.readBits(5); - } - } - if (0 == entry.strmtyp) { - if (1 == brb.readBits(1)) { - brb.readBits(6); - } - if (0 == entry.acmod) { - if (1 == brb.readBits(1)) { - brb.readBits(6); - } - } - if (1 == brb.readBits(1)) { - brb.readBits(6); - } - int mixdef = brb.readBits(2); - if (1 == mixdef) { - brb.readBits(5); - } else if (2 == mixdef) { - brb.readBits(12); - } else if (3 == mixdef) { - int mixdeflen = brb.readBits(5); - if (1 == brb.readBits(1)) { - brb.readBits(5); - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - if (1 == brb.readBits(1)) { - brb.readBits(4); - } - } - } - if (1 == brb.readBits(1)) { - brb.readBits(5); - if (1 == brb.readBits(1)) { - brb.readBits(7); - if (1 == brb.readBits(1)) { - brb.readBits(8); - } - } - } - for (int i = 0; i < (mixdeflen + 2); i++) { - brb.readBits(8); - } - brb.byteSync(); - } - if (entry.acmod < 2) { - if (1 == brb.readBits(1)) { - brb.readBits(14); - } - if (0 == entry.acmod) { - if (1 == brb.readBits(1)) { - brb.readBits(14); - } - } - if (1 == brb.readBits(1)) { - if (numblkscod == 0) { - brb.readBits(5); - } else { - for (int i = 0; i < numberOfBlocksPerSyncFrame; i++) { - if (1 == brb.readBits(1)) { - brb.readBits(5); - } - } - } - - } - } - } - } - if (1 == brb.readBits(1)) { // infomdate - entry.bsmod = brb.readBits(3); - } - - switch (entry.fscod) { - case 0: - entry.samplerate = 48000; - break; - - case 1: - entry.samplerate = 44100; - break; - - case 2: - entry.samplerate = 32000; - break; - - case 3: { - switch (fscod2) { - case 0: - entry.samplerate = 24000; - break; - - case 1: - entry.samplerate = 22050; - break; - - case 2: - entry.samplerate = 16000; - break; - - case 3: - entry.samplerate = 0; - break; - } - break; - } - - } - if (entry.samplerate == 0) { - return null; - } - - entry.bitrate = (int) (((double) entry.samplerate) / 1536.0 * entry.frameSize * 8); - - return entry; - } - - private boolean readSamples() throws IOException { - int read = frameSize; - boolean ret = false; - while (frameSize == read) { - ret = true; - byte[] data = new byte[frameSize]; - read = inputStream.read(data); - if (read == frameSize) { - samples.add(ByteBuffer.wrap(data)); - stts.add(new TimeToSampleBox.Entry(1, 1536)); - } - } - return ret; - } - - public static class BitStreamInfo extends EC3SpecificBox.Entry { - public int frameSize; - public int substreamid; - public int bitrate; - public int samplerate; - public int strmtyp; - public int chanmap; - - @Override - public String toString() { - return "BitStreamInfo{" + - "frameSize=" + frameSize + - ", substreamid=" + substreamid + - ", bitrate=" + bitrate + - ", samplerate=" + samplerate + - ", strmtyp=" + strmtyp + - ", chanmap=" + chanmap + - '}'; - } - } - - @Override - public String toString() { - return "EC3TrackImpl{" + - "bitrate=" + bitrate + - ", samplerate=" + samplerate + - ", entries=" + entries + - '}'; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/H264TrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/H264TrackImpl.java.svn-base deleted file mode 100644 index b3c1866..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/H264TrackImpl.java.svn-base +++ /dev/null @@ -1,740 +0,0 @@ -package com.googlecode.mp4parser.authoring.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.h264.AvcConfigurationBox; -import com.coremedia.iso.boxes.sampleentry.VisualSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.h264.model.PictureParameterSet; -import com.googlecode.mp4parser.h264.model.SeqParameterSet; -import com.googlecode.mp4parser.h264.read.CAVLCReader; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Logger; - -/** - * The <code>H264TrackImpl</code> creates a <code>Track</code> from an H.264 - * Annex B file. - */ -public class H264TrackImpl extends AbstractTrack { - private static final Logger LOG = Logger.getLogger(H264TrackImpl.class.getName()); - - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - - private ReaderWrapper reader; - private List<ByteBuffer> samples; - boolean readSamples = false; - - List<TimeToSampleBox.Entry> stts; - List<CompositionTimeToSample.Entry> ctts; - List<SampleDependencyTypeBox.Entry> sdtp; - List<Integer> stss; - - SeqParameterSet seqParameterSet = null; - PictureParameterSet pictureParameterSet = null; - LinkedList<byte[]> seqParameterSetList = new LinkedList<byte[]>(); - LinkedList<byte[]> pictureParameterSetList = new LinkedList<byte[]>(); - - private int width; - private int height; - private int timescale; - private int frametick; - private int currentScSize; - private int prevScSize; - - private SEIMessage seiMessage; - int frameNrInGop = 0; - private boolean determineFrameRate = true; - private String lang = "und"; - - public H264TrackImpl(InputStream inputStream, String lang, long timescale) throws IOException { - this.lang = lang; - if (timescale > 1000) { - timescale = timescale; //e.g. 23976 - frametick = 1000; - determineFrameRate = false; - } else { - throw new IllegalArgumentException("Timescale must be specified in milliseconds!"); - } - parse(inputStream); - } - - public H264TrackImpl(InputStream inputStream, String lang) throws IOException { - this.lang = lang; - parse(inputStream); - } - - public H264TrackImpl(InputStream inputStream) throws IOException { - parse(inputStream); - } - - private void parse(InputStream inputStream) throws IOException { - this.reader = new ReaderWrapper(inputStream); - stts = new LinkedList<TimeToSampleBox.Entry>(); - ctts = new LinkedList<CompositionTimeToSample.Entry>(); - sdtp = new LinkedList<SampleDependencyTypeBox.Entry>(); - stss = new LinkedList<Integer>(); - - samples = new LinkedList<ByteBuffer>(); - if (!readSamples()) { - throw new IOException(); - } - - if (!readVariables()) { - throw new IOException(); - } - - sampleDescriptionBox = new SampleDescriptionBox(); - VisualSampleEntry visualSampleEntry = new VisualSampleEntry("avc1"); - visualSampleEntry.setDataReferenceIndex(1); - visualSampleEntry.setDepth(24); - visualSampleEntry.setFrameCount(1); - visualSampleEntry.setHorizresolution(72); - visualSampleEntry.setVertresolution(72); - visualSampleEntry.setWidth(width); - visualSampleEntry.setHeight(height); - visualSampleEntry.setCompressorname("AVC Coding"); - - AvcConfigurationBox avcConfigurationBox = new AvcConfigurationBox(); - - avcConfigurationBox.setSequenceParameterSets(seqParameterSetList); - avcConfigurationBox.setPictureParameterSets(pictureParameterSetList); - avcConfigurationBox.setAvcLevelIndication(seqParameterSet.level_idc); - avcConfigurationBox.setAvcProfileIndication(seqParameterSet.profile_idc); - avcConfigurationBox.setBitDepthLumaMinus8(seqParameterSet.bit_depth_luma_minus8); - avcConfigurationBox.setBitDepthChromaMinus8(seqParameterSet.bit_depth_chroma_minus8); - avcConfigurationBox.setChromaFormat(seqParameterSet.chroma_format_idc.getId()); - avcConfigurationBox.setConfigurationVersion(1); - avcConfigurationBox.setLengthSizeMinusOne(3); - avcConfigurationBox.setProfileCompatibility(seqParameterSetList.get(0)[1]); - - visualSampleEntry.addBox(avcConfigurationBox); - sampleDescriptionBox.addBox(visualSampleEntry); - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setLanguage(lang); - trackMetaData.setTimescale(timescale); - trackMetaData.setWidth(width); - trackMetaData.setHeight(height); - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return ctts; - } - - public long[] getSyncSamples() { - long[] returns = new long[stss.size()]; - for (int i = 0; i < stss.size(); i++) { - returns[i] = stss.get(i); - } - return returns; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return sdtp; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "vide"; - } - - public List<ByteBuffer> getSamples() { - return samples; - } - - public AbstractMediaHeaderBox getMediaHeaderBox() { - return new VideoMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - - private boolean readVariables() { - width = (seqParameterSet.pic_width_in_mbs_minus1 + 1) * 16; - int mult = 2; - if (seqParameterSet.frame_mbs_only_flag) { - mult = 1; - } - height = 16 * (seqParameterSet.pic_height_in_map_units_minus1 + 1) * mult; - if (seqParameterSet.frame_cropping_flag) { - int chromaArrayType = 0; - if (seqParameterSet.residual_color_transform_flag == false) { - chromaArrayType = seqParameterSet.chroma_format_idc.getId(); - } - int cropUnitX = 1; - int cropUnitY = mult; - if (chromaArrayType != 0) { - cropUnitX = seqParameterSet.chroma_format_idc.getSubWidth(); - cropUnitY = seqParameterSet.chroma_format_idc.getSubHeight() * mult; - } - - width -= cropUnitX * (seqParameterSet.frame_crop_left_offset + seqParameterSet.frame_crop_right_offset); - height -= cropUnitY * (seqParameterSet.frame_crop_top_offset + seqParameterSet.frame_crop_bottom_offset); - } - return true; - } - - private boolean findNextStartcode() throws IOException { - byte[] test = new byte[]{-1, -1, -1, -1}; - - int c; - while ((c = reader.read()) != -1) { - test[0] = test[1]; - test[1] = test[2]; - test[2] = test[3]; - test[3] = (byte) c; - if (test[0] == 0 && test[1] == 0 && test[2] == 0 && test[3] == 1) { - prevScSize = currentScSize; - currentScSize = 4; - return true; - } - if (test[0] == 0 && test[1] == 0 && test[2] == 1) { - prevScSize = currentScSize; - currentScSize = 3; - return true; - } - } - return false; - } - - private enum NALActions { - IGNORE, BUFFER, STORE, END - } - - private boolean readSamples() throws IOException { - if (readSamples) { - return true; - } - - readSamples = true; - - - findNextStartcode(); - reader.mark(); - long pos = reader.getPos(); - - ArrayList<byte[]> buffered = new ArrayList<byte[]>(); - - int frameNr = 0; - - while (findNextStartcode()) { - long newpos = reader.getPos(); - int size = (int) (newpos - pos - prevScSize); - reader.reset(); - byte[] data = new byte[size ]; - reader.read(data); - int type = data[0]; - int nal_ref_idc = (type >> 5) & 3; - int nal_unit_type = type & 0x1f; - LOG.fine("Found startcode at " + (pos -4) + " Type: " + nal_unit_type + " ref idc: " + nal_ref_idc + " (size " + size + ")"); - NALActions action = handleNALUnit(nal_ref_idc, nal_unit_type, data); - switch (action) { - case IGNORE: - break; - - case BUFFER: - buffered.add(data); - break; - - case STORE: - int stdpValue = 22; - frameNr++; - buffered.add(data); - ByteBuffer bb = createSample(buffered); - boolean IdrPicFlag = false; - if (nal_unit_type == 5) { - stdpValue += 16; - IdrPicFlag = true; - } - ByteArrayInputStream bs = cleanBuffer(buffered.get(buffered.size() - 1)); - SliceHeader sh = new SliceHeader(bs, seqParameterSet, pictureParameterSet, IdrPicFlag); - if (sh.slice_type == SliceHeader.SliceType.B) { - stdpValue += 4; - } - LOG.fine("Adding sample with size " + bb.capacity() + " and header " + sh); - buffered.clear(); - samples.add(bb); - stts.add(new TimeToSampleBox.Entry(1, frametick)); - if (nal_unit_type == 5) { // IDR Picture - stss.add(frameNr); - } - if (seiMessage.n_frames == 0) { - frameNrInGop = 0; - } - int offset = 0; - if (seiMessage.clock_timestamp_flag) { - offset = seiMessage.n_frames - frameNrInGop; - } else if (seiMessage.removal_delay_flag) { - offset = seiMessage.dpb_removal_delay / 2; - } - ctts.add(new CompositionTimeToSample.Entry(1, offset * frametick)); - sdtp.add(new SampleDependencyTypeBox.Entry(stdpValue)); - frameNrInGop++; - break; - - case END: - return true; - - - } - pos = newpos; - reader.seek(currentScSize); - reader.mark(); - } - return true; - } - - private ByteBuffer createSample(List<byte[]> buffers) { - int outsize = 0; - for (int i = 0; i < buffers.size(); i++) { - outsize += buffers.get(i).length + 4; - } - byte[] output = new byte[outsize]; - - ByteBuffer bb = ByteBuffer.wrap(output); - for (int i = 0; i < buffers.size(); i++) { - bb.putInt(buffers.get(i).length); - bb.put(buffers.get(i)); - } - bb.rewind(); - return bb; - } - - private ByteArrayInputStream cleanBuffer(byte[] data) { - byte[] output = new byte[data.length]; - int inPos = 0; - int outPos = 0; - while (inPos < data.length) { - if (data[inPos] == 0 && data[inPos + 1] == 0 && data[inPos + 2] == 3) { - output[outPos] = 0; - output[outPos + 1] = 0; - inPos += 3; - outPos += 2; - } else { - output[outPos] = data[inPos]; - inPos++; - outPos++; - } - } - return new ByteArrayInputStream(output, 0, outPos); - } - - private NALActions handleNALUnit(int nal_ref_idc, int nal_unit_type, byte[] data) throws IOException { - NALActions action; - switch (nal_unit_type) { - case 1: - case 2: - case 3: - case 4: - case 5: - action = NALActions.STORE; // Will only work in single slice per frame mode! - break; - - case 6: - seiMessage = new SEIMessage(cleanBuffer(data), seqParameterSet); - action = NALActions.BUFFER; - break; - - case 9: -// printAccessUnitDelimiter(data); - int type = data[1] >> 5; - LOG.fine("Access unit delimiter type: " + type); - action = NALActions.BUFFER; - break; - - - case 7: - if (seqParameterSet == null) { - ByteArrayInputStream is = cleanBuffer(data); - is.read(); - seqParameterSet = SeqParameterSet.read(is); - seqParameterSetList.add(data); - configureFramerate(); - } - action = NALActions.IGNORE; - break; - - case 8: - if (pictureParameterSet == null) { - ByteArrayInputStream is = new ByteArrayInputStream(data); - is.read(); - pictureParameterSet = PictureParameterSet.read(is); - pictureParameterSetList.add(data); - } - action = NALActions.IGNORE; - break; - - case 10: - case 11: - action = NALActions.END; - break; - - default: - System.err.println("Unknown NAL unit type: " + nal_unit_type); - action = NALActions.IGNORE; - - } - - return action; - } - - private void configureFramerate() { - if (determineFrameRate) { - if (seqParameterSet.vuiParams != null) { - timescale = seqParameterSet.vuiParams.time_scale >> 1; // Not sure why, but I found this in several places, and it works... - frametick = seqParameterSet.vuiParams.num_units_in_tick; - if (timescale == 0 || frametick == 0) { - System.err.println("Warning: vuiParams contain invalid values: time_scale: " + timescale + " and frame_tick: " + frametick + ". Setting frame rate to 25fps"); - timescale = 90000; - frametick = 3600; - } - } else { - System.err.println("Warning: Can't determine frame rate. Guessing 25 fps"); - timescale = 90000; - frametick = 3600; - } - } - } - - public void printAccessUnitDelimiter(byte[] data) { - LOG.fine("Access unit delimiter: " + (data[1] >> 5)); - } - - public static class SliceHeader { - - public enum SliceType { - P, B, I, SP, SI - } - - public int first_mb_in_slice; - public SliceType slice_type; - public int pic_parameter_set_id; - public int colour_plane_id; - public int frame_num; - public boolean field_pic_flag = false; - public boolean bottom_field_flag = false; - public int idr_pic_id; - public int pic_order_cnt_lsb; - public int delta_pic_order_cnt_bottom; - - public SliceHeader(InputStream is, SeqParameterSet sps, PictureParameterSet pps, boolean IdrPicFlag) throws IOException { - is.read(); - CAVLCReader reader = new CAVLCReader(is); - first_mb_in_slice = reader.readUE("SliceHeader: first_mb_in_slice"); - switch (reader.readUE("SliceHeader: slice_type")) { - case 0: - case 5: - slice_type = SliceType.P; - break; - - case 1: - case 6: - slice_type = SliceType.B; - break; - - case 2: - case 7: - slice_type = SliceType.I; - break; - - case 3: - case 8: - slice_type = SliceType.SP; - break; - - case 4: - case 9: - slice_type = SliceType.SI; - break; - - } - pic_parameter_set_id = reader.readUE("SliceHeader: pic_parameter_set_id"); - if (sps.residual_color_transform_flag) { - colour_plane_id = reader.readU(2, "SliceHeader: colour_plane_id"); - } - frame_num = reader.readU(sps.log2_max_frame_num_minus4 + 4, "SliceHeader: frame_num"); - - if (!sps.frame_mbs_only_flag) { - field_pic_flag = reader.readBool("SliceHeader: field_pic_flag"); - if (field_pic_flag) { - bottom_field_flag = reader.readBool("SliceHeader: bottom_field_flag"); - } - } - if (IdrPicFlag) { - idr_pic_id = reader.readUE("SliceHeader: idr_pic_id"); - if (sps.pic_order_cnt_type == 0) { - pic_order_cnt_lsb = reader.readU(sps.log2_max_pic_order_cnt_lsb_minus4 + 4, "SliceHeader: pic_order_cnt_lsb"); - if (pps.pic_order_present_flag && !field_pic_flag) { - delta_pic_order_cnt_bottom = reader.readSE("SliceHeader: delta_pic_order_cnt_bottom"); - } - } - } - } - - @Override - public String toString() { - return "SliceHeader{" + - "first_mb_in_slice=" + first_mb_in_slice + - ", slice_type=" + slice_type + - ", pic_parameter_set_id=" + pic_parameter_set_id + - ", colour_plane_id=" + colour_plane_id + - ", frame_num=" + frame_num + - ", field_pic_flag=" + field_pic_flag + - ", bottom_field_flag=" + bottom_field_flag + - ", idr_pic_id=" + idr_pic_id + - ", pic_order_cnt_lsb=" + pic_order_cnt_lsb + - ", delta_pic_order_cnt_bottom=" + delta_pic_order_cnt_bottom + - '}'; - } - } - - private class ReaderWrapper { - private InputStream inputStream; - private long pos = 0; - - private long markPos = 0; - - - private ReaderWrapper(InputStream inputStream) { - this.inputStream = inputStream; - } - - int read() throws IOException { - pos++; - return inputStream.read(); - } - - long read(byte[] data) throws IOException { - long read = inputStream.read(data); - pos += read; - return read; - } - - long seek(int dist) throws IOException { - long seeked = inputStream.skip(dist); - pos += seeked; - return seeked; - } - - public long getPos() { - return pos; - } - - public void mark() { - int i = 1048576; - LOG.fine("Marking with " + i + " at " + pos); - inputStream.mark(i); - markPos = pos; - } - - - public void reset() throws IOException { - long diff = pos - markPos; - LOG.fine("Resetting to " + markPos + " (pos is " + pos + ") which makes the buffersize " + diff); - inputStream.reset(); - pos = markPos; - } - } - - public class SEIMessage { - - int payloadType = 0; - int payloadSize = 0; - - boolean removal_delay_flag; - int cpb_removal_delay; - int dpb_removal_delay; - - boolean clock_timestamp_flag; - int pic_struct; - int ct_type; - int nuit_field_based_flag; - int counting_type; - int full_timestamp_flag; - int discontinuity_flag; - int cnt_dropped_flag; - int n_frames; - int seconds_value; - int minutes_value; - int hours_value; - int time_offset_length; - int time_offset; - - SeqParameterSet sps; - - public SEIMessage(InputStream is, SeqParameterSet sps) throws IOException { - this.sps = sps; - is.read(); - int datasize = is.available(); - int read = 0; - while (read < datasize) { - payloadType = 0; - payloadSize = 0; - int last_payload_type_bytes = is.read(); - read++; - while (last_payload_type_bytes == 0xff) { - payloadType += last_payload_type_bytes; - last_payload_type_bytes = is.read(); - read++; - } - payloadType += last_payload_type_bytes; - int last_payload_size_bytes = is.read(); - read++; - - while (last_payload_size_bytes == 0xff) { - payloadSize += last_payload_size_bytes; - last_payload_size_bytes = is.read(); - read++; - } - payloadSize += last_payload_size_bytes; - if (datasize - read >= payloadSize) { - if (payloadType == 1) { // pic_timing is what we are interested in! - if (sps.vuiParams != null && (sps.vuiParams.nalHRDParams != null || sps.vuiParams.vclHRDParams != null || sps.vuiParams.pic_struct_present_flag)) { - byte[] data = new byte[payloadSize]; - is.read(data); - read += payloadSize; - CAVLCReader reader = new CAVLCReader(new ByteArrayInputStream(data)); - if (sps.vuiParams.nalHRDParams != null || sps.vuiParams.vclHRDParams != null) { - removal_delay_flag = true; - cpb_removal_delay = reader.readU(sps.vuiParams.nalHRDParams.cpb_removal_delay_length_minus1 + 1, "SEI: cpb_removal_delay"); - dpb_removal_delay = reader.readU(sps.vuiParams.nalHRDParams.dpb_output_delay_length_minus1 + 1, "SEI: dpb_removal_delay"); - } else { - removal_delay_flag = false; - } - if (sps.vuiParams.pic_struct_present_flag) { - pic_struct = reader.readU(4, "SEI: pic_struct"); - int numClockTS; - switch (pic_struct) { - case 0: - case 1: - case 2: - default: - numClockTS = 1; - break; - - case 3: - case 4: - case 7: - numClockTS = 2; - break; - - case 5: - case 6: - case 8: - numClockTS = 3; - break; - } - for (int i = 0; i < numClockTS; i++) { - clock_timestamp_flag = reader.readBool("pic_timing SEI: clock_timestamp_flag[" + i + "]"); - if (clock_timestamp_flag) { - ct_type = reader.readU(2, "pic_timing SEI: ct_type"); - nuit_field_based_flag = reader.readU(1, "pic_timing SEI: nuit_field_based_flag"); - counting_type = reader.readU(5, "pic_timing SEI: counting_type"); - full_timestamp_flag = reader.readU(1, "pic_timing SEI: full_timestamp_flag"); - discontinuity_flag = reader.readU(1, "pic_timing SEI: discontinuity_flag"); - cnt_dropped_flag = reader.readU(1, "pic_timing SEI: cnt_dropped_flag"); - n_frames = reader.readU(8, "pic_timing SEI: n_frames"); - if (full_timestamp_flag == 1) { - seconds_value = reader.readU(6, "pic_timing SEI: seconds_value"); - minutes_value = reader.readU(6, "pic_timing SEI: minutes_value"); - hours_value = reader.readU(5, "pic_timing SEI: hours_value"); - } else { - if (reader.readBool("pic_timing SEI: seconds_flag")) { - seconds_value = reader.readU(6, "pic_timing SEI: seconds_value"); - if (reader.readBool("pic_timing SEI: minutes_flag")) { - minutes_value = reader.readU(6, "pic_timing SEI: minutes_value"); - if (reader.readBool("pic_timing SEI: hours_flag")) { - hours_value = reader.readU(5, "pic_timing SEI: hours_value"); - } - } - } - } - if (true) { - if (sps.vuiParams.nalHRDParams != null) { - time_offset_length = sps.vuiParams.nalHRDParams.time_offset_length; - } else if (sps.vuiParams.vclHRDParams != null) { - time_offset_length = sps.vuiParams.vclHRDParams.time_offset_length; - } else { - time_offset_length = 24; - } - time_offset = reader.readU(24, "pic_timing SEI: time_offset"); - } - } - } - } - - } else { - for (int i = 0; i < payloadSize; i++) { - is.read(); - read++; - } - } - } else { - for (int i = 0; i < payloadSize; i++) { - is.read(); - read++; - } - } - } else { - read = datasize; - } - LOG.fine(this.toString()); - } - } - - @Override - public String toString() { - String out = "SEIMessage{" + - "payloadType=" + payloadType + - ", payloadSize=" + payloadSize; - if (payloadType == 1) { - if (sps.vuiParams.nalHRDParams != null || sps.vuiParams.vclHRDParams != null) { - - out += ", cpb_removal_delay=" + cpb_removal_delay + - ", dpb_removal_delay=" + dpb_removal_delay; - } - if (sps.vuiParams.pic_struct_present_flag) { - out += ", pic_struct=" + pic_struct; - if (clock_timestamp_flag) { - out += ", ct_type=" + ct_type + - ", nuit_field_based_flag=" + nuit_field_based_flag + - ", counting_type=" + counting_type + - ", full_timestamp_flag=" + full_timestamp_flag + - ", discontinuity_flag=" + discontinuity_flag + - ", cnt_dropped_flag=" + cnt_dropped_flag + - ", n_frames=" + n_frames + - ", seconds_value=" + seconds_value + - ", minutes_value=" + minutes_value + - ", hours_value=" + hours_value + - ", time_offset_length=" + time_offset_length + - ", time_offset=" + time_offset; - } - } - } - out += '}'; - return out; - } - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/MultiplyTimeScaleTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/MultiplyTimeScaleTrack.java.svn-base deleted file mode 100644 index e9a90e4..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/MultiplyTimeScaleTrack.java.svn-base +++ /dev/null @@ -1,130 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.TrackMetaData; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import static com.googlecode.mp4parser.util.CastUtils.l2i; -import static com.googlecode.mp4parser.util.Math.gcd; -import static com.googlecode.mp4parser.util.Math.lcm; -import static java.lang.Math.round; - -/** - * Changes the timescale of a track by wrapping the track. - */ -public class MultiplyTimeScaleTrack implements Track { - Track source; - private int timeScaleFactor; - - public MultiplyTimeScaleTrack(Track source, int timeScaleFactor) { - this.source = source; - this.timeScaleFactor = timeScaleFactor; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return source.getSampleDescriptionBox(); - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return adjustTts(source.getDecodingTimeEntries(), timeScaleFactor); - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return adjustCtts(source.getCompositionTimeEntries(), timeScaleFactor); - } - - public long[] getSyncSamples() { - return source.getSyncSamples(); - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return source.getSampleDependencies(); - } - - public TrackMetaData getTrackMetaData() { - TrackMetaData trackMetaData = (TrackMetaData) source.getTrackMetaData().clone(); - trackMetaData.setTimescale(source.getTrackMetaData().getTimescale() * this.timeScaleFactor); - return trackMetaData; - } - - public String getHandler() { - return source.getHandler(); - } - - public boolean isEnabled() { - return source.isEnabled(); - } - - public boolean isInMovie() { - return source.isInMovie(); - } - - public boolean isInPreview() { - return source.isInPreview(); - } - - public boolean isInPoster() { - return source.isInPoster(); - } - - public List<ByteBuffer> getSamples() { - return source.getSamples(); - } - - - static List<CompositionTimeToSample.Entry> adjustCtts(List<CompositionTimeToSample.Entry> source, int timeScaleFactor) { - if (source != null) { - List<CompositionTimeToSample.Entry> entries2 = new ArrayList<CompositionTimeToSample.Entry>(source.size()); - for (CompositionTimeToSample.Entry entry : source) { - entries2.add(new CompositionTimeToSample.Entry(entry.getCount(), timeScaleFactor * entry.getOffset())); - } - return entries2; - } else { - return null; - } - } - - static List<TimeToSampleBox.Entry> adjustTts(List<TimeToSampleBox.Entry> source, int timeScaleFactor) { - LinkedList<TimeToSampleBox.Entry> entries2 = new LinkedList<TimeToSampleBox.Entry>(); - for (TimeToSampleBox.Entry e : source) { - entries2.add(new TimeToSampleBox.Entry(e.getCount(), timeScaleFactor * e.getDelta())); - } - return entries2; - } - - public Box getMediaHeaderBox() { - return source.getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return source.getSubsampleInformationBox(); - } - - @Override - public String toString() { - return "MultiplyTimeScaleTrack{" + - "source=" + source + - '}'; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/QuicktimeTextTrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/QuicktimeTextTrackImpl.java.svn-base deleted file mode 100644 index 8efa399..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/QuicktimeTextTrackImpl.java.svn-base +++ /dev/null @@ -1,165 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.sampleentry.TextSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.apple.BaseMediaInfoAtom; -import com.googlecode.mp4parser.boxes.apple.GenericMediaHeaderAtom; -import com.googlecode.mp4parser.boxes.apple.GenericMediaHeaderTextAtom; -import com.googlecode.mp4parser.boxes.apple.QuicktimeTextSampleEntry; -import com.googlecode.mp4parser.boxes.threegpp26245.FontTableBox; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -/** - * A Text track as Quicktime Pro would create. - */ -public class QuicktimeTextTrackImpl extends AbstractTrack { - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - List<Line> subs = new LinkedList<Line>(); - - public List<Line> getSubs() { - return subs; - } - - public QuicktimeTextTrackImpl() { - sampleDescriptionBox = new SampleDescriptionBox(); - QuicktimeTextSampleEntry textTrack = new QuicktimeTextSampleEntry(); - textTrack.setDataReferenceIndex(1); - sampleDescriptionBox.addBox(textTrack); - - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setTimescale(1000); - - - } - - - public List<ByteBuffer> getSamples() { - List<ByteBuffer> samples = new LinkedList<ByteBuffer>(); - long lastEnd = 0; - for (Line sub : subs) { - long silentTime = sub.from - lastEnd; - if (silentTime > 0) { - samples.add(ByteBuffer.wrap(new byte[]{0, 0})); - } else if (silentTime < 0) { - throw new Error("Subtitle display times may not intersect"); - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(baos); - try { - dos.writeShort(sub.text.getBytes("UTF-8").length); - dos.write(sub.text.getBytes("UTF-8")); - dos.close(); - } catch (IOException e) { - throw new Error("VM is broken. Does not support UTF-8"); - } - samples.add(ByteBuffer.wrap(baos.toByteArray())); - lastEnd = sub.to; - } - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - List<TimeToSampleBox.Entry> stts = new LinkedList<TimeToSampleBox.Entry>(); - long lastEnd = 0; - for (Line sub : subs) { - long silentTime = sub.from - lastEnd; - if (silentTime > 0) { - stts.add(new TimeToSampleBox.Entry(1, silentTime)); - } else if (silentTime < 0) { - throw new Error("Subtitle display times may not intersect"); - } - stts.add(new TimeToSampleBox.Entry(1, sub.to - sub.from)); - lastEnd = sub.to; - } - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "text"; - } - - - public static class Line { - long from; - long to; - String text; - - - public Line(long from, long to, String text) { - this.from = from; - this.to = to; - this.text = text; - } - - public long getFrom() { - return from; - } - - public String getText() { - return text; - } - - public long getTo() { - return to; - } - } - - public Box getMediaHeaderBox() { - GenericMediaHeaderAtom ghmd = new GenericMediaHeaderAtom(); - ghmd.addBox(new BaseMediaInfoAtom()); - ghmd.addBox(new GenericMediaHeaderTextAtom()); - return ghmd; - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ReplaceSampleTrack.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ReplaceSampleTrack.java.svn-base deleted file mode 100644 index 81a129d..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/ReplaceSampleTrack.java.svn-base +++ /dev/null @@ -1,104 +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.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.AbstractList; -import java.util.LinkedList; -import java.util.List; - -/** - * Generates a Track where a single sample has been replaced by a given <code>ByteBuffer</code>. - */ - -public class ReplaceSampleTrack extends AbstractTrack { - Track origTrack; - private long sampleNumber; - private ByteBuffer sampleContent; - private List<ByteBuffer> samples; - - public ReplaceSampleTrack(Track origTrack, long sampleNumber, ByteBuffer content) { - this.origTrack = origTrack; - this.sampleNumber = sampleNumber; - this.sampleContent = content; - this.samples = new ReplaceASingleEntryList(); - - } - - public List<ByteBuffer> getSamples() { - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return origTrack.getSampleDescriptionBox(); - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return origTrack.getDecodingTimeEntries(); - - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return origTrack.getCompositionTimeEntries(); - - } - - synchronized public long[] getSyncSamples() { - return origTrack.getSyncSamples(); - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return origTrack.getSampleDependencies(); - } - - public TrackMetaData getTrackMetaData() { - return origTrack.getTrackMetaData(); - } - - public String getHandler() { - return origTrack.getHandler(); - } - - public Box getMediaHeaderBox() { - return origTrack.getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return origTrack.getSubsampleInformationBox(); - } - - private class ReplaceASingleEntryList extends AbstractList<ByteBuffer> { - @Override - public ByteBuffer get(int index) { - if (ReplaceSampleTrack.this.sampleNumber == index) { - return ReplaceSampleTrack.this.sampleContent; - } else { - return ReplaceSampleTrack.this.origTrack.getSamples().get(index); - } - } - - @Override - public int size() { - return ReplaceSampleTrack.this.origTrack.getSamples().size(); - } - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/SilenceTrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/SilenceTrackImpl.java.svn-base deleted file mode 100644 index f74ab3c..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/SilenceTrackImpl.java.svn-base +++ /dev/null @@ -1,98 +0,0 @@ -package com.googlecode.mp4parser.authoring.tracks; - -import com.coremedia.iso.boxes.*; -import com.googlecode.mp4parser.authoring.Mp4TrackImpl; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.TrackMetaData; - -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * This is just a basic idea how things could work but they don't. - */ -public class SilenceTrackImpl implements Track { - Track source; - - List<ByteBuffer> samples = new LinkedList<ByteBuffer>(); - TimeToSampleBox.Entry entry; - - public SilenceTrackImpl(Track ofType, long ms) { - source = ofType; - if ("mp4a".equals(ofType.getSampleDescriptionBox().getSampleEntry().getType())) { - long numFrames = getTrackMetaData().getTimescale() * ms / 1000 / 1024; - long standZeit = getTrackMetaData().getTimescale() * ms / numFrames / 1000; - entry = new TimeToSampleBox.Entry(numFrames, standZeit); - - - while (numFrames-- > 0) { - samples.add((ByteBuffer) ByteBuffer.wrap(new byte[]{ - 0x21, 0x10, 0x04, 0x60, (byte) 0x8c, 0x1c, - }).rewind()); - } - - } else { - throw new RuntimeException("Tracks of type " + ofType.getClass().getSimpleName() + " are not supported"); - } - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return source.getSampleDescriptionBox(); - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - return Collections.singletonList(entry); - - } - - public TrackMetaData getTrackMetaData() { - return source.getTrackMetaData(); - } - - public String getHandler() { - return source.getHandler(); - } - - public boolean isEnabled() { - return source.isEnabled(); - } - - public boolean isInMovie() { - return source.isInMovie(); - } - - public boolean isInPreview() { - return source.isInPreview(); - } - - public boolean isInPoster() { - return source.isInPoster(); - } - - public List<ByteBuffer> getSamples() { - return samples; - } - - public Box getMediaHeaderBox() { - return source.getMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - -} diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/TextTrackImpl.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/TextTrackImpl.java.svn-base deleted file mode 100644 index 3bae143..0000000 --- a/isoparser/src/main/java/com/googlecode/mp4parser/authoring/tracks/.svn/text-base/TextTrackImpl.java.svn-base +++ /dev/null @@ -1,165 +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.tracks; - -import com.coremedia.iso.boxes.*; -import com.coremedia.iso.boxes.sampleentry.TextSampleEntry; -import com.googlecode.mp4parser.authoring.AbstractTrack; -import com.googlecode.mp4parser.authoring.TrackMetaData; -import com.googlecode.mp4parser.boxes.threegpp26245.FontTableBox; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -/** - * - */ -public class TextTrackImpl extends AbstractTrack { - TrackMetaData trackMetaData = new TrackMetaData(); - SampleDescriptionBox sampleDescriptionBox; - List<Line> subs = new LinkedList<Line>(); - - public List<Line> getSubs() { - return subs; - } - - public TextTrackImpl() { - sampleDescriptionBox = new SampleDescriptionBox(); - TextSampleEntry tx3g = new TextSampleEntry("tx3g"); - tx3g.setDataReferenceIndex(1); - tx3g.setStyleRecord(new TextSampleEntry.StyleRecord()); - tx3g.setBoxRecord(new TextSampleEntry.BoxRecord()); - sampleDescriptionBox.addBox(tx3g); - - FontTableBox ftab = new FontTableBox(); - ftab.setEntries(Collections.singletonList(new FontTableBox.FontRecord(1, "Serif"))); - - tx3g.addBox(ftab); - - - trackMetaData.setCreationTime(new Date()); - trackMetaData.setModificationTime(new Date()); - trackMetaData.setTimescale(1000); // Text tracks use millieseconds - - - } - - - public List<ByteBuffer> getSamples() { - List<ByteBuffer> samples = new LinkedList<ByteBuffer>(); - long lastEnd = 0; - for (Line sub : subs) { - long silentTime = sub.from - lastEnd; - if (silentTime > 0) { - samples.add(ByteBuffer.wrap(new byte[]{0, 0})); - } else if (silentTime < 0) { - throw new Error("Subtitle display times may not intersect"); - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(baos); - try { - dos.writeShort(sub.text.getBytes("UTF-8").length); - dos.write(sub.text.getBytes("UTF-8")); - dos.close(); - } catch (IOException e) { - throw new Error("VM is broken. Does not support UTF-8"); - } - samples.add(ByteBuffer.wrap(baos.toByteArray())); - lastEnd = sub.to; - } - return samples; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { - List<TimeToSampleBox.Entry> stts = new LinkedList<TimeToSampleBox.Entry>(); - long lastEnd = 0; - for (Line sub : subs) { - long silentTime = sub.from - lastEnd; - if (silentTime > 0) { - stts.add(new TimeToSampleBox.Entry(1, silentTime)); - } else if (silentTime < 0) { - throw new Error("Subtitle display times may not intersect"); - } - stts.add(new TimeToSampleBox.Entry(1, sub.to - sub.from)); - lastEnd = sub.to; - } - return stts; - } - - public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { - return null; - } - - public long[] getSyncSamples() { - return null; - } - - public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { - return null; - } - - public TrackMetaData getTrackMetaData() { - return trackMetaData; - } - - public String getHandler() { - return "sbtl"; - } - - - public static class Line { - long from; - long to; - String text; - - - public Line(long from, long to, String text) { - this.from = from; - this.to = to; - this.text = text; - } - - public long getFrom() { - return from; - } - - public String getText() { - return text; - } - - public long getTo() { - return to; - } - } - - public AbstractMediaHeaderBox getMediaHeaderBox() { - return new NullMediaHeaderBox(); - } - - public SubSampleInformationBox getSubsampleInformationBox() { - return null; - } -} |