diff options
Diffstat (limited to 'isoparser/src/main/java/com/coremedia/iso')
352 files changed, 33857 insertions, 0 deletions
diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/.svn/all-wcprops new file mode 100644 index 0000000..9b50c5a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/all-wcprops @@ -0,0 +1,77 @@ +K 25 +svn:wc:ra_dav:version-url +V 65 +/svn/!svn/ver/777/trunk/isoparser/src/main/java/com/coremedia/iso +END +IsoTypeReader.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/659/trunk/isoparser/src/main/java/com/coremedia/iso/IsoTypeReader.java +END +IsoTypeWriterVariable.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/426/trunk/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriterVariable.java +END +Hex.java +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/619/trunk/isoparser/src/main/java/com/coremedia/iso/Hex.java +END +IsoTypeReaderVariable.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/419/trunk/isoparser/src/main/java/com/coremedia/iso/IsoTypeReaderVariable.java +END +BoxParser.java +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/419/trunk/isoparser/src/main/java/com/coremedia/iso/BoxParser.java +END +Utf8.java +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/!svn/ver/419/trunk/isoparser/src/main/java/com/coremedia/iso/Utf8.java +END +Ascii.java +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/!svn/ver/419/trunk/isoparser/src/main/java/com/coremedia/iso/Ascii.java +END +ChannelHelper.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/ChannelHelper.java +END +IsoTypeWriter.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/692/trunk/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriter.java +END +AbstractBoxParser.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/AbstractBoxParser.java +END +IsoFile.java +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/!svn/ver/742/trunk/isoparser/src/main/java/com/coremedia/iso/IsoFile.java +END +PropertyBoxParserImpl.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/PropertyBoxParserImpl.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/.svn/entries new file mode 100644 index 0000000..0114cad --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/entries @@ -0,0 +1,442 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso +http://mp4parser.googlecode.com/svn + + + +2012-09-10T14:56:10.036617Z +777 +sebastian.annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +IsoTypeReader.java +file + + + + +2012-09-14T17:27:53.147256Z +1b3832056109e2538ddb064410e145a3 +2012-06-06T10:36:53.498661Z +659 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4181 + +IsoTypeWriterVariable.java +file + + + + +2012-09-14T17:27:53.157256Z +dc08bcfd952e251e81f54d6876cf2822 +2012-03-12T12:55:40.927472Z +426 +hoemmagnus@gmail.com + + + + + + + + + + + + + + + + + + + + + +1471 + +boxes +dir + +Hex.java +file + + + + +2012-09-14T17:27:53.157256Z +834508c38dadb7747ba2a9e611a29f75 +2012-05-20T18:32:15.672660Z +619 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2026 + +mdta +dir + +IsoTypeReaderVariable.java +file + + + + +2012-09-14T17:27:53.157256Z +a2e5fe2ff8d860e485a09fe069b23b67 +2012-03-11T20:58:41.111953Z +419 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1283 + +BoxParser.java +file + + + + +2012-09-14T17:27:53.157256Z +7ffb4de0f5409f6be08384c50ed1f239 +2012-03-11T20:58:41.111953Z +419 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1089 + +Utf8.java +file + + + + +2012-09-14T17:27:53.157256Z +7e580cd68183dc1f3927fb0866b2030b +2012-03-11T20:58:41.111953Z +419 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1712 + +Ascii.java +file + + + + +2012-09-14T17:27:53.157256Z +30e0990932cfaaf6df4603a5aabbd724 +2012-03-11T20:58:41.111953Z +419 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1274 + +ChannelHelper.java +file + + + + +2012-09-14T17:27:53.157256Z +363efdcb385f027569cf4748273c9533 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2750 + +IsoTypeWriter.java +file + + + + +2012-09-14T17:27:53.157256Z +746a167bf3de7edb454855bed18ec21b +2012-06-25T03:13:15.796438Z +692 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +2840 + +AbstractBoxParser.java +file + + + + +2012-09-14T17:27:53.157256Z +e5bf90052f2d10b984827de45560b8b8 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4828 + +IsoFile.java +file + + + + +2012-09-14T17:27:53.157256Z +fa74e86d8e2f3f19c2a91319ee286b38 +2012-08-12T09:16:02.229115Z +742 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +5567 + +PropertyBoxParserImpl.java +file + + + + +2012-09-14T17:27:53.157256Z +e93996880a8025f186a835bbff195141 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +7247 + diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/AbstractBoxParser.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/AbstractBoxParser.java.svn-base new file mode 100644 index 0000000..6d92acd --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/AbstractBoxParser.java.svn-base @@ -0,0 +1,130 @@ +/* + * 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.coremedia.iso; + +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.coremedia.iso.boxes.UserBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.util.logging.Logger; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This BoxParser handles the basic stuff like reading size and extracting box type. + */ +public abstract class AbstractBoxParser implements BoxParser { + + private static Logger LOG = Logger.getLogger(AbstractBoxParser.class.getName()); + + public abstract Box createBox(String type, byte[] userType, String parent); + + /** + * Parses the next size and type, creates a box instance and parses the box's content. + * + * @param byteChannel the FileChannel pointing to the ISO file + * @param parent the current box's parent (null if no parent) + * @return the box just parsed + * @throws java.io.IOException if reading from <code>in</code> fails + */ + public Box parseBox(ReadableByteChannel byteChannel, ContainerBox parent) throws IOException { + + + ByteBuffer header = ChannelHelper.readFully(byteChannel, 8); + + long size = IsoTypeReader.readUInt32(header); + // do plausibility check + if (size < 8 && size > 1) { + LOG.severe("Plausibility check failed: size < 8 (size = " + size + "). Stop parsing!"); + return null; + } + + + String type = IsoTypeReader.read4cc(header); + byte[] usertype = null; + long contentSize; + + if (size == 1) { + ByteBuffer bb = ByteBuffer.allocate(8); + byteChannel.read(bb); + bb.rewind(); + size = IsoTypeReader.readUInt64(bb); + contentSize = size - 16; + } else if (size == 0) { + if (byteChannel instanceof FileChannel) { + size = ((FileChannel) byteChannel).size() - ((FileChannel) byteChannel).position() - 8; + } else { + throw new RuntimeException("Only FileChannel inputs may use size == 0 (box reaches to the end of file)"); + } + contentSize = size - 8; + } else { + contentSize = size - 8; + } + if (UserBox.TYPE.equals(type)) { + ByteBuffer bb = ByteBuffer.allocate(16); + byteChannel.read(bb); + bb.rewind(); + usertype = bb.array(); + contentSize -= 16; + } + Box box = createBox(type, usertype, parent.getType()); + box.setParent(parent); + LOG.finest("Parsing " + box.getType()); + // System.out.println("parsing " + Arrays.toString(box.getType()) + " " + box.getClass().getName() + " size=" + size); + + + if (l2i(size - contentSize) == 8) { + // default - no large box - no uuid + // do nothing header's already correct + header.rewind(); + } else if (l2i(size - contentSize) == 16) { + header = ByteBuffer.allocate(16); + IsoTypeWriter.writeUInt32(header, 1); + header.put(IsoFile.fourCCtoBytes(type)); + IsoTypeWriter.writeUInt64(header, size); + } else if (l2i(size - contentSize) == 24) { + header = ByteBuffer.allocate(24); + IsoTypeWriter.writeUInt32(header, size); + header.put(IsoFile.fourCCtoBytes(type)); + header.put(usertype); + } else if (l2i(size - contentSize) == 32) { + header = ByteBuffer.allocate(32); + IsoTypeWriter.writeUInt32(header, size); + header.put(IsoFile.fourCCtoBytes(type)); + IsoTypeWriter.writeUInt64(header, size); + header.put(usertype); + } else { + throw new RuntimeException("I didn't expect that"); + } + + + box.parse(byteChannel, header, contentSize, this); + // System.out.println("box = " + box); + + + assert size == box.getSize() : + "Reconstructed Size is not x to the number of parsed bytes! (" + + box.getType() + ")" + + " Actual Box size: " + size + " Calculated size: " + box.getSize(); + return box; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Ascii.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Ascii.java.svn-base new file mode 100644 index 0000000..2a659d7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Ascii.java.svn-base @@ -0,0 +1,47 @@ +/* + * 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.coremedia.iso; + +import java.io.UnsupportedEncodingException; + +/** + * Converts <code>byte[]</code> -> <code>String</code> and vice versa. + */ +public final class Ascii { + public static byte[] convert(String s) { + try { + if (s != null) { + return s.getBytes("us-ascii"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static String convert(byte[] b) { + try { + if (b != null) { + return new String(b, "us-ascii"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/BoxParser.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/BoxParser.java.svn-base new file mode 100644 index 0000000..cbe9a6f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/BoxParser.java.svn-base @@ -0,0 +1,31 @@ +/* + * 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.coremedia.iso; + +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.io.IOException; +import java.nio.channels.ReadableByteChannel; + +/** + * Basic interface to create boxes from a <code>IsoBufferWrapper</code> and its parent. + */ +public interface BoxParser { + Class<? extends Box> getClassForFourCc(String type, byte[] userType, String parent); + + Box parseBox(ReadableByteChannel in, ContainerBox parent) throws IOException; +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/ChannelHelper.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/ChannelHelper.java.svn-base new file mode 100644 index 0000000..2ec1d05 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/ChannelHelper.java.svn-base @@ -0,0 +1,90 @@ +/* + * 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.coremedia.iso; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.WritableByteChannel; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + + +public class ChannelHelper { + public static ByteBuffer readFully(final ReadableByteChannel channel, long size) throws IOException { + + if (channel instanceof FileChannel && size > 1024 * 1024) { + ByteBuffer bb = ((FileChannel) channel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) channel).position(), size); + ((FileChannel) channel).position(((FileChannel) channel).position() + size); + return bb; + } else { + ByteBuffer buf = ByteBuffer.allocate(l2i(size)); + readFully(channel, buf, buf.limit()); + buf.rewind(); + assert buf.limit() == size; + + return buf; + } + + } + + + public static void readFully(final ReadableByteChannel channel, final ByteBuffer buf) + throws IOException { + readFully(channel, buf, buf.remaining()); + } + + public static int readFully(final ReadableByteChannel channel, final ByteBuffer buf, final int length) + throws IOException { + int n, count = 0; + while (-1 != (n = channel.read(buf))) { + count += n; + if (count == length) { + break; + } + } + if (n == -1) { + throw new EOFException("End of file. No more boxes."); + } + return count; + } + + + public static void writeFully(final WritableByteChannel channel, final ByteBuffer buf) + throws IOException { + do { + int written = channel.write(buf); + if (written < 0) { + throw new EOFException(); + } + } while (buf.hasRemaining()); + } + + + public static void close(SelectionKey key) { + try { + key.channel().close(); + } catch (IOException e) { + // nop + } + + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Hex.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Hex.java.svn-base new file mode 100644 index 0000000..b3d55ef --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Hex.java.svn-base @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* +Extracted from commons-codec + */ +package com.coremedia.iso; + +import java.io.ByteArrayOutputStream; + +/** + * Converts hexadecimal Strings. + */ +public class Hex { + private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + public static String encodeHex(byte[] data) { + return encodeHex(data, 0); + } + + public static String encodeHex(byte[] data, int group) { + int l = data.length; + char[] out = new char[(l << 1) + (group > 0 ? (l / group) : 0)]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + if ((group > 0) && ((i % group) == 0) && j > 0) { + out[j++] = '-'; + } + + out[j++] = DIGITS[(0xF0 & data[i]) >>> 4]; + out[j++] = DIGITS[0x0F & data[i]]; + } + return new String(out); + } + + public static byte[] decodeHex(String hexString) { + ByteArrayOutputStream bas = new ByteArrayOutputStream(); + for (int i = 0; i < hexString.length(); i += 2) { + int b = Integer.parseInt(hexString.substring(i, i + 2), 16); + bas.write(b); + } + return bas.toByteArray(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoFile.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoFile.java.svn-base new file mode 100644 index 0000000..a6f4b2b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoFile.java.svn-base @@ -0,0 +1,195 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.MovieBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * The most upper container for ISO Boxes. It is a container box that is a file. + * Uses IsoBufferWrapper to access the underlying file. + */ +@DoNotParseDetail +public class IsoFile extends AbstractContainerBox implements Closeable { + protected BoxParser boxParser = new PropertyBoxParserImpl(); + ReadableByteChannel byteChannel; + + public IsoFile() { + super(""); + } + + public IsoFile(File f) throws IOException { + super(""); + this.byteChannel = new FileInputStream(f).getChannel(); + boxParser = createBoxParser(); + parse(); + } + + public IsoFile(ReadableByteChannel byteChannel) throws IOException { + super(""); + this.byteChannel = byteChannel; + boxParser = createBoxParser(); + parse(); + } + + public IsoFile(ReadableByteChannel byteChannel, BoxParser boxParser) throws IOException { + super(""); + this.byteChannel = byteChannel; + this.boxParser = boxParser; + parse(); + + + } + + protected BoxParser createBoxParser() { + return new PropertyBoxParserImpl(); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + // there are no details to parse we should be just file + } + + public void parse(ReadableByteChannel inFC, ByteBuffer header, long contentSize, AbstractBoxParser abstractBoxParser) throws IOException { + throw new IOException("This method is not meant to be called. Use #parse() directly."); + } + + private void parse() throws IOException { + + boolean done = false; + while (!done) { + try { + Box box = boxParser.parseBox(byteChannel, this); + if (box != null) { + // System.err.println(box.getType()); + boxes.add(box); + } else { + done = true; + } + } catch (EOFException e) { + done = true; + } + } + } + + @DoNotParseDetail + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("IsoFile["); + if (boxes == null) { + buffer.append("unparsed"); + } else { + for (int i = 0; i < boxes.size(); i++) { + if (i > 0) { + buffer.append(";"); + } + buffer.append(boxes.get(i).toString()); + } + } + buffer.append("]"); + return buffer.toString(); + } + + @DoNotParseDetail + public static byte[] fourCCtoBytes(String fourCC) { + byte[] result = new byte[4]; + if (fourCC != null) { + for (int i = 0; i < Math.min(4, fourCC.length()); i++) { + result[i] = (byte) fourCC.charAt(i); + } + } + return result; + } + + @DoNotParseDetail + public static String bytesToFourCC(byte[] type) { + byte[] result = new byte[]{0, 0, 0, 0}; + if (type != null) { + System.arraycopy(type, 0, result, 0, Math.min(type.length, 4)); + } + try { + return new String(result, "ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + throw new Error("Required character encoding is missing", e); + } + } + + + @Override + public long getNumOfBytesToFirstChild() { + return 0; + } + + @Override + public long getSize() { + long size = 0; + for (Box box : boxes) { + size += box.getSize(); + } + return size; + } + + @Override + public IsoFile getIsoFile() { + return this; + } + + + /** + * Shortcut to get the MovieBox since it is often needed and present in + * nearly all ISO 14496 files (at least if they are derived from MP4 ). + * + * @return the MovieBox or <code>null</code> + */ + @DoNotParseDetail + public MovieBox getMovieBox() { + for (Box box : boxes) { + if (box instanceof MovieBox) { + return (MovieBox) box; + } + } + return null; + } + + public void getBox(WritableByteChannel os) throws IOException { + for (Box box : boxes) { + + if (os instanceof FileChannel) { + long startPos = ((FileChannel) os).position(); + box.getBox(os); + long size = ((FileChannel) os).position() - startPos; + assert size == box.getSize(); + } else { + box.getBox(os); + } + + } + } + + public void close() throws IOException { + this.byteChannel.close(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReader.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReader.java.svn-base new file mode 100644 index 0000000..6d9e86e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReader.java.svn-base @@ -0,0 +1,147 @@ +/* + * 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.coremedia.iso; + +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; + +public final class IsoTypeReader { + + + public static long readUInt32BE(ByteBuffer bb) { + long ch1 = readUInt8(bb); + long ch2 = readUInt8(bb); + long ch3 = readUInt8(bb); + long ch4 = readUInt8(bb); + return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); + + } + + + public static long readUInt32(ByteBuffer bb) { + long i = bb.getInt(); + if (i < 0) { + i += 1l<<32; + } + return i; + } + + public static int readUInt24(ByteBuffer bb) { + int result = 0; + result += readUInt16(bb) << 8; + result += byte2int(bb.get()); + return result; + } + + + public static int readUInt16(ByteBuffer bb) { + int result = 0; + result += byte2int(bb.get()) << 8; + result += byte2int(bb.get()); + return result; + } + + public static int readUInt16BE(ByteBuffer bb) { + int result = 0; + result += byte2int(bb.get()); + result += byte2int(bb.get()) << 8; + return result; + } + + public static int readUInt8(ByteBuffer bb) { + return byte2int(bb.get()); + } + + public static int byte2int(byte b) { + return b < 0 ? b + 256 : b; + } + + + /** + * Reads a zero terminated UTF-8 string. + * + * @param byteBuffer the data source + * @return the string readByte + * @throws Error in case of an error in the underlying stream + */ + public static String readString(ByteBuffer byteBuffer) { + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int read; + while ((read = byteBuffer.get()) != 0) { + out.write(read); + } + return Utf8.convert(out.toByteArray()); + } + + public static String readString(ByteBuffer byteBuffer, int length) { + byte[] buffer = new byte[length]; + byteBuffer.get(buffer); + return Utf8.convert(buffer); + + } + + public static long readUInt64(ByteBuffer byteBuffer) { + long result = 0; + // thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed + result += readUInt32(byteBuffer) << 32; + if (result < 0) { + throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt"); + } + result += readUInt32(byteBuffer); + + return result; + } + + public static double readFixedPoint1616(ByteBuffer bb) { + byte[] bytes = new byte[4]; + bb.get(bytes); + + int result = 0; + result |= ((bytes[0] << 24) & 0xFF000000); + result |= ((bytes[1] << 16) & 0xFF0000); + result |= ((bytes[2] << 8) & 0xFF00); + result |= ((bytes[3]) & 0xFF); + return ((double) result) / 65536; + + } + + public static float readFixedPoint88(ByteBuffer bb) { + byte[] bytes = new byte[2]; + bb.get(bytes); + short result = 0; + result |= ((bytes[0] << 8) & 0xFF00); + result |= ((bytes[1]) & 0xFF); + return ((float) result) / 256; + } + + public static String readIso639(ByteBuffer bb) { + int bits = readUInt16(bb); + StringBuilder result = new StringBuilder(); + for (int i = 0; i < 3; i++) { + int c = (bits >> (2 - i) * 5) & 0x1f; + result.append((char) (c + 0x60)); + } + return result.toString(); + } + + public static String read4cc(ByteBuffer bb) { + byte[] b = new byte[4]; + bb.get(b); + return IsoFile.bytesToFourCC(b); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReaderVariable.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReaderVariable.java.svn-base new file mode 100644 index 0000000..a2e4681 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeReaderVariable.java.svn-base @@ -0,0 +1,39 @@ +/* + * 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.coremedia.iso; + +import java.nio.ByteBuffer; + +public final class IsoTypeReaderVariable { + + public static long read(ByteBuffer bb, int bytes) { + switch (bytes) { + case 1: + return IsoTypeReader.readUInt8(bb); + case 2: + return IsoTypeReader.readUInt16(bb); + case 3: + return IsoTypeReader.readUInt24(bb); + case 4: + return IsoTypeReader.readUInt32(bb); + case 8: + return IsoTypeReader.readUInt64(bb); + default: + throw new RuntimeException("I don't know how to read " + bytes + " bytes"); + } + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriter.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriter.java.svn-base new file mode 100644 index 0000000..6da6998 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriter.java.svn-base @@ -0,0 +1,95 @@ +/* + * 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.coremedia.iso; + +import java.nio.ByteBuffer; + +public final class IsoTypeWriter { + + public static void writeUInt64(ByteBuffer bb, long u) { + bb.putLong(u); + } + + public static void writeUInt32(ByteBuffer bb, long u) { + bb.putInt((int) u); + + } + + public static void writeUInt32BE(ByteBuffer bb, long u) { + assert u >= 0 && u <= 1L << 32 : "The given long is not in the range of uint32 (" + u + ")"; + writeUInt16BE(bb, (int) u & 0xFFFF); + writeUInt16BE(bb, (int) ((u >> 16) & 0xFFFF)); + + } + + + public static void writeUInt24(ByteBuffer bb, int i) { + i = i & 0xFFFFFF; + writeUInt16(bb, i >> 8); + writeUInt8(bb, i); + + } + + + public static void writeUInt16(ByteBuffer bb, int i) { + i = i & 0xFFFF; + writeUInt8(bb, i >> 8); + writeUInt8(bb, i & 0xFF); + } + + public static void writeUInt16BE(ByteBuffer bb, int i) { + i = i & 0xFFFF; + writeUInt8(bb, i & 0xFF); + writeUInt8(bb, i >> 8); + } + + public static void writeUInt8(ByteBuffer bb, int i) { + i = i & 0xFF; + bb.put((byte) i); + } + + + public static void writeFixedPont1616(ByteBuffer bb, double v) { + int result = (int) (v * 65536); + bb.put((byte) ((result & 0xFF000000) >> 24)); + bb.put((byte) ((result & 0x00FF0000) >> 16)); + bb.put((byte) ((result & 0x0000FF00) >> 8)); + bb.put((byte) ((result & 0x000000FF))); + } + + public static void writeFixedPont88(ByteBuffer bb, double v) { + short result = (short) (v * 256); + bb.put((byte) ((result & 0xFF00) >> 8)); + bb.put((byte) ((result & 0x00FF))); + } + + public static void writeIso639(ByteBuffer bb, String language) { + if (language.getBytes().length != 3) { + throw new IllegalArgumentException("\"" + language + "\" language string isn't exactly 3 characters long!"); + } + int bits = 0; + for (int i = 0; i < 3; i++) { + bits += (language.getBytes()[i] - 0x60) << (2 - i) * 5; + } + writeUInt16(bb, bits); + } + + public static void writeUtf8String(ByteBuffer bb, String string) { + + bb.put(Utf8.convert(string)); + writeUInt8(bb, 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriterVariable.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriterVariable.java.svn-base new file mode 100644 index 0000000..3b3bdd4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoTypeWriterVariable.java.svn-base @@ -0,0 +1,45 @@ +/* + * 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.coremedia.iso; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public final class IsoTypeWriterVariable { + + public static void write(long v, ByteBuffer bb, int bytes) { + switch (bytes) { + case 1: + IsoTypeWriter.writeUInt8(bb, (int) (v & 0xff)); + break; + case 2: + IsoTypeWriter.writeUInt16(bb, (int) (v & 0xffff)); + break; + case 3: + IsoTypeWriter.writeUInt24(bb, (int) (v & 0xffffff)); + break; + case 4: + IsoTypeWriter.writeUInt32(bb, v); + break; + case 8: + IsoTypeWriter.writeUInt64(bb, v); + break; + default: + throw new RuntimeException("I don't know how to read " + bytes + " bytes"); + } + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/PropertyBoxParserImpl.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/PropertyBoxParserImpl.java.svn-base new file mode 100644 index 0000000..f1bcc01 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/PropertyBoxParserImpl.java.svn-base @@ -0,0 +1,199 @@ +/* + * 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.coremedia.iso; + +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A Property file based BoxFactory + */ +public class PropertyBoxParserImpl extends AbstractBoxParser { + Properties mapping; + + public PropertyBoxParserImpl(String... customProperties) { + InputStream is = new BufferedInputStream(getClass().getResourceAsStream("/isoparser-default.properties")); + try { + mapping = new Properties(); + try { + mapping.load(is); + Enumeration<URL> enumeration = Thread.currentThread().getContextClassLoader().getResources("isoparser-custom.properties"); + + while (enumeration.hasMoreElements()) { + URL url = enumeration.nextElement(); + InputStream customIS = new BufferedInputStream(url.openStream()); + try { + mapping.load(customIS); + } finally { + customIS.close(); + } + } + for (String customProperty : customProperties) { + mapping.load(new BufferedInputStream(getClass().getResourceAsStream(customProperty))); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + // ignore - I can't help + } + } + } + + public PropertyBoxParserImpl(Properties mapping) { + this.mapping = mapping; + } + + Pattern p = Pattern.compile("(.*)\\((.*?)\\)"); + + @SuppressWarnings("unchecked") + public Class<? extends Box> getClassForFourCc(String type, byte[] userType, String parent) { + FourCcToBox fourCcToBox = new FourCcToBox(type, userType, parent).invoke(); + try { + return (Class<? extends Box>) Class.forName(fourCcToBox.clazzName); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public Box createBox(String type, byte[] userType, String parent) { + + FourCcToBox fourCcToBox = new FourCcToBox(type, userType, parent).invoke(); + String[] param = fourCcToBox.getParam(); + String clazzName = fourCcToBox.getClazzName(); + try { + if (param[0].trim().length() == 0) { + param = new String[]{}; + } + Class clazz = Class.forName(clazzName); + + Class[] constructorArgsClazz = new Class[param.length]; + Object[] constructorArgs = new Object[param.length]; + for (int i = 0; i < param.length; i++) { + + if ("userType".equals(param[i])) { + constructorArgs[i] = userType; + constructorArgsClazz[i] = byte[].class; + } else if ("type".equals(param[i])) { + constructorArgs[i] = type; + constructorArgsClazz[i] = String.class; + } else if ("parent".equals(param[i])) { + constructorArgs[i] = parent; + constructorArgsClazz[i] = String.class; + } else { + throw new InternalError("No such param: " + param[i]); + } + + + } + Constructor<AbstractBox> constructorObject; + try { + if (param.length > 0) { + constructorObject = clazz.getConstructor(constructorArgsClazz); + } else { + constructorObject = clazz.getConstructor(); + } + + return constructorObject.newInstance(constructorArgs); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private class FourCcToBox { + private String type; + private byte[] userType; + private String parent; + private String clazzName; + private String[] param; + + public FourCcToBox(String type, byte[] userType, String parent) { + this.type = type; + this.parent = parent; + this.userType = userType; + } + + public String getClazzName() { + return clazzName; + } + + public String[] getParam() { + return param; + } + + public FourCcToBox invoke() { + String constructor; + if (userType != null) { + if (!"uuid".equals((type))) { + throw new RuntimeException("we have a userType but no uuid box type. Something's wrong"); + } + constructor = mapping.getProperty((parent) + "-uuid[" + Hex.encodeHex(userType).toUpperCase() + "]"); + if (constructor == null) { + constructor = mapping.getProperty("uuid[" + Hex.encodeHex(userType).toUpperCase() + "]"); + } + if (constructor == null) { + constructor = mapping.getProperty("uuid"); + } + } else { + constructor = mapping.getProperty((parent) + "-" + (type)); + if (constructor == null) { + constructor = mapping.getProperty((type)); + } + } + if (constructor == null) { + constructor = mapping.getProperty("default"); + } + if (constructor == null) { + throw new RuntimeException("No box object found for " + type); + } + Matcher m = p.matcher(constructor); + boolean matches = m.matches(); + if (!matches) { + throw new RuntimeException("Cannot work with that constructor: " + constructor); + } + clazzName = m.group(1); + param = m.group(2).split(","); + return this; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Utf8.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Utf8.java.svn-base new file mode 100644 index 0000000..a30497e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/Utf8.java.svn-base @@ -0,0 +1,59 @@ +/* + * 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.coremedia.iso; + +import java.io.UnsupportedEncodingException; + +/** + * Converts <code>byte[]</code> -> <code>String</code> and vice versa. + */ +public final class Utf8 { + public static byte[] convert(String s) { + try { + if (s != null) { + return s.getBytes("UTF-8"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static String convert(byte[] b) { + try { + if (b != null) { + return new String(b, "UTF-8"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static int utf8StringLengthInBytes(String utf8) { + try { + if (utf8 != null) { + return utf8.getBytes("UTF-8").length; + } else { + return 0; + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(); + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/AbstractBoxParser.java b/isoparser/src/main/java/com/coremedia/iso/AbstractBoxParser.java new file mode 100644 index 0000000..6d92acd --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/AbstractBoxParser.java @@ -0,0 +1,130 @@ +/* + * 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.coremedia.iso; + +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.coremedia.iso.boxes.UserBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.util.logging.Logger; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This BoxParser handles the basic stuff like reading size and extracting box type. + */ +public abstract class AbstractBoxParser implements BoxParser { + + private static Logger LOG = Logger.getLogger(AbstractBoxParser.class.getName()); + + public abstract Box createBox(String type, byte[] userType, String parent); + + /** + * Parses the next size and type, creates a box instance and parses the box's content. + * + * @param byteChannel the FileChannel pointing to the ISO file + * @param parent the current box's parent (null if no parent) + * @return the box just parsed + * @throws java.io.IOException if reading from <code>in</code> fails + */ + public Box parseBox(ReadableByteChannel byteChannel, ContainerBox parent) throws IOException { + + + ByteBuffer header = ChannelHelper.readFully(byteChannel, 8); + + long size = IsoTypeReader.readUInt32(header); + // do plausibility check + if (size < 8 && size > 1) { + LOG.severe("Plausibility check failed: size < 8 (size = " + size + "). Stop parsing!"); + return null; + } + + + String type = IsoTypeReader.read4cc(header); + byte[] usertype = null; + long contentSize; + + if (size == 1) { + ByteBuffer bb = ByteBuffer.allocate(8); + byteChannel.read(bb); + bb.rewind(); + size = IsoTypeReader.readUInt64(bb); + contentSize = size - 16; + } else if (size == 0) { + if (byteChannel instanceof FileChannel) { + size = ((FileChannel) byteChannel).size() - ((FileChannel) byteChannel).position() - 8; + } else { + throw new RuntimeException("Only FileChannel inputs may use size == 0 (box reaches to the end of file)"); + } + contentSize = size - 8; + } else { + contentSize = size - 8; + } + if (UserBox.TYPE.equals(type)) { + ByteBuffer bb = ByteBuffer.allocate(16); + byteChannel.read(bb); + bb.rewind(); + usertype = bb.array(); + contentSize -= 16; + } + Box box = createBox(type, usertype, parent.getType()); + box.setParent(parent); + LOG.finest("Parsing " + box.getType()); + // System.out.println("parsing " + Arrays.toString(box.getType()) + " " + box.getClass().getName() + " size=" + size); + + + if (l2i(size - contentSize) == 8) { + // default - no large box - no uuid + // do nothing header's already correct + header.rewind(); + } else if (l2i(size - contentSize) == 16) { + header = ByteBuffer.allocate(16); + IsoTypeWriter.writeUInt32(header, 1); + header.put(IsoFile.fourCCtoBytes(type)); + IsoTypeWriter.writeUInt64(header, size); + } else if (l2i(size - contentSize) == 24) { + header = ByteBuffer.allocate(24); + IsoTypeWriter.writeUInt32(header, size); + header.put(IsoFile.fourCCtoBytes(type)); + header.put(usertype); + } else if (l2i(size - contentSize) == 32) { + header = ByteBuffer.allocate(32); + IsoTypeWriter.writeUInt32(header, size); + header.put(IsoFile.fourCCtoBytes(type)); + IsoTypeWriter.writeUInt64(header, size); + header.put(usertype); + } else { + throw new RuntimeException("I didn't expect that"); + } + + + box.parse(byteChannel, header, contentSize, this); + // System.out.println("box = " + box); + + + assert size == box.getSize() : + "Reconstructed Size is not x to the number of parsed bytes! (" + + box.getType() + ")" + + " Actual Box size: " + size + " Calculated size: " + box.getSize(); + return box; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/Ascii.java b/isoparser/src/main/java/com/coremedia/iso/Ascii.java new file mode 100644 index 0000000..2a659d7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/Ascii.java @@ -0,0 +1,47 @@ +/* + * 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.coremedia.iso; + +import java.io.UnsupportedEncodingException; + +/** + * Converts <code>byte[]</code> -> <code>String</code> and vice versa. + */ +public final class Ascii { + public static byte[] convert(String s) { + try { + if (s != null) { + return s.getBytes("us-ascii"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static String convert(byte[] b) { + try { + if (b != null) { + return new String(b, "us-ascii"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/BoxParser.java b/isoparser/src/main/java/com/coremedia/iso/BoxParser.java new file mode 100644 index 0000000..cbe9a6f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/BoxParser.java @@ -0,0 +1,31 @@ +/* + * 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.coremedia.iso; + +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.io.IOException; +import java.nio.channels.ReadableByteChannel; + +/** + * Basic interface to create boxes from a <code>IsoBufferWrapper</code> and its parent. + */ +public interface BoxParser { + Class<? extends Box> getClassForFourCc(String type, byte[] userType, String parent); + + Box parseBox(ReadableByteChannel in, ContainerBox parent) throws IOException; +} diff --git a/isoparser/src/main/java/com/coremedia/iso/ChannelHelper.java b/isoparser/src/main/java/com/coremedia/iso/ChannelHelper.java new file mode 100644 index 0000000..2ec1d05 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/ChannelHelper.java @@ -0,0 +1,90 @@ +/* + * 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.coremedia.iso; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.WritableByteChannel; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + + +public class ChannelHelper { + public static ByteBuffer readFully(final ReadableByteChannel channel, long size) throws IOException { + + if (channel instanceof FileChannel && size > 1024 * 1024) { + ByteBuffer bb = ((FileChannel) channel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) channel).position(), size); + ((FileChannel) channel).position(((FileChannel) channel).position() + size); + return bb; + } else { + ByteBuffer buf = ByteBuffer.allocate(l2i(size)); + readFully(channel, buf, buf.limit()); + buf.rewind(); + assert buf.limit() == size; + + return buf; + } + + } + + + public static void readFully(final ReadableByteChannel channel, final ByteBuffer buf) + throws IOException { + readFully(channel, buf, buf.remaining()); + } + + public static int readFully(final ReadableByteChannel channel, final ByteBuffer buf, final int length) + throws IOException { + int n, count = 0; + while (-1 != (n = channel.read(buf))) { + count += n; + if (count == length) { + break; + } + } + if (n == -1) { + throw new EOFException("End of file. No more boxes."); + } + return count; + } + + + public static void writeFully(final WritableByteChannel channel, final ByteBuffer buf) + throws IOException { + do { + int written = channel.write(buf); + if (written < 0) { + throw new EOFException(); + } + } while (buf.hasRemaining()); + } + + + public static void close(SelectionKey key) { + try { + key.channel().close(); + } catch (IOException e) { + // nop + } + + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/Hex.java b/isoparser/src/main/java/com/coremedia/iso/Hex.java new file mode 100644 index 0000000..b3d55ef --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/Hex.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* +Extracted from commons-codec + */ +package com.coremedia.iso; + +import java.io.ByteArrayOutputStream; + +/** + * Converts hexadecimal Strings. + */ +public class Hex { + private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + public static String encodeHex(byte[] data) { + return encodeHex(data, 0); + } + + public static String encodeHex(byte[] data, int group) { + int l = data.length; + char[] out = new char[(l << 1) + (group > 0 ? (l / group) : 0)]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + if ((group > 0) && ((i % group) == 0) && j > 0) { + out[j++] = '-'; + } + + out[j++] = DIGITS[(0xF0 & data[i]) >>> 4]; + out[j++] = DIGITS[0x0F & data[i]]; + } + return new String(out); + } + + public static byte[] decodeHex(String hexString) { + ByteArrayOutputStream bas = new ByteArrayOutputStream(); + for (int i = 0; i < hexString.length(); i += 2) { + int b = Integer.parseInt(hexString.substring(i, i + 2), 16); + bas.write(b); + } + return bas.toByteArray(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/IsoFile.java b/isoparser/src/main/java/com/coremedia/iso/IsoFile.java new file mode 100644 index 0000000..a6f4b2b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/IsoFile.java @@ -0,0 +1,195 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.MovieBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * The most upper container for ISO Boxes. It is a container box that is a file. + * Uses IsoBufferWrapper to access the underlying file. + */ +@DoNotParseDetail +public class IsoFile extends AbstractContainerBox implements Closeable { + protected BoxParser boxParser = new PropertyBoxParserImpl(); + ReadableByteChannel byteChannel; + + public IsoFile() { + super(""); + } + + public IsoFile(File f) throws IOException { + super(""); + this.byteChannel = new FileInputStream(f).getChannel(); + boxParser = createBoxParser(); + parse(); + } + + public IsoFile(ReadableByteChannel byteChannel) throws IOException { + super(""); + this.byteChannel = byteChannel; + boxParser = createBoxParser(); + parse(); + } + + public IsoFile(ReadableByteChannel byteChannel, BoxParser boxParser) throws IOException { + super(""); + this.byteChannel = byteChannel; + this.boxParser = boxParser; + parse(); + + + } + + protected BoxParser createBoxParser() { + return new PropertyBoxParserImpl(); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + // there are no details to parse we should be just file + } + + public void parse(ReadableByteChannel inFC, ByteBuffer header, long contentSize, AbstractBoxParser abstractBoxParser) throws IOException { + throw new IOException("This method is not meant to be called. Use #parse() directly."); + } + + private void parse() throws IOException { + + boolean done = false; + while (!done) { + try { + Box box = boxParser.parseBox(byteChannel, this); + if (box != null) { + // System.err.println(box.getType()); + boxes.add(box); + } else { + done = true; + } + } catch (EOFException e) { + done = true; + } + } + } + + @DoNotParseDetail + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("IsoFile["); + if (boxes == null) { + buffer.append("unparsed"); + } else { + for (int i = 0; i < boxes.size(); i++) { + if (i > 0) { + buffer.append(";"); + } + buffer.append(boxes.get(i).toString()); + } + } + buffer.append("]"); + return buffer.toString(); + } + + @DoNotParseDetail + public static byte[] fourCCtoBytes(String fourCC) { + byte[] result = new byte[4]; + if (fourCC != null) { + for (int i = 0; i < Math.min(4, fourCC.length()); i++) { + result[i] = (byte) fourCC.charAt(i); + } + } + return result; + } + + @DoNotParseDetail + public static String bytesToFourCC(byte[] type) { + byte[] result = new byte[]{0, 0, 0, 0}; + if (type != null) { + System.arraycopy(type, 0, result, 0, Math.min(type.length, 4)); + } + try { + return new String(result, "ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + throw new Error("Required character encoding is missing", e); + } + } + + + @Override + public long getNumOfBytesToFirstChild() { + return 0; + } + + @Override + public long getSize() { + long size = 0; + for (Box box : boxes) { + size += box.getSize(); + } + return size; + } + + @Override + public IsoFile getIsoFile() { + return this; + } + + + /** + * Shortcut to get the MovieBox since it is often needed and present in + * nearly all ISO 14496 files (at least if they are derived from MP4 ). + * + * @return the MovieBox or <code>null</code> + */ + @DoNotParseDetail + public MovieBox getMovieBox() { + for (Box box : boxes) { + if (box instanceof MovieBox) { + return (MovieBox) box; + } + } + return null; + } + + public void getBox(WritableByteChannel os) throws IOException { + for (Box box : boxes) { + + if (os instanceof FileChannel) { + long startPos = ((FileChannel) os).position(); + box.getBox(os); + long size = ((FileChannel) os).position() - startPos; + assert size == box.getSize(); + } else { + box.getBox(os); + } + + } + } + + public void close() throws IOException { + this.byteChannel.close(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/IsoTypeReader.java b/isoparser/src/main/java/com/coremedia/iso/IsoTypeReader.java new file mode 100644 index 0000000..6d9e86e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/IsoTypeReader.java @@ -0,0 +1,147 @@ +/* + * 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.coremedia.iso; + +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; + +public final class IsoTypeReader { + + + public static long readUInt32BE(ByteBuffer bb) { + long ch1 = readUInt8(bb); + long ch2 = readUInt8(bb); + long ch3 = readUInt8(bb); + long ch4 = readUInt8(bb); + return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); + + } + + + public static long readUInt32(ByteBuffer bb) { + long i = bb.getInt(); + if (i < 0) { + i += 1l<<32; + } + return i; + } + + public static int readUInt24(ByteBuffer bb) { + int result = 0; + result += readUInt16(bb) << 8; + result += byte2int(bb.get()); + return result; + } + + + public static int readUInt16(ByteBuffer bb) { + int result = 0; + result += byte2int(bb.get()) << 8; + result += byte2int(bb.get()); + return result; + } + + public static int readUInt16BE(ByteBuffer bb) { + int result = 0; + result += byte2int(bb.get()); + result += byte2int(bb.get()) << 8; + return result; + } + + public static int readUInt8(ByteBuffer bb) { + return byte2int(bb.get()); + } + + public static int byte2int(byte b) { + return b < 0 ? b + 256 : b; + } + + + /** + * Reads a zero terminated UTF-8 string. + * + * @param byteBuffer the data source + * @return the string readByte + * @throws Error in case of an error in the underlying stream + */ + public static String readString(ByteBuffer byteBuffer) { + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int read; + while ((read = byteBuffer.get()) != 0) { + out.write(read); + } + return Utf8.convert(out.toByteArray()); + } + + public static String readString(ByteBuffer byteBuffer, int length) { + byte[] buffer = new byte[length]; + byteBuffer.get(buffer); + return Utf8.convert(buffer); + + } + + public static long readUInt64(ByteBuffer byteBuffer) { + long result = 0; + // thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed + result += readUInt32(byteBuffer) << 32; + if (result < 0) { + throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt"); + } + result += readUInt32(byteBuffer); + + return result; + } + + public static double readFixedPoint1616(ByteBuffer bb) { + byte[] bytes = new byte[4]; + bb.get(bytes); + + int result = 0; + result |= ((bytes[0] << 24) & 0xFF000000); + result |= ((bytes[1] << 16) & 0xFF0000); + result |= ((bytes[2] << 8) & 0xFF00); + result |= ((bytes[3]) & 0xFF); + return ((double) result) / 65536; + + } + + public static float readFixedPoint88(ByteBuffer bb) { + byte[] bytes = new byte[2]; + bb.get(bytes); + short result = 0; + result |= ((bytes[0] << 8) & 0xFF00); + result |= ((bytes[1]) & 0xFF); + return ((float) result) / 256; + } + + public static String readIso639(ByteBuffer bb) { + int bits = readUInt16(bb); + StringBuilder result = new StringBuilder(); + for (int i = 0; i < 3; i++) { + int c = (bits >> (2 - i) * 5) & 0x1f; + result.append((char) (c + 0x60)); + } + return result.toString(); + } + + public static String read4cc(ByteBuffer bb) { + byte[] b = new byte[4]; + bb.get(b); + return IsoFile.bytesToFourCC(b); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/IsoTypeReaderVariable.java b/isoparser/src/main/java/com/coremedia/iso/IsoTypeReaderVariable.java new file mode 100644 index 0000000..a2e4681 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/IsoTypeReaderVariable.java @@ -0,0 +1,39 @@ +/* + * 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.coremedia.iso; + +import java.nio.ByteBuffer; + +public final class IsoTypeReaderVariable { + + public static long read(ByteBuffer bb, int bytes) { + switch (bytes) { + case 1: + return IsoTypeReader.readUInt8(bb); + case 2: + return IsoTypeReader.readUInt16(bb); + case 3: + return IsoTypeReader.readUInt24(bb); + case 4: + return IsoTypeReader.readUInt32(bb); + case 8: + return IsoTypeReader.readUInt64(bb); + default: + throw new RuntimeException("I don't know how to read " + bytes + " bytes"); + } + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriter.java b/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriter.java new file mode 100644 index 0000000..6da6998 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriter.java @@ -0,0 +1,95 @@ +/* + * 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.coremedia.iso; + +import java.nio.ByteBuffer; + +public final class IsoTypeWriter { + + public static void writeUInt64(ByteBuffer bb, long u) { + bb.putLong(u); + } + + public static void writeUInt32(ByteBuffer bb, long u) { + bb.putInt((int) u); + + } + + public static void writeUInt32BE(ByteBuffer bb, long u) { + assert u >= 0 && u <= 1L << 32 : "The given long is not in the range of uint32 (" + u + ")"; + writeUInt16BE(bb, (int) u & 0xFFFF); + writeUInt16BE(bb, (int) ((u >> 16) & 0xFFFF)); + + } + + + public static void writeUInt24(ByteBuffer bb, int i) { + i = i & 0xFFFFFF; + writeUInt16(bb, i >> 8); + writeUInt8(bb, i); + + } + + + public static void writeUInt16(ByteBuffer bb, int i) { + i = i & 0xFFFF; + writeUInt8(bb, i >> 8); + writeUInt8(bb, i & 0xFF); + } + + public static void writeUInt16BE(ByteBuffer bb, int i) { + i = i & 0xFFFF; + writeUInt8(bb, i & 0xFF); + writeUInt8(bb, i >> 8); + } + + public static void writeUInt8(ByteBuffer bb, int i) { + i = i & 0xFF; + bb.put((byte) i); + } + + + public static void writeFixedPont1616(ByteBuffer bb, double v) { + int result = (int) (v * 65536); + bb.put((byte) ((result & 0xFF000000) >> 24)); + bb.put((byte) ((result & 0x00FF0000) >> 16)); + bb.put((byte) ((result & 0x0000FF00) >> 8)); + bb.put((byte) ((result & 0x000000FF))); + } + + public static void writeFixedPont88(ByteBuffer bb, double v) { + short result = (short) (v * 256); + bb.put((byte) ((result & 0xFF00) >> 8)); + bb.put((byte) ((result & 0x00FF))); + } + + public static void writeIso639(ByteBuffer bb, String language) { + if (language.getBytes().length != 3) { + throw new IllegalArgumentException("\"" + language + "\" language string isn't exactly 3 characters long!"); + } + int bits = 0; + for (int i = 0; i < 3; i++) { + bits += (language.getBytes()[i] - 0x60) << (2 - i) * 5; + } + writeUInt16(bb, bits); + } + + public static void writeUtf8String(ByteBuffer bb, String string) { + + bb.put(Utf8.convert(string)); + writeUInt8(bb, 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriterVariable.java b/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriterVariable.java new file mode 100644 index 0000000..3b3bdd4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/IsoTypeWriterVariable.java @@ -0,0 +1,45 @@ +/* + * 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.coremedia.iso; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public final class IsoTypeWriterVariable { + + public static void write(long v, ByteBuffer bb, int bytes) { + switch (bytes) { + case 1: + IsoTypeWriter.writeUInt8(bb, (int) (v & 0xff)); + break; + case 2: + IsoTypeWriter.writeUInt16(bb, (int) (v & 0xffff)); + break; + case 3: + IsoTypeWriter.writeUInt24(bb, (int) (v & 0xffffff)); + break; + case 4: + IsoTypeWriter.writeUInt32(bb, v); + break; + case 8: + IsoTypeWriter.writeUInt64(bb, v); + break; + default: + throw new RuntimeException("I don't know how to read " + bytes + " bytes"); + } + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/PropertyBoxParserImpl.java b/isoparser/src/main/java/com/coremedia/iso/PropertyBoxParserImpl.java new file mode 100644 index 0000000..f1bcc01 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/PropertyBoxParserImpl.java @@ -0,0 +1,199 @@ +/* + * 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.coremedia.iso; + +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A Property file based BoxFactory + */ +public class PropertyBoxParserImpl extends AbstractBoxParser { + Properties mapping; + + public PropertyBoxParserImpl(String... customProperties) { + InputStream is = new BufferedInputStream(getClass().getResourceAsStream("/isoparser-default.properties")); + try { + mapping = new Properties(); + try { + mapping.load(is); + Enumeration<URL> enumeration = Thread.currentThread().getContextClassLoader().getResources("isoparser-custom.properties"); + + while (enumeration.hasMoreElements()) { + URL url = enumeration.nextElement(); + InputStream customIS = new BufferedInputStream(url.openStream()); + try { + mapping.load(customIS); + } finally { + customIS.close(); + } + } + for (String customProperty : customProperties) { + mapping.load(new BufferedInputStream(getClass().getResourceAsStream(customProperty))); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + // ignore - I can't help + } + } + } + + public PropertyBoxParserImpl(Properties mapping) { + this.mapping = mapping; + } + + Pattern p = Pattern.compile("(.*)\\((.*?)\\)"); + + @SuppressWarnings("unchecked") + public Class<? extends Box> getClassForFourCc(String type, byte[] userType, String parent) { + FourCcToBox fourCcToBox = new FourCcToBox(type, userType, parent).invoke(); + try { + return (Class<? extends Box>) Class.forName(fourCcToBox.clazzName); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public Box createBox(String type, byte[] userType, String parent) { + + FourCcToBox fourCcToBox = new FourCcToBox(type, userType, parent).invoke(); + String[] param = fourCcToBox.getParam(); + String clazzName = fourCcToBox.getClazzName(); + try { + if (param[0].trim().length() == 0) { + param = new String[]{}; + } + Class clazz = Class.forName(clazzName); + + Class[] constructorArgsClazz = new Class[param.length]; + Object[] constructorArgs = new Object[param.length]; + for (int i = 0; i < param.length; i++) { + + if ("userType".equals(param[i])) { + constructorArgs[i] = userType; + constructorArgsClazz[i] = byte[].class; + } else if ("type".equals(param[i])) { + constructorArgs[i] = type; + constructorArgsClazz[i] = String.class; + } else if ("parent".equals(param[i])) { + constructorArgs[i] = parent; + constructorArgsClazz[i] = String.class; + } else { + throw new InternalError("No such param: " + param[i]); + } + + + } + Constructor<AbstractBox> constructorObject; + try { + if (param.length > 0) { + constructorObject = clazz.getConstructor(constructorArgsClazz); + } else { + constructorObject = clazz.getConstructor(); + } + + return constructorObject.newInstance(constructorArgs); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private class FourCcToBox { + private String type; + private byte[] userType; + private String parent; + private String clazzName; + private String[] param; + + public FourCcToBox(String type, byte[] userType, String parent) { + this.type = type; + this.parent = parent; + this.userType = userType; + } + + public String getClazzName() { + return clazzName; + } + + public String[] getParam() { + return param; + } + + public FourCcToBox invoke() { + String constructor; + if (userType != null) { + if (!"uuid".equals((type))) { + throw new RuntimeException("we have a userType but no uuid box type. Something's wrong"); + } + constructor = mapping.getProperty((parent) + "-uuid[" + Hex.encodeHex(userType).toUpperCase() + "]"); + if (constructor == null) { + constructor = mapping.getProperty("uuid[" + Hex.encodeHex(userType).toUpperCase() + "]"); + } + if (constructor == null) { + constructor = mapping.getProperty("uuid"); + } + } else { + constructor = mapping.getProperty((parent) + "-" + (type)); + if (constructor == null) { + constructor = mapping.getProperty((type)); + } + } + if (constructor == null) { + constructor = mapping.getProperty("default"); + } + if (constructor == null) { + throw new RuntimeException("No box object found for " + type); + } + Matcher m = p.matcher(constructor); + boolean matches = m.matches(); + if (!matches) { + throw new RuntimeException("Cannot work with that constructor: " + constructor); + } + clazzName = m.group(1); + param = m.group(2).split(","); + return this; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/Utf8.java b/isoparser/src/main/java/com/coremedia/iso/Utf8.java new file mode 100644 index 0000000..a30497e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/Utf8.java @@ -0,0 +1,59 @@ +/* + * 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.coremedia.iso; + +import java.io.UnsupportedEncodingException; + +/** + * Converts <code>byte[]</code> -> <code>String</code> and vice versa. + */ +public final class Utf8 { + public static byte[] convert(String s) { + try { + if (s != null) { + return s.getBytes("UTF-8"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static String convert(byte[] b) { + try { + if (b != null) { + return new String(b, "UTF-8"); + } else { + return null; + } + } catch (UnsupportedEncodingException e) { + throw new Error(e); + } + } + + public static int utf8StringLengthInBytes(String utf8) { + try { + if (utf8 != null) { + return utf8.getBytes("UTF-8").length; + } else { + return 0; + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(); + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/all-wcprops new file mode 100644 index 0000000..8c356fa --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/all-wcprops @@ -0,0 +1,443 @@ +K 25 +svn:wc:ra_dav:version-url +V 71 +/svn/!svn/ver/777/trunk/isoparser/src/main/java/com/coremedia/iso/boxes +END +DataReferenceBox.java +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/DataReferenceBox.java +END +ChunkOffset64BitBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffset64BitBox.java +END +ItemDataBox.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ItemDataBox.java +END +BitRateBox.java +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/BitRateBox.java +END +UnknownBox.java +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/UnknownBox.java +END +XmlBox.java +K 25 +svn:wc:ra_dav:version-url +V 83 +/svn/!svn/ver/624/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/XmlBox.java +END +CompositionShiftLeastGreatestAtom.java +K 25 +svn:wc:ra_dav:version-url +V 110 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionShiftLeastGreatestAtom.java +END +TrackBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TrackBox.java +END +ItemProtectionBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ItemProtectionBox.java +END +SampleAuxiliaryInformationOffsetsBox.java +K 25 +svn:wc:ra_dav:version-url +V 113 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationOffsetsBox.java +END +SchemeInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeInformationBox.java +END +OmaDrmAccessUnitFormatBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/OmaDrmAccessUnitFormatBox.java +END +HintMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/HintMediaHeaderBox.java +END +SampleSizeBox.java +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleSizeBox.java +END +TrackHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TrackHeaderBox.java +END +CompositionTimeToSample.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java +END +UserBox.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/UserBox.java +END +MediaBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MediaBox.java +END +DataInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/DataInformationBox.java +END +FileTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/580/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/FileTypeBox.java +END +FreeBox.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/668/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/FreeBox.java +END +TitleBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TitleBox.java +END +NullMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/NullMediaHeaderBox.java +END +SampleDescriptionBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDescriptionBox.java +END +StaticChunkOffsetBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/StaticChunkOffsetBox.java +END +WriteListener.java +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/!svn/ver/98/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/WriteListener.java +END +RecordingYearBox.java +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/RecordingYearBox.java +END +PerformerBox.java +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/PerformerBox.java +END +AuthorBox.java +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/AuthorBox.java +END +SubtitleMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SubtitleMediaHeaderBox.java +END +ObjectDescriptorBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/84/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ObjectDescriptorBox.java +END +SchemeTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeTypeBox.java +END +KeywordsBox.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/KeywordsBox.java +END +AbstractMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/AbstractMediaHeaderBox.java +END +HandlerBox.java +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/HandlerBox.java +END +OriginalFormatBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/OriginalFormatBox.java +END +SampleToChunkBox.java +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleToChunkBox.java +END +Box.java +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/510/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/Box.java +END +DescriptionBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/DescriptionBox.java +END +EditBox.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/EditBox.java +END +ItemLocationBox.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ItemLocationBox.java +END +MovieHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/688/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MovieHeaderBox.java +END +ClassificationBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ClassificationBox.java +END +odf-boxes.zip +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/odf-boxes.zip +END +GenreBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/GenreBox.java +END +AlbumBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/AlbumBox.java +END +SubSampleInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SubSampleInformationBox.java +END +FullBox.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/FullBox.java +END +TimeToSampleBox.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TimeToSampleBox.java +END +UserDataBox.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/UserDataBox.java +END +CopyrightBox.java +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/CopyrightBox.java +END +SyncSampleBox.java +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SyncSampleBox.java +END +ChunkOffsetBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffsetBox.java +END +RatingBox.java +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/RatingBox.java +END +TrackReferenceTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceTypeBox.java +END +MetaBox.java +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MetaBox.java +END +MediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/616/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MediaHeaderBox.java +END +SampleTableBox.java +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleTableBox.java +END +rtp-boxes.zip +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/rtp-boxes.zip +END +FreeSpaceBox.java +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/FreeSpaceBox.java +END +SampleAuxiliaryInformationSizesBox.java +K 25 +svn:wc:ra_dav:version-url +V 111 +/svn/!svn/ver/727/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationSizesBox.java +END +SoundMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SoundMediaHeaderBox.java +END +ProgressiveDownloadInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 110 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ProgressiveDownloadInformationBox.java +END +DataEntryUrlBox.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrlBox.java +END +VideoMediaHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/VideoMediaHeaderBox.java +END +MovieBox.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MovieBox.java +END +DataEntryUrnBox.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrnBox.java +END +ProtectionSchemeInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ProtectionSchemeInformationBox.java +END +EditListBox.java +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/EditListBox.java +END +SampleDependencyTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDependencyTypeBox.java +END +ContainerBox.java +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/!svn/ver/132/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/ContainerBox.java +END +TrackReferenceBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceBox.java +END +MediaInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/MediaInformationBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/entries new file mode 100644 index 0000000..abb566b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/entries @@ -0,0 +1,2534 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes +http://mp4parser.googlecode.com/svn + + + +2012-09-10T14:56:10.036617Z +777 +sebastian.annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +DataReferenceBox.java +file + + + + +2012-09-14T17:27:53.057255Z +9903c0a889788836ccc2cb2265196393 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2206 + +ChunkOffset64BitBox.java +file + + + + +2012-09-14T17:27:53.057255Z +01fec67b09938a06c351b1f61ddd3eca +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +1288 + +ItemDataBox.java +file + + + + +2012-09-14T17:27:53.057255Z +d89b6e2c38b3dcd74a3574131391d0c0 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +823 + +BitRateBox.java +file + + + + +2012-09-14T17:27:53.057255Z +8b80a19e9d0180804dd3e8cdd51fe652 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2585 + +UnknownBox.java +file + + + + +2012-09-14T17:27:53.057255Z +6f1e688b0e1c8a5b4cb76b7e734f50d2 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1539 + +XmlBox.java +file + + + + +2012-09-14T17:27:53.057255Z +3466d3b5e977ee5cc212d3846f16f387 +2012-05-21T11:57:37.647327Z +624 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1079 + +CompositionShiftLeastGreatestAtom.java +file + + + + +2012-09-14T17:27:53.057255Z +409e9d1a7bf3d4c309d7d7f5847816d3 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3179 + +TrackBox.java +file + + + + +2012-09-14T17:27:53.057255Z +fee5b44d47cf99419d838238864e696c +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2234 + +ItemProtectionBox.java +file + + + + +2012-09-14T17:27:53.057255Z +78f95c81797d21680e71c2476caf5a19 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1810 + +vodafone +dir + +apple +dir + +SampleAuxiliaryInformationOffsetsBox.java +file + + + + +2012-09-14T17:27:53.057255Z +96eb95e44d49e9cf2cc480ad6e6a44a1 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3773 + +fragment +dir + +OmaDrmAccessUnitFormatBox.java +file + + + + +2012-09-14T17:27:53.057255Z +71e60410948a327722a34931d6b6690d +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2554 + +SchemeInformationBox.java +file + + + + +2012-09-14T17:27:53.067255Z +2b7467575e1b4ae45e2021528a5660ae +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1216 + +HintMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +a2face08c70d66256f2c0dc7fa9397c1 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2682 + +SampleSizeBox.java +file + + + + +2012-09-14T17:27:53.067255Z +8574502d967dcb457f9760c4613e9c60 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3416 + +TrackHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +c545735fa9f6b46b6ddaa97fa191b6ed +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +7950 + +CompositionTimeToSample.java +file + + + + +2012-09-14T17:27:53.067255Z +24d6bf8af948cf9724c9c6b963d60e05 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4123 + +UserBox.java +file + + + + +2012-09-14T17:27:53.067255Z +b2c4353c1cdfb1ae08f404b7d4c6e88a +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1629 + +MediaBox.java +file + + + + +2012-09-14T17:27:53.067255Z +8903b483282e444e19e09019396588e3 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1675 + +DataInformationBox.java +file + + + + +2012-09-14T17:27:53.067255Z +c06ffa206dbc8a97dab729e7e9d16127 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1169 + +FileTypeBox.java +file + + + + +2012-09-14T17:27:53.067255Z +019751b42d06e4caa726c38102be4820 +2012-05-04T18:32:18.338607Z +580 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4381 + +FreeBox.java +file + + + + +2012-09-14T17:27:53.067255Z +05c03ad86d424b209975515c10e27143 +2012-06-08T10:14:31.301984Z +668 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3395 + +TitleBox.java +file + + + + +2012-09-14T17:27:53.067255Z +f4b9dbcee26737350024b0d15e2aed1c +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2326 + +NullMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +2085a3a59a3ad7387eabc995525b0ac3 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1228 + +SampleDescriptionBox.java +file + + + + +2012-09-14T17:27:53.067255Z +a0c4559c8d7c474e32f6c491a82b78c7 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3328 + +WriteListener.java +file + + + + +2012-09-14T17:27:53.067255Z +3af0a5ef179d43c4bcbec9f9981dc397 +2011-03-09T17:58:20.876792Z +98 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +277 + +StaticChunkOffsetBox.java +file + + + + +2012-09-14T17:27:53.067255Z +fdb4124cdbd7503e86559be883fabbe9 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2079 + +mdat +dir + +RecordingYearBox.java +file + + + + +2012-09-14T17:27:53.067255Z +18244842b093dc4f2afed5e2fe83051f +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1602 + +PerformerBox.java +file + + + + +2012-09-14T17:27:53.067255Z +d1807b59f86c3b1c078f5424485504f3 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2225 + +AuthorBox.java +file + + + + +2012-09-14T17:27:53.067255Z +d277c32f45368d98c0e7f284b53af023 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2625 + +SubtitleMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +2d0a0d6508e401d64bba308335167c8f +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +619 + +ObjectDescriptorBox.java +file + + + + +2012-09-14T17:27:53.067255Z +d41d8cd98f00b204e9800998ecf8427e +2011-02-24T14:29:07.487725Z +84 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +0 + +SchemeTypeBox.java +file + + + + +2012-09-14T17:27:53.067255Z +e5aac0ed26846099c0c9b3901c605d34 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3147 + +KeywordsBox.java +file + + + + +2012-09-14T17:27:53.067255Z +1b30dd2dd9a4a2cc71dbbd93673454c5 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2884 + +dece +dir + +sampleentry +dir + +AbstractMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +fae5d0df177984d5429ec108759ff0ea +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +989 + +HandlerBox.java +file + + + + +2012-09-14T17:27:53.067255Z +7d0687f791f2a2a762df2ddb743fa15f +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +5425 + +OriginalFormatBox.java +file + + + + +2012-09-14T17:27:53.067255Z +ddb06cb6a4fdf016e8d74b02a916f026 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1844 + +SampleToChunkBox.java +file + + + + +2012-09-14T17:27:53.067255Z +bfe8cb30f157785f58eacf5e7e61033a +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +5178 + +Box.java +file + + + + +2012-09-14T17:27:53.067255Z +85e9f91cd74a90a0796c556689a72972 +2012-04-22T09:16:09.151890Z +510 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1677 + +DescriptionBox.java +file + + + + +2012-09-14T17:27:53.067255Z +64c10e153fbfc1dea0c14fe48ebf0a55 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2207 + +EditBox.java +file + + + + +2012-09-14T17:27:53.067255Z +75252edf8148360e335ebac2f838118f +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1066 + +ItemLocationBox.java +file + + + + +2012-09-14T17:27:53.067255Z +3e27a64bf1fd101c7fd324d9cdbb7f21 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +10845 + +MovieHeaderBox.java +file + + + + +2012-09-14T17:27:53.067255Z +d1eececbea781c89399d83dca0ecf5a0 +2012-06-24T21:02:28.697657Z +688 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +8025 + +h264 +dir + +ClassificationBox.java +file + + + + +2012-09-14T17:27:53.067255Z +a61f9cac340a30bfe69bbd3866a8179e +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3544 + +odf-boxes.zip +file + + + + +2012-09-14T17:27:53.067255Z +4c8dc9b701c5de0144269f58d168f621 +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +37706 + +GenreBox.java +file + + + + +2012-09-14T17:27:53.077255Z +8a42cc14e1f999aa99bbe26675991dc7 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2162 + +AlbumBox.java +file + + + + +2012-09-14T17:27:53.067255Z +063882f7ab178937a59190ff933ed1cf +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3360 + +SubSampleInformationBox.java +file + + + + +2012-09-14T17:27:53.077255Z +62c871d625fa41c8c5667b60e1a96084 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +7003 + +FullBox.java +file + + + + +2012-09-14T17:27:53.077255Z +b25b6cfe0af3936de4507b280c9a80f9 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +375 + +TimeToSampleBox.java +file + + + + +2012-09-14T17:27:53.077255Z +87761496666ed6ed43d1055c39daec07 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4719 + +UserDataBox.java +file + + + + +2012-09-14T17:27:53.077255Z +44ba8dc0558f53582186a9fb4bd937e5 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2209 + +CopyrightBox.java +file + + + + +2012-09-14T17:27:53.077255Z +d3fa4843e4ca4973476a0243b1e90c76 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2386 + +SyncSampleBox.java +file + + + + +2012-09-14T17:27:53.077255Z +e88379417c7537d02c2bdd14c16d2d98 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2444 + +ChunkOffsetBox.java +file + + + + +2012-09-14T17:27:53.077255Z +2a7cb5f28a7c28ff4125e73e44027e00 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +440 + +RatingBox.java +file + + + + +2012-09-14T17:27:53.077255Z +77d5aae6d65403599af0d0e62f65b44b +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3812 + +TrackReferenceTypeBox.java +file + + + + +2012-09-14T17:27:53.077255Z +01ff3b9bf0898d65ca27f199d4baee40 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2193 + +MetaBox.java +file + + + + +2012-09-14T17:27:53.077255Z +bd6ccb4b26b177f64b960d16da5f5a30 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3224 + +threegpp26244 +dir + +MediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.077255Z +9381ac78989b7089d482c2b44526c282 +2012-05-17T09:04:15.805545Z +616 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4561 + +SampleTableBox.java +file + + + + +2012-09-14T17:27:53.077255Z +7c86e7ceab9e74c9f681fed071a4dc0c +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4313 + +rtp-boxes.zip +file + + + + +2012-09-14T17:27:53.077255Z +b6fbe151f5fec8953cb3ce9e58784729 +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +31772 + +SampleAuxiliaryInformationSizesBox.java +file + + + + +2012-09-14T17:27:53.077255Z +31f750177546a2e82ca8de769972f872 +2012-08-08T07:05:08.133759Z +727 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4409 + +FreeSpaceBox.java +file + + + + +2012-09-14T17:27:53.077255Z +54792878d4a9e36d969c58ddd86692bf +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1724 + +SoundMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.077255Z +a997902bd90b258f996ef83e827e8580 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1639 + +ProgressiveDownloadInformationBox.java +file + + + + +2012-09-14T17:27:53.077255Z +8f230a1e42bea52f81bab49a91236f89 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2339 + +DataEntryUrlBox.java +file + + + + +2012-09-14T17:27:53.077255Z +c95d854ae68f925b06282c6aafdc07f6 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1389 + +VideoMediaHeaderBox.java +file + + + + +2012-09-14T17:27:53.077255Z +fce940b90e4ffe11ec8553c13cc9e357 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2420 + +MovieBox.java +file + + + + +2012-09-14T17:27:53.077255Z +847eb9e7c4bb29f730913b57ec25a68b +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2152 + +DataEntryUrnBox.java +file + + + + +2012-09-14T17:27:53.077255Z +af48983c19d5b39783baea8517578f53 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1956 + +ProtectionSchemeInformationBox.java +file + + + + +2012-09-14T17:27:53.077255Z +e2b7ff1f04405872d0da3dd9a22e1ac4 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1623 + +EditListBox.java +file + + + + +2012-09-14T17:27:53.077255Z +1b135924d295a0f357d8744a6b49ec3f +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +8432 + +SampleDependencyTypeBox.java +file + + + + +2012-09-14T17:27:53.077255Z +035c90e133e9799d14c92b5388cf4353 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3701 + +ContainerBox.java +file + + + + +2012-09-14T17:27:53.077255Z +77b4f7d07f35cfebac08c440d56986a0 +2011-05-13T11:05:56.209382Z +132 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2239 + +TrackReferenceBox.java +file + + + + +2012-09-14T17:27:53.077255Z +ea9697511c11cbe5115c898455b4f2e3 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1584 + +MediaInformationBox.java +file + + + + +2012-09-14T17:27:53.077255Z +c21e4a8822e8391001fcc3c1817a69ff +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1468 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffset64BitBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffset64BitBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffset64BitBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffsetBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffsetBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/ChunkOffsetBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/odf-boxes.zip.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/odf-boxes.zip.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/odf-boxes.zip.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/rtp-boxes.zip.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/rtp-boxes.zip.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/prop-base/rtp-boxes.zip.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AbstractMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AbstractMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..cc141ae --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AbstractMediaHeaderBox.java.svn-base @@ -0,0 +1,29 @@ +/* + * Copyright 2011 Sebastian Annies, Hamburg, Germany + * + * 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +/** + * A common superclass for all MediaInformationHeaderBoxes. E.g. + * VideoMediaHeaderBox, SoundMediaHeaderBox & HintMediaHeaderBox + */ +public abstract class AbstractMediaHeaderBox extends AbstractFullBox { + protected AbstractMediaHeaderBox(String type) { + super(type); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AlbumBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AlbumBox.java.svn-base new file mode 100644 index 0000000..d666806 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AlbumBox.java.svn-base @@ -0,0 +1,112 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Meta information in a 'udta' box about a track. + * Defined in 3GPP 26.244. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class AlbumBox extends AbstractFullBox { + public static final String TYPE = "albm"; + + private String language; + private String albumTitle; + private int trackNumber; + + public AlbumBox() { + super(TYPE); + } + + /** + * Declares the language code for the {@link #getAlbumTitle()} return value. See ISO 639-2/T for the set of three + * character codes.Each character is packed as the difference between its ASCII value and 0x60. The code is + * confined to being three lower-case letters, so these values are strictly positive. + * + * @return the language code + */ + public String getLanguage() { + return language; + } + + public String getAlbumTitle() { + return albumTitle; + } + + public int getTrackNumber() { + return trackNumber; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAlbumTitle(String albumTitle) { + this.albumTitle = albumTitle; + } + + public void setTrackNumber(int trackNumber) { + this.trackNumber = trackNumber; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(albumTitle) + 1 + (trackNumber == -1 ? 0 : 1); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + albumTitle = IsoTypeReader.readString(content); + + if (content.remaining() > 0) { + trackNumber = IsoTypeReader.readUInt8(content); + } else { + trackNumber = -1; + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(albumTitle)); + byteBuffer.put((byte) 0); + if (trackNumber != -1) { + IsoTypeWriter.writeUInt8(byteBuffer, trackNumber); + } + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("AlbumBox[language=").append(getLanguage()).append(";"); + buffer.append("albumTitle=").append(getAlbumTitle()); + if (trackNumber >= 0) { + buffer.append(";trackNumber=").append(getTrackNumber()); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AuthorBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AuthorBox.java.svn-base new file mode 100644 index 0000000..672cde2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/AuthorBox.java.svn-base @@ -0,0 +1,94 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Meta information in a 'udta' box about a track. + * Defined in 3GPP 26.244. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class AuthorBox extends AbstractFullBox { + public static final String TYPE = "auth"; + + private String language; + private String author; + + public AuthorBox() { + super(TYPE); + } + + /** + * Declares the language code for the {@link #getAuthor()} return value. See ISO 639-2/T for the set of three + * character codes.Each character is packed as the difference between its ASCII value and 0x60. The code is + * confined to being three lower-case letters, so these values are strictly positive. + * + * @return the language code + */ + public String getLanguage() { + return language; + } + + /** + * Author information. + * + * @return the author + */ + public String getAuthor() { + return author; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAuthor(String author) { + this.author = author; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(author); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + author = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(author)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + return "AuthorBox[language=" + getLanguage() + ";author=" + getAuthor() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/BitRateBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/BitRateBox.java.svn-base new file mode 100644 index 0000000..6c4b0e6 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/BitRateBox.java.svn-base @@ -0,0 +1,91 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * <code>class BitRateBox extends Box('btrt') {<br/> + * unsigned int(32) bufferSizeDB;<br/> + * // gives the size of the decoding buffer for<br/> + * // the elementary stream in bytes.<br/> + * unsigned int(32) maxBitrate;<br/> + * // gives the maximum rate in bits/second <br/> + * // over any window of one second.<br/> + * unsigned int(32) avgBitrate;<br/> + * // avgBitrate gives the average rate in <br/> + * // bits/second over the entire presentation.<br/> + * }</code> + */ + +public final class BitRateBox extends AbstractBox { + public static final String TYPE = "btrt"; + + private long bufferSizeDb; + private long maxBitrate; + private long avgBitrate; + + public BitRateBox() { + super(TYPE); + } + + protected long getContentSize() { + return 12; + } + + @Override + public void _parseDetails(ByteBuffer content) { + bufferSizeDb = IsoTypeReader.readUInt32(content); + maxBitrate = IsoTypeReader.readUInt32(content); + avgBitrate = IsoTypeReader.readUInt32(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + IsoTypeWriter.writeUInt32(byteBuffer, bufferSizeDb); + IsoTypeWriter.writeUInt32(byteBuffer, maxBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, avgBitrate); + } + + public long getBufferSizeDb() { + return bufferSizeDb; + } + + public void setBufferSizeDb(long bufferSizeDb) { + this.bufferSizeDb = bufferSizeDb; + } + + public long getMaxBitrate() { + return maxBitrate; + } + + public void setMaxBitrate(long maxBitrate) { + this.maxBitrate = maxBitrate; + } + + public long getAvgBitrate() { + return avgBitrate; + } + + public void setAvgBitrate(long avgBitrate) { + this.avgBitrate = avgBitrate; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/Box.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/Box.java.svn-base new file mode 100644 index 0000000..f6ca302 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/Box.java.svn-base @@ -0,0 +1,51 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.boxes.ContainerBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * Defines basic interaction possibilities for any ISO box. Each box has a parent box and a type. + */ +public interface Box { + ContainerBox getParent(); + + void setParent(ContainerBox parent); + + long getSize(); + + /** + * The box's 4-cc type. + * @return the 4 character type of the box + */ + String getType(); + + /** + * Writes the complete box - size | 4-cc | content - to the given <code>writableByteChannel</code>. + * @param writableByteChannel the box's sink + * @throws IOException in case of problems with the <code>Channel</code> + */ + void getBox(WritableByteChannel writableByteChannel) throws IOException; + + void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException; +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffset64BitBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffset64BitBox.java.svn-base new file mode 100644 index 0000000..f2340b9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffset64BitBox.java.svn-base @@ -0,0 +1,51 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Abstract Chunk Offset Box + */ +public class ChunkOffset64BitBox extends ChunkOffsetBox { + public static final String TYPE = "co64"; + private long[] chunkOffsets; + + public ChunkOffset64BitBox() { + super(TYPE); + } + + @Override + public long[] getChunkOffsets() { + return chunkOffsets; + } + + @Override + protected long getContentSize() { + return 8 + 8 * chunkOffsets.length; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + chunkOffsets = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + chunkOffsets[i] = IsoTypeReader.readUInt64(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffsets.length); + for (long chunkOffset : chunkOffsets) { + IsoTypeWriter.writeUInt64(byteBuffer, chunkOffset); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffsetBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffsetBox.java.svn-base new file mode 100644 index 0000000..01f5ae4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ChunkOffsetBox.java.svn-base @@ -0,0 +1,21 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +/** + * Abstract Chunk Offset Box + */ +public abstract class ChunkOffsetBox extends AbstractFullBox { + + public ChunkOffsetBox(String type) { + super(type); + } + + public abstract long[] getChunkOffsets(); + + + public String toString() { + return this.getClass().getSimpleName() + "[entryCount=" + getChunkOffsets().length + "]"; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ClassificationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ClassificationBox.java.svn-base new file mode 100644 index 0000000..a20feca --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ClassificationBox.java.svn-base @@ -0,0 +1,110 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Classification of the media according to 3GPP 26.244. + */ +public class ClassificationBox extends AbstractFullBox { + public static final String TYPE = "clsf"; + + + private String classificationEntity; + private int classificationTableIndex; + private String language; + private String classificationInfo; + + public ClassificationBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getClassificationEntity() { + return classificationEntity; + } + + public int getClassificationTableIndex() { + return classificationTableIndex; + } + + public String getClassificationInfo() { + return classificationInfo; + } + + public void setClassificationEntity(String classificationEntity) { + this.classificationEntity = classificationEntity; + } + + public void setClassificationTableIndex(int classificationTableIndex) { + this.classificationTableIndex = classificationTableIndex; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setClassificationInfo(String classificationInfo) { + this.classificationInfo = classificationInfo; + } + + protected long getContentSize() { + return 4 + 2 + 2 + Utf8.utf8StringLengthInBytes(classificationInfo) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + byte[] cE = new byte[4]; + content.get(cE); + classificationEntity = IsoFile.bytesToFourCC(cE); + classificationTableIndex = IsoTypeReader.readUInt16(content); + language = IsoTypeReader.readIso639(content); + classificationInfo = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(classificationEntity)); + IsoTypeWriter.writeUInt16(byteBuffer, classificationTableIndex); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(classificationInfo)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("ClassificationBox[language=").append(getLanguage()); + buffer.append("classificationEntity=").append(getClassificationEntity()); + buffer.append(";classificationTableIndex=").append(getClassificationTableIndex()); + buffer.append(";language=").append(getLanguage()); + buffer.append(";classificationInfo=").append(getClassificationInfo()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionShiftLeastGreatestAtom.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionShiftLeastGreatestAtom.java.svn-base new file mode 100644 index 0000000..3534b7f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionShiftLeastGreatestAtom.java.svn-base @@ -0,0 +1,101 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The optional composition shift least greatest atom summarizes the calculated + * minimum and maximum offsets between decode and composition time, as well as + * the start and end times, for all samples. This allows a reader to determine + * the minimum required time for decode to obtain proper presentation order without + * needing to scan the sample table for the range of offsets. The type of the + * composition shift least greatest atom is ‘cslg’. + */ +public class CompositionShiftLeastGreatestAtom extends AbstractFullBox { + public CompositionShiftLeastGreatestAtom() { + super("cslg"); + } + + // A 32-bit unsigned integer that specifies the calculated value. + int compositionOffsetToDisplayOffsetShift; + + // A 32-bit signed integer that specifies the calculated value. + int leastDisplayOffset; + + // A 32-bit signed integer that specifies the calculated value. + int greatestDisplayOffset; + + //A 32-bit signed integer that specifies the calculated value. + int displayStartTime; + + //A 32-bit signed integer that specifies the calculated value. + int displayEndTime; + + + @Override + protected long getContentSize() { + return 24; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + compositionOffsetToDisplayOffsetShift = content.getInt(); + leastDisplayOffset = content.getInt(); + greatestDisplayOffset = content.getInt(); + displayStartTime = content.getInt(); + displayEndTime = content.getInt(); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.putInt(compositionOffsetToDisplayOffsetShift); + byteBuffer.putInt(leastDisplayOffset); + byteBuffer.putInt(greatestDisplayOffset); + byteBuffer.putInt(displayStartTime); + byteBuffer.putInt(displayEndTime); + } + + + public int getCompositionOffsetToDisplayOffsetShift() { + return compositionOffsetToDisplayOffsetShift; + } + + public void setCompositionOffsetToDisplayOffsetShift(int compositionOffsetToDisplayOffsetShift) { + this.compositionOffsetToDisplayOffsetShift = compositionOffsetToDisplayOffsetShift; + } + + public int getLeastDisplayOffset() { + return leastDisplayOffset; + } + + public void setLeastDisplayOffset(int leastDisplayOffset) { + this.leastDisplayOffset = leastDisplayOffset; + } + + public int getGreatestDisplayOffset() { + return greatestDisplayOffset; + } + + public void setGreatestDisplayOffset(int greatestDisplayOffset) { + this.greatestDisplayOffset = greatestDisplayOffset; + } + + public int getDisplayStartTime() { + return displayStartTime; + } + + public void setDisplayStartTime(int displayStartTime) { + this.displayStartTime = displayStartTime; + } + + public int getDisplayEndTime() { + return displayEndTime; + } + + public void setDisplayEndTime(int displayEndTime) { + this.displayEndTime = displayEndTime; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionTimeToSample.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionTimeToSample.java.svn-base new file mode 100644 index 0000000..411bfe9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CompositionTimeToSample.java.svn-base @@ -0,0 +1,150 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * <pre> + * aligned(8) class CompositionOffsetBox + * extends FullBox(‘ctts’, version = 0, 0) { + * unsigned int(32) entry_count; + * int i; + * if (version==0) { + * for (i=0; i < entry_count; i++) { + * unsigned int(32) sample_count; + * unsigned int(32) sample_offset; + * } + * } + * else if (version == 1) { + * for (i=0; i < entry_count; i++) { + * unsigned int(32) sample_count; + * signed int(32) sample_offset; + * } + * } + * } + * </pre> + * <p/> + * This box provides the offset between decoding time and composition time. + * In version 0 of this box the decoding time must be less than the composition time, and + * the offsets are expressed as unsigned numbers such that + * CT(n) = DT(n) + CTTS(n) where CTTS(n) is the (uncompressed) table entry for sample n. + * <p/> + * In version 1 of this box, the composition timeline and the decoding timeline are + * still derived from each other, but the offsets are signed. + * It is recommended that for the computed composition timestamps, there is + * exactly one with the value 0 (zero). + */ +public class CompositionTimeToSample extends AbstractFullBox { + public static final String TYPE = "ctts"; + + List<Entry> entries = Collections.emptyList(); + + public CompositionTimeToSample() { + super(TYPE); + } + + protected long getContentSize() { + return 8 + 8 * entries.size(); + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int numberOfEntries = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(numberOfEntries); + for (int i = 0; i < numberOfEntries; i++) { + Entry e = new Entry(l2i(IsoTypeReader.readUInt32(content)), content.getInt()); + entries.add(e); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount()); + byteBuffer.putInt(entry.getOffset()); + } + + } + + + public static class Entry { + int count; + int offset; + + public Entry(int count, int offset) { + this.count = count; + this.offset = offset; + } + + public int getCount() { + return count; + } + + public int getOffset() { + return offset; + } + + public void setCount(int count) { + this.count = count; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + @Override + public String toString() { + return "Entry{" + + "count=" + count + + ", offset=" + offset + + '}'; + } + } + + + /** + * Decompresses the list of entries and returns the list of composition times. + * + * @return decoding time per sample + */ + public static int[] blowupCompositionTimes(List<CompositionTimeToSample.Entry> entries) { + long numOfSamples = 0; + for (CompositionTimeToSample.Entry entry : entries) { + numOfSamples += entry.getCount(); + } + assert numOfSamples <= Integer.MAX_VALUE; + int[] decodingTime = new int[(int) numOfSamples]; + + int current = 0; + + + for (CompositionTimeToSample.Entry entry : entries) { + for (int i = 0; i < entry.getCount(); i++) { + decodingTime[current++] = entry.getOffset(); + } + } + + return decodingTime; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ContainerBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ContainerBox.java.svn-base new file mode 100644 index 0000000..a016374 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ContainerBox.java.svn-base @@ -0,0 +1,74 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; + +import java.util.List; + +/** + * Interface for all ISO boxes that may contain other boxes. + */ +public interface ContainerBox extends Box { + + /** + * Gets all child boxes. May not return <code>null</code>. + * + * @return an array of boxes, empty array in case of no children. + */ + List<Box> getBoxes(); + + /** + * Sets all boxes and removes all previous child boxes. + * @param boxes the new list of children + */ + void setBoxes(List<Box> boxes); + + /** + * Gets all child boxes of the given type. May not return <code>null</code>. + * + * @param clazz child box's type + * @return an array of boxes, empty array in case of no children. + */ + <T extends Box> List<T> getBoxes(Class<T> clazz); + + /** + * Gets all child boxes of the given type. May not return <code>null</code>. + * + * @param clazz child box's type + * @param recursive step down the tree + * @return an array of boxes, empty array in case of no children. + */ + <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive); + + /** + * Gets the parent box. May be <code>null</code> in case of the + * {@link com.coremedia.iso.IsoFile} itself. + * + * @return a <code>ContainerBox</code> that contains <code>this</code> + */ + ContainerBox getParent(); + + /** + * Returns the number of bytes from the start of the box to start of the first child. + * + * @return offset of first child from box start + */ + long getNumOfBytesToFirstChild(); + + IsoFile getIsoFile(); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CopyrightBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CopyrightBox.java.svn-base new file mode 100644 index 0000000..86bc215 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/CopyrightBox.java.svn-base @@ -0,0 +1,86 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The copyright box contains a copyright declaration which applies to the entire presentation, when contained + * within the MovieBox, or, when contained in a track, to that entire track. There may be multple boxes using + * different language codes. + * + * @see MovieBox + * @see TrackBox + */ +public class CopyrightBox extends AbstractFullBox { + public static final String TYPE = "cprt"; + + private String language; + private String copyright; + + public CopyrightBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getCopyright() { + return copyright; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setCopyright(String copyright) { + this.copyright = copyright; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(copyright); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + copyright = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(copyright)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "CopyrightBox[language=" + getLanguage() + ";copyright=" + getCopyright() + "]"; + } + + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrlBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrlBox.java.svn-base new file mode 100644 index 0000000..b58608d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrlBox.java.svn-base @@ -0,0 +1,53 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Only used within the DataReferenceBox. Find more information there. + * + * @see com.coremedia.iso.boxes.DataReferenceBox + */ +public class DataEntryUrlBox extends AbstractFullBox { + public static final String TYPE = "url "; + + public DataEntryUrlBox() { + super(TYPE); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } + + protected long getContentSize() { + return 4; + } + + public String toString() { + return "DataEntryUrlBox[]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrnBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrnBox.java.svn-base new file mode 100644 index 0000000..042a972 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataEntryUrnBox.java.svn-base @@ -0,0 +1,69 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Only used within the DataReferenceBox. Find more information there. + * + * @see com.coremedia.iso.boxes.DataReferenceBox + */ +public class DataEntryUrnBox extends AbstractFullBox { + private String name; + private String location; + public static final String TYPE = "urn "; + + public DataEntryUrnBox() { + super(TYPE); + } + + public String getName() { + return name; + } + + public String getLocation() { + return location; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(name) + 1 + Utf8.utf8StringLengthInBytes(location) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + name = IsoTypeReader.readString(content); + location = IsoTypeReader.readString(content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(Utf8.convert(name)); + byteBuffer.put((byte) 0); + byteBuffer.put(Utf8.convert(location)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "DataEntryUrlBox[name=" + getName() + ";location=" + getLocation() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataInformationBox.java.svn-base new file mode 100644 index 0000000..7f058eb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataInformationBox.java.svn-base @@ -0,0 +1,36 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * <code> + * Box Type: 'dinf'<br> + * Container: {@link com.coremedia.iso.boxes.MediaInformationBox} ('minf')<br> + * Mandatory: Yes<br> + * Quantity: Exactly one<br><br></code> + * The data information box contains objects that declare the location of the media information in a track. + */ +public class DataInformationBox extends AbstractContainerBox { + public static final String TYPE = "dinf"; + + public DataInformationBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataReferenceBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataReferenceBox.java.svn-base new file mode 100644 index 0000000..8156d3f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DataReferenceBox.java.svn-base @@ -0,0 +1,65 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The data reference object contains a table of data references (normally URLs) that declare the location(s) of + * the media data used within the presentation. The data reference index in the sample description ties entries in + * this table to the samples in the track. A track may be split over several sources in this way. + * If the flag is set indicating that the data is in the same file as this box, then no string (not even an empty one) + * shall be supplied in the entry field. + * The DataEntryBox within the DataReferenceBox shall be either a DataEntryUrnBox or a DataEntryUrlBox. + * + * @see com.coremedia.iso.boxes.DataEntryUrlBox + * @see com.coremedia.iso.boxes.DataEntryUrnBox + */ +public class DataReferenceBox extends FullContainerBox { + + public static final String TYPE = "dref"; + + public DataReferenceBox() { + super(TYPE); + + } + + @Override + protected long getContentSize() { + return super.getContentSize() + 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + content.get(new byte[4]); // basically a skip of 4 bytes signaling the number of child boxes + parseChildBoxes(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, getBoxes().size()); + writeChildBoxes(byteBuffer); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DescriptionBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DescriptionBox.java.svn-base new file mode 100644 index 0000000..8352051 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/DescriptionBox.java.svn-base @@ -0,0 +1,77 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Gives a language dependent description of the media contained in the ISO file. + */ +public class DescriptionBox extends AbstractFullBox { + public static final String TYPE = "dscp"; + + private String language; + private String description; + + public DescriptionBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getDescription() { + return description; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(description); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + description = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(description)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "DescriptionBox[language=" + getLanguage() + ";description=" + getDescription() + "]"; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditBox.java.svn-base new file mode 100644 index 0000000..db3bc25 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditBox.java.svn-base @@ -0,0 +1,34 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * An Edit Box maps the presentation time-line to the media time-line as it is stored in the file. + * The Edit Box is a container fpr the edit lists. Defined in ISO/IEC 14496-12. + * + * @see EditListBox + */ +public class EditBox extends AbstractContainerBox { + public static final String TYPE = "edts"; + + public EditBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditListBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditListBox.java.svn-base new file mode 100644 index 0000000..231f8be --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/EditListBox.java.svn-base @@ -0,0 +1,248 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * <code> + * Box Type : 'elst'<br> + * Container: {@link EditBox}('edts')<br> + * Mandatory: No<br> + * Quantity : Zero or one</code><br><br> + * This box contains an explicit timeline map. Each entry defines part of the track time-line: by mapping part of + * the media time-line, or by indicating 'empty' time, or by defining a 'dwell', where a single time-point in the + * media is held for a period.<br> + * Note that edits are not restricted to fall on sample times. This means that when entering an edit, it can be + * necessary to (a) back up to a sync point, and pre-roll from there and then (b) be careful about the duration of + * the first sample - it might have been truncated if the edit enters it during its normal duration. If this is audio, + * that frame might need to be decoded, and then the final slicing done. Likewise, the duration of the last sample + * in an edit might need slicing. <br> + * Starting offsets for tracks (streams) are represented by an initial empty edit. For example, to play a track from + * its start for 30 seconds, but at 10 seconds into the presentation, we have the following edit list:<br> + * <p/> + * <li>Entry-count = 2</li> + * <li>Segment-duration = 10 seconds</li> + * <li>Media-Time = -1</li> + * <li>Media-Rate = 1</li> + * <li>Segment-duration = 30 seconds (could be the length of the whole track)</li> + * <li>Media-Time = 0 seconds</li> + * <li>Media-Rate = 1</li> + */ +public class EditListBox extends AbstractFullBox { + private List<Entry> entries = new LinkedList<Entry>(); + public static final String TYPE = "elst"; + + public EditListBox() { + super(TYPE); + } + + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + protected long getContentSize() { + long contentSize = 8; + if (getVersion() == 1) { + contentSize += entries.size() * 20; + } else { + contentSize += entries.size() * 12; + } + + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new LinkedList<Entry>(); + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry(this, content)); + + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + entry.getContent(byteBuffer); + } + } + + @Override + public String toString() { + return "EditListBox{" + + "entries=" + entries + + '}'; + } + + public static class Entry { + private long segmentDuration; + private long mediaTime; + private double mediaRate; + EditListBox editListBox; + + /** + * Creates a new <code>Entry</code> with all values set. + * + * @param segmentDuration duration in movie timescale + * @param mediaTime starting time + * @param mediaRate relative play rate + */ + public Entry(EditListBox editListBox, long segmentDuration, long mediaTime, double mediaRate) { + this.segmentDuration = segmentDuration; + this.mediaTime = mediaTime; + this.mediaRate = mediaRate; + this.editListBox = editListBox; + } + + public Entry(EditListBox editListBox, ByteBuffer bb) { + if (editListBox.getVersion() == 1) { + segmentDuration = IsoTypeReader.readUInt64(bb); + mediaTime = IsoTypeReader.readUInt64(bb); + mediaRate = IsoTypeReader.readFixedPoint1616(bb); + } else { + segmentDuration = IsoTypeReader.readUInt32(bb); + mediaTime = IsoTypeReader.readUInt32(bb); + mediaRate = IsoTypeReader.readFixedPoint1616(bb); + } + this.editListBox = editListBox; + } + + /** + * The segment duration is an integer that specifies the duration + * of this edit segment in units of the timescale in the Movie + * Header Box + * + * @return segment duration in movie timescale + */ + public long getSegmentDuration() { + return segmentDuration; + } + + /** + * The segment duration is an integer that specifies the duration + * of this edit segment in units of the timescale in the Movie + * Header Box + * + * @param segmentDuration new segment duration in movie timescale + */ + public void setSegmentDuration(long segmentDuration) { + this.segmentDuration = segmentDuration; + } + + /** + * The media time is an integer containing the starting time + * within the media of a specific edit segment(in media time + * scale units, in composition time) + * + * @return starting time + */ + public long getMediaTime() { + return mediaTime; + } + + /** + * The media time is an integer containing the starting time + * within the media of a specific edit segment(in media time + * scale units, in composition time) + * + * @param mediaTime starting time + */ + public void setMediaTime(long mediaTime) { + this.mediaTime = mediaTime; + } + + /** + * The media rate specifies the relative rate at which to play the + * media corresponding to a specific edit segment. + * + * @return relative play rate + */ + public double getMediaRate() { + return mediaRate; + } + + /** + * The media rate specifies the relative rate at which to play the + * media corresponding to a specific edit segment. + * + * @param mediaRate new relative play rate + */ + public void setMediaRate(double mediaRate) { + this.mediaRate = mediaRate; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Entry entry = (Entry) o; + + if (mediaTime != entry.mediaTime) return false; + if (segmentDuration != entry.segmentDuration) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (segmentDuration ^ (segmentDuration >>> 32)); + result = 31 * result + (int) (mediaTime ^ (mediaTime >>> 32)); + return result; + } + + public void getContent(ByteBuffer bb) { + if (editListBox.getVersion() == 1) { + IsoTypeWriter.writeUInt64(bb, segmentDuration); + IsoTypeWriter.writeUInt64(bb, mediaTime); + } else { + IsoTypeWriter.writeUInt32(bb, l2i(segmentDuration)); + bb.putInt(l2i(mediaTime)); + } + IsoTypeWriter.writeFixedPont1616(bb, mediaRate); + } + + @Override + public String toString() { + return "Entry{" + + "segmentDuration=" + segmentDuration + + ", mediaTime=" + mediaTime + + ", mediaRate=" + mediaRate + + '}'; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FileTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FileTypeBox.java.svn-base new file mode 100644 index 0000000..e6eed20 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FileTypeBox.java.svn-base @@ -0,0 +1,144 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * This box identifies the specifications to which this file complies. <br> + * Each brand is a printable four-character code, registered with ISO, that + * identifies a precise specification. + */ +public class FileTypeBox extends AbstractBox { + public static final String TYPE = "ftyp"; + + private String majorBrand; + private long minorVersion; + private List<String> compatibleBrands = Collections.emptyList(); + + public FileTypeBox() { + super(TYPE); + } + + public FileTypeBox(String majorBrand, long minorVersion, List<String> compatibleBrands) { + super(TYPE); + this.majorBrand = majorBrand; + this.minorVersion = minorVersion; + this.compatibleBrands = compatibleBrands; + } + + protected long getContentSize() { + return 8 + compatibleBrands.size() * 4; + + } + + @Override + public void _parseDetails(ByteBuffer content) { + majorBrand = IsoTypeReader.read4cc(content); + minorVersion = IsoTypeReader.readUInt32(content); + int compatibleBrandsCount = content.remaining() / 4; + compatibleBrands = new LinkedList<String>(); + for (int i = 0; i < compatibleBrandsCount; i++) { + compatibleBrands.add(IsoTypeReader.read4cc(content)); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(majorBrand)); + IsoTypeWriter.writeUInt32(byteBuffer, minorVersion); + for (String compatibleBrand : compatibleBrands) { + byteBuffer.put(IsoFile.fourCCtoBytes(compatibleBrand)); + } + + } + + /** + * Gets the brand identifier. + * + * @return the brand identifier + */ + public String getMajorBrand() { + return majorBrand; + } + + /** + * Sets the major brand of the file used to determine an appropriate reader. + * + * @param majorBrand the new major brand + */ + public void setMajorBrand(String majorBrand) { + this.majorBrand = majorBrand; + } + + /** + * Sets the "informative integer for the minor version of the major brand". + * + * @param minorVersion the version number of the major brand + */ + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + /** + * Gets an informative integer for the minor version of the major brand. + * + * @return an informative integer + * @see FileTypeBox#getMajorBrand() + */ + public long getMinorVersion() { + return minorVersion; + } + + /** + * Gets an array of 4-cc brands. + * + * @return the compatible brands + */ + public List<String> getCompatibleBrands() { + return compatibleBrands; + } + + public void setCompatibleBrands(List<String> compatibleBrands) { + this.compatibleBrands = compatibleBrands; + } + + @DoNotParseDetail + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("FileTypeBox["); + result.append("majorBrand=").append(getMajorBrand()); + result.append(";"); + result.append("minorVersion=").append(getMinorVersion()); + for (String compatibleBrand : compatibleBrands) { + result.append(";"); + result.append("compatibleBrand=").append(compatibleBrand); + } + result.append("]"); + return result.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeBox.java.svn-base new file mode 100644 index 0000000..636c9a7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeBox.java.svn-base @@ -0,0 +1,114 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.ChannelHelper; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * A free box. Just a placeholder to enable editing without rewriting the whole file. + */ +public class FreeBox implements Box { + public static final String TYPE = "free"; + ByteBuffer data; + List<Box> replacers = new LinkedList<Box>(); + private ContainerBox parent; + + public FreeBox() { + } + + public FreeBox(int size) { + this.data = ByteBuffer.allocate(size); + } + + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } + + public void getBox(WritableByteChannel os) throws IOException { + for (Box replacer : replacers) { + replacer.getBox(os); + } + ByteBuffer header = ByteBuffer.allocate(8); + IsoTypeWriter.writeUInt32(header, 8 + data.limit()); + header.put(TYPE.getBytes()); + header.rewind(); + os.write(header); + data.rewind(); + os.write(data); + + } + + public ContainerBox getParent() { + return parent; + } + + public void setParent(ContainerBox parent) { + this.parent = parent; + } + + public long getSize() { + long size = 8; + for (Box replacer : replacers) { + size += replacer.getSize(); + } + size += data.limit(); + return size; + } + + public String getType() { + return TYPE; + } + + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + if (readableByteChannel instanceof FileChannel && contentSize > 1024 * 1024) { + // It's quite expensive to map a file into the memory. Just do it when the box is larger than a MB. + data = ((FileChannel) readableByteChannel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) readableByteChannel).position(), contentSize); + ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); + } else { + assert contentSize < Integer.MAX_VALUE; + data = ChannelHelper.readFully(readableByteChannel, contentSize); + } + } + + + public void addAndReplace(Box box) { + data.position(l2i(box.getSize())); + data = data.slice(); + replacers.add(box); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeSpaceBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeSpaceBox.java.svn-base new file mode 100644 index 0000000..ed42bf9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FreeSpaceBox.java.svn-base @@ -0,0 +1,63 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * The contents of a free-space box are irrelevant and may be ignored, or the object deleted, without affecting the + * presentation. Care should be excercized when deleting the object, as this may invalidate the offsets used in the + * sample table. + */ +public class FreeSpaceBox extends AbstractBox { + public static final String TYPE = "skip"; + + byte[] data; + + protected long getContentSize() { + return data.length; + } + + public FreeSpaceBox() { + super(TYPE); + } + + public void setData(byte[] data) { + this.data = data; + } + + public byte[] getData() { + return data; + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = new byte[content.remaining()]; + content.get(data); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } + + public String toString() { + return "FreeSpaceBox[size=" + data.length + ";type=" + getType() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FullBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FullBox.java.svn-base new file mode 100644 index 0000000..1515d76 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/FullBox.java.svn-base @@ -0,0 +1,17 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.boxes.Box; + +/** + * The <code>FullBox</code> contains all getters and setters specific + * to a so-called full box according to the ISO/IEC 14496/12 specification. + */ +public interface FullBox extends Box { + int getVersion(); + + void setVersion(int version); + + int getFlags(); + + void setFlags(int flags); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/GenreBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/GenreBox.java.svn-base new file mode 100644 index 0000000..e2d1faf --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/GenreBox.java.svn-base @@ -0,0 +1,80 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Containing genre information and contained in the <code>UserDataBox</code>. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class GenreBox extends AbstractFullBox { + public static final String TYPE = "gnre"; + + private String language; + private String genre; + + public GenreBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getGenre() { + return genre; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setGenre(String genre) { + this.genre = genre; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(genre); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + genre = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(genre)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "GenreBox[language=" + getLanguage() + ";genre=" + getGenre() + "]"; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HandlerBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HandlerBox.java.svn-base new file mode 100644 index 0000000..01dcaca --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HandlerBox.java.svn-base @@ -0,0 +1,151 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This box within a Media Box declares the process by which the media-data in the track is presented, + * and thus, the nature of the media in a track. + * This Box when present in a Meta Box, declares the structure or format of the 'meta' box contents. + * See ISO/IEC 14496-12 for details. + * + * @see MetaBox + * @see MediaBox + */ +public class HandlerBox extends AbstractFullBox { + public static final String TYPE = "hdlr"; + public static final Map<String, String> readableTypes; + + static { + HashMap<String, String> hm = new HashMap<String, String>(); + hm.put("odsm", "ObjectDescriptorStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("crsm", "ClockReferenceStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("sdsm", "SceneDescriptionStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("m7sm", "MPEG7Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("ocsm", "ObjectContentInfoStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("ipsm", "IPMP Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("mjsm", "MPEG-J Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("mdir", "Apple Meta Data iTunes Reader"); + hm.put("mp7b", "MPEG-7 binary XML"); + hm.put("mp7t", "MPEG-7 XML"); + hm.put("vide", "Video Track"); + hm.put("soun", "Sound Track"); + hm.put("hint", "Hint Track"); + hm.put("appl", "Apple specific"); + hm.put("meta", "Timed Metadata track - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + + readableTypes = Collections.unmodifiableMap(hm); + + } + + private String handlerType; + private String name = null; + private long a, b, c; + private boolean zeroTerm = true; + + private long shouldBeZeroButAppleWritesHereSomeValue; + + public HandlerBox() { + super(TYPE); + } + + public String getHandlerType() { + return handlerType; + } + + /** + * You are required to add a '\0' string termination by yourself. + * + * @param name the new human readable name + */ + public void setName(String name) { + this.name = name; + } + + public void setHandlerType(String handlerType) { + this.handlerType = handlerType; + } + + public String getName() { + return name; + } + + public String getHumanReadableTrackType() { + return readableTypes.get(handlerType) != null ? readableTypes.get(handlerType) : "Unknown Handler Type"; + } + + protected long getContentSize() { + if (zeroTerm) { + return 25 + Utf8.utf8StringLengthInBytes(name); + } else { + return 24 + Utf8.utf8StringLengthInBytes(name); + } + + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + shouldBeZeroButAppleWritesHereSomeValue = IsoTypeReader.readUInt32(content); + handlerType = IsoTypeReader.read4cc(content); + a = IsoTypeReader.readUInt32(content); + b = IsoTypeReader.readUInt32(content); + c = IsoTypeReader.readUInt32(content); + if (content.remaining() > 0) { + name = IsoTypeReader.readString(content, content.remaining()); + if (name.endsWith("\0")) { + name = name.substring(0, name.length() - 1); + zeroTerm = true; + } else { + zeroTerm = false; + } + } else { + zeroTerm = false; //No string at all, not even zero term char + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, shouldBeZeroButAppleWritesHereSomeValue); + byteBuffer.put(IsoFile.fourCCtoBytes(handlerType)); + IsoTypeWriter.writeUInt32(byteBuffer, a); + IsoTypeWriter.writeUInt32(byteBuffer, b); + IsoTypeWriter.writeUInt32(byteBuffer, c); + if (name != null) { + byteBuffer.put(Utf8.convert(name)); + } + if (zeroTerm) { + byteBuffer.put((byte) 0); + } + } + + public String toString() { + return "HandlerBox[handlerType=" + getHandlerType() + ";name=" + getName() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HintMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HintMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..3477738 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/HintMediaHeaderBox.java.svn-base @@ -0,0 +1,91 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * The hint media header contains general information, independent of the protocaol, for hint tracks. Resides + * in Media Information Box. + * + * @see com.coremedia.iso.boxes.MediaInformationBox + */ +public class HintMediaHeaderBox extends AbstractMediaHeaderBox { + private int maxPduSize; + private int avgPduSize; + private long maxBitrate; + private long avgBitrate; + public static final String TYPE = "hmhd"; + + public HintMediaHeaderBox() { + super(TYPE); + } + + public int getMaxPduSize() { + return maxPduSize; + } + + public int getAvgPduSize() { + return avgPduSize; + } + + public long getMaxBitrate() { + return maxBitrate; + } + + public long getAvgBitrate() { + return avgBitrate; + } + + protected long getContentSize() { + return 20; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + maxPduSize = IsoTypeReader.readUInt16(content); + avgPduSize = IsoTypeReader.readUInt16(content); + maxBitrate = IsoTypeReader.readUInt32(content); + avgBitrate = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); // reserved! + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, maxPduSize); + IsoTypeWriter.writeUInt16(byteBuffer, avgPduSize); + IsoTypeWriter.writeUInt32(byteBuffer, maxBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, avgBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + } + + @Override + public String toString() { + return "HintMediaHeaderBox{" + + "maxPduSize=" + maxPduSize + + ", avgPduSize=" + avgPduSize + + ", maxBitrate=" + maxBitrate + + ", avgBitrate=" + avgBitrate + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemDataBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemDataBox.java.svn-base new file mode 100644 index 0000000..46097cc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemDataBox.java.svn-base @@ -0,0 +1,43 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class ItemDataBox extends AbstractBox { + ByteBuffer data = ByteBuffer.allocate(0); + public static final String TYPE = "idat"; + + + public ItemDataBox() { + super(TYPE); + } + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } + + @Override + protected long getContentSize() { + return data.limit(); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + data = content.slice(); + content.position(content.position() + content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemLocationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemLocationBox.java.svn-base new file mode 100644 index 0000000..6dcee6f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemLocationBox.java.svn-base @@ -0,0 +1,360 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeReaderVariable; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.IsoTypeWriterVariable; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +/** + * aligned(8) class ItemLocationBox extends FullBox(‘iloc’, version, 0) { + * unsigned int(4) offset_size; + * unsigned int(4) length_size; + * unsigned int(4) base_offset_size; + * if (version == 1) + * unsigned int(4) index_size; + * else + * unsigned int(4) reserved; + * unsigned int(16) item_count; + * for (i=0; i<item_count; i++) { + * unsigned int(16) item_ID; + * if (version == 1) { + * unsigned int(12) reserved = 0; + * unsigned int(4) construction_method; + * } + * unsigned int(16) data_reference_index; + * unsigned int(base_offset_size*8) base_offset; + * unsigned int(16) extent_count; + * for (j=0; j<extent_count; j++) { + * if ((version == 1) && (index_size > 0)) { + * unsigned int(index_size*8) extent_index; + * } + * unsigned int(offset_size*8) extent_offset; + * unsigned int(length_size*8) extent_length; + * } + * } + * } + */ +public class ItemLocationBox extends AbstractFullBox { + public int offsetSize = 8; + public int lengthSize = 8; + public int baseOffsetSize = 8; + public int indexSize = 0; + public List<Item> items = new LinkedList<Item>(); + + public static final String TYPE = "iloc"; + + public ItemLocationBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + long size = 8; + for (Item item : items) { + size += item.getSize(); + } + return size; + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt8(byteBuffer, ((offsetSize << 4) | lengthSize)); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4 | indexSize)); + } else { + IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4)); + } + IsoTypeWriter.writeUInt16(byteBuffer, items.size()); + for (Item item : items) { + item.getContent(byteBuffer); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int tmp = IsoTypeReader.readUInt8(content); + offsetSize = tmp >>> 4; + lengthSize = tmp & 0xf; + tmp = IsoTypeReader.readUInt8(content); + baseOffsetSize = tmp >>> 4; + + if (getVersion() == 1) { + indexSize = tmp & 0xf; + } + int itemCount = IsoTypeReader.readUInt16(content); + for (int i = 0; i < itemCount; i++) { + items.add(new Item(content)); + } + } + + + public int getOffsetSize() { + return offsetSize; + } + + public void setOffsetSize(int offsetSize) { + this.offsetSize = offsetSize; + } + + public int getLengthSize() { + return lengthSize; + } + + public void setLengthSize(int lengthSize) { + this.lengthSize = lengthSize; + } + + public int getBaseOffsetSize() { + return baseOffsetSize; + } + + public void setBaseOffsetSize(int baseOffsetSize) { + this.baseOffsetSize = baseOffsetSize; + } + + public int getIndexSize() { + return indexSize; + } + + public void setIndexSize(int indexSize) { + this.indexSize = indexSize; + } + + public List<Item> getItems() { + return items; + } + + public void setItems(List<Item> items) { + this.items = items; + } + + + public Item createItem(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { + return new Item(itemId, constructionMethod, dataReferenceIndex, baseOffset, extents); + } + + Item createItem(ByteBuffer bb) { + return new Item(bb); + } + + public class Item { + public int itemId; + public int constructionMethod; + public int dataReferenceIndex; + public long baseOffset; + public List<Extent> extents = new LinkedList<Extent>(); + + public Item(ByteBuffer in) { + itemId = IsoTypeReader.readUInt16(in); + + if (getVersion() == 1) { + int tmp = IsoTypeReader.readUInt16(in); + constructionMethod = tmp & 0xf; + } + + dataReferenceIndex = IsoTypeReader.readUInt16(in); + if (baseOffsetSize > 0) { + baseOffset = IsoTypeReaderVariable.read(in, baseOffsetSize); + } else { + baseOffset = 0; + } + int extentCount = IsoTypeReader.readUInt16(in); + + + for (int i = 0; i < extentCount; i++) { + extents.add(new Extent(in)); + } + } + + public Item(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { + this.itemId = itemId; + this.constructionMethod = constructionMethod; + this.dataReferenceIndex = dataReferenceIndex; + this.baseOffset = baseOffset; + this.extents = extents; + } + + public int getSize() { + int size = 2; + + if (getVersion() == 1) { + size += 2; + } + + size += 2; + size += baseOffsetSize; + size += 2; + + + for (Extent extent : extents) { + size += extent.getSize(); + } + return size; + } + + public void setBaseOffset(long baseOffset) { + this.baseOffset = baseOffset; + } + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, itemId); + + if (getVersion() == 1) { + IsoTypeWriter.writeUInt16(bb, constructionMethod); + } + + + IsoTypeWriter.writeUInt16(bb, dataReferenceIndex); + if (baseOffsetSize > 0) { + IsoTypeWriterVariable.write(baseOffset, bb, baseOffsetSize); + } + IsoTypeWriter.writeUInt16(bb, extents.size()); + + for (Extent extent : extents) { + extent.getContent(bb); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Item item = (Item) o; + + if (baseOffset != item.baseOffset) return false; + if (constructionMethod != item.constructionMethod) return false; + if (dataReferenceIndex != item.dataReferenceIndex) return false; + if (itemId != item.itemId) return false; + if (extents != null ? !extents.equals(item.extents) : item.extents != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = itemId; + result = 31 * result + constructionMethod; + result = 31 * result + dataReferenceIndex; + result = 31 * result + (int) (baseOffset ^ (baseOffset >>> 32)); + result = 31 * result + (extents != null ? extents.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Item{" + + "baseOffset=" + baseOffset + + ", itemId=" + itemId + + ", constructionMethod=" + constructionMethod + + ", dataReferenceIndex=" + dataReferenceIndex + + ", extents=" + extents + + '}'; + } + } + + + public Extent createExtent(long extentOffset, long extentLength, long extentIndex) { + return new Extent(extentOffset, extentLength, extentIndex); + } + + Extent createExtent(ByteBuffer bb) { + return new Extent(bb); + } + + + public class Extent { + public long extentOffset; + public long extentLength; + public long extentIndex; + + public Extent(long extentOffset, long extentLength, long extentIndex) { + this.extentOffset = extentOffset; + this.extentLength = extentLength; + this.extentIndex = extentIndex; + } + + + public Extent(ByteBuffer in) { + if ((getVersion() == 1) && indexSize > 0) { + extentIndex = IsoTypeReaderVariable.read(in, indexSize); + } + extentOffset = IsoTypeReaderVariable.read(in, offsetSize); + extentLength = IsoTypeReaderVariable.read(in, lengthSize); + } + + public void getContent(ByteBuffer os) { + if ((getVersion() == 1) && indexSize > 0) { + IsoTypeWriterVariable.write(extentIndex, os, indexSize); + } + IsoTypeWriterVariable.write(extentOffset, os, offsetSize); + IsoTypeWriterVariable.write(extentLength, os, lengthSize); + } + + public int getSize() { + return (indexSize > 0 ? indexSize : 0) + offsetSize + lengthSize; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Extent extent = (Extent) o; + + if (extentIndex != extent.extentIndex) return false; + if (extentLength != extent.extentLength) return false; + if (extentOffset != extent.extentOffset) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (extentOffset ^ (extentOffset >>> 32)); + result = 31 * result + (int) (extentLength ^ (extentLength >>> 32)); + result = 31 * result + (int) (extentIndex ^ (extentIndex >>> 32)); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Extent"); + sb.append("{extentOffset=").append(extentOffset); + sb.append(", extentLength=").append(extentLength); + sb.append(", extentIndex=").append(extentIndex); + sb.append('}'); + return sb.toString(); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemProtectionBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemProtectionBox.java.svn-base new file mode 100644 index 0000000..7eed790 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ItemProtectionBox.java.svn-base @@ -0,0 +1,61 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The Item Protection Box provides an array of item protection information, for use by the Item Information Box. + * + * @see com.coremedia.iso.boxes.ItemProtectionBox + */ +public class ItemProtectionBox extends FullContainerBox { + + public static final String TYPE = "ipro"; + + public ItemProtectionBox() { + super(TYPE); + } + + public SchemeInformationBox getItemProtectionScheme() { + if (!getBoxes(SchemeInformationBox.class).isEmpty()) { + return getBoxes(SchemeInformationBox.class).get(0); + } else { + return null; + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + IsoTypeReader.readUInt16(content); + parseChildBoxes(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, getBoxes().size()); + writeChildBoxes(byteBuffer); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/KeywordsBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/KeywordsBox.java.svn-base new file mode 100644 index 0000000..d9b7c0c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/KeywordsBox.java.svn-base @@ -0,0 +1,95 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * List of keywords according to 3GPP 26.244. + */ +public class KeywordsBox extends AbstractFullBox { + public static final String TYPE = "kywd"; + + private String language; + private String[] keywords; + + public KeywordsBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String[] getKeywords() { + return keywords; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setKeywords(String[] keywords) { + this.keywords = keywords; + } + + protected long getContentSize() { + long contentSize = 7; + for (String keyword : keywords) { + contentSize += 1 + Utf8.utf8StringLengthInBytes(keyword) + 1; + } + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + int keywordCount = IsoTypeReader.readUInt8(content); + keywords = new String[keywordCount]; + for (int i = 0; i < keywordCount; i++) { + IsoTypeReader.readUInt8(content); + keywords[i] = IsoTypeReader.readString(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + IsoTypeWriter.writeUInt8(byteBuffer, keywords.length); + for (String keyword : keywords) { + IsoTypeWriter.writeUInt8(byteBuffer, Utf8.utf8StringLengthInBytes(keyword) + 1); + byteBuffer.put(Utf8.convert(keyword)); + } + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("KeywordsBox[language=").append(getLanguage()); + for (int i = 0; i < keywords.length; i++) { + buffer.append(";keyword").append(i).append("=").append(keywords[i]); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaBox.java.svn-base new file mode 100644 index 0000000..fa5642c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaBox.java.svn-base @@ -0,0 +1,61 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The media declaration container contains all the objects that declare information about the media data within a + * track. + */ +public class MediaBox extends AbstractContainerBox { + public static final String TYPE = "mdia"; + + public MediaBox() { + super(TYPE); + } + + public MediaInformationBox getMediaInformationBox() { + for (Box box : boxes) { + if (box instanceof MediaInformationBox) { + return (MediaInformationBox) box; + } + } + return null; + } + + public MediaHeaderBox getMediaHeaderBox() { + for (Box box : boxes) { + if (box instanceof MediaHeaderBox) { + return (MediaHeaderBox) box; + } + } + return null; + } + + public HandlerBox getHandlerBox() { + for (Box box : boxes) { + if (box instanceof HandlerBox) { + return (HandlerBox) box; + } + } + return null; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaHeaderBox.java.svn-base new file mode 100644 index 0000000..69b538b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaHeaderBox.java.svn-base @@ -0,0 +1,147 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * This box defines overall information which is media-independent, and relevant to the entire presentation + * considered as a whole. + */ +public class MediaHeaderBox extends AbstractFullBox { + public static final String TYPE = "mdhd"; + + + private long creationTime; + private long modificationTime; + private long timescale; + private long duration; + private String language; + + public MediaHeaderBox() { + super(TYPE); + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTimescale() { + return timescale; + } + + public long getDuration() { + return duration; + } + + public String getLanguage() { + return language; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 8 + 8 + 4 + 8; + } else { + contentSize += 4 + 4 + 4 + 4; + } + contentSize += 2; + contentSize += 2; + return contentSize; + + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTimescale(long timescale) { + this.timescale = timescale; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setLanguage(String language) { + this.language = language; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } + language = IsoTypeReader.readIso639(content); + IsoTypeReader.readUInt16(content); + } + + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("MediaHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("timescale=").append(getTimescale()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("language=").append(getLanguage()); + result.append("]"); + return result.toString(); + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } + IsoTypeWriter.writeIso639(byteBuffer, language); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaInformationBox.java.svn-base new file mode 100644 index 0000000..ed25051 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MediaInformationBox.java.svn-base @@ -0,0 +1,49 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * This box contains all the objects that declare characteristic information of the media in the track. + */ +public class MediaInformationBox extends AbstractContainerBox { + public static final String TYPE = "minf"; + + public MediaInformationBox() { + super(TYPE); + } + + public SampleTableBox getSampleTableBox() { + for (Box box : boxes) { + if (box instanceof SampleTableBox) { + return (SampleTableBox) box; + } + } + return null; + } + + public AbstractMediaHeaderBox getMediaHeaderBox() { + for (Box box : boxes) { + if (box instanceof AbstractMediaHeaderBox) { + return (AbstractMediaHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MetaBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MetaBox.java.svn-base new file mode 100644 index 0000000..35499ec --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MetaBox.java.svn-base @@ -0,0 +1,113 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.IOException; +import java.nio.ByteBuffer; + + +/** + * A common base structure to contain general metadata. See ISO/IEC 14496-12 Ch. 8.44.1. + */ +public class MetaBox extends AbstractContainerBox { + private int version = 0; + private int flags = 0; + + public static final String TYPE = "meta"; + + public MetaBox() { + super(TYPE); + } + + @Override + public long getContentSize() { + if (isMp4Box()) { + // it's a fullbox + return 4 + super.getContentSize(); + } else { + // it's an apple metabox + return super.getContentSize(); + } + } + + @Override + public long getNumOfBytesToFirstChild() { + if (isMp4Box()) { + // it's a fullbox + return 12; + } else { + // it's an apple metabox + return 8; + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + int pos = content.position(); + content.get(new byte[4]); + String isHdlr = IsoTypeReader.read4cc(content); + if ("hdlr".equals(isHdlr)) { + // this is apple bullshit - it's NO FULLBOX + content.position(pos); + version = -1; + flags = -1; + } else { + content.position(pos); + version = IsoTypeReader.readUInt8(content); + flags = IsoTypeReader.readUInt24(content); + } + while (content.remaining() >= 8) { + try { + boxes.add(boxParser.parseBox(new ByteBufferByteChannel(content), this)); + } catch (IOException e) { + throw new RuntimeException("Sebastian needs to fix 7518765283"); + } + } + if (content.remaining() > 0) { + throw new RuntimeException("Sebastian needs to fix it 90732r26537"); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + if (isMp4Box()) { + IsoTypeWriter.writeUInt8(byteBuffer, version); + IsoTypeWriter.writeUInt24(byteBuffer, flags); + } + writeChildBoxes(byteBuffer); + } + + + public boolean isMp4Box() { + return version != -1 && flags != -1; + } + + public void setMp4Box(boolean mp4) { + if (mp4) { + version = 0; + flags = 0; + } else { + version = -1; + flags = -1; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieBox.java.svn-base new file mode 100644 index 0000000..3aff7d8 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieBox.java.svn-base @@ -0,0 +1,67 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.AbstractContainerBox; + +import java.util.List; + +/** + * The metadata for a presentation is stored in the single Movie Box which occurs at the top-level of a file. + * Normally this box is close to the beginning or end of the file, though this is not required. + */ +public class MovieBox extends AbstractContainerBox { + public static final String TYPE = "moov"; + + public MovieBox() { + super(TYPE); + } + + public int getTrackCount() { + return getBoxes(TrackBox.class).size(); + } + + + /** + * Returns the track numbers associated with this <code>MovieBox</code>. + * + * @return the tracknumbers (IDs) of the tracks in their order of appearance in the file + */ + public long[] getTrackNumbers() { + + List<TrackBox> trackBoxes = this.getBoxes(TrackBox.class); + long[] trackNumbers = new long[trackBoxes.size()]; + for (int trackCounter = 0; trackCounter < trackBoxes.size(); trackCounter++) { + AbstractBox trackBoxe = trackBoxes.get(trackCounter); + TrackBox trackBox = (TrackBox) trackBoxe; + trackNumbers[trackCounter] = trackBox.getTrackHeaderBox().getTrackId(); + } + return trackNumbers; + } + + public MovieHeaderBox getMovieHeaderBox() { + for (Box box : boxes) { + if (box instanceof MovieHeaderBox) { + return (MovieHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieHeaderBox.java.svn-base new file mode 100644 index 0000000..30fbe8c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/MovieHeaderBox.java.svn-base @@ -0,0 +1,278 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * <code> + * Box Type: 'mvhd'<br> + * Container: {@link MovieBox} ('moov')<br> + * Mandatory: Yes<br> + * Quantity: Exactly one<br><br> + * </code> + * This box defines overall information which is media-independent, and relevant to the entire presentation + * considered as a whole. + */ +public class MovieHeaderBox extends AbstractFullBox { + private long creationTime; + private long modificationTime; + private long timescale; + private long duration; + private double rate = 1.0; + private float volume = 1.0f; + private long[] matrix = new long[]{0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; + private long nextTrackId; + + private int previewTime; + private int previewDuration; + private int posterTime; + private int selectionTime; + private int selectionDuration; + private int currentTime; + + + public static final String TYPE = "mvhd"; + + public MovieHeaderBox() { + super(TYPE); + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTimescale() { + return timescale; + } + + public long getDuration() { + return duration; + } + + public double getRate() { + return rate; + } + + public float getVolume() { + return volume; + } + + public long[] getMatrix() { + return matrix; + } + + public long getNextTrackId() { + return nextTrackId; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 28; + } else { + contentSize += 16; + } + contentSize += 80; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } + rate = IsoTypeReader.readFixedPoint1616(content); + volume = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); + IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + matrix = new long[9]; + for (int i = 0; i < 9; i++) { + matrix[i] = IsoTypeReader.readUInt32(content); + } + + previewTime = content.getInt(); + previewDuration = content.getInt(); + posterTime = content.getInt(); + selectionTime = content.getInt(); + selectionDuration = content.getInt(); + currentTime = content.getInt(); + + nextTrackId = IsoTypeReader.readUInt32(content); + + } + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("MovieHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("timescale=").append(getTimescale()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("rate=").append(getRate()); + result.append(";"); + result.append("volume=").append(getVolume()); + for (int i = 0; i < matrix.length; i++) { + result.append(";"); + result.append("matrix").append(i).append("=").append(matrix[i]); + } + result.append(";"); + result.append("nextTrackId=").append(getNextTrackId()); + result.append("]"); + return result.toString(); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } + IsoTypeWriter.writeFixedPont1616(byteBuffer, rate); + IsoTypeWriter.writeFixedPont88(byteBuffer, volume); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + + + for (int i = 0; i < 9; i++) { + IsoTypeWriter.writeUInt32(byteBuffer, matrix[i]); + } + + + byteBuffer.putInt(previewTime); + byteBuffer.putInt(previewDuration); + byteBuffer.putInt(posterTime); + byteBuffer.putInt(selectionTime); + byteBuffer.putInt(selectionDuration); + byteBuffer.putInt(currentTime); + + IsoTypeWriter.writeUInt32(byteBuffer, nextTrackId); + } + + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTimescale(long timescale) { + this.timescale = timescale; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setRate(double rate) { + this.rate = rate; + } + + public void setVolume(float volume) { + this.volume = volume; + } + + public void setMatrix(long[] matrix) { + this.matrix = matrix; + } + + public void setNextTrackId(long nextTrackId) { + this.nextTrackId = nextTrackId; + } + + public int getPreviewTime() { + return previewTime; + } + + public void setPreviewTime(int previewTime) { + this.previewTime = previewTime; + } + + public int getPreviewDuration() { + return previewDuration; + } + + public void setPreviewDuration(int previewDuration) { + this.previewDuration = previewDuration; + } + + public int getPosterTime() { + return posterTime; + } + + public void setPosterTime(int posterTime) { + this.posterTime = posterTime; + } + + public int getSelectionTime() { + return selectionTime; + } + + public void setSelectionTime(int selectionTime) { + this.selectionTime = selectionTime; + } + + public int getSelectionDuration() { + return selectionDuration; + } + + public void setSelectionDuration(int selectionDuration) { + this.selectionDuration = selectionDuration; + } + + public int getCurrentTime() { + return currentTime; + } + + public void setCurrentTime(int currentTime) { + this.currentTime = currentTime; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/NullMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/NullMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..562f8d4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/NullMediaHeaderBox.java.svn-base @@ -0,0 +1,43 @@ +/* + * Copyright 2011 Sebastian Annies, Hamburg, Germany + * + * 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.coremedia.iso.boxes; + +import java.nio.ByteBuffer; + +/** + * Streams other than visual and audio (e.g., timed metadata streams) may use a + * Null Media Header Box. + */ +public class NullMediaHeaderBox extends AbstractMediaHeaderBox { + public NullMediaHeaderBox() { + super("nmhd"); + } + + @Override + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ObjectDescriptorBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ObjectDescriptorBox.java.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ObjectDescriptorBox.java.svn-base diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OmaDrmAccessUnitFormatBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OmaDrmAccessUnitFormatBox.java.svn-base new file mode 100644 index 0000000..020881b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OmaDrmAccessUnitFormatBox.java.svn-base @@ -0,0 +1,87 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Describes the format of media access units in PDCF files. + */ +public final class OmaDrmAccessUnitFormatBox extends AbstractFullBox { + public static final String TYPE = "odaf"; + + private boolean selectiveEncryption; + private byte allBits; + + private int keyIndicatorLength; + private int initVectorLength; + + protected long getContentSize() { + return 7; + } + + public OmaDrmAccessUnitFormatBox() { + super("odaf"); + } + + public boolean isSelectiveEncryption() { + return selectiveEncryption; + } + + public int getKeyIndicatorLength() { + return keyIndicatorLength; + } + + public int getInitVectorLength() { + return initVectorLength; + } + + public void setInitVectorLength(int initVectorLength) { + this.initVectorLength = initVectorLength; + } + + public void setKeyIndicatorLength(int keyIndicatorLength) { + this.keyIndicatorLength = keyIndicatorLength; + } + + public void setAllBits(byte allBits) { + this.allBits = allBits; + selectiveEncryption = (allBits & 0x80) == 0x80; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + allBits = (byte) IsoTypeReader.readUInt8(content); + selectiveEncryption = (allBits & 0x80) == 0x80; + keyIndicatorLength = IsoTypeReader.readUInt8(content); + initVectorLength = IsoTypeReader.readUInt8(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt8(byteBuffer, allBits); + IsoTypeWriter.writeUInt8(byteBuffer, keyIndicatorLength); + IsoTypeWriter.writeUInt8(byteBuffer, initVectorLength); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OriginalFormatBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OriginalFormatBox.java.svn-base new file mode 100644 index 0000000..004c6c2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/OriginalFormatBox.java.svn-base @@ -0,0 +1,69 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * The Original Format Box contains the four-character-code of the original untransformed sample description. + * See ISO/IEC 14496-12 for details. + * + * @see ProtectionSchemeInformationBox + */ + +public class OriginalFormatBox extends AbstractBox { + public static final String TYPE = "frma"; + + private String dataFormat = " "; + + public OriginalFormatBox() { + super("frma"); + } + + public String getDataFormat() { + return dataFormat; + } + + + public void setDataFormat(String dataFormat) { + assert dataFormat.length() == 4; + this.dataFormat = dataFormat; + } + + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + dataFormat = IsoTypeReader.read4cc(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(dataFormat)); + } + + + public String toString() { + return "OriginalFormatBox[dataFormat=" + getDataFormat() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/PerformerBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/PerformerBox.java.svn-base new file mode 100644 index 0000000..cf702dc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/PerformerBox.java.svn-base @@ -0,0 +1,78 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Used to give information about the performer. Mostly used in confunction with music files. + * See 3GPP 26.234 for details. + */ +public class PerformerBox extends AbstractFullBox { + public static final String TYPE = "perf"; + + private String language; + private String performer; + + public PerformerBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getPerformer() { + return performer; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setPerformer(String performer) { + this.performer = performer; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(performer) + 1; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(performer)); + byteBuffer.put((byte) 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + performer = IsoTypeReader.readString(content); + } + + public String toString() { + return "PerformerBox[language=" + getLanguage() + ";performer=" + getPerformer() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProgressiveDownloadInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProgressiveDownloadInformationBox.java.svn-base new file mode 100644 index 0000000..7acd7ed --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProgressiveDownloadInformationBox.java.svn-base @@ -0,0 +1,95 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class ProgressiveDownloadInformationBox extends AbstractFullBox { + + + List<Entry> entries = Collections.emptyList(); + + public ProgressiveDownloadInformationBox() { + super("pdin"); + } + + @Override + protected long getContentSize() { + return 4 + entries.size() * 8; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getRate()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getInitialDelay()); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + entries = new LinkedList<Entry>(); + while (content.remaining() >= 8) { + Entry entry = new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content)); + entries.add(entry); + } + } + + + public static class Entry { + long rate; + long initialDelay; + + public Entry(long rate, long initialDelay) { + this.rate = rate; + this.initialDelay = initialDelay; + } + + public long getRate() { + return rate; + } + + public void setRate(long rate) { + this.rate = rate; + } + + public long getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(long initialDelay) { + this.initialDelay = initialDelay; + } + + @Override + public String toString() { + return "Entry{" + + "rate=" + rate + + ", initialDelay=" + initialDelay + + '}'; + } + } + + @Override + public String toString() { + return "ProgressiveDownloadInfoBox{" + + "entries=" + entries + + '}'; + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProtectionSchemeInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProtectionSchemeInformationBox.java.svn-base new file mode 100644 index 0000000..87069d3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/ProtectionSchemeInformationBox.java.svn-base @@ -0,0 +1,42 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The <code>ProtectionSchemeInformationBox</code> contains all the information required both + * to understand the encryption transform applied and its parameters, and also to find other + * information such as the kind and location of the key management system. It also documents the + * the original (unencrypted) format of the media. The <code>ProtectionSchemeInformationBox</code> + * is a container box. It is mandatory in a sample entry that uses a code idicating a + * protected stream. + * + * @see com.coremedia.iso.boxes.odf.OmaDrmKeyManagenentSystemBox + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry#TYPE_ENCRYPTED + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry#TYPE_ENCRYPTED + */ +public class ProtectionSchemeInformationBox extends AbstractContainerBox { + public static final String TYPE = "sinf"; + + public ProtectionSchemeInformationBox() { + super(TYPE); + + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RatingBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RatingBox.java.svn-base new file mode 100644 index 0000000..ad32749 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RatingBox.java.svn-base @@ -0,0 +1,124 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + + +/** + * Contained a the <code>UserDataBox</code> and containing information about the media's rating. E.g. + * PG13or FSK16. + */ +public class RatingBox extends AbstractFullBox { + public static final String TYPE = "rtng"; + + private String ratingEntity; + private String ratingCriteria; + private String language; + private String ratingInfo; + + public RatingBox() { + super(TYPE); + } + + + public void setRatingEntity(String ratingEntity) { + this.ratingEntity = ratingEntity; + } + + public void setRatingCriteria(String ratingCriteria) { + this.ratingCriteria = ratingCriteria; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setRatingInfo(String ratingInfo) { + this.ratingInfo = ratingInfo; + } + + public String getLanguage() { + return language; + } + + /** + * Gets a four-character code that indicates the rating entity grading the asset, e.g., 'BBFC'. The values of this + * field should follow common names of worldwide movie rating systems, such as those mentioned in + * [http://www.movie-ratings.net/, October 2002]. + * + * @return the rating organization + */ + public String getRatingEntity() { + return ratingEntity; + } + + /** + * Gets the four-character code that indicates which rating criteria are being used for the corresponding rating + * entity, e.g., 'PG13'. + * + * @return the actual rating + */ + public String getRatingCriteria() { + return ratingCriteria; + } + + public String getRatingInfo() { + return ratingInfo; + } + + protected long getContentSize() { + return 15 + Utf8.utf8StringLengthInBytes(ratingInfo); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + ratingEntity = IsoTypeReader.read4cc(content); + ratingCriteria = IsoTypeReader.read4cc(content); + language = IsoTypeReader.readIso639(content); + ratingInfo = IsoTypeReader.readString(content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(IsoFile.fourCCtoBytes(ratingEntity)); + byteBuffer.put(IsoFile.fourCCtoBytes(ratingCriteria)); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(ratingInfo)); + byteBuffer.put((byte) 0); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RatingBox[language=").append(getLanguage()); + buffer.append("ratingEntity=").append(getRatingEntity()); + buffer.append(";ratingCriteria=").append(getRatingCriteria()); + buffer.append(";language=").append(getLanguage()); + buffer.append(";ratingInfo=").append(getRatingInfo()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RecordingYearBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RecordingYearBox.java.svn-base new file mode 100644 index 0000000..e2dcbd9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/RecordingYearBox.java.svn-base @@ -0,0 +1,63 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class RecordingYearBox extends AbstractFullBox { + public static final String TYPE = "yrrc"; + + int recordingYear; + + public RecordingYearBox() { + super(TYPE); + } + + + protected long getContentSize() { + return 6; + } + + public int getRecordingYear() { + return recordingYear; + } + + public void setRecordingYear(int recordingYear) { + this.recordingYear = recordingYear; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + recordingYear = IsoTypeReader.readUInt16(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, recordingYear); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationOffsetsBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationOffsetsBox.java.svn-base new file mode 100644 index 0000000..517bc03 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationOffsetsBox.java.svn-base @@ -0,0 +1,127 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/* +aligned(8) class SampleAuxiliaryInformationOffsetsBox + extends FullBox(‘saio’, version, flags) +{ + if (flags & 1) { + unsigned int(32) aux_info_type; + unsigned int(32) aux_info_type_parameter; + } + unsigned int(32) entry_count; + if ( version == 0 ) + { + unsigned int(32) offset[ entry_count ]; + } + else + { + unsigned int(64) offset[ entry_count ]; + } +} + */ +public class SampleAuxiliaryInformationOffsetsBox extends AbstractFullBox { + public static final String TYPE = "saio"; + + private List<Long> offsets = new LinkedList<Long>(); + private long auxInfoType; + private long auxInfoTypeParameter; + + public SampleAuxiliaryInformationOffsetsBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 8 + (getVersion() == 0 ? 4 * offsets.size() : 8 * offsets.size()) + ((getFlags() & 1) == 1 ? 8 : 0); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if ((getFlags() & 1) == 1) { + IsoTypeWriter.writeUInt32(byteBuffer, auxInfoType); + IsoTypeWriter.writeUInt32(byteBuffer, auxInfoTypeParameter); + } + + IsoTypeWriter.writeUInt32(byteBuffer, offsets.size()); + for (Long offset : offsets) { + if (getVersion() == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, offset); + } else { + IsoTypeWriter.writeUInt64(byteBuffer, offset); + } + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + + if ((getFlags() & 1) == 1) { + auxInfoType = IsoTypeReader.readUInt32(content); + auxInfoTypeParameter = IsoTypeReader.readUInt32(content); + } + + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + offsets.clear(); + + for (int i = 0; i < entryCount; i++) { + if (getVersion() == 0) { + offsets.add(IsoTypeReader.readUInt32(content)); + } else { + offsets.add(IsoTypeReader.readUInt64(content)); + } + } + } + + + public long getAuxInfoType() { + return auxInfoType; + } + + public void setAuxInfoType(long auxInfoType) { + this.auxInfoType = auxInfoType; + } + + public long getAuxInfoTypeParameter() { + return auxInfoTypeParameter; + } + + public void setAuxInfoTypeParameter(long auxInfoTypeParameter) { + this.auxInfoTypeParameter = auxInfoTypeParameter; + } + + public List<Long> getOffsets() { + return offsets; + } + + public void setOffsets(List<Long> offsets) { + this.offsets = offsets; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationSizesBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationSizesBox.java.svn-base new file mode 100644 index 0000000..4032d01 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleAuxiliaryInformationSizesBox.java.svn-base @@ -0,0 +1,145 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +public class SampleAuxiliaryInformationSizesBox extends AbstractFullBox { + public static final String TYPE = "saiz"; + + private int defaultSampleInfoSize; + private List<Short> sampleInfoSizes = new LinkedList<Short>(); + private int sampleCount; + private String auxInfoType; + private String auxInfoTypeParameter; + + public SampleAuxiliaryInformationSizesBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + int size = 4; + if ((getFlags() & 1) == 1) { + size += 8; + } + + size += 5; + size += defaultSampleInfoSize == 0 ? sampleInfoSizes.size() : 0; + return size; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if ((getFlags() & 1) == 1) { + byteBuffer.put(IsoFile.fourCCtoBytes(auxInfoType)); + byteBuffer.put(IsoFile.fourCCtoBytes(auxInfoTypeParameter)); + } + + IsoTypeWriter.writeUInt8(byteBuffer, defaultSampleInfoSize); + + if (defaultSampleInfoSize == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleInfoSizes.size()); + for (short sampleInfoSize : sampleInfoSizes) { + IsoTypeWriter.writeUInt8(byteBuffer, sampleInfoSize); + } + } else { + IsoTypeWriter.writeUInt32(byteBuffer, sampleCount); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if ((getFlags() & 1) == 1) { + auxInfoType = IsoTypeReader.read4cc(content); + auxInfoTypeParameter = IsoTypeReader.read4cc(content); + } + + defaultSampleInfoSize = (short) IsoTypeReader.readUInt8(content); + sampleCount = l2i(IsoTypeReader.readUInt32(content)); + + sampleInfoSizes.clear(); + + if (defaultSampleInfoSize == 0) { + for (int i = 0; i < sampleCount; i++) { + sampleInfoSizes.add((short) IsoTypeReader.readUInt8(content)); + } + } + } + + public String getAuxInfoType() { + return auxInfoType; + } + + public void setAuxInfoType(String auxInfoType) { + this.auxInfoType = auxInfoType; + } + + public String getAuxInfoTypeParameter() { + return auxInfoTypeParameter; + } + + public void setAuxInfoTypeParameter(String auxInfoTypeParameter) { + this.auxInfoTypeParameter = auxInfoTypeParameter; + } + + public int getDefaultSampleInfoSize() { + return defaultSampleInfoSize; + } + + public void setDefaultSampleInfoSize(int defaultSampleInfoSize) { + assert defaultSampleInfoSize <= 255; + this.defaultSampleInfoSize = defaultSampleInfoSize; + } + + public List<Short> getSampleInfoSizes() { + return sampleInfoSizes; + } + + public void setSampleInfoSizes(List<Short> sampleInfoSizes) { + this.sampleInfoSizes = sampleInfoSizes; + } + + public int getSampleCount() { + return sampleCount; + } + + public void setSampleCount(int sampleCount) { + this.sampleCount = sampleCount; + } + + @Override + public String toString() { + return "SampleAuxiliaryInformationSizesBox{" + + "defaultSampleInfoSize=" + defaultSampleInfoSize + + ", sampleCount=" + sampleCount + + ", auxInfoType='" + auxInfoType + '\'' + + ", auxInfoTypeParameter='" + auxInfoTypeParameter + '\'' + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDependencyTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDependencyTypeBox.java.svn-base new file mode 100644 index 0000000..bb38d8c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDependencyTypeBox.java.svn-base @@ -0,0 +1,136 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * aligned(8) class SampleDependencyTypeBox + * extends FullBox('sdtp', version = 0, 0) { + * for (i=0; i < sample_count; i++){ + * unsigned int(2) reserved = 0; + * unsigned int(2) sample_depends_on; + * unsigned int(2) sample_is_depended_on; + * unsigned int(2) sample_has_redundancy; + * } + * } + */ +public class SampleDependencyTypeBox extends AbstractFullBox { + public static final String TYPE = "sdtp"; + + private List<Entry> entries = new ArrayList<Entry>(); + + public static class Entry { + + public Entry(int value) { + this.value = value; + } + + private int value; + + + public int getReserved() { + return (value >> 6) & 0x03; + } + + public void setReserved(int res) { + value = (res & 0x03) << 6 | value & 0x3f; + } + + public int getSampleDependsOn() { + return (value >> 4) & 0x03; + } + + public void setSampleDependsOn(int sdo) { + value = (sdo & 0x03) << 4 | value & 0xcf; + } + + public int getSampleIsDependentOn() { + return (value >> 2) & 0x03; + } + + public void setSampleIsDependentOn(int sido) { + value = (sido & 0x03) << 2 | value & 0xf3; + } + + public int getSampleHasRedundancy() { + return value & 0x03; + } + + public void setSampleHasRedundancy(int shr) { + value = shr & 0x03 | value & 0xfc; + } + + @Override + public String toString() { + return "Entry{" + + "reserved=" + getReserved() + + ", sampleDependsOn=" + getSampleDependsOn() + + ", sampleIsDependentOn=" + getSampleIsDependentOn() + + ", sampleHasRedundancy=" + getSampleHasRedundancy() + + '}'; + } + } + + public SampleDependencyTypeBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 4 + entries.size(); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt8(byteBuffer, entry.value); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + while (content.remaining() > 0) { + entries.add(new Entry(IsoTypeReader.readUInt8(content))); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("SampleDependencyTypeBox"); + sb.append("{entries=").append(entries); + sb.append('}'); + return sb.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDescriptionBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDescriptionBox.java.svn-base new file mode 100644 index 0000000..662fa99 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleDescriptionBox.java.svn-base @@ -0,0 +1,81 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.sampleentry.SampleEntry; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The sample description table gives detailed information about the coding type used, and any initialization + * information needed for that coding. <br> + * The information stored in the sample description box after the entry-count is both track-type specific as + * documented here, and can also have variants within a track type (e.g. different codings may use different + * specific information after some common fields, even within a video track).<br> + * For video tracks, a VisualSampleEntry is used; for audio tracks, an AudioSampleEntry. Hint tracks use an + * entry format specific to their protocol, with an appropriate name. Timed Text tracks use a TextSampleEntry + * For hint tracks, the sample description contains appropriate declarative data for the streaming protocol being + * used, and the format of the hint track. The definition of the sample description is specific to the protocol. + * Multiple descriptions may be used within a track.<br> + * The 'protocol' and 'codingname' fields are registered identifiers that uniquely identify the streaming protocol or + * compression format decoder to be used. A given protocol or codingname may have optional or required + * extensions to the sample description (e.g. codec initialization parameters). All such extensions shall be within + * boxes; these boxes occur after the required fields. Unrecognized boxes shall be ignored. + * <br> + * Defined in ISO/IEC 14496-12 + * + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.TextSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + */ +public class SampleDescriptionBox extends FullContainerBox { + public static final String TYPE = "stsd"; + + public SampleDescriptionBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return super.getContentSize() + 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + content.get(new byte[4]); + parseChildBoxes(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, boxes.size()); + writeChildBoxes(byteBuffer); + } + + public SampleEntry getSampleEntry() { + for (Box box : boxes) { + if (box instanceof SampleEntry) { + return (SampleEntry) box; + } + } + return null; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleSizeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleSizeBox.java.svn-base new file mode 100644 index 0000000..3bc1df0 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleSizeBox.java.svn-base @@ -0,0 +1,121 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box containes the sample count and a table giving the size in bytes of each sample. + * Defined in ISO/IEC 14496-12. + */ +public class SampleSizeBox extends AbstractFullBox { + private long sampleSize; + private long[] sampleSizes = new long[0]; + public static final String TYPE = "stsz"; + int sampleCount; + + public SampleSizeBox() { + super(TYPE); + } + + /** + * Returns the field sample size. + * If sampleSize > 0 every sample has the same size. + * If sampleSize == 0 the samples have different size as stated in the sampleSizes field. + * + * @return the sampleSize field + */ + public long getSampleSize() { + return sampleSize; + } + + public void setSampleSize(long sampleSize) { + this.sampleSize = sampleSize; + } + + + public long getSampleSizeAtIndex(int index) { + if (sampleSize > 0) { + return sampleSize; + } else { + return sampleSizes[index]; + } + } + + public long getSampleCount() { + if (sampleSize > 0) { + return sampleCount; + } else { + return sampleSizes.length; + } + + } + + public long[] getSampleSizes() { + return sampleSizes; + } + + public void setSampleSizes(long[] sampleSizes) { + this.sampleSizes = sampleSizes; + } + + protected long getContentSize() { + return 12 + (sampleSize == 0 ? sampleSizes.length * 4 : 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + sampleSize = IsoTypeReader.readUInt32(content); + sampleCount = l2i(IsoTypeReader.readUInt32(content)); + + if (sampleSize == 0) { + sampleSizes = new long[(int) sampleCount]; + + for (int i = 0; i < sampleCount; i++) { + sampleSizes[i] = IsoTypeReader.readUInt32(content); + } + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, sampleSize); + + if (sampleSize == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleSizes.length); + for (long sampleSize1 : sampleSizes) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleSize1); + } + } else { + IsoTypeWriter.writeUInt32(byteBuffer, sampleCount); + } + + } + + public String toString() { + return "SampleSizeBox[sampleSize=" + getSampleSize() + ";sampleCount=" + getSampleCount() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleTableBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleTableBox.java.svn-base new file mode 100644 index 0000000..33968b3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleTableBox.java.svn-base @@ -0,0 +1,124 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The sample table contains all the time and data indexing of the media samples in a track. Using the tables + * here, it is possible to locate samples in time, determine their type (e.g. I-frame or not), and determine their + * size, container, and offset into that container. <br> + * If the track that contains the Sample Table Box references no data, then the Sample Table Box does not need + * to contain any sub-boxes (this is not a very useful media track). <br> + * If the track that the Sample Table Box is contained in does reference data, then the following sub-boxes are + * required: Sample Description, Sample Size, Sample To Chunk, and Chunk Offset. Further, the Sample + * Description Box shall contain at least one entry. A Sample Description Box is required because it contains the + * data reference index field which indicates which Data Reference Box to use to retrieve the media samples. + * Without the Sample Description, it is not possible to determine where the media samples are stored. The Sync + * Sample Box is optional. If the Sync Sample Box is not present, all samples are sync samples.<br> + * Annex A provides a narrative description of random access using the structures defined in the Sample Table + * Box. + */ +public class SampleTableBox extends AbstractContainerBox { + public static final String TYPE = "stbl"; + + public SampleTableBox() { + super(TYPE); + } + + public SampleDescriptionBox getSampleDescriptionBox() { + for (Box box : boxes) { + if (box instanceof SampleDescriptionBox) { + return (SampleDescriptionBox) box; + } + } + return null; + } + + public SampleSizeBox getSampleSizeBox() { + for (Box box : boxes) { + if (box instanceof SampleSizeBox) { + return (SampleSizeBox) box; + } + } + return null; + } + + public SampleToChunkBox getSampleToChunkBox() { + for (Box box : boxes) { + if (box instanceof SampleToChunkBox) { + return (SampleToChunkBox) box; + } + } + return null; + } + + public ChunkOffsetBox getChunkOffsetBox() { + for (Box box : boxes) { + if (box instanceof ChunkOffsetBox) { + return (ChunkOffsetBox) box; + } + } + return null; + } + + public void setChunkOffsetBox(ChunkOffsetBox b) { + for (int i = 0; i < boxes.size(); i++) { + Box box = boxes.get(i); + if (box instanceof ChunkOffsetBox) { + boxes.set(i, b); + } + } + } + + public TimeToSampleBox getTimeToSampleBox() { + for (Box box : boxes) { + if (box instanceof TimeToSampleBox) { + return (TimeToSampleBox) box; + } + } + return null; + } + + public SyncSampleBox getSyncSampleBox() { + for (Box box : boxes) { + if (box instanceof SyncSampleBox) { + return (SyncSampleBox) box; + } + } + return null; + } + + public CompositionTimeToSample getCompositionTimeToSample() { + for (Box box : boxes) { + if (box instanceof CompositionTimeToSample) { + return (CompositionTimeToSample) box; + } + } + return null; + } + + public SampleDependencyTypeBox getSampleDependencyTypeBox() { + for (Box box : boxes) { + if (box instanceof SampleDependencyTypeBox) { + return (SampleDependencyTypeBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleToChunkBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleToChunkBox.java.svn-base new file mode 100644 index 0000000..593504d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SampleToChunkBox.java.svn-base @@ -0,0 +1,156 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Samples within the media data are grouped into chunks. Chunks can be of different sizes, and the + * samples within a chunk can have different sizes. This table can be used to find the chunk that + * contains a sample, its position, and the associated sample description. Defined in ISO/IEC 14496-12. + */ +public class SampleToChunkBox extends AbstractFullBox { + List<Entry> entries = Collections.emptyList(); + + public static final String TYPE = "stsc"; + + public SampleToChunkBox() { + super(TYPE); + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + protected long getContentSize() { + return entries.size() * 12 + 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(entryCount); + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry( + IsoTypeReader.readUInt32(content), + IsoTypeReader.readUInt32(content), + IsoTypeReader.readUInt32(content))); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getFirstChunk()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getSamplesPerChunk()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleDescriptionIndex()); + } + } + + public String toString() { + return "SampleToChunkBox[entryCount=" + entries.size() + "]"; + } + + /** + * Decompresses the list of entries and returns the number of samples per chunk for + * every single chunk. + * + * @param chunkCount overall number of chunks + * @return number of samples per chunk + */ + public long[] blowup(int chunkCount) { + long[] numberOfSamples = new long[chunkCount]; + int j = 0; + List<SampleToChunkBox.Entry> sampleToChunkEntries = new LinkedList<Entry>(entries); + Collections.reverse(sampleToChunkEntries); + Iterator<Entry> iterator = sampleToChunkEntries.iterator(); + SampleToChunkBox.Entry currentEntry = iterator.next(); + + for (int i = numberOfSamples.length; i > 1; i--) { + numberOfSamples[i - 1] = currentEntry.getSamplesPerChunk(); + if (i == currentEntry.getFirstChunk()) { + currentEntry = iterator.next(); + } + } + numberOfSamples[0] = currentEntry.getSamplesPerChunk(); + return numberOfSamples; + } + + public static class Entry { + long firstChunk; + long samplesPerChunk; + long sampleDescriptionIndex; + + public Entry(long firstChunk, long samplesPerChunk, long sampleDescriptionIndex) { + this.firstChunk = firstChunk; + this.samplesPerChunk = samplesPerChunk; + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + public long getFirstChunk() { + return firstChunk; + } + + public void setFirstChunk(long firstChunk) { + this.firstChunk = firstChunk; + } + + public long getSamplesPerChunk() { + return samplesPerChunk; + } + + public void setSamplesPerChunk(long samplesPerChunk) { + this.samplesPerChunk = samplesPerChunk; + } + + public long getSampleDescriptionIndex() { + return sampleDescriptionIndex; + } + + public void setSampleDescriptionIndex(long sampleDescriptionIndex) { + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + @Override + public String toString() { + return "Entry{" + + "firstChunk=" + firstChunk + + ", samplesPerChunk=" + samplesPerChunk + + ", sampleDescriptionIndex=" + sampleDescriptionIndex + + '}'; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeInformationBox.java.svn-base new file mode 100644 index 0000000..5e3565e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeInformationBox.java.svn-base @@ -0,0 +1,33 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The Scheme Information Box is a container box that is only interpreted by the scheme beeing used. + * Any information the encryption system needs is stored here. The content of this box is a series of + * boxexes whose type annd format are defined by the scheme declared in the {@link com.coremedia.iso.boxes.SchemeTypeBox}. + */ +public class SchemeInformationBox extends AbstractContainerBox { + public static final String TYPE = "schi"; + + public SchemeInformationBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeTypeBox.java.svn-base new file mode 100644 index 0000000..ed517da --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SchemeTypeBox.java.svn-base @@ -0,0 +1,101 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The Scheme Type Box identifies the protection scheme. Resides in a Protection Scheme Information Box or + * an SRTP Process Box. + * + * @see com.coremedia.iso.boxes.SchemeInformationBox + */ +public class SchemeTypeBox extends AbstractFullBox { + public static final String TYPE = "schm"; + String schemeType = " "; + long schemeVersion; + String schemeUri = null; + + public SchemeTypeBox() { + super(TYPE); + } + + public String getSchemeType() { + return schemeType; + } + + public long getSchemeVersion() { + return schemeVersion; + } + + public String getSchemeUri() { + return schemeUri; + } + + public void setSchemeType(String schemeType) { + assert schemeType != null && schemeType.length() == 4 : "SchemeType may not be null or not 4 bytes long"; + this.schemeType = schemeType; + } + + public void setSchemeVersion(int schemeVersion) { + this.schemeVersion = schemeVersion; + } + + public void setSchemeUri(String schemeUri) { + this.schemeUri = schemeUri; + } + + protected long getContentSize() { + return 12 + (((getFlags() & 1) == 1) ? Utf8.utf8StringLengthInBytes(schemeUri) + 1 : 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + schemeType = IsoTypeReader.read4cc(content); + schemeVersion = IsoTypeReader.readUInt32(content); + if ((getFlags() & 1) == 1) { + schemeUri = IsoTypeReader.readString(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(IsoFile.fourCCtoBytes(schemeType)); + IsoTypeWriter.writeUInt32(byteBuffer, schemeVersion); + if ((getFlags() & 1) == 1) { + byteBuffer.put(Utf8.convert(schemeUri)); + } + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("Schema Type Box["); + buffer.append("schemeUri=").append(schemeUri).append("; "); + buffer.append("schemeType=").append(schemeType).append("; "); + buffer.append("schemeVersion=").append(schemeUri).append("; "); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SoundMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SoundMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..c5fb88d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SoundMediaHeaderBox.java.svn-base @@ -0,0 +1,58 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +public class SoundMediaHeaderBox extends AbstractMediaHeaderBox { + + public static final String TYPE = "smhd"; + private float balance; + + public SoundMediaHeaderBox() { + super(TYPE); + } + + public float getBalance() { + return balance; + } + + protected long getContentSize() { + return 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + balance = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeFixedPont88(byteBuffer, balance); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + } + + public String toString() { + return "SoundMediaHeaderBox[balance=" + getBalance() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/StaticChunkOffsetBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/StaticChunkOffsetBox.java.svn-base new file mode 100644 index 0000000..efcdd14 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/StaticChunkOffsetBox.java.svn-base @@ -0,0 +1,71 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * The chunk offset table gives the index of each chunk into the containing file. Defined in ISO/IEC 14496-12. + */ +public class StaticChunkOffsetBox extends ChunkOffsetBox { + public static final String TYPE = "stco"; + + private long[] chunkOffsets = new long[0]; + + public StaticChunkOffsetBox() { + super(TYPE); + } + + public long[] getChunkOffsets() { + return chunkOffsets; + } + + protected long getContentSize() { + return 8 + chunkOffsets.length * 4; + } + + public void setChunkOffsets(long[] chunkOffsets) { + this.chunkOffsets = chunkOffsets; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + chunkOffsets = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + chunkOffsets[i] = IsoTypeReader.readUInt32(content); + } + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffsets.length); + for (long chunkOffset : chunkOffsets) { + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffset); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubSampleInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubSampleInformationBox.java.svn-base new file mode 100644 index 0000000..f5806eb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubSampleInformationBox.java.svn-base @@ -0,0 +1,208 @@ +package com.coremedia.iso.boxes;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * aligned(8) class SubSampleInformationBox
+ * extends FullBox('subs', version, 0) {
+ * unsigned int(32) entry_count;
+ * int i,j;
+ * for (i=0; i < entry_count; i++) {
+ * unsigned int(32) sample_delta;
+ * unsigned int(16) subsample_count;
+ * if (subsample_count > 0) {
+ * for (j=0; j < subsample_count; j++) {
+ * if(version == 1)
+ * {
+ * unsigned int(32) subsample_size;
+ * }
+ * else
+ * {
+ * unsigned int(16) subsample_size;
+ * }
+ * unsigned int(8) subsample_priority;
+ * unsigned int(8) discardable;
+ * unsigned int(32) reserved = 0;
+ * }
+ * }
+ * }
+ * }
+ */
+public class SubSampleInformationBox extends AbstractFullBox {
+ public static final String TYPE = "subs";
+
+ private long entryCount;
+ private List<SampleEntry> entries = new ArrayList<SampleEntry>();
+
+ public SubSampleInformationBox() {
+ super(TYPE);
+ }
+
+ public List<SampleEntry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<SampleEntry> entries) {
+ this.entries = entries;
+ entryCount = entries.size();
+ }
+
+ @Override
+ protected long getContentSize() {
+ long entries = 8 + ((4 + 2) * entryCount);
+ int subsampleEntries = 0;
+ for (SampleEntry sampleEntry : this.entries) {
+ subsampleEntries += sampleEntry.getSubsampleCount() * (((getVersion() == 1) ? 4 : 2) + 1 + 1 + 4);
+ }
+ return entries + subsampleEntries;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+
+ entryCount = IsoTypeReader.readUInt32(content);
+
+ for (int i = 0; i < entryCount; i++) {
+ SampleEntry sampleEntry = new SampleEntry();
+ sampleEntry.setSampleDelta(IsoTypeReader.readUInt32(content));
+ int subsampleCount = IsoTypeReader.readUInt16(content);
+ for (int j = 0; j < subsampleCount; j++) {
+ SampleEntry.SubsampleEntry subsampleEntry = new SampleEntry.SubsampleEntry();
+ subsampleEntry.setSubsampleSize(getVersion() == 1 ? IsoTypeReader.readUInt32(content) : IsoTypeReader.readUInt16(content));
+ subsampleEntry.setSubsamplePriority(IsoTypeReader.readUInt8(content));
+ subsampleEntry.setDiscardable(IsoTypeReader.readUInt8(content));
+ subsampleEntry.setReserved(IsoTypeReader.readUInt32(content));
+ sampleEntry.addSubsampleEntry(subsampleEntry);
+ }
+ entries.add(sampleEntry);
+ }
+
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (SampleEntry sampleEntry : entries) {
+ IsoTypeWriter.writeUInt32(byteBuffer, sampleEntry.getSampleDelta());
+ IsoTypeWriter.writeUInt16(byteBuffer, sampleEntry.getSubsampleCount());
+ List<SampleEntry.SubsampleEntry> subsampleEntries = sampleEntry.getSubsampleEntries();
+ for (SampleEntry.SubsampleEntry subsampleEntry : subsampleEntries) {
+ if (getVersion() == 1) {
+ IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getSubsampleSize());
+ } else {
+ IsoTypeWriter.writeUInt16(byteBuffer, l2i(subsampleEntry.getSubsampleSize()));
+ }
+ IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getSubsamplePriority());
+ IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getDiscardable());
+ IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getReserved());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SubSampleInformationBox{" +
+ "entryCount=" + entryCount +
+ ", entries=" + entries +
+ '}';
+ }
+
+ public static class SampleEntry {
+ private long sampleDelta;
+ private int subsampleCount;
+ private List<SubsampleEntry> subsampleEntries = new ArrayList<SubsampleEntry>();
+
+ public long getSampleDelta() {
+ return sampleDelta;
+ }
+
+ public void setSampleDelta(long sampleDelta) {
+ this.sampleDelta = sampleDelta;
+ }
+
+ public int getSubsampleCount() {
+ return subsampleCount;
+ }
+
+ public void setSubsampleCount(int subsampleCount) {
+ this.subsampleCount = subsampleCount;
+ }
+
+ public List<SubsampleEntry> getSubsampleEntries() {
+ return subsampleEntries;
+ }
+
+ public void addSubsampleEntry(SubsampleEntry subsampleEntry) {
+ subsampleEntries.add(subsampleEntry);
+ subsampleCount++;
+ }
+
+ public static class SubsampleEntry {
+ private long subsampleSize;
+ private int subsamplePriority;
+ private int discardable;
+ private long reserved;
+
+ public long getSubsampleSize() {
+ return subsampleSize;
+ }
+
+ public void setSubsampleSize(long subsampleSize) {
+ this.subsampleSize = subsampleSize;
+ }
+
+ public int getSubsamplePriority() {
+ return subsamplePriority;
+ }
+
+ public void setSubsamplePriority(int subsamplePriority) {
+ this.subsamplePriority = subsamplePriority;
+ }
+
+ public int getDiscardable() {
+ return discardable;
+ }
+
+ public void setDiscardable(int discardable) {
+ this.discardable = discardable;
+ }
+
+ public long getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(long reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "SubsampleEntry{" +
+ "subsampleSize=" + subsampleSize +
+ ", subsamplePriority=" + subsamplePriority +
+ ", discardable=" + discardable +
+ ", reserved=" + reserved +
+ '}';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SampleEntry{" +
+ "sampleDelta=" + sampleDelta +
+ ", subsampleCount=" + subsampleCount +
+ ", subsampleEntries=" + subsampleEntries +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubtitleMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubtitleMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..fa25a5c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SubtitleMediaHeaderBox.java.svn-base @@ -0,0 +1,30 @@ +package com.coremedia.iso.boxes; + +import java.nio.ByteBuffer; + +public class SubtitleMediaHeaderBox extends AbstractMediaHeaderBox { + + public static final String TYPE = "sthd"; + + public SubtitleMediaHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } + + public String toString() { + return "SubtitleMediaHeaderBox"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SyncSampleBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SyncSampleBox.java.svn-base new file mode 100644 index 0000000..5fc758b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/SyncSampleBox.java.svn-base @@ -0,0 +1,83 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box provides a compact marking of the random access points withinthe stream. The table is arranged in + * strictly decreasinf order of sample number. Defined in ISO/IEC 14496-12. + */ +public class SyncSampleBox extends AbstractFullBox { + public static final String TYPE = "stss"; + + private long[] sampleNumber; + + public SyncSampleBox() { + super(TYPE); + } + + /** + * Gives the numbers of the samples that are random access points in the stream. + * + * @return random access sample numbers. + */ + public long[] getSampleNumber() { + return sampleNumber; + } + + protected long getContentSize() { + return sampleNumber.length * 4 + 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + + sampleNumber = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + sampleNumber[i] = IsoTypeReader.readUInt32(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + + IsoTypeWriter.writeUInt32(byteBuffer, sampleNumber.length); + + for (long aSampleNumber : sampleNumber) { + IsoTypeWriter.writeUInt32(byteBuffer, aSampleNumber); + } + + } + + public String toString() { + return "SyncSampleBox[entryCount=" + sampleNumber.length + "]"; + } + + public void setSampleNumber(long[] sampleNumber) { + this.sampleNumber = sampleNumber; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TimeToSampleBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TimeToSampleBox.java.svn-base new file mode 100644 index 0000000..8f4f97e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TimeToSampleBox.java.svn-base @@ -0,0 +1,152 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box contains a compact version of a table that allows indexing from decoding time to sample number. + * Other tables give sample sizes and pointers, from the sample number. Each entry in the table gives the + * number of consecutive samples with the same time delta, and the delta of those samples. By adding the + * deltas a complete time-to-sample map may be built.<br> + * The Decoding Time to Sample Box contains decode time delta's: <code>DT(n+1) = DT(n) + STTS(n)</code> where STTS(n) + * is the (uncompressed) table entry for sample n.<br> + * The sample entries are ordered by decoding time stamps; therefore the deltas are all non-negative. <br> + * The DT axis has a zero origin; <code>DT(i) = SUM(for j=0 to i-1 of delta(j))</code>, and the sum of all + * deltas gives the length of the media in the track (not mapped to the overall timescale, and not considering + * any edit list). <br> + * The Edit List Box provides the initial CT value if it is non-empty (non-zero). + */ +public class TimeToSampleBox extends AbstractFullBox { + public static final String TYPE = "stts"; + + List<Entry> entries = Collections.emptyList(); + + + public TimeToSampleBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8 + entries.size() * 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(entryCount); + + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content))); + } + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getDelta()); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + public String toString() { + return "TimeToSampleBox[entryCount=" + entries.size() + "]"; + } + + public static class Entry { + long count; + long delta; + + public Entry(long count, long delta) { + this.count = count; + this.delta = delta; + } + + public long getCount() { + return count; + } + + public long getDelta() { + return delta; + } + + public void setCount(long count) { + this.count = count; + } + + public void setDelta(long delta) { + this.delta = delta; + } + + @Override + public String toString() { + return "Entry{" + + "count=" + count + + ", delta=" + delta + + '}'; + } + } + + /** + * Decompresses the list of entries and returns the list of decoding times. + * + * @return decoding time per sample + */ + public static long[] blowupTimeToSamples(List<TimeToSampleBox.Entry> entries) { + long numOfSamples = 0; + for (TimeToSampleBox.Entry entry : entries) { + numOfSamples += entry.getCount(); + } + assert numOfSamples <= Integer.MAX_VALUE; + long[] decodingTime = new long[(int) numOfSamples]; + + int current = 0; + + + for (TimeToSampleBox.Entry entry : entries) { + for (int i = 0; i < entry.getCount(); i++) { + decodingTime[current++] = entry.getDelta(); + } + } + + return decodingTime; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TitleBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TitleBox.java.svn-base new file mode 100644 index 0000000..46ee5ee --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TitleBox.java.svn-base @@ -0,0 +1,89 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * <code> + * Box Type: 'titl'<br> + * Container: {@link UserDataBox} ('udta')<br> + * Mandatory: No<br> + * Quantity: Zero or one<br><br> + * </code> + * <p/> + * Title for the media. + */ +public class TitleBox extends AbstractFullBox { + public static final String TYPE = "titl"; + + private String language; + private String title; + + public TitleBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getTitle() { + return title; + } + + /** + * Sets the 3-letter ISO-639 language for this title. + * + * @param language 3-letter ISO-639 code + */ + public void setLanguage(String language) { + this.language = language; + } + + public void setTitle(String title) { + this.title = title; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(title); + } + + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(title)); + byteBuffer.put((byte) 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + title = IsoTypeReader.readString(content); + } + + public String toString() { + return "TitleBox[language=" + getLanguage() + ";title=" + getTitle() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackBox.java.svn-base new file mode 100644 index 0000000..c2806b5 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackBox.java.svn-base @@ -0,0 +1,71 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * Tracks are used for two purposes: (a) to contain media data (media tracks) and (b) to contain packetization + * information for streaming protocols (hint tracks). <br> + * There shall be at least one media track within an ISO file, and all the media tracks that contributed to the hint + * tracks shall remain in the file, even if the media data within them is not referenced by the hint tracks; after + * deleting all hint tracks, the entire un-hinted presentation shall remain. + */ +public class TrackBox extends AbstractContainerBox { + public static final String TYPE = "trak"; + + public TrackBox() { + super(TYPE); + } + + public TrackHeaderBox getTrackHeaderBox() { + for (Box box : boxes) { + if (box instanceof TrackHeaderBox) { + return (TrackHeaderBox) box; + } + } + return null; + } + + /** + * Gets the SampleTableBox at mdia/minf/stbl if existing. + * + * @return the SampleTableBox or <code>null</code> + */ + public SampleTableBox getSampleTableBox() { + MediaBox mdia = getMediaBox(); + if (mdia != null) { + MediaInformationBox minf = mdia.getMediaInformationBox(); + if (minf != null) { + return minf.getSampleTableBox(); + } + } + return null; + + } + + + public MediaBox getMediaBox() { + for (Box box : boxes) { + if (box instanceof MediaBox) { + return (MediaBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackHeaderBox.java.svn-base new file mode 100644 index 0000000..8816bb9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackHeaderBox.java.svn-base @@ -0,0 +1,249 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track.<br> + * In the absence of an edit list, the presentation of a track starts at the beginning of the overall presentation. An + * empty edit is used to offset the start time of a track. <br> + * The default value of the track header flags for media tracks is 7 (track_enabled, track_in_movie, + * track_in_preview). If in a presentation all tracks have neither track_in_movie nor track_in_preview set, then all + * tracks shall be treated as if both flags were set on all tracks. Hint tracks should have the track header flags set + * to 0, so that they are ignored for local playback and preview. + */ +public class TrackHeaderBox extends AbstractFullBox { + + public static final String TYPE = "tkhd"; + + private long creationTime; + private long modificationTime; + private long trackId; + private long duration; + private int layer; + private int alternateGroup; + private float volume; + private long[] matrix = new long[]{0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; + private double width; + private double height; + + + public TrackHeaderBox() { + super(TYPE); + + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTrackId() { + return trackId; + } + + public long getDuration() { + return duration; + } + + public int getLayer() { + return layer; + } + + public int getAlternateGroup() { + return alternateGroup; + } + + public float getVolume() { + return volume; + } + + public long[] getMatrix() { + return matrix; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 32; + } else { + contentSize += 20; + } + contentSize += 60; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + trackId = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + trackId = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } // 196 + IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + layer = IsoTypeReader.readUInt16(content); // 204 + alternateGroup = IsoTypeReader.readUInt16(content); + volume = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); // 212 + matrix = new long[9]; + for (int i = 0; i < 9; i++) { + matrix[i] = IsoTypeReader.readUInt32(content); + } + width = IsoTypeReader.readFixedPoint1616(content); // 248 + height = IsoTypeReader.readFixedPoint1616(content); + } + + public void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } // 196 + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, layer); + IsoTypeWriter.writeUInt16(byteBuffer, alternateGroup); + IsoTypeWriter.writeFixedPont88(byteBuffer, volume); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + for (int i = 0; i < 9; i++) { + IsoTypeWriter.writeUInt32(byteBuffer, matrix[i]); + } + IsoTypeWriter.writeFixedPont1616(byteBuffer, width); + IsoTypeWriter.writeFixedPont1616(byteBuffer, height); + } + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("TrackHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("trackId=").append(getTrackId()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("layer=").append(getLayer()); + result.append(";"); + result.append("alternateGroup=").append(getAlternateGroup()); + result.append(";"); + result.append("volume=").append(getVolume()); + for (int i = 0; i < matrix.length; i++) { + result.append(";"); + result.append("matrix").append(i).append("=").append(matrix[i]); + } + result.append(";"); + result.append("width=").append(getWidth()); + result.append(";"); + result.append("height=").append(getHeight()); + result.append("]"); + return result.toString(); + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setLayer(int layer) { + this.layer = layer; + } + + public void setAlternateGroup(int alternateGroup) { + this.alternateGroup = alternateGroup; + } + + public void setVolume(float volume) { + this.volume = volume; + } + + public void setMatrix(long[] matrix) { + this.matrix = matrix; + } + + public void setWidth(double width) { + this.width = width; + } + + public void setHeight(double height) { + this.height = height; + } + + + public boolean isEnabled() { + return (getFlags() & 1) > 0; + } + + public boolean isInMovie() { + return (getFlags() & 2) > 0; + } + + public boolean isInPreview() { + return (getFlags() & 4) > 0; + } + + public boolean isInPoster() { + return (getFlags() & 8) > 0; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceBox.java.svn-base new file mode 100644 index 0000000..1b4a7fb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceBox.java.svn-base @@ -0,0 +1,41 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * <code> + * Box Type: 'tref'<br> + * Container: {@link TrackBox} ('trak')<br> + * Mandatory: No<br> + * Quantity: Zero or one<br><br> + * </code> + * This box provides a reference from the containing track to another track in the presentation. These references + * are typed. A 'hint' reference links from the containing hint track to the media data that it hints. A content + * description reference 'cdsc' links a descriptive or metadata track to the content which it describes. + * Exactly one Track Reference Box can be contained within the Track Box. + * If this box is not present, the track is not referencing any other track in any way. The reference array is sized + * to fill the reference type box. + */ +public class TrackReferenceBox extends AbstractContainerBox { + public static final String TYPE = "tref"; + + public TrackReferenceBox() { + super(TYPE); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceTypeBox.java.svn-base new file mode 100644 index 0000000..297932d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/TrackReferenceTypeBox.java.svn-base @@ -0,0 +1,76 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * Contains a reference to a track. The type of the box gives the kind of reference. + */ +public class TrackReferenceTypeBox extends AbstractBox { + + public static final String TYPE1 = "hint"; + public static final String TYPE2 = "cdsc"; + + private long[] trackIds; + + public TrackReferenceTypeBox(String type) { + super(type); + } + + public long[] getTrackIds() { + return trackIds; + } + + @Override + public void _parseDetails(ByteBuffer content) { + int count = (int) (content.remaining() / 4); + trackIds = new long[count]; + for (int i = 0; i < count; i++) { + trackIds[i] = IsoTypeReader.readUInt32(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + for (long trackId : trackIds) { + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + } + } + + + protected long getContentSize() { + return trackIds.length * 4; + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("TrackReferenceTypeBox[type=").append(getType()); + for (int i = 0; i < trackIds.length; i++) { + buffer.append(";trackId"); + buffer.append(i); + buffer.append("="); + buffer.append(trackIds[i]); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UnknownBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UnknownBox.java.svn-base new file mode 100644 index 0000000..f76481c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UnknownBox.java.svn-base @@ -0,0 +1,59 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * A box unknown to the ISO Parser. If there is no specific Box implementation for a Box this <code>UnknownBox</code> + * will just hold the box's data. + */ +public class UnknownBox extends AbstractBox { + ByteBuffer data; + + public UnknownBox(String type) { + super(type); + } + + @Override + protected long getContentSize() { + return data.limit(); + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = content; + content.position(content.position() + content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + data.rewind(); + byteBuffer.put(data); + } + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserBox.java.svn-base new file mode 100644 index 0000000..db0e741 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserBox.java.svn-base @@ -0,0 +1,64 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * A user specifc box. See ISO/IEC 14496-12 for details. + */ +public class UserBox extends AbstractBox { + byte[] data; + public static final String TYPE = "uuid"; + + public UserBox(byte[] userType) { + super(TYPE, userType); + } + + + protected long getContentSize() { + return data.length; + } + + public String toString() { + return "UserBox[type=" + (getType()) + + ";userType=" + new String(getUserType()) + + ";contentLength=" + data.length + "]"; + } + + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = new byte[content.remaining()]; + content.get(data); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserDataBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserDataBox.java.svn-base new file mode 100644 index 0000000..65c5808 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/UserDataBox.java.svn-base @@ -0,0 +1,59 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.BoxParser; +import com.googlecode.mp4parser.AbstractContainerBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +/** + * This box contains objects that declare user information about the containing box and its data (presentation or + * track).<br> + * The User Data Box is a container box for informative user-data. This user data is formatted as a set of boxes + * with more specific box types, which declare more precisely their content + */ +public class UserDataBox extends AbstractContainerBox { + public static final String TYPE = "udta"; + + @Override + protected long getContentSize() { + return super.getContentSize(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + super.parse(readableByteChannel, header, contentSize, boxParser); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public void _parseDetails(ByteBuffer content) { + super._parseDetails(content); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + super.getContent(byteBuffer); //To change body of overridden methods use File | Settings | File Templates. + } + + public UserDataBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/VideoMediaHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/VideoMediaHeaderBox.java.svn-base new file mode 100644 index 0000000..421a67d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/VideoMediaHeaderBox.java.svn-base @@ -0,0 +1,81 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * The video media header contains general presentation information, independent of the coding, for video + * media. Note that the flags field has the value 1. + */ +public class VideoMediaHeaderBox extends AbstractMediaHeaderBox { + private int graphicsmode = 0; + private int[] opcolor = new int[]{0, 0, 0}; + public static final String TYPE = "vmhd"; + + public VideoMediaHeaderBox() { + super(TYPE); + setFlags(1); // 1 is default. + } + + public int getGraphicsmode() { + return graphicsmode; + } + + public int[] getOpcolor() { + return opcolor; + } + + protected long getContentSize() { + return 12; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + graphicsmode = IsoTypeReader.readUInt16(content); + opcolor = new int[3]; + for (int i = 0; i < 3; i++) { + opcolor[i] = IsoTypeReader.readUInt16(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, graphicsmode); + for (int anOpcolor : opcolor) { + IsoTypeWriter.writeUInt16(byteBuffer, anOpcolor); + } + } + + public String toString() { + return "VideoMediaHeaderBox[graphicsmode=" + getGraphicsmode() + ";opcolor0=" + getOpcolor()[0] + ";opcolor1=" + getOpcolor()[1] + ";opcolor2=" + getOpcolor()[2] + "]"; + } + + public void setOpcolor(int[] opcolor) { + this.opcolor = opcolor; + } + + public void setGraphicsmode(int graphicsmode) { + this.graphicsmode = graphicsmode; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/WriteListener.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/WriteListener.java.svn-base new file mode 100644 index 0000000..dc22d52 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/WriteListener.java.svn-base @@ -0,0 +1,10 @@ +package com.coremedia.iso.boxes; + +/** + * The <class>WriteListener</class> is used to get the offset of + * a box before writing the box. This can be used if a box written + * later needs an offset. + */ +public interface WriteListener { + public void beforeWrite(long offset); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/XmlBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/XmlBox.java.svn-base new file mode 100644 index 0000000..43727e1 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/XmlBox.java.svn-base @@ -0,0 +1,51 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class XmlBox extends AbstractFullBox { + String xml = ""; + public static final String TYPE = "xml "; + + public XmlBox() { + super(TYPE); + } + + public String getXml() { + return xml; + } + + public void setXml(String xml) { + this.xml = xml; + } + + @Override + protected long getContentSize() { + return 4 + Utf8.utf8StringLengthInBytes(xml); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + xml = IsoTypeReader.readString(content, content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(xml)); + } + + @Override + public String toString() { + return "XmlBox{" + + "xml='" + xml + '\'' + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/odf-boxes.zip.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/odf-boxes.zip.svn-base Binary files differnew file mode 100644 index 0000000..04e0e5e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/odf-boxes.zip.svn-base diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/rtp-boxes.zip.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/rtp-boxes.zip.svn-base Binary files differnew file mode 100644 index 0000000..be1a167 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/.svn/text-base/rtp-boxes.zip.svn-base diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/AbstractMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/AbstractMediaHeaderBox.java new file mode 100644 index 0000000..cc141ae --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/AbstractMediaHeaderBox.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011 Sebastian Annies, Hamburg, Germany + * + * 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +/** + * A common superclass for all MediaInformationHeaderBoxes. E.g. + * VideoMediaHeaderBox, SoundMediaHeaderBox & HintMediaHeaderBox + */ +public abstract class AbstractMediaHeaderBox extends AbstractFullBox { + protected AbstractMediaHeaderBox(String type) { + super(type); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/AlbumBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/AlbumBox.java new file mode 100644 index 0000000..d666806 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/AlbumBox.java @@ -0,0 +1,112 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Meta information in a 'udta' box about a track. + * Defined in 3GPP 26.244. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class AlbumBox extends AbstractFullBox { + public static final String TYPE = "albm"; + + private String language; + private String albumTitle; + private int trackNumber; + + public AlbumBox() { + super(TYPE); + } + + /** + * Declares the language code for the {@link #getAlbumTitle()} return value. See ISO 639-2/T for the set of three + * character codes.Each character is packed as the difference between its ASCII value and 0x60. The code is + * confined to being three lower-case letters, so these values are strictly positive. + * + * @return the language code + */ + public String getLanguage() { + return language; + } + + public String getAlbumTitle() { + return albumTitle; + } + + public int getTrackNumber() { + return trackNumber; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAlbumTitle(String albumTitle) { + this.albumTitle = albumTitle; + } + + public void setTrackNumber(int trackNumber) { + this.trackNumber = trackNumber; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(albumTitle) + 1 + (trackNumber == -1 ? 0 : 1); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + albumTitle = IsoTypeReader.readString(content); + + if (content.remaining() > 0) { + trackNumber = IsoTypeReader.readUInt8(content); + } else { + trackNumber = -1; + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(albumTitle)); + byteBuffer.put((byte) 0); + if (trackNumber != -1) { + IsoTypeWriter.writeUInt8(byteBuffer, trackNumber); + } + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("AlbumBox[language=").append(getLanguage()).append(";"); + buffer.append("albumTitle=").append(getAlbumTitle()); + if (trackNumber >= 0) { + buffer.append(";trackNumber=").append(getTrackNumber()); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/AuthorBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/AuthorBox.java new file mode 100644 index 0000000..672cde2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/AuthorBox.java @@ -0,0 +1,94 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Meta information in a 'udta' box about a track. + * Defined in 3GPP 26.244. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class AuthorBox extends AbstractFullBox { + public static final String TYPE = "auth"; + + private String language; + private String author; + + public AuthorBox() { + super(TYPE); + } + + /** + * Declares the language code for the {@link #getAuthor()} return value. See ISO 639-2/T for the set of three + * character codes.Each character is packed as the difference between its ASCII value and 0x60. The code is + * confined to being three lower-case letters, so these values are strictly positive. + * + * @return the language code + */ + public String getLanguage() { + return language; + } + + /** + * Author information. + * + * @return the author + */ + public String getAuthor() { + return author; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAuthor(String author) { + this.author = author; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(author); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + author = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(author)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + return "AuthorBox[language=" + getLanguage() + ";author=" + getAuthor() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/BitRateBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/BitRateBox.java new file mode 100644 index 0000000..6c4b0e6 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/BitRateBox.java @@ -0,0 +1,91 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * <code>class BitRateBox extends Box('btrt') {<br/> + * unsigned int(32) bufferSizeDB;<br/> + * // gives the size of the decoding buffer for<br/> + * // the elementary stream in bytes.<br/> + * unsigned int(32) maxBitrate;<br/> + * // gives the maximum rate in bits/second <br/> + * // over any window of one second.<br/> + * unsigned int(32) avgBitrate;<br/> + * // avgBitrate gives the average rate in <br/> + * // bits/second over the entire presentation.<br/> + * }</code> + */ + +public final class BitRateBox extends AbstractBox { + public static final String TYPE = "btrt"; + + private long bufferSizeDb; + private long maxBitrate; + private long avgBitrate; + + public BitRateBox() { + super(TYPE); + } + + protected long getContentSize() { + return 12; + } + + @Override + public void _parseDetails(ByteBuffer content) { + bufferSizeDb = IsoTypeReader.readUInt32(content); + maxBitrate = IsoTypeReader.readUInt32(content); + avgBitrate = IsoTypeReader.readUInt32(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + IsoTypeWriter.writeUInt32(byteBuffer, bufferSizeDb); + IsoTypeWriter.writeUInt32(byteBuffer, maxBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, avgBitrate); + } + + public long getBufferSizeDb() { + return bufferSizeDb; + } + + public void setBufferSizeDb(long bufferSizeDb) { + this.bufferSizeDb = bufferSizeDb; + } + + public long getMaxBitrate() { + return maxBitrate; + } + + public void setMaxBitrate(long maxBitrate) { + this.maxBitrate = maxBitrate; + } + + public long getAvgBitrate() { + return avgBitrate; + } + + public void setAvgBitrate(long avgBitrate) { + this.avgBitrate = avgBitrate; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/Box.java b/isoparser/src/main/java/com/coremedia/iso/boxes/Box.java new file mode 100644 index 0000000..f6ca302 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/Box.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.boxes.ContainerBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +/** + * Defines basic interaction possibilities for any ISO box. Each box has a parent box and a type. + */ +public interface Box { + ContainerBox getParent(); + + void setParent(ContainerBox parent); + + long getSize(); + + /** + * The box's 4-cc type. + * @return the 4 character type of the box + */ + String getType(); + + /** + * Writes the complete box - size | 4-cc | content - to the given <code>writableByteChannel</code>. + * @param writableByteChannel the box's sink + * @throws IOException in case of problems with the <code>Channel</code> + */ + void getBox(WritableByteChannel writableByteChannel) throws IOException; + + void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException; +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffset64BitBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffset64BitBox.java new file mode 100755 index 0000000..f2340b9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffset64BitBox.java @@ -0,0 +1,51 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Abstract Chunk Offset Box + */ +public class ChunkOffset64BitBox extends ChunkOffsetBox { + public static final String TYPE = "co64"; + private long[] chunkOffsets; + + public ChunkOffset64BitBox() { + super(TYPE); + } + + @Override + public long[] getChunkOffsets() { + return chunkOffsets; + } + + @Override + protected long getContentSize() { + return 8 + 8 * chunkOffsets.length; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + chunkOffsets = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + chunkOffsets[i] = IsoTypeReader.readUInt64(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffsets.length); + for (long chunkOffset : chunkOffsets) { + IsoTypeWriter.writeUInt64(byteBuffer, chunkOffset); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffsetBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffsetBox.java new file mode 100755 index 0000000..01f5ae4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ChunkOffsetBox.java @@ -0,0 +1,21 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +/** + * Abstract Chunk Offset Box + */ +public abstract class ChunkOffsetBox extends AbstractFullBox { + + public ChunkOffsetBox(String type) { + super(type); + } + + public abstract long[] getChunkOffsets(); + + + public String toString() { + return this.getClass().getSimpleName() + "[entryCount=" + getChunkOffsets().length + "]"; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ClassificationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ClassificationBox.java new file mode 100644 index 0000000..a20feca --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ClassificationBox.java @@ -0,0 +1,110 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Classification of the media according to 3GPP 26.244. + */ +public class ClassificationBox extends AbstractFullBox { + public static final String TYPE = "clsf"; + + + private String classificationEntity; + private int classificationTableIndex; + private String language; + private String classificationInfo; + + public ClassificationBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getClassificationEntity() { + return classificationEntity; + } + + public int getClassificationTableIndex() { + return classificationTableIndex; + } + + public String getClassificationInfo() { + return classificationInfo; + } + + public void setClassificationEntity(String classificationEntity) { + this.classificationEntity = classificationEntity; + } + + public void setClassificationTableIndex(int classificationTableIndex) { + this.classificationTableIndex = classificationTableIndex; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setClassificationInfo(String classificationInfo) { + this.classificationInfo = classificationInfo; + } + + protected long getContentSize() { + return 4 + 2 + 2 + Utf8.utf8StringLengthInBytes(classificationInfo) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + byte[] cE = new byte[4]; + content.get(cE); + classificationEntity = IsoFile.bytesToFourCC(cE); + classificationTableIndex = IsoTypeReader.readUInt16(content); + language = IsoTypeReader.readIso639(content); + classificationInfo = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(classificationEntity)); + IsoTypeWriter.writeUInt16(byteBuffer, classificationTableIndex); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(classificationInfo)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("ClassificationBox[language=").append(getLanguage()); + buffer.append("classificationEntity=").append(getClassificationEntity()); + buffer.append(";classificationTableIndex=").append(getClassificationTableIndex()); + buffer.append(";language=").append(getLanguage()); + buffer.append(";classificationInfo=").append(getClassificationInfo()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionShiftLeastGreatestAtom.java b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionShiftLeastGreatestAtom.java new file mode 100644 index 0000000..3534b7f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionShiftLeastGreatestAtom.java @@ -0,0 +1,101 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The optional composition shift least greatest atom summarizes the calculated + * minimum and maximum offsets between decode and composition time, as well as + * the start and end times, for all samples. This allows a reader to determine + * the minimum required time for decode to obtain proper presentation order without + * needing to scan the sample table for the range of offsets. The type of the + * composition shift least greatest atom is ‘cslg’. + */ +public class CompositionShiftLeastGreatestAtom extends AbstractFullBox { + public CompositionShiftLeastGreatestAtom() { + super("cslg"); + } + + // A 32-bit unsigned integer that specifies the calculated value. + int compositionOffsetToDisplayOffsetShift; + + // A 32-bit signed integer that specifies the calculated value. + int leastDisplayOffset; + + // A 32-bit signed integer that specifies the calculated value. + int greatestDisplayOffset; + + //A 32-bit signed integer that specifies the calculated value. + int displayStartTime; + + //A 32-bit signed integer that specifies the calculated value. + int displayEndTime; + + + @Override + protected long getContentSize() { + return 24; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + compositionOffsetToDisplayOffsetShift = content.getInt(); + leastDisplayOffset = content.getInt(); + greatestDisplayOffset = content.getInt(); + displayStartTime = content.getInt(); + displayEndTime = content.getInt(); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.putInt(compositionOffsetToDisplayOffsetShift); + byteBuffer.putInt(leastDisplayOffset); + byteBuffer.putInt(greatestDisplayOffset); + byteBuffer.putInt(displayStartTime); + byteBuffer.putInt(displayEndTime); + } + + + public int getCompositionOffsetToDisplayOffsetShift() { + return compositionOffsetToDisplayOffsetShift; + } + + public void setCompositionOffsetToDisplayOffsetShift(int compositionOffsetToDisplayOffsetShift) { + this.compositionOffsetToDisplayOffsetShift = compositionOffsetToDisplayOffsetShift; + } + + public int getLeastDisplayOffset() { + return leastDisplayOffset; + } + + public void setLeastDisplayOffset(int leastDisplayOffset) { + this.leastDisplayOffset = leastDisplayOffset; + } + + public int getGreatestDisplayOffset() { + return greatestDisplayOffset; + } + + public void setGreatestDisplayOffset(int greatestDisplayOffset) { + this.greatestDisplayOffset = greatestDisplayOffset; + } + + public int getDisplayStartTime() { + return displayStartTime; + } + + public void setDisplayStartTime(int displayStartTime) { + this.displayStartTime = displayStartTime; + } + + public int getDisplayEndTime() { + return displayEndTime; + } + + public void setDisplayEndTime(int displayEndTime) { + this.displayEndTime = displayEndTime; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java new file mode 100644 index 0000000..411bfe9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java @@ -0,0 +1,150 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * <pre> + * aligned(8) class CompositionOffsetBox + * extends FullBox(‘ctts’, version = 0, 0) { + * unsigned int(32) entry_count; + * int i; + * if (version==0) { + * for (i=0; i < entry_count; i++) { + * unsigned int(32) sample_count; + * unsigned int(32) sample_offset; + * } + * } + * else if (version == 1) { + * for (i=0; i < entry_count; i++) { + * unsigned int(32) sample_count; + * signed int(32) sample_offset; + * } + * } + * } + * </pre> + * <p/> + * This box provides the offset between decoding time and composition time. + * In version 0 of this box the decoding time must be less than the composition time, and + * the offsets are expressed as unsigned numbers such that + * CT(n) = DT(n) + CTTS(n) where CTTS(n) is the (uncompressed) table entry for sample n. + * <p/> + * In version 1 of this box, the composition timeline and the decoding timeline are + * still derived from each other, but the offsets are signed. + * It is recommended that for the computed composition timestamps, there is + * exactly one with the value 0 (zero). + */ +public class CompositionTimeToSample extends AbstractFullBox { + public static final String TYPE = "ctts"; + + List<Entry> entries = Collections.emptyList(); + + public CompositionTimeToSample() { + super(TYPE); + } + + protected long getContentSize() { + return 8 + 8 * entries.size(); + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int numberOfEntries = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(numberOfEntries); + for (int i = 0; i < numberOfEntries; i++) { + Entry e = new Entry(l2i(IsoTypeReader.readUInt32(content)), content.getInt()); + entries.add(e); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount()); + byteBuffer.putInt(entry.getOffset()); + } + + } + + + public static class Entry { + int count; + int offset; + + public Entry(int count, int offset) { + this.count = count; + this.offset = offset; + } + + public int getCount() { + return count; + } + + public int getOffset() { + return offset; + } + + public void setCount(int count) { + this.count = count; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + @Override + public String toString() { + return "Entry{" + + "count=" + count + + ", offset=" + offset + + '}'; + } + } + + + /** + * Decompresses the list of entries and returns the list of composition times. + * + * @return decoding time per sample + */ + public static int[] blowupCompositionTimes(List<CompositionTimeToSample.Entry> entries) { + long numOfSamples = 0; + for (CompositionTimeToSample.Entry entry : entries) { + numOfSamples += entry.getCount(); + } + assert numOfSamples <= Integer.MAX_VALUE; + int[] decodingTime = new int[(int) numOfSamples]; + + int current = 0; + + + for (CompositionTimeToSample.Entry entry : entries) { + for (int i = 0; i < entry.getCount(); i++) { + decodingTime[current++] = entry.getOffset(); + } + } + + return decodingTime; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ContainerBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ContainerBox.java new file mode 100644 index 0000000..a016374 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ContainerBox.java @@ -0,0 +1,74 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; + +import java.util.List; + +/** + * Interface for all ISO boxes that may contain other boxes. + */ +public interface ContainerBox extends Box { + + /** + * Gets all child boxes. May not return <code>null</code>. + * + * @return an array of boxes, empty array in case of no children. + */ + List<Box> getBoxes(); + + /** + * Sets all boxes and removes all previous child boxes. + * @param boxes the new list of children + */ + void setBoxes(List<Box> boxes); + + /** + * Gets all child boxes of the given type. May not return <code>null</code>. + * + * @param clazz child box's type + * @return an array of boxes, empty array in case of no children. + */ + <T extends Box> List<T> getBoxes(Class<T> clazz); + + /** + * Gets all child boxes of the given type. May not return <code>null</code>. + * + * @param clazz child box's type + * @param recursive step down the tree + * @return an array of boxes, empty array in case of no children. + */ + <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive); + + /** + * Gets the parent box. May be <code>null</code> in case of the + * {@link com.coremedia.iso.IsoFile} itself. + * + * @return a <code>ContainerBox</code> that contains <code>this</code> + */ + ContainerBox getParent(); + + /** + * Returns the number of bytes from the start of the box to start of the first child. + * + * @return offset of first child from box start + */ + long getNumOfBytesToFirstChild(); + + IsoFile getIsoFile(); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/CopyrightBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/CopyrightBox.java new file mode 100644 index 0000000..86bc215 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/CopyrightBox.java @@ -0,0 +1,86 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The copyright box contains a copyright declaration which applies to the entire presentation, when contained + * within the MovieBox, or, when contained in a track, to that entire track. There may be multple boxes using + * different language codes. + * + * @see MovieBox + * @see TrackBox + */ +public class CopyrightBox extends AbstractFullBox { + public static final String TYPE = "cprt"; + + private String language; + private String copyright; + + public CopyrightBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getCopyright() { + return copyright; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setCopyright(String copyright) { + this.copyright = copyright; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(copyright); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + copyright = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(copyright)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "CopyrightBox[language=" + getLanguage() + ";copyright=" + getCopyright() + "]"; + } + + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrlBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrlBox.java new file mode 100644 index 0000000..b58608d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrlBox.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Only used within the DataReferenceBox. Find more information there. + * + * @see com.coremedia.iso.boxes.DataReferenceBox + */ +public class DataEntryUrlBox extends AbstractFullBox { + public static final String TYPE = "url "; + + public DataEntryUrlBox() { + super(TYPE); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } + + protected long getContentSize() { + return 4; + } + + public String toString() { + return "DataEntryUrlBox[]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrnBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrnBox.java new file mode 100644 index 0000000..042a972 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/DataEntryUrnBox.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Only used within the DataReferenceBox. Find more information there. + * + * @see com.coremedia.iso.boxes.DataReferenceBox + */ +public class DataEntryUrnBox extends AbstractFullBox { + private String name; + private String location; + public static final String TYPE = "urn "; + + public DataEntryUrnBox() { + super(TYPE); + } + + public String getName() { + return name; + } + + public String getLocation() { + return location; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(name) + 1 + Utf8.utf8StringLengthInBytes(location) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + name = IsoTypeReader.readString(content); + location = IsoTypeReader.readString(content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(Utf8.convert(name)); + byteBuffer.put((byte) 0); + byteBuffer.put(Utf8.convert(location)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "DataEntryUrlBox[name=" + getName() + ";location=" + getLocation() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/DataInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/DataInformationBox.java new file mode 100644 index 0000000..7f058eb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/DataInformationBox.java @@ -0,0 +1,36 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * <code> + * Box Type: 'dinf'<br> + * Container: {@link com.coremedia.iso.boxes.MediaInformationBox} ('minf')<br> + * Mandatory: Yes<br> + * Quantity: Exactly one<br><br></code> + * The data information box contains objects that declare the location of the media information in a track. + */ +public class DataInformationBox extends AbstractContainerBox { + public static final String TYPE = "dinf"; + + public DataInformationBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/DataReferenceBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/DataReferenceBox.java new file mode 100644 index 0000000..8156d3f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/DataReferenceBox.java @@ -0,0 +1,65 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The data reference object contains a table of data references (normally URLs) that declare the location(s) of + * the media data used within the presentation. The data reference index in the sample description ties entries in + * this table to the samples in the track. A track may be split over several sources in this way. + * If the flag is set indicating that the data is in the same file as this box, then no string (not even an empty one) + * shall be supplied in the entry field. + * The DataEntryBox within the DataReferenceBox shall be either a DataEntryUrnBox or a DataEntryUrlBox. + * + * @see com.coremedia.iso.boxes.DataEntryUrlBox + * @see com.coremedia.iso.boxes.DataEntryUrnBox + */ +public class DataReferenceBox extends FullContainerBox { + + public static final String TYPE = "dref"; + + public DataReferenceBox() { + super(TYPE); + + } + + @Override + protected long getContentSize() { + return super.getContentSize() + 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + content.get(new byte[4]); // basically a skip of 4 bytes signaling the number of child boxes + parseChildBoxes(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, getBoxes().size()); + writeChildBoxes(byteBuffer); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/DescriptionBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/DescriptionBox.java new file mode 100644 index 0000000..8352051 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/DescriptionBox.java @@ -0,0 +1,77 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Gives a language dependent description of the media contained in the ISO file. + */ +public class DescriptionBox extends AbstractFullBox { + public static final String TYPE = "dscp"; + + private String language; + private String description; + + public DescriptionBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getDescription() { + return description; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(description); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + description = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(description)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "DescriptionBox[language=" + getLanguage() + ";description=" + getDescription() + "]"; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/EditBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/EditBox.java new file mode 100644 index 0000000..db3bc25 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/EditBox.java @@ -0,0 +1,34 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * An Edit Box maps the presentation time-line to the media time-line as it is stored in the file. + * The Edit Box is a container fpr the edit lists. Defined in ISO/IEC 14496-12. + * + * @see EditListBox + */ +public class EditBox extends AbstractContainerBox { + public static final String TYPE = "edts"; + + public EditBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/EditListBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/EditListBox.java new file mode 100644 index 0000000..231f8be --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/EditListBox.java @@ -0,0 +1,248 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * <code> + * Box Type : 'elst'<br> + * Container: {@link EditBox}('edts')<br> + * Mandatory: No<br> + * Quantity : Zero or one</code><br><br> + * This box contains an explicit timeline map. Each entry defines part of the track time-line: by mapping part of + * the media time-line, or by indicating 'empty' time, or by defining a 'dwell', where a single time-point in the + * media is held for a period.<br> + * Note that edits are not restricted to fall on sample times. This means that when entering an edit, it can be + * necessary to (a) back up to a sync point, and pre-roll from there and then (b) be careful about the duration of + * the first sample - it might have been truncated if the edit enters it during its normal duration. If this is audio, + * that frame might need to be decoded, and then the final slicing done. Likewise, the duration of the last sample + * in an edit might need slicing. <br> + * Starting offsets for tracks (streams) are represented by an initial empty edit. For example, to play a track from + * its start for 30 seconds, but at 10 seconds into the presentation, we have the following edit list:<br> + * <p/> + * <li>Entry-count = 2</li> + * <li>Segment-duration = 10 seconds</li> + * <li>Media-Time = -1</li> + * <li>Media-Rate = 1</li> + * <li>Segment-duration = 30 seconds (could be the length of the whole track)</li> + * <li>Media-Time = 0 seconds</li> + * <li>Media-Rate = 1</li> + */ +public class EditListBox extends AbstractFullBox { + private List<Entry> entries = new LinkedList<Entry>(); + public static final String TYPE = "elst"; + + public EditListBox() { + super(TYPE); + } + + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + protected long getContentSize() { + long contentSize = 8; + if (getVersion() == 1) { + contentSize += entries.size() * 20; + } else { + contentSize += entries.size() * 12; + } + + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new LinkedList<Entry>(); + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry(this, content)); + + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + entry.getContent(byteBuffer); + } + } + + @Override + public String toString() { + return "EditListBox{" + + "entries=" + entries + + '}'; + } + + public static class Entry { + private long segmentDuration; + private long mediaTime; + private double mediaRate; + EditListBox editListBox; + + /** + * Creates a new <code>Entry</code> with all values set. + * + * @param segmentDuration duration in movie timescale + * @param mediaTime starting time + * @param mediaRate relative play rate + */ + public Entry(EditListBox editListBox, long segmentDuration, long mediaTime, double mediaRate) { + this.segmentDuration = segmentDuration; + this.mediaTime = mediaTime; + this.mediaRate = mediaRate; + this.editListBox = editListBox; + } + + public Entry(EditListBox editListBox, ByteBuffer bb) { + if (editListBox.getVersion() == 1) { + segmentDuration = IsoTypeReader.readUInt64(bb); + mediaTime = IsoTypeReader.readUInt64(bb); + mediaRate = IsoTypeReader.readFixedPoint1616(bb); + } else { + segmentDuration = IsoTypeReader.readUInt32(bb); + mediaTime = IsoTypeReader.readUInt32(bb); + mediaRate = IsoTypeReader.readFixedPoint1616(bb); + } + this.editListBox = editListBox; + } + + /** + * The segment duration is an integer that specifies the duration + * of this edit segment in units of the timescale in the Movie + * Header Box + * + * @return segment duration in movie timescale + */ + public long getSegmentDuration() { + return segmentDuration; + } + + /** + * The segment duration is an integer that specifies the duration + * of this edit segment in units of the timescale in the Movie + * Header Box + * + * @param segmentDuration new segment duration in movie timescale + */ + public void setSegmentDuration(long segmentDuration) { + this.segmentDuration = segmentDuration; + } + + /** + * The media time is an integer containing the starting time + * within the media of a specific edit segment(in media time + * scale units, in composition time) + * + * @return starting time + */ + public long getMediaTime() { + return mediaTime; + } + + /** + * The media time is an integer containing the starting time + * within the media of a specific edit segment(in media time + * scale units, in composition time) + * + * @param mediaTime starting time + */ + public void setMediaTime(long mediaTime) { + this.mediaTime = mediaTime; + } + + /** + * The media rate specifies the relative rate at which to play the + * media corresponding to a specific edit segment. + * + * @return relative play rate + */ + public double getMediaRate() { + return mediaRate; + } + + /** + * The media rate specifies the relative rate at which to play the + * media corresponding to a specific edit segment. + * + * @param mediaRate new relative play rate + */ + public void setMediaRate(double mediaRate) { + this.mediaRate = mediaRate; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Entry entry = (Entry) o; + + if (mediaTime != entry.mediaTime) return false; + if (segmentDuration != entry.segmentDuration) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (segmentDuration ^ (segmentDuration >>> 32)); + result = 31 * result + (int) (mediaTime ^ (mediaTime >>> 32)); + return result; + } + + public void getContent(ByteBuffer bb) { + if (editListBox.getVersion() == 1) { + IsoTypeWriter.writeUInt64(bb, segmentDuration); + IsoTypeWriter.writeUInt64(bb, mediaTime); + } else { + IsoTypeWriter.writeUInt32(bb, l2i(segmentDuration)); + bb.putInt(l2i(mediaTime)); + } + IsoTypeWriter.writeFixedPont1616(bb, mediaRate); + } + + @Override + public String toString() { + return "Entry{" + + "segmentDuration=" + segmentDuration + + ", mediaTime=" + mediaTime + + ", mediaRate=" + mediaRate + + '}'; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/FileTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/FileTypeBox.java new file mode 100644 index 0000000..e6eed20 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/FileTypeBox.java @@ -0,0 +1,144 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * This box identifies the specifications to which this file complies. <br> + * Each brand is a printable four-character code, registered with ISO, that + * identifies a precise specification. + */ +public class FileTypeBox extends AbstractBox { + public static final String TYPE = "ftyp"; + + private String majorBrand; + private long minorVersion; + private List<String> compatibleBrands = Collections.emptyList(); + + public FileTypeBox() { + super(TYPE); + } + + public FileTypeBox(String majorBrand, long minorVersion, List<String> compatibleBrands) { + super(TYPE); + this.majorBrand = majorBrand; + this.minorVersion = minorVersion; + this.compatibleBrands = compatibleBrands; + } + + protected long getContentSize() { + return 8 + compatibleBrands.size() * 4; + + } + + @Override + public void _parseDetails(ByteBuffer content) { + majorBrand = IsoTypeReader.read4cc(content); + minorVersion = IsoTypeReader.readUInt32(content); + int compatibleBrandsCount = content.remaining() / 4; + compatibleBrands = new LinkedList<String>(); + for (int i = 0; i < compatibleBrandsCount; i++) { + compatibleBrands.add(IsoTypeReader.read4cc(content)); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(majorBrand)); + IsoTypeWriter.writeUInt32(byteBuffer, minorVersion); + for (String compatibleBrand : compatibleBrands) { + byteBuffer.put(IsoFile.fourCCtoBytes(compatibleBrand)); + } + + } + + /** + * Gets the brand identifier. + * + * @return the brand identifier + */ + public String getMajorBrand() { + return majorBrand; + } + + /** + * Sets the major brand of the file used to determine an appropriate reader. + * + * @param majorBrand the new major brand + */ + public void setMajorBrand(String majorBrand) { + this.majorBrand = majorBrand; + } + + /** + * Sets the "informative integer for the minor version of the major brand". + * + * @param minorVersion the version number of the major brand + */ + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + /** + * Gets an informative integer for the minor version of the major brand. + * + * @return an informative integer + * @see FileTypeBox#getMajorBrand() + */ + public long getMinorVersion() { + return minorVersion; + } + + /** + * Gets an array of 4-cc brands. + * + * @return the compatible brands + */ + public List<String> getCompatibleBrands() { + return compatibleBrands; + } + + public void setCompatibleBrands(List<String> compatibleBrands) { + this.compatibleBrands = compatibleBrands; + } + + @DoNotParseDetail + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("FileTypeBox["); + result.append("majorBrand=").append(getMajorBrand()); + result.append(";"); + result.append("minorVersion=").append(getMinorVersion()); + for (String compatibleBrand : compatibleBrands) { + result.append(";"); + result.append("compatibleBrand=").append(compatibleBrand); + } + result.append("]"); + return result.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/FreeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/FreeBox.java new file mode 100644 index 0000000..636c9a7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/FreeBox.java @@ -0,0 +1,114 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.ChannelHelper; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * A free box. Just a placeholder to enable editing without rewriting the whole file. + */ +public class FreeBox implements Box { + public static final String TYPE = "free"; + ByteBuffer data; + List<Box> replacers = new LinkedList<Box>(); + private ContainerBox parent; + + public FreeBox() { + } + + public FreeBox(int size) { + this.data = ByteBuffer.allocate(size); + } + + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } + + public void getBox(WritableByteChannel os) throws IOException { + for (Box replacer : replacers) { + replacer.getBox(os); + } + ByteBuffer header = ByteBuffer.allocate(8); + IsoTypeWriter.writeUInt32(header, 8 + data.limit()); + header.put(TYPE.getBytes()); + header.rewind(); + os.write(header); + data.rewind(); + os.write(data); + + } + + public ContainerBox getParent() { + return parent; + } + + public void setParent(ContainerBox parent) { + this.parent = parent; + } + + public long getSize() { + long size = 8; + for (Box replacer : replacers) { + size += replacer.getSize(); + } + size += data.limit(); + return size; + } + + public String getType() { + return TYPE; + } + + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + if (readableByteChannel instanceof FileChannel && contentSize > 1024 * 1024) { + // It's quite expensive to map a file into the memory. Just do it when the box is larger than a MB. + data = ((FileChannel) readableByteChannel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) readableByteChannel).position(), contentSize); + ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); + } else { + assert contentSize < Integer.MAX_VALUE; + data = ChannelHelper.readFully(readableByteChannel, contentSize); + } + } + + + public void addAndReplace(Box box) { + data.position(l2i(box.getSize())); + data = data.slice(); + replacers.add(box); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/FreeSpaceBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/FreeSpaceBox.java new file mode 100644 index 0000000..ed42bf9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/FreeSpaceBox.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * The contents of a free-space box are irrelevant and may be ignored, or the object deleted, without affecting the + * presentation. Care should be excercized when deleting the object, as this may invalidate the offsets used in the + * sample table. + */ +public class FreeSpaceBox extends AbstractBox { + public static final String TYPE = "skip"; + + byte[] data; + + protected long getContentSize() { + return data.length; + } + + public FreeSpaceBox() { + super(TYPE); + } + + public void setData(byte[] data) { + this.data = data; + } + + public byte[] getData() { + return data; + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = new byte[content.remaining()]; + content.get(data); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } + + public String toString() { + return "FreeSpaceBox[size=" + data.length + ";type=" + getType() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/FullBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/FullBox.java new file mode 100644 index 0000000..1515d76 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/FullBox.java @@ -0,0 +1,17 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.boxes.Box; + +/** + * The <code>FullBox</code> contains all getters and setters specific + * to a so-called full box according to the ISO/IEC 14496/12 specification. + */ +public interface FullBox extends Box { + int getVersion(); + + void setVersion(int version); + + int getFlags(); + + void setFlags(int flags); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/GenreBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/GenreBox.java new file mode 100644 index 0000000..e2d1faf --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/GenreBox.java @@ -0,0 +1,80 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Containing genre information and contained in the <code>UserDataBox</code>. + * + * @see com.coremedia.iso.boxes.UserDataBox + */ +public class GenreBox extends AbstractFullBox { + public static final String TYPE = "gnre"; + + private String language; + private String genre; + + public GenreBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getGenre() { + return genre; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setGenre(String genre) { + this.genre = genre; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(genre); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + genre = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(genre)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "GenreBox[language=" + getLanguage() + ";genre=" + getGenre() + "]"; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/HandlerBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/HandlerBox.java new file mode 100644 index 0000000..01dcaca --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/HandlerBox.java @@ -0,0 +1,151 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This box within a Media Box declares the process by which the media-data in the track is presented, + * and thus, the nature of the media in a track. + * This Box when present in a Meta Box, declares the structure or format of the 'meta' box contents. + * See ISO/IEC 14496-12 for details. + * + * @see MetaBox + * @see MediaBox + */ +public class HandlerBox extends AbstractFullBox { + public static final String TYPE = "hdlr"; + public static final Map<String, String> readableTypes; + + static { + HashMap<String, String> hm = new HashMap<String, String>(); + hm.put("odsm", "ObjectDescriptorStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("crsm", "ClockReferenceStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("sdsm", "SceneDescriptionStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("m7sm", "MPEG7Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("ocsm", "ObjectContentInfoStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("ipsm", "IPMP Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("mjsm", "MPEG-J Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + hm.put("mdir", "Apple Meta Data iTunes Reader"); + hm.put("mp7b", "MPEG-7 binary XML"); + hm.put("mp7t", "MPEG-7 XML"); + hm.put("vide", "Video Track"); + hm.put("soun", "Sound Track"); + hm.put("hint", "Hint Track"); + hm.put("appl", "Apple specific"); + hm.put("meta", "Timed Metadata track - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); + + readableTypes = Collections.unmodifiableMap(hm); + + } + + private String handlerType; + private String name = null; + private long a, b, c; + private boolean zeroTerm = true; + + private long shouldBeZeroButAppleWritesHereSomeValue; + + public HandlerBox() { + super(TYPE); + } + + public String getHandlerType() { + return handlerType; + } + + /** + * You are required to add a '\0' string termination by yourself. + * + * @param name the new human readable name + */ + public void setName(String name) { + this.name = name; + } + + public void setHandlerType(String handlerType) { + this.handlerType = handlerType; + } + + public String getName() { + return name; + } + + public String getHumanReadableTrackType() { + return readableTypes.get(handlerType) != null ? readableTypes.get(handlerType) : "Unknown Handler Type"; + } + + protected long getContentSize() { + if (zeroTerm) { + return 25 + Utf8.utf8StringLengthInBytes(name); + } else { + return 24 + Utf8.utf8StringLengthInBytes(name); + } + + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + shouldBeZeroButAppleWritesHereSomeValue = IsoTypeReader.readUInt32(content); + handlerType = IsoTypeReader.read4cc(content); + a = IsoTypeReader.readUInt32(content); + b = IsoTypeReader.readUInt32(content); + c = IsoTypeReader.readUInt32(content); + if (content.remaining() > 0) { + name = IsoTypeReader.readString(content, content.remaining()); + if (name.endsWith("\0")) { + name = name.substring(0, name.length() - 1); + zeroTerm = true; + } else { + zeroTerm = false; + } + } else { + zeroTerm = false; //No string at all, not even zero term char + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, shouldBeZeroButAppleWritesHereSomeValue); + byteBuffer.put(IsoFile.fourCCtoBytes(handlerType)); + IsoTypeWriter.writeUInt32(byteBuffer, a); + IsoTypeWriter.writeUInt32(byteBuffer, b); + IsoTypeWriter.writeUInt32(byteBuffer, c); + if (name != null) { + byteBuffer.put(Utf8.convert(name)); + } + if (zeroTerm) { + byteBuffer.put((byte) 0); + } + } + + public String toString() { + return "HandlerBox[handlerType=" + getHandlerType() + ";name=" + getName() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/HintMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/HintMediaHeaderBox.java new file mode 100644 index 0000000..3477738 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/HintMediaHeaderBox.java @@ -0,0 +1,91 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * The hint media header contains general information, independent of the protocaol, for hint tracks. Resides + * in Media Information Box. + * + * @see com.coremedia.iso.boxes.MediaInformationBox + */ +public class HintMediaHeaderBox extends AbstractMediaHeaderBox { + private int maxPduSize; + private int avgPduSize; + private long maxBitrate; + private long avgBitrate; + public static final String TYPE = "hmhd"; + + public HintMediaHeaderBox() { + super(TYPE); + } + + public int getMaxPduSize() { + return maxPduSize; + } + + public int getAvgPduSize() { + return avgPduSize; + } + + public long getMaxBitrate() { + return maxBitrate; + } + + public long getAvgBitrate() { + return avgBitrate; + } + + protected long getContentSize() { + return 20; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + maxPduSize = IsoTypeReader.readUInt16(content); + avgPduSize = IsoTypeReader.readUInt16(content); + maxBitrate = IsoTypeReader.readUInt32(content); + avgBitrate = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); // reserved! + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, maxPduSize); + IsoTypeWriter.writeUInt16(byteBuffer, avgPduSize); + IsoTypeWriter.writeUInt32(byteBuffer, maxBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, avgBitrate); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + } + + @Override + public String toString() { + return "HintMediaHeaderBox{" + + "maxPduSize=" + maxPduSize + + ", avgPduSize=" + avgPduSize + + ", maxBitrate=" + maxBitrate + + ", avgBitrate=" + avgBitrate + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ItemDataBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemDataBox.java new file mode 100644 index 0000000..46097cc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemDataBox.java @@ -0,0 +1,43 @@ +package com.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class ItemDataBox extends AbstractBox { + ByteBuffer data = ByteBuffer.allocate(0); + public static final String TYPE = "idat"; + + + public ItemDataBox() { + super(TYPE); + } + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } + + @Override + protected long getContentSize() { + return data.limit(); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + data = content.slice(); + content.position(content.position() + content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ItemLocationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemLocationBox.java new file mode 100644 index 0000000..6dcee6f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemLocationBox.java @@ -0,0 +1,360 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeReaderVariable; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.IsoTypeWriterVariable; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +/** + * aligned(8) class ItemLocationBox extends FullBox(‘iloc’, version, 0) { + * unsigned int(4) offset_size; + * unsigned int(4) length_size; + * unsigned int(4) base_offset_size; + * if (version == 1) + * unsigned int(4) index_size; + * else + * unsigned int(4) reserved; + * unsigned int(16) item_count; + * for (i=0; i<item_count; i++) { + * unsigned int(16) item_ID; + * if (version == 1) { + * unsigned int(12) reserved = 0; + * unsigned int(4) construction_method; + * } + * unsigned int(16) data_reference_index; + * unsigned int(base_offset_size*8) base_offset; + * unsigned int(16) extent_count; + * for (j=0; j<extent_count; j++) { + * if ((version == 1) && (index_size > 0)) { + * unsigned int(index_size*8) extent_index; + * } + * unsigned int(offset_size*8) extent_offset; + * unsigned int(length_size*8) extent_length; + * } + * } + * } + */ +public class ItemLocationBox extends AbstractFullBox { + public int offsetSize = 8; + public int lengthSize = 8; + public int baseOffsetSize = 8; + public int indexSize = 0; + public List<Item> items = new LinkedList<Item>(); + + public static final String TYPE = "iloc"; + + public ItemLocationBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + long size = 8; + for (Item item : items) { + size += item.getSize(); + } + return size; + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt8(byteBuffer, ((offsetSize << 4) | lengthSize)); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4 | indexSize)); + } else { + IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4)); + } + IsoTypeWriter.writeUInt16(byteBuffer, items.size()); + for (Item item : items) { + item.getContent(byteBuffer); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int tmp = IsoTypeReader.readUInt8(content); + offsetSize = tmp >>> 4; + lengthSize = tmp & 0xf; + tmp = IsoTypeReader.readUInt8(content); + baseOffsetSize = tmp >>> 4; + + if (getVersion() == 1) { + indexSize = tmp & 0xf; + } + int itemCount = IsoTypeReader.readUInt16(content); + for (int i = 0; i < itemCount; i++) { + items.add(new Item(content)); + } + } + + + public int getOffsetSize() { + return offsetSize; + } + + public void setOffsetSize(int offsetSize) { + this.offsetSize = offsetSize; + } + + public int getLengthSize() { + return lengthSize; + } + + public void setLengthSize(int lengthSize) { + this.lengthSize = lengthSize; + } + + public int getBaseOffsetSize() { + return baseOffsetSize; + } + + public void setBaseOffsetSize(int baseOffsetSize) { + this.baseOffsetSize = baseOffsetSize; + } + + public int getIndexSize() { + return indexSize; + } + + public void setIndexSize(int indexSize) { + this.indexSize = indexSize; + } + + public List<Item> getItems() { + return items; + } + + public void setItems(List<Item> items) { + this.items = items; + } + + + public Item createItem(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { + return new Item(itemId, constructionMethod, dataReferenceIndex, baseOffset, extents); + } + + Item createItem(ByteBuffer bb) { + return new Item(bb); + } + + public class Item { + public int itemId; + public int constructionMethod; + public int dataReferenceIndex; + public long baseOffset; + public List<Extent> extents = new LinkedList<Extent>(); + + public Item(ByteBuffer in) { + itemId = IsoTypeReader.readUInt16(in); + + if (getVersion() == 1) { + int tmp = IsoTypeReader.readUInt16(in); + constructionMethod = tmp & 0xf; + } + + dataReferenceIndex = IsoTypeReader.readUInt16(in); + if (baseOffsetSize > 0) { + baseOffset = IsoTypeReaderVariable.read(in, baseOffsetSize); + } else { + baseOffset = 0; + } + int extentCount = IsoTypeReader.readUInt16(in); + + + for (int i = 0; i < extentCount; i++) { + extents.add(new Extent(in)); + } + } + + public Item(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { + this.itemId = itemId; + this.constructionMethod = constructionMethod; + this.dataReferenceIndex = dataReferenceIndex; + this.baseOffset = baseOffset; + this.extents = extents; + } + + public int getSize() { + int size = 2; + + if (getVersion() == 1) { + size += 2; + } + + size += 2; + size += baseOffsetSize; + size += 2; + + + for (Extent extent : extents) { + size += extent.getSize(); + } + return size; + } + + public void setBaseOffset(long baseOffset) { + this.baseOffset = baseOffset; + } + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, itemId); + + if (getVersion() == 1) { + IsoTypeWriter.writeUInt16(bb, constructionMethod); + } + + + IsoTypeWriter.writeUInt16(bb, dataReferenceIndex); + if (baseOffsetSize > 0) { + IsoTypeWriterVariable.write(baseOffset, bb, baseOffsetSize); + } + IsoTypeWriter.writeUInt16(bb, extents.size()); + + for (Extent extent : extents) { + extent.getContent(bb); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Item item = (Item) o; + + if (baseOffset != item.baseOffset) return false; + if (constructionMethod != item.constructionMethod) return false; + if (dataReferenceIndex != item.dataReferenceIndex) return false; + if (itemId != item.itemId) return false; + if (extents != null ? !extents.equals(item.extents) : item.extents != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = itemId; + result = 31 * result + constructionMethod; + result = 31 * result + dataReferenceIndex; + result = 31 * result + (int) (baseOffset ^ (baseOffset >>> 32)); + result = 31 * result + (extents != null ? extents.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Item{" + + "baseOffset=" + baseOffset + + ", itemId=" + itemId + + ", constructionMethod=" + constructionMethod + + ", dataReferenceIndex=" + dataReferenceIndex + + ", extents=" + extents + + '}'; + } + } + + + public Extent createExtent(long extentOffset, long extentLength, long extentIndex) { + return new Extent(extentOffset, extentLength, extentIndex); + } + + Extent createExtent(ByteBuffer bb) { + return new Extent(bb); + } + + + public class Extent { + public long extentOffset; + public long extentLength; + public long extentIndex; + + public Extent(long extentOffset, long extentLength, long extentIndex) { + this.extentOffset = extentOffset; + this.extentLength = extentLength; + this.extentIndex = extentIndex; + } + + + public Extent(ByteBuffer in) { + if ((getVersion() == 1) && indexSize > 0) { + extentIndex = IsoTypeReaderVariable.read(in, indexSize); + } + extentOffset = IsoTypeReaderVariable.read(in, offsetSize); + extentLength = IsoTypeReaderVariable.read(in, lengthSize); + } + + public void getContent(ByteBuffer os) { + if ((getVersion() == 1) && indexSize > 0) { + IsoTypeWriterVariable.write(extentIndex, os, indexSize); + } + IsoTypeWriterVariable.write(extentOffset, os, offsetSize); + IsoTypeWriterVariable.write(extentLength, os, lengthSize); + } + + public int getSize() { + return (indexSize > 0 ? indexSize : 0) + offsetSize + lengthSize; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Extent extent = (Extent) o; + + if (extentIndex != extent.extentIndex) return false; + if (extentLength != extent.extentLength) return false; + if (extentOffset != extent.extentOffset) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (extentOffset ^ (extentOffset >>> 32)); + result = 31 * result + (int) (extentLength ^ (extentLength >>> 32)); + result = 31 * result + (int) (extentIndex ^ (extentIndex >>> 32)); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Extent"); + sb.append("{extentOffset=").append(extentOffset); + sb.append(", extentLength=").append(extentLength); + sb.append(", extentIndex=").append(extentIndex); + sb.append('}'); + return sb.toString(); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ItemProtectionBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemProtectionBox.java new file mode 100644 index 0000000..7eed790 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ItemProtectionBox.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The Item Protection Box provides an array of item protection information, for use by the Item Information Box. + * + * @see com.coremedia.iso.boxes.ItemProtectionBox + */ +public class ItemProtectionBox extends FullContainerBox { + + public static final String TYPE = "ipro"; + + public ItemProtectionBox() { + super(TYPE); + } + + public SchemeInformationBox getItemProtectionScheme() { + if (!getBoxes(SchemeInformationBox.class).isEmpty()) { + return getBoxes(SchemeInformationBox.class).get(0); + } else { + return null; + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + IsoTypeReader.readUInt16(content); + parseChildBoxes(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, getBoxes().size()); + writeChildBoxes(byteBuffer); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/KeywordsBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/KeywordsBox.java new file mode 100644 index 0000000..d9b7c0c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/KeywordsBox.java @@ -0,0 +1,95 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * List of keywords according to 3GPP 26.244. + */ +public class KeywordsBox extends AbstractFullBox { + public static final String TYPE = "kywd"; + + private String language; + private String[] keywords; + + public KeywordsBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String[] getKeywords() { + return keywords; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setKeywords(String[] keywords) { + this.keywords = keywords; + } + + protected long getContentSize() { + long contentSize = 7; + for (String keyword : keywords) { + contentSize += 1 + Utf8.utf8StringLengthInBytes(keyword) + 1; + } + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + int keywordCount = IsoTypeReader.readUInt8(content); + keywords = new String[keywordCount]; + for (int i = 0; i < keywordCount; i++) { + IsoTypeReader.readUInt8(content); + keywords[i] = IsoTypeReader.readString(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + IsoTypeWriter.writeUInt8(byteBuffer, keywords.length); + for (String keyword : keywords) { + IsoTypeWriter.writeUInt8(byteBuffer, Utf8.utf8StringLengthInBytes(keyword) + 1); + byteBuffer.put(Utf8.convert(keyword)); + } + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("KeywordsBox[language=").append(getLanguage()); + for (int i = 0; i < keywords.length; i++) { + buffer.append(";keyword").append(i).append("=").append(keywords[i]); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MediaBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaBox.java new file mode 100644 index 0000000..fa5642c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaBox.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The media declaration container contains all the objects that declare information about the media data within a + * track. + */ +public class MediaBox extends AbstractContainerBox { + public static final String TYPE = "mdia"; + + public MediaBox() { + super(TYPE); + } + + public MediaInformationBox getMediaInformationBox() { + for (Box box : boxes) { + if (box instanceof MediaInformationBox) { + return (MediaInformationBox) box; + } + } + return null; + } + + public MediaHeaderBox getMediaHeaderBox() { + for (Box box : boxes) { + if (box instanceof MediaHeaderBox) { + return (MediaHeaderBox) box; + } + } + return null; + } + + public HandlerBox getHandlerBox() { + for (Box box : boxes) { + if (box instanceof HandlerBox) { + return (HandlerBox) box; + } + } + return null; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaHeaderBox.java new file mode 100644 index 0000000..69b538b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaHeaderBox.java @@ -0,0 +1,147 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * This box defines overall information which is media-independent, and relevant to the entire presentation + * considered as a whole. + */ +public class MediaHeaderBox extends AbstractFullBox { + public static final String TYPE = "mdhd"; + + + private long creationTime; + private long modificationTime; + private long timescale; + private long duration; + private String language; + + public MediaHeaderBox() { + super(TYPE); + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTimescale() { + return timescale; + } + + public long getDuration() { + return duration; + } + + public String getLanguage() { + return language; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 8 + 8 + 4 + 8; + } else { + contentSize += 4 + 4 + 4 + 4; + } + contentSize += 2; + contentSize += 2; + return contentSize; + + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTimescale(long timescale) { + this.timescale = timescale; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setLanguage(String language) { + this.language = language; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } + language = IsoTypeReader.readIso639(content); + IsoTypeReader.readUInt16(content); + } + + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("MediaHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("timescale=").append(getTimescale()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("language=").append(getLanguage()); + result.append("]"); + return result.toString(); + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } + IsoTypeWriter.writeIso639(byteBuffer, language); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MediaInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaInformationBox.java new file mode 100644 index 0000000..ed25051 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MediaInformationBox.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * This box contains all the objects that declare characteristic information of the media in the track. + */ +public class MediaInformationBox extends AbstractContainerBox { + public static final String TYPE = "minf"; + + public MediaInformationBox() { + super(TYPE); + } + + public SampleTableBox getSampleTableBox() { + for (Box box : boxes) { + if (box instanceof SampleTableBox) { + return (SampleTableBox) box; + } + } + return null; + } + + public AbstractMediaHeaderBox getMediaHeaderBox() { + for (Box box : boxes) { + if (box instanceof AbstractMediaHeaderBox) { + return (AbstractMediaHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MetaBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MetaBox.java new file mode 100644 index 0000000..35499ec --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MetaBox.java @@ -0,0 +1,113 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.IOException; +import java.nio.ByteBuffer; + + +/** + * A common base structure to contain general metadata. See ISO/IEC 14496-12 Ch. 8.44.1. + */ +public class MetaBox extends AbstractContainerBox { + private int version = 0; + private int flags = 0; + + public static final String TYPE = "meta"; + + public MetaBox() { + super(TYPE); + } + + @Override + public long getContentSize() { + if (isMp4Box()) { + // it's a fullbox + return 4 + super.getContentSize(); + } else { + // it's an apple metabox + return super.getContentSize(); + } + } + + @Override + public long getNumOfBytesToFirstChild() { + if (isMp4Box()) { + // it's a fullbox + return 12; + } else { + // it's an apple metabox + return 8; + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + int pos = content.position(); + content.get(new byte[4]); + String isHdlr = IsoTypeReader.read4cc(content); + if ("hdlr".equals(isHdlr)) { + // this is apple bullshit - it's NO FULLBOX + content.position(pos); + version = -1; + flags = -1; + } else { + content.position(pos); + version = IsoTypeReader.readUInt8(content); + flags = IsoTypeReader.readUInt24(content); + } + while (content.remaining() >= 8) { + try { + boxes.add(boxParser.parseBox(new ByteBufferByteChannel(content), this)); + } catch (IOException e) { + throw new RuntimeException("Sebastian needs to fix 7518765283"); + } + } + if (content.remaining() > 0) { + throw new RuntimeException("Sebastian needs to fix it 90732r26537"); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + if (isMp4Box()) { + IsoTypeWriter.writeUInt8(byteBuffer, version); + IsoTypeWriter.writeUInt24(byteBuffer, flags); + } + writeChildBoxes(byteBuffer); + } + + + public boolean isMp4Box() { + return version != -1 && flags != -1; + } + + public void setMp4Box(boolean mp4) { + if (mp4) { + version = 0; + flags = 0; + } else { + version = -1; + flags = -1; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MovieBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MovieBox.java new file mode 100644 index 0000000..3aff7d8 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MovieBox.java @@ -0,0 +1,67 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.AbstractContainerBox; + +import java.util.List; + +/** + * The metadata for a presentation is stored in the single Movie Box which occurs at the top-level of a file. + * Normally this box is close to the beginning or end of the file, though this is not required. + */ +public class MovieBox extends AbstractContainerBox { + public static final String TYPE = "moov"; + + public MovieBox() { + super(TYPE); + } + + public int getTrackCount() { + return getBoxes(TrackBox.class).size(); + } + + + /** + * Returns the track numbers associated with this <code>MovieBox</code>. + * + * @return the tracknumbers (IDs) of the tracks in their order of appearance in the file + */ + public long[] getTrackNumbers() { + + List<TrackBox> trackBoxes = this.getBoxes(TrackBox.class); + long[] trackNumbers = new long[trackBoxes.size()]; + for (int trackCounter = 0; trackCounter < trackBoxes.size(); trackCounter++) { + AbstractBox trackBoxe = trackBoxes.get(trackCounter); + TrackBox trackBox = (TrackBox) trackBoxe; + trackNumbers[trackCounter] = trackBox.getTrackHeaderBox().getTrackId(); + } + return trackNumbers; + } + + public MovieHeaderBox getMovieHeaderBox() { + for (Box box : boxes) { + if (box instanceof MovieHeaderBox) { + return (MovieHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/MovieHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/MovieHeaderBox.java new file mode 100644 index 0000000..30fbe8c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/MovieHeaderBox.java @@ -0,0 +1,278 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * <code> + * Box Type: 'mvhd'<br> + * Container: {@link MovieBox} ('moov')<br> + * Mandatory: Yes<br> + * Quantity: Exactly one<br><br> + * </code> + * This box defines overall information which is media-independent, and relevant to the entire presentation + * considered as a whole. + */ +public class MovieHeaderBox extends AbstractFullBox { + private long creationTime; + private long modificationTime; + private long timescale; + private long duration; + private double rate = 1.0; + private float volume = 1.0f; + private long[] matrix = new long[]{0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; + private long nextTrackId; + + private int previewTime; + private int previewDuration; + private int posterTime; + private int selectionTime; + private int selectionDuration; + private int currentTime; + + + public static final String TYPE = "mvhd"; + + public MovieHeaderBox() { + super(TYPE); + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTimescale() { + return timescale; + } + + public long getDuration() { + return duration; + } + + public double getRate() { + return rate; + } + + public float getVolume() { + return volume; + } + + public long[] getMatrix() { + return matrix; + } + + public long getNextTrackId() { + return nextTrackId; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 28; + } else { + contentSize += 16; + } + contentSize += 80; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + timescale = IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } + rate = IsoTypeReader.readFixedPoint1616(content); + volume = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); + IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + matrix = new long[9]; + for (int i = 0; i < 9; i++) { + matrix[i] = IsoTypeReader.readUInt32(content); + } + + previewTime = content.getInt(); + previewDuration = content.getInt(); + posterTime = content.getInt(); + selectionTime = content.getInt(); + selectionDuration = content.getInt(); + currentTime = content.getInt(); + + nextTrackId = IsoTypeReader.readUInt32(content); + + } + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("MovieHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("timescale=").append(getTimescale()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("rate=").append(getRate()); + result.append(";"); + result.append("volume=").append(getVolume()); + for (int i = 0; i < matrix.length; i++) { + result.append(";"); + result.append("matrix").append(i).append("=").append(matrix[i]); + } + result.append(";"); + result.append("nextTrackId=").append(getNextTrackId()); + result.append("]"); + return result.toString(); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, timescale); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } + IsoTypeWriter.writeFixedPont1616(byteBuffer, rate); + IsoTypeWriter.writeFixedPont88(byteBuffer, volume); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + + + for (int i = 0; i < 9; i++) { + IsoTypeWriter.writeUInt32(byteBuffer, matrix[i]); + } + + + byteBuffer.putInt(previewTime); + byteBuffer.putInt(previewDuration); + byteBuffer.putInt(posterTime); + byteBuffer.putInt(selectionTime); + byteBuffer.putInt(selectionDuration); + byteBuffer.putInt(currentTime); + + IsoTypeWriter.writeUInt32(byteBuffer, nextTrackId); + } + + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTimescale(long timescale) { + this.timescale = timescale; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setRate(double rate) { + this.rate = rate; + } + + public void setVolume(float volume) { + this.volume = volume; + } + + public void setMatrix(long[] matrix) { + this.matrix = matrix; + } + + public void setNextTrackId(long nextTrackId) { + this.nextTrackId = nextTrackId; + } + + public int getPreviewTime() { + return previewTime; + } + + public void setPreviewTime(int previewTime) { + this.previewTime = previewTime; + } + + public int getPreviewDuration() { + return previewDuration; + } + + public void setPreviewDuration(int previewDuration) { + this.previewDuration = previewDuration; + } + + public int getPosterTime() { + return posterTime; + } + + public void setPosterTime(int posterTime) { + this.posterTime = posterTime; + } + + public int getSelectionTime() { + return selectionTime; + } + + public void setSelectionTime(int selectionTime) { + this.selectionTime = selectionTime; + } + + public int getSelectionDuration() { + return selectionDuration; + } + + public void setSelectionDuration(int selectionDuration) { + this.selectionDuration = selectionDuration; + } + + public int getCurrentTime() { + return currentTime; + } + + public void setCurrentTime(int currentTime) { + this.currentTime = currentTime; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/NullMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/NullMediaHeaderBox.java new file mode 100644 index 0000000..562f8d4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/NullMediaHeaderBox.java @@ -0,0 +1,43 @@ +/* + * Copyright 2011 Sebastian Annies, Hamburg, Germany + * + * 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.coremedia.iso.boxes; + +import java.nio.ByteBuffer; + +/** + * Streams other than visual and audio (e.g., timed metadata streams) may use a + * Null Media Header Box. + */ +public class NullMediaHeaderBox extends AbstractMediaHeaderBox { + public NullMediaHeaderBox() { + super("nmhd"); + } + + @Override + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ObjectDescriptorBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ObjectDescriptorBox.java new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ObjectDescriptorBox.java diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/OmaDrmAccessUnitFormatBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/OmaDrmAccessUnitFormatBox.java new file mode 100644 index 0000000..020881b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/OmaDrmAccessUnitFormatBox.java @@ -0,0 +1,87 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Describes the format of media access units in PDCF files. + */ +public final class OmaDrmAccessUnitFormatBox extends AbstractFullBox { + public static final String TYPE = "odaf"; + + private boolean selectiveEncryption; + private byte allBits; + + private int keyIndicatorLength; + private int initVectorLength; + + protected long getContentSize() { + return 7; + } + + public OmaDrmAccessUnitFormatBox() { + super("odaf"); + } + + public boolean isSelectiveEncryption() { + return selectiveEncryption; + } + + public int getKeyIndicatorLength() { + return keyIndicatorLength; + } + + public int getInitVectorLength() { + return initVectorLength; + } + + public void setInitVectorLength(int initVectorLength) { + this.initVectorLength = initVectorLength; + } + + public void setKeyIndicatorLength(int keyIndicatorLength) { + this.keyIndicatorLength = keyIndicatorLength; + } + + public void setAllBits(byte allBits) { + this.allBits = allBits; + selectiveEncryption = (allBits & 0x80) == 0x80; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + allBits = (byte) IsoTypeReader.readUInt8(content); + selectiveEncryption = (allBits & 0x80) == 0x80; + keyIndicatorLength = IsoTypeReader.readUInt8(content); + initVectorLength = IsoTypeReader.readUInt8(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt8(byteBuffer, allBits); + IsoTypeWriter.writeUInt8(byteBuffer, keyIndicatorLength); + IsoTypeWriter.writeUInt8(byteBuffer, initVectorLength); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/OriginalFormatBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/OriginalFormatBox.java new file mode 100644 index 0000000..004c6c2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/OriginalFormatBox.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * The Original Format Box contains the four-character-code of the original untransformed sample description. + * See ISO/IEC 14496-12 for details. + * + * @see ProtectionSchemeInformationBox + */ + +public class OriginalFormatBox extends AbstractBox { + public static final String TYPE = "frma"; + + private String dataFormat = " "; + + public OriginalFormatBox() { + super("frma"); + } + + public String getDataFormat() { + return dataFormat; + } + + + public void setDataFormat(String dataFormat) { + assert dataFormat.length() == 4; + this.dataFormat = dataFormat; + } + + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + dataFormat = IsoTypeReader.read4cc(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(dataFormat)); + } + + + public String toString() { + return "OriginalFormatBox[dataFormat=" + getDataFormat() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/PerformerBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/PerformerBox.java new file mode 100644 index 0000000..cf702dc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/PerformerBox.java @@ -0,0 +1,78 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Used to give information about the performer. Mostly used in confunction with music files. + * See 3GPP 26.234 for details. + */ +public class PerformerBox extends AbstractFullBox { + public static final String TYPE = "perf"; + + private String language; + private String performer; + + public PerformerBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getPerformer() { + return performer; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setPerformer(String performer) { + this.performer = performer; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(performer) + 1; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(performer)); + byteBuffer.put((byte) 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + performer = IsoTypeReader.readString(content); + } + + public String toString() { + return "PerformerBox[language=" + getLanguage() + ";performer=" + getPerformer() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ProgressiveDownloadInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ProgressiveDownloadInformationBox.java new file mode 100644 index 0000000..7acd7ed --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ProgressiveDownloadInformationBox.java @@ -0,0 +1,95 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class ProgressiveDownloadInformationBox extends AbstractFullBox { + + + List<Entry> entries = Collections.emptyList(); + + public ProgressiveDownloadInformationBox() { + super("pdin"); + } + + @Override + protected long getContentSize() { + return 4 + entries.size() * 8; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getRate()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getInitialDelay()); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + entries = new LinkedList<Entry>(); + while (content.remaining() >= 8) { + Entry entry = new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content)); + entries.add(entry); + } + } + + + public static class Entry { + long rate; + long initialDelay; + + public Entry(long rate, long initialDelay) { + this.rate = rate; + this.initialDelay = initialDelay; + } + + public long getRate() { + return rate; + } + + public void setRate(long rate) { + this.rate = rate; + } + + public long getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(long initialDelay) { + this.initialDelay = initialDelay; + } + + @Override + public String toString() { + return "Entry{" + + "rate=" + rate + + ", initialDelay=" + initialDelay + + '}'; + } + } + + @Override + public String toString() { + return "ProgressiveDownloadInfoBox{" + + "entries=" + entries + + '}'; + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/ProtectionSchemeInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/ProtectionSchemeInformationBox.java new file mode 100644 index 0000000..87069d3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/ProtectionSchemeInformationBox.java @@ -0,0 +1,42 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The <code>ProtectionSchemeInformationBox</code> contains all the information required both + * to understand the encryption transform applied and its parameters, and also to find other + * information such as the kind and location of the key management system. It also documents the + * the original (unencrypted) format of the media. The <code>ProtectionSchemeInformationBox</code> + * is a container box. It is mandatory in a sample entry that uses a code idicating a + * protected stream. + * + * @see com.coremedia.iso.boxes.odf.OmaDrmKeyManagenentSystemBox + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry#TYPE_ENCRYPTED + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry#TYPE_ENCRYPTED + */ +public class ProtectionSchemeInformationBox extends AbstractContainerBox { + public static final String TYPE = "sinf"; + + public ProtectionSchemeInformationBox() { + super(TYPE); + + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/RatingBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/RatingBox.java new file mode 100644 index 0000000..ad32749 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/RatingBox.java @@ -0,0 +1,124 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + + +/** + * Contained a the <code>UserDataBox</code> and containing information about the media's rating. E.g. + * PG13or FSK16. + */ +public class RatingBox extends AbstractFullBox { + public static final String TYPE = "rtng"; + + private String ratingEntity; + private String ratingCriteria; + private String language; + private String ratingInfo; + + public RatingBox() { + super(TYPE); + } + + + public void setRatingEntity(String ratingEntity) { + this.ratingEntity = ratingEntity; + } + + public void setRatingCriteria(String ratingCriteria) { + this.ratingCriteria = ratingCriteria; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setRatingInfo(String ratingInfo) { + this.ratingInfo = ratingInfo; + } + + public String getLanguage() { + return language; + } + + /** + * Gets a four-character code that indicates the rating entity grading the asset, e.g., 'BBFC'. The values of this + * field should follow common names of worldwide movie rating systems, such as those mentioned in + * [http://www.movie-ratings.net/, October 2002]. + * + * @return the rating organization + */ + public String getRatingEntity() { + return ratingEntity; + } + + /** + * Gets the four-character code that indicates which rating criteria are being used for the corresponding rating + * entity, e.g., 'PG13'. + * + * @return the actual rating + */ + public String getRatingCriteria() { + return ratingCriteria; + } + + public String getRatingInfo() { + return ratingInfo; + } + + protected long getContentSize() { + return 15 + Utf8.utf8StringLengthInBytes(ratingInfo); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + ratingEntity = IsoTypeReader.read4cc(content); + ratingCriteria = IsoTypeReader.read4cc(content); + language = IsoTypeReader.readIso639(content); + ratingInfo = IsoTypeReader.readString(content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(IsoFile.fourCCtoBytes(ratingEntity)); + byteBuffer.put(IsoFile.fourCCtoBytes(ratingCriteria)); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(ratingInfo)); + byteBuffer.put((byte) 0); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RatingBox[language=").append(getLanguage()); + buffer.append("ratingEntity=").append(getRatingEntity()); + buffer.append(";ratingCriteria=").append(getRatingCriteria()); + buffer.append(";language=").append(getLanguage()); + buffer.append(";ratingInfo=").append(getRatingInfo()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/RecordingYearBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/RecordingYearBox.java new file mode 100644 index 0000000..e2dcbd9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/RecordingYearBox.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class RecordingYearBox extends AbstractFullBox { + public static final String TYPE = "yrrc"; + + int recordingYear; + + public RecordingYearBox() { + super(TYPE); + } + + + protected long getContentSize() { + return 6; + } + + public int getRecordingYear() { + return recordingYear; + } + + public void setRecordingYear(int recordingYear) { + this.recordingYear = recordingYear; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + recordingYear = IsoTypeReader.readUInt16(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, recordingYear); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationOffsetsBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationOffsetsBox.java new file mode 100644 index 0000000..517bc03 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationOffsetsBox.java @@ -0,0 +1,127 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/* +aligned(8) class SampleAuxiliaryInformationOffsetsBox + extends FullBox(‘saio’, version, flags) +{ + if (flags & 1) { + unsigned int(32) aux_info_type; + unsigned int(32) aux_info_type_parameter; + } + unsigned int(32) entry_count; + if ( version == 0 ) + { + unsigned int(32) offset[ entry_count ]; + } + else + { + unsigned int(64) offset[ entry_count ]; + } +} + */ +public class SampleAuxiliaryInformationOffsetsBox extends AbstractFullBox { + public static final String TYPE = "saio"; + + private List<Long> offsets = new LinkedList<Long>(); + private long auxInfoType; + private long auxInfoTypeParameter; + + public SampleAuxiliaryInformationOffsetsBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 8 + (getVersion() == 0 ? 4 * offsets.size() : 8 * offsets.size()) + ((getFlags() & 1) == 1 ? 8 : 0); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if ((getFlags() & 1) == 1) { + IsoTypeWriter.writeUInt32(byteBuffer, auxInfoType); + IsoTypeWriter.writeUInt32(byteBuffer, auxInfoTypeParameter); + } + + IsoTypeWriter.writeUInt32(byteBuffer, offsets.size()); + for (Long offset : offsets) { + if (getVersion() == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, offset); + } else { + IsoTypeWriter.writeUInt64(byteBuffer, offset); + } + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + + if ((getFlags() & 1) == 1) { + auxInfoType = IsoTypeReader.readUInt32(content); + auxInfoTypeParameter = IsoTypeReader.readUInt32(content); + } + + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + offsets.clear(); + + for (int i = 0; i < entryCount; i++) { + if (getVersion() == 0) { + offsets.add(IsoTypeReader.readUInt32(content)); + } else { + offsets.add(IsoTypeReader.readUInt64(content)); + } + } + } + + + public long getAuxInfoType() { + return auxInfoType; + } + + public void setAuxInfoType(long auxInfoType) { + this.auxInfoType = auxInfoType; + } + + public long getAuxInfoTypeParameter() { + return auxInfoTypeParameter; + } + + public void setAuxInfoTypeParameter(long auxInfoTypeParameter) { + this.auxInfoTypeParameter = auxInfoTypeParameter; + } + + public List<Long> getOffsets() { + return offsets; + } + + public void setOffsets(List<Long> offsets) { + this.offsets = offsets; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationSizesBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationSizesBox.java new file mode 100644 index 0000000..4032d01 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleAuxiliaryInformationSizesBox.java @@ -0,0 +1,145 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +public class SampleAuxiliaryInformationSizesBox extends AbstractFullBox { + public static final String TYPE = "saiz"; + + private int defaultSampleInfoSize; + private List<Short> sampleInfoSizes = new LinkedList<Short>(); + private int sampleCount; + private String auxInfoType; + private String auxInfoTypeParameter; + + public SampleAuxiliaryInformationSizesBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + int size = 4; + if ((getFlags() & 1) == 1) { + size += 8; + } + + size += 5; + size += defaultSampleInfoSize == 0 ? sampleInfoSizes.size() : 0; + return size; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if ((getFlags() & 1) == 1) { + byteBuffer.put(IsoFile.fourCCtoBytes(auxInfoType)); + byteBuffer.put(IsoFile.fourCCtoBytes(auxInfoTypeParameter)); + } + + IsoTypeWriter.writeUInt8(byteBuffer, defaultSampleInfoSize); + + if (defaultSampleInfoSize == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleInfoSizes.size()); + for (short sampleInfoSize : sampleInfoSizes) { + IsoTypeWriter.writeUInt8(byteBuffer, sampleInfoSize); + } + } else { + IsoTypeWriter.writeUInt32(byteBuffer, sampleCount); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if ((getFlags() & 1) == 1) { + auxInfoType = IsoTypeReader.read4cc(content); + auxInfoTypeParameter = IsoTypeReader.read4cc(content); + } + + defaultSampleInfoSize = (short) IsoTypeReader.readUInt8(content); + sampleCount = l2i(IsoTypeReader.readUInt32(content)); + + sampleInfoSizes.clear(); + + if (defaultSampleInfoSize == 0) { + for (int i = 0; i < sampleCount; i++) { + sampleInfoSizes.add((short) IsoTypeReader.readUInt8(content)); + } + } + } + + public String getAuxInfoType() { + return auxInfoType; + } + + public void setAuxInfoType(String auxInfoType) { + this.auxInfoType = auxInfoType; + } + + public String getAuxInfoTypeParameter() { + return auxInfoTypeParameter; + } + + public void setAuxInfoTypeParameter(String auxInfoTypeParameter) { + this.auxInfoTypeParameter = auxInfoTypeParameter; + } + + public int getDefaultSampleInfoSize() { + return defaultSampleInfoSize; + } + + public void setDefaultSampleInfoSize(int defaultSampleInfoSize) { + assert defaultSampleInfoSize <= 255; + this.defaultSampleInfoSize = defaultSampleInfoSize; + } + + public List<Short> getSampleInfoSizes() { + return sampleInfoSizes; + } + + public void setSampleInfoSizes(List<Short> sampleInfoSizes) { + this.sampleInfoSizes = sampleInfoSizes; + } + + public int getSampleCount() { + return sampleCount; + } + + public void setSampleCount(int sampleCount) { + this.sampleCount = sampleCount; + } + + @Override + public String toString() { + return "SampleAuxiliaryInformationSizesBox{" + + "defaultSampleInfoSize=" + defaultSampleInfoSize + + ", sampleCount=" + sampleCount + + ", auxInfoType='" + auxInfoType + '\'' + + ", auxInfoTypeParameter='" + auxInfoTypeParameter + '\'' + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDependencyTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDependencyTypeBox.java new file mode 100644 index 0000000..bb38d8c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDependencyTypeBox.java @@ -0,0 +1,136 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * aligned(8) class SampleDependencyTypeBox + * extends FullBox('sdtp', version = 0, 0) { + * for (i=0; i < sample_count; i++){ + * unsigned int(2) reserved = 0; + * unsigned int(2) sample_depends_on; + * unsigned int(2) sample_is_depended_on; + * unsigned int(2) sample_has_redundancy; + * } + * } + */ +public class SampleDependencyTypeBox extends AbstractFullBox { + public static final String TYPE = "sdtp"; + + private List<Entry> entries = new ArrayList<Entry>(); + + public static class Entry { + + public Entry(int value) { + this.value = value; + } + + private int value; + + + public int getReserved() { + return (value >> 6) & 0x03; + } + + public void setReserved(int res) { + value = (res & 0x03) << 6 | value & 0x3f; + } + + public int getSampleDependsOn() { + return (value >> 4) & 0x03; + } + + public void setSampleDependsOn(int sdo) { + value = (sdo & 0x03) << 4 | value & 0xcf; + } + + public int getSampleIsDependentOn() { + return (value >> 2) & 0x03; + } + + public void setSampleIsDependentOn(int sido) { + value = (sido & 0x03) << 2 | value & 0xf3; + } + + public int getSampleHasRedundancy() { + return value & 0x03; + } + + public void setSampleHasRedundancy(int shr) { + value = shr & 0x03 | value & 0xfc; + } + + @Override + public String toString() { + return "Entry{" + + "reserved=" + getReserved() + + ", sampleDependsOn=" + getSampleDependsOn() + + ", sampleIsDependentOn=" + getSampleIsDependentOn() + + ", sampleHasRedundancy=" + getSampleHasRedundancy() + + '}'; + } + } + + public SampleDependencyTypeBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 4 + entries.size(); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt8(byteBuffer, entry.value); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + while (content.remaining() > 0) { + entries.add(new Entry(IsoTypeReader.readUInt8(content))); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("SampleDependencyTypeBox"); + sb.append("{entries=").append(entries); + sb.append('}'); + return sb.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDescriptionBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDescriptionBox.java new file mode 100644 index 0000000..662fa99 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleDescriptionBox.java @@ -0,0 +1,81 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.sampleentry.SampleEntry; +import com.googlecode.mp4parser.FullContainerBox; + +import java.nio.ByteBuffer; + +/** + * The sample description table gives detailed information about the coding type used, and any initialization + * information needed for that coding. <br> + * The information stored in the sample description box after the entry-count is both track-type specific as + * documented here, and can also have variants within a track type (e.g. different codings may use different + * specific information after some common fields, even within a video track).<br> + * For video tracks, a VisualSampleEntry is used; for audio tracks, an AudioSampleEntry. Hint tracks use an + * entry format specific to their protocol, with an appropriate name. Timed Text tracks use a TextSampleEntry + * For hint tracks, the sample description contains appropriate declarative data for the streaming protocol being + * used, and the format of the hint track. The definition of the sample description is specific to the protocol. + * Multiple descriptions may be used within a track.<br> + * The 'protocol' and 'codingname' fields are registered identifiers that uniquely identify the streaming protocol or + * compression format decoder to be used. A given protocol or codingname may have optional or required + * extensions to the sample description (e.g. codec initialization parameters). All such extensions shall be within + * boxes; these boxes occur after the required fields. Unrecognized boxes shall be ignored. + * <br> + * Defined in ISO/IEC 14496-12 + * + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.TextSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + */ +public class SampleDescriptionBox extends FullContainerBox { + public static final String TYPE = "stsd"; + + public SampleDescriptionBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return super.getContentSize() + 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + content.get(new byte[4]); + parseChildBoxes(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, boxes.size()); + writeChildBoxes(byteBuffer); + } + + public SampleEntry getSampleEntry() { + for (Box box : boxes) { + if (box instanceof SampleEntry) { + return (SampleEntry) box; + } + } + return null; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleSizeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleSizeBox.java new file mode 100644 index 0000000..3bc1df0 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleSizeBox.java @@ -0,0 +1,121 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box containes the sample count and a table giving the size in bytes of each sample. + * Defined in ISO/IEC 14496-12. + */ +public class SampleSizeBox extends AbstractFullBox { + private long sampleSize; + private long[] sampleSizes = new long[0]; + public static final String TYPE = "stsz"; + int sampleCount; + + public SampleSizeBox() { + super(TYPE); + } + + /** + * Returns the field sample size. + * If sampleSize > 0 every sample has the same size. + * If sampleSize == 0 the samples have different size as stated in the sampleSizes field. + * + * @return the sampleSize field + */ + public long getSampleSize() { + return sampleSize; + } + + public void setSampleSize(long sampleSize) { + this.sampleSize = sampleSize; + } + + + public long getSampleSizeAtIndex(int index) { + if (sampleSize > 0) { + return sampleSize; + } else { + return sampleSizes[index]; + } + } + + public long getSampleCount() { + if (sampleSize > 0) { + return sampleCount; + } else { + return sampleSizes.length; + } + + } + + public long[] getSampleSizes() { + return sampleSizes; + } + + public void setSampleSizes(long[] sampleSizes) { + this.sampleSizes = sampleSizes; + } + + protected long getContentSize() { + return 12 + (sampleSize == 0 ? sampleSizes.length * 4 : 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + sampleSize = IsoTypeReader.readUInt32(content); + sampleCount = l2i(IsoTypeReader.readUInt32(content)); + + if (sampleSize == 0) { + sampleSizes = new long[(int) sampleCount]; + + for (int i = 0; i < sampleCount; i++) { + sampleSizes[i] = IsoTypeReader.readUInt32(content); + } + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, sampleSize); + + if (sampleSize == 0) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleSizes.length); + for (long sampleSize1 : sampleSizes) { + IsoTypeWriter.writeUInt32(byteBuffer, sampleSize1); + } + } else { + IsoTypeWriter.writeUInt32(byteBuffer, sampleCount); + } + + } + + public String toString() { + return "SampleSizeBox[sampleSize=" + getSampleSize() + ";sampleCount=" + getSampleCount() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleTableBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleTableBox.java new file mode 100644 index 0000000..33968b3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleTableBox.java @@ -0,0 +1,124 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The sample table contains all the time and data indexing of the media samples in a track. Using the tables + * here, it is possible to locate samples in time, determine their type (e.g. I-frame or not), and determine their + * size, container, and offset into that container. <br> + * If the track that contains the Sample Table Box references no data, then the Sample Table Box does not need + * to contain any sub-boxes (this is not a very useful media track). <br> + * If the track that the Sample Table Box is contained in does reference data, then the following sub-boxes are + * required: Sample Description, Sample Size, Sample To Chunk, and Chunk Offset. Further, the Sample + * Description Box shall contain at least one entry. A Sample Description Box is required because it contains the + * data reference index field which indicates which Data Reference Box to use to retrieve the media samples. + * Without the Sample Description, it is not possible to determine where the media samples are stored. The Sync + * Sample Box is optional. If the Sync Sample Box is not present, all samples are sync samples.<br> + * Annex A provides a narrative description of random access using the structures defined in the Sample Table + * Box. + */ +public class SampleTableBox extends AbstractContainerBox { + public static final String TYPE = "stbl"; + + public SampleTableBox() { + super(TYPE); + } + + public SampleDescriptionBox getSampleDescriptionBox() { + for (Box box : boxes) { + if (box instanceof SampleDescriptionBox) { + return (SampleDescriptionBox) box; + } + } + return null; + } + + public SampleSizeBox getSampleSizeBox() { + for (Box box : boxes) { + if (box instanceof SampleSizeBox) { + return (SampleSizeBox) box; + } + } + return null; + } + + public SampleToChunkBox getSampleToChunkBox() { + for (Box box : boxes) { + if (box instanceof SampleToChunkBox) { + return (SampleToChunkBox) box; + } + } + return null; + } + + public ChunkOffsetBox getChunkOffsetBox() { + for (Box box : boxes) { + if (box instanceof ChunkOffsetBox) { + return (ChunkOffsetBox) box; + } + } + return null; + } + + public void setChunkOffsetBox(ChunkOffsetBox b) { + for (int i = 0; i < boxes.size(); i++) { + Box box = boxes.get(i); + if (box instanceof ChunkOffsetBox) { + boxes.set(i, b); + } + } + } + + public TimeToSampleBox getTimeToSampleBox() { + for (Box box : boxes) { + if (box instanceof TimeToSampleBox) { + return (TimeToSampleBox) box; + } + } + return null; + } + + public SyncSampleBox getSyncSampleBox() { + for (Box box : boxes) { + if (box instanceof SyncSampleBox) { + return (SyncSampleBox) box; + } + } + return null; + } + + public CompositionTimeToSample getCompositionTimeToSample() { + for (Box box : boxes) { + if (box instanceof CompositionTimeToSample) { + return (CompositionTimeToSample) box; + } + } + return null; + } + + public SampleDependencyTypeBox getSampleDependencyTypeBox() { + for (Box box : boxes) { + if (box instanceof SampleDependencyTypeBox) { + return (SampleDependencyTypeBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SampleToChunkBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleToChunkBox.java new file mode 100644 index 0000000..593504d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SampleToChunkBox.java @@ -0,0 +1,156 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Samples within the media data are grouped into chunks. Chunks can be of different sizes, and the + * samples within a chunk can have different sizes. This table can be used to find the chunk that + * contains a sample, its position, and the associated sample description. Defined in ISO/IEC 14496-12. + */ +public class SampleToChunkBox extends AbstractFullBox { + List<Entry> entries = Collections.emptyList(); + + public static final String TYPE = "stsc"; + + public SampleToChunkBox() { + super(TYPE); + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + protected long getContentSize() { + return entries.size() * 12 + 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(entryCount); + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry( + IsoTypeReader.readUInt32(content), + IsoTypeReader.readUInt32(content), + IsoTypeReader.readUInt32(content))); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getFirstChunk()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getSamplesPerChunk()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleDescriptionIndex()); + } + } + + public String toString() { + return "SampleToChunkBox[entryCount=" + entries.size() + "]"; + } + + /** + * Decompresses the list of entries and returns the number of samples per chunk for + * every single chunk. + * + * @param chunkCount overall number of chunks + * @return number of samples per chunk + */ + public long[] blowup(int chunkCount) { + long[] numberOfSamples = new long[chunkCount]; + int j = 0; + List<SampleToChunkBox.Entry> sampleToChunkEntries = new LinkedList<Entry>(entries); + Collections.reverse(sampleToChunkEntries); + Iterator<Entry> iterator = sampleToChunkEntries.iterator(); + SampleToChunkBox.Entry currentEntry = iterator.next(); + + for (int i = numberOfSamples.length; i > 1; i--) { + numberOfSamples[i - 1] = currentEntry.getSamplesPerChunk(); + if (i == currentEntry.getFirstChunk()) { + currentEntry = iterator.next(); + } + } + numberOfSamples[0] = currentEntry.getSamplesPerChunk(); + return numberOfSamples; + } + + public static class Entry { + long firstChunk; + long samplesPerChunk; + long sampleDescriptionIndex; + + public Entry(long firstChunk, long samplesPerChunk, long sampleDescriptionIndex) { + this.firstChunk = firstChunk; + this.samplesPerChunk = samplesPerChunk; + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + public long getFirstChunk() { + return firstChunk; + } + + public void setFirstChunk(long firstChunk) { + this.firstChunk = firstChunk; + } + + public long getSamplesPerChunk() { + return samplesPerChunk; + } + + public void setSamplesPerChunk(long samplesPerChunk) { + this.samplesPerChunk = samplesPerChunk; + } + + public long getSampleDescriptionIndex() { + return sampleDescriptionIndex; + } + + public void setSampleDescriptionIndex(long sampleDescriptionIndex) { + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + @Override + public String toString() { + return "Entry{" + + "firstChunk=" + firstChunk + + ", samplesPerChunk=" + samplesPerChunk + + ", sampleDescriptionIndex=" + sampleDescriptionIndex + + '}'; + } + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeInformationBox.java new file mode 100644 index 0000000..5e3565e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeInformationBox.java @@ -0,0 +1,33 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * The Scheme Information Box is a container box that is only interpreted by the scheme beeing used. + * Any information the encryption system needs is stored here. The content of this box is a series of + * boxexes whose type annd format are defined by the scheme declared in the {@link com.coremedia.iso.boxes.SchemeTypeBox}. + */ +public class SchemeInformationBox extends AbstractContainerBox { + public static final String TYPE = "schi"; + + public SchemeInformationBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeTypeBox.java new file mode 100644 index 0000000..ed517da --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SchemeTypeBox.java @@ -0,0 +1,101 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * The Scheme Type Box identifies the protection scheme. Resides in a Protection Scheme Information Box or + * an SRTP Process Box. + * + * @see com.coremedia.iso.boxes.SchemeInformationBox + */ +public class SchemeTypeBox extends AbstractFullBox { + public static final String TYPE = "schm"; + String schemeType = " "; + long schemeVersion; + String schemeUri = null; + + public SchemeTypeBox() { + super(TYPE); + } + + public String getSchemeType() { + return schemeType; + } + + public long getSchemeVersion() { + return schemeVersion; + } + + public String getSchemeUri() { + return schemeUri; + } + + public void setSchemeType(String schemeType) { + assert schemeType != null && schemeType.length() == 4 : "SchemeType may not be null or not 4 bytes long"; + this.schemeType = schemeType; + } + + public void setSchemeVersion(int schemeVersion) { + this.schemeVersion = schemeVersion; + } + + public void setSchemeUri(String schemeUri) { + this.schemeUri = schemeUri; + } + + protected long getContentSize() { + return 12 + (((getFlags() & 1) == 1) ? Utf8.utf8StringLengthInBytes(schemeUri) + 1 : 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + schemeType = IsoTypeReader.read4cc(content); + schemeVersion = IsoTypeReader.readUInt32(content); + if ((getFlags() & 1) == 1) { + schemeUri = IsoTypeReader.readString(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(IsoFile.fourCCtoBytes(schemeType)); + IsoTypeWriter.writeUInt32(byteBuffer, schemeVersion); + if ((getFlags() & 1) == 1) { + byteBuffer.put(Utf8.convert(schemeUri)); + } + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("Schema Type Box["); + buffer.append("schemeUri=").append(schemeUri).append("; "); + buffer.append("schemeType=").append(schemeType).append("; "); + buffer.append("schemeVersion=").append(schemeUri).append("; "); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SoundMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SoundMediaHeaderBox.java new file mode 100644 index 0000000..c5fb88d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SoundMediaHeaderBox.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +public class SoundMediaHeaderBox extends AbstractMediaHeaderBox { + + public static final String TYPE = "smhd"; + private float balance; + + public SoundMediaHeaderBox() { + super(TYPE); + } + + public float getBalance() { + return balance; + } + + protected long getContentSize() { + return 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + balance = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeFixedPont88(byteBuffer, balance); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + } + + public String toString() { + return "SoundMediaHeaderBox[balance=" + getBalance() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/StaticChunkOffsetBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/StaticChunkOffsetBox.java new file mode 100644 index 0000000..efcdd14 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/StaticChunkOffsetBox.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * The chunk offset table gives the index of each chunk into the containing file. Defined in ISO/IEC 14496-12. + */ +public class StaticChunkOffsetBox extends ChunkOffsetBox { + public static final String TYPE = "stco"; + + private long[] chunkOffsets = new long[0]; + + public StaticChunkOffsetBox() { + super(TYPE); + } + + public long[] getChunkOffsets() { + return chunkOffsets; + } + + protected long getContentSize() { + return 8 + chunkOffsets.length * 4; + } + + public void setChunkOffsets(long[] chunkOffsets) { + this.chunkOffsets = chunkOffsets; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + chunkOffsets = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + chunkOffsets[i] = IsoTypeReader.readUInt32(content); + } + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffsets.length); + for (long chunkOffset : chunkOffsets) { + IsoTypeWriter.writeUInt32(byteBuffer, chunkOffset); + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SubSampleInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SubSampleInformationBox.java new file mode 100644 index 0000000..f5806eb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SubSampleInformationBox.java @@ -0,0 +1,208 @@ +package com.coremedia.iso.boxes;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * aligned(8) class SubSampleInformationBox
+ * extends FullBox('subs', version, 0) {
+ * unsigned int(32) entry_count;
+ * int i,j;
+ * for (i=0; i < entry_count; i++) {
+ * unsigned int(32) sample_delta;
+ * unsigned int(16) subsample_count;
+ * if (subsample_count > 0) {
+ * for (j=0; j < subsample_count; j++) {
+ * if(version == 1)
+ * {
+ * unsigned int(32) subsample_size;
+ * }
+ * else
+ * {
+ * unsigned int(16) subsample_size;
+ * }
+ * unsigned int(8) subsample_priority;
+ * unsigned int(8) discardable;
+ * unsigned int(32) reserved = 0;
+ * }
+ * }
+ * }
+ * }
+ */
+public class SubSampleInformationBox extends AbstractFullBox {
+ public static final String TYPE = "subs";
+
+ private long entryCount;
+ private List<SampleEntry> entries = new ArrayList<SampleEntry>();
+
+ public SubSampleInformationBox() {
+ super(TYPE);
+ }
+
+ public List<SampleEntry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<SampleEntry> entries) {
+ this.entries = entries;
+ entryCount = entries.size();
+ }
+
+ @Override
+ protected long getContentSize() {
+ long entries = 8 + ((4 + 2) * entryCount);
+ int subsampleEntries = 0;
+ for (SampleEntry sampleEntry : this.entries) {
+ subsampleEntries += sampleEntry.getSubsampleCount() * (((getVersion() == 1) ? 4 : 2) + 1 + 1 + 4);
+ }
+ return entries + subsampleEntries;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+
+ entryCount = IsoTypeReader.readUInt32(content);
+
+ for (int i = 0; i < entryCount; i++) {
+ SampleEntry sampleEntry = new SampleEntry();
+ sampleEntry.setSampleDelta(IsoTypeReader.readUInt32(content));
+ int subsampleCount = IsoTypeReader.readUInt16(content);
+ for (int j = 0; j < subsampleCount; j++) {
+ SampleEntry.SubsampleEntry subsampleEntry = new SampleEntry.SubsampleEntry();
+ subsampleEntry.setSubsampleSize(getVersion() == 1 ? IsoTypeReader.readUInt32(content) : IsoTypeReader.readUInt16(content));
+ subsampleEntry.setSubsamplePriority(IsoTypeReader.readUInt8(content));
+ subsampleEntry.setDiscardable(IsoTypeReader.readUInt8(content));
+ subsampleEntry.setReserved(IsoTypeReader.readUInt32(content));
+ sampleEntry.addSubsampleEntry(subsampleEntry);
+ }
+ entries.add(sampleEntry);
+ }
+
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (SampleEntry sampleEntry : entries) {
+ IsoTypeWriter.writeUInt32(byteBuffer, sampleEntry.getSampleDelta());
+ IsoTypeWriter.writeUInt16(byteBuffer, sampleEntry.getSubsampleCount());
+ List<SampleEntry.SubsampleEntry> subsampleEntries = sampleEntry.getSubsampleEntries();
+ for (SampleEntry.SubsampleEntry subsampleEntry : subsampleEntries) {
+ if (getVersion() == 1) {
+ IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getSubsampleSize());
+ } else {
+ IsoTypeWriter.writeUInt16(byteBuffer, l2i(subsampleEntry.getSubsampleSize()));
+ }
+ IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getSubsamplePriority());
+ IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getDiscardable());
+ IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getReserved());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SubSampleInformationBox{" +
+ "entryCount=" + entryCount +
+ ", entries=" + entries +
+ '}';
+ }
+
+ public static class SampleEntry {
+ private long sampleDelta;
+ private int subsampleCount;
+ private List<SubsampleEntry> subsampleEntries = new ArrayList<SubsampleEntry>();
+
+ public long getSampleDelta() {
+ return sampleDelta;
+ }
+
+ public void setSampleDelta(long sampleDelta) {
+ this.sampleDelta = sampleDelta;
+ }
+
+ public int getSubsampleCount() {
+ return subsampleCount;
+ }
+
+ public void setSubsampleCount(int subsampleCount) {
+ this.subsampleCount = subsampleCount;
+ }
+
+ public List<SubsampleEntry> getSubsampleEntries() {
+ return subsampleEntries;
+ }
+
+ public void addSubsampleEntry(SubsampleEntry subsampleEntry) {
+ subsampleEntries.add(subsampleEntry);
+ subsampleCount++;
+ }
+
+ public static class SubsampleEntry {
+ private long subsampleSize;
+ private int subsamplePriority;
+ private int discardable;
+ private long reserved;
+
+ public long getSubsampleSize() {
+ return subsampleSize;
+ }
+
+ public void setSubsampleSize(long subsampleSize) {
+ this.subsampleSize = subsampleSize;
+ }
+
+ public int getSubsamplePriority() {
+ return subsamplePriority;
+ }
+
+ public void setSubsamplePriority(int subsamplePriority) {
+ this.subsamplePriority = subsamplePriority;
+ }
+
+ public int getDiscardable() {
+ return discardable;
+ }
+
+ public void setDiscardable(int discardable) {
+ this.discardable = discardable;
+ }
+
+ public long getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(long reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "SubsampleEntry{" +
+ "subsampleSize=" + subsampleSize +
+ ", subsamplePriority=" + subsamplePriority +
+ ", discardable=" + discardable +
+ ", reserved=" + reserved +
+ '}';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SampleEntry{" +
+ "sampleDelta=" + sampleDelta +
+ ", subsampleCount=" + subsampleCount +
+ ", subsampleEntries=" + subsampleEntries +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SubtitleMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SubtitleMediaHeaderBox.java new file mode 100644 index 0000000..fa25a5c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SubtitleMediaHeaderBox.java @@ -0,0 +1,30 @@ +package com.coremedia.iso.boxes; + +import java.nio.ByteBuffer; + +public class SubtitleMediaHeaderBox extends AbstractMediaHeaderBox { + + public static final String TYPE = "sthd"; + + public SubtitleMediaHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + return 4; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + } + + public String toString() { + return "SubtitleMediaHeaderBox"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/SyncSampleBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/SyncSampleBox.java new file mode 100644 index 0000000..5fc758b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/SyncSampleBox.java @@ -0,0 +1,83 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box provides a compact marking of the random access points withinthe stream. The table is arranged in + * strictly decreasinf order of sample number. Defined in ISO/IEC 14496-12. + */ +public class SyncSampleBox extends AbstractFullBox { + public static final String TYPE = "stss"; + + private long[] sampleNumber; + + public SyncSampleBox() { + super(TYPE); + } + + /** + * Gives the numbers of the samples that are random access points in the stream. + * + * @return random access sample numbers. + */ + public long[] getSampleNumber() { + return sampleNumber; + } + + protected long getContentSize() { + return sampleNumber.length * 4 + 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + + sampleNumber = new long[entryCount]; + for (int i = 0; i < entryCount; i++) { + sampleNumber[i] = IsoTypeReader.readUInt32(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + + IsoTypeWriter.writeUInt32(byteBuffer, sampleNumber.length); + + for (long aSampleNumber : sampleNumber) { + IsoTypeWriter.writeUInt32(byteBuffer, aSampleNumber); + } + + } + + public String toString() { + return "SyncSampleBox[entryCount=" + sampleNumber.length + "]"; + } + + public void setSampleNumber(long[] sampleNumber) { + this.sampleNumber = sampleNumber; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TimeToSampleBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TimeToSampleBox.java new file mode 100644 index 0000000..8f4f97e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TimeToSampleBox.java @@ -0,0 +1,152 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box contains a compact version of a table that allows indexing from decoding time to sample number. + * Other tables give sample sizes and pointers, from the sample number. Each entry in the table gives the + * number of consecutive samples with the same time delta, and the delta of those samples. By adding the + * deltas a complete time-to-sample map may be built.<br> + * The Decoding Time to Sample Box contains decode time delta's: <code>DT(n+1) = DT(n) + STTS(n)</code> where STTS(n) + * is the (uncompressed) table entry for sample n.<br> + * The sample entries are ordered by decoding time stamps; therefore the deltas are all non-negative. <br> + * The DT axis has a zero origin; <code>DT(i) = SUM(for j=0 to i-1 of delta(j))</code>, and the sum of all + * deltas gives the length of the media in the track (not mapped to the overall timescale, and not considering + * any edit list). <br> + * The Edit List Box provides the initial CT value if it is non-empty (non-zero). + */ +public class TimeToSampleBox extends AbstractFullBox { + public static final String TYPE = "stts"; + + List<Entry> entries = Collections.emptyList(); + + + public TimeToSampleBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8 + entries.size() * 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + int entryCount = l2i(IsoTypeReader.readUInt32(content)); + entries = new ArrayList<Entry>(entryCount); + + for (int i = 0; i < entryCount; i++) { + entries.add(new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content))); + } + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + for (Entry entry : entries) { + IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount()); + IsoTypeWriter.writeUInt32(byteBuffer, entry.getDelta()); + } + } + + public List<Entry> getEntries() { + return entries; + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + public String toString() { + return "TimeToSampleBox[entryCount=" + entries.size() + "]"; + } + + public static class Entry { + long count; + long delta; + + public Entry(long count, long delta) { + this.count = count; + this.delta = delta; + } + + public long getCount() { + return count; + } + + public long getDelta() { + return delta; + } + + public void setCount(long count) { + this.count = count; + } + + public void setDelta(long delta) { + this.delta = delta; + } + + @Override + public String toString() { + return "Entry{" + + "count=" + count + + ", delta=" + delta + + '}'; + } + } + + /** + * Decompresses the list of entries and returns the list of decoding times. + * + * @return decoding time per sample + */ + public static long[] blowupTimeToSamples(List<TimeToSampleBox.Entry> entries) { + long numOfSamples = 0; + for (TimeToSampleBox.Entry entry : entries) { + numOfSamples += entry.getCount(); + } + assert numOfSamples <= Integer.MAX_VALUE; + long[] decodingTime = new long[(int) numOfSamples]; + + int current = 0; + + + for (TimeToSampleBox.Entry entry : entries) { + for (int i = 0; i < entry.getCount(); i++) { + decodingTime[current++] = entry.getDelta(); + } + } + + return decodingTime; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TitleBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TitleBox.java new file mode 100644 index 0000000..46ee5ee --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TitleBox.java @@ -0,0 +1,89 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * <code> + * Box Type: 'titl'<br> + * Container: {@link UserDataBox} ('udta')<br> + * Mandatory: No<br> + * Quantity: Zero or one<br><br> + * </code> + * <p/> + * Title for the media. + */ +public class TitleBox extends AbstractFullBox { + public static final String TYPE = "titl"; + + private String language; + private String title; + + public TitleBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getTitle() { + return title; + } + + /** + * Sets the 3-letter ISO-639 language for this title. + * + * @param language 3-letter ISO-639 code + */ + public void setLanguage(String language) { + this.language = language; + } + + public void setTitle(String title) { + this.title = title; + } + + protected long getContentSize() { + return 7 + Utf8.utf8StringLengthInBytes(title); + } + + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(title)); + byteBuffer.put((byte) 0); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + title = IsoTypeReader.readString(content); + } + + public String toString() { + return "TitleBox[language=" + getLanguage() + ";title=" + getTitle() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TrackBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackBox.java new file mode 100644 index 0000000..c2806b5 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackBox.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * Tracks are used for two purposes: (a) to contain media data (media tracks) and (b) to contain packetization + * information for streaming protocols (hint tracks). <br> + * There shall be at least one media track within an ISO file, and all the media tracks that contributed to the hint + * tracks shall remain in the file, even if the media data within them is not referenced by the hint tracks; after + * deleting all hint tracks, the entire un-hinted presentation shall remain. + */ +public class TrackBox extends AbstractContainerBox { + public static final String TYPE = "trak"; + + public TrackBox() { + super(TYPE); + } + + public TrackHeaderBox getTrackHeaderBox() { + for (Box box : boxes) { + if (box instanceof TrackHeaderBox) { + return (TrackHeaderBox) box; + } + } + return null; + } + + /** + * Gets the SampleTableBox at mdia/minf/stbl if existing. + * + * @return the SampleTableBox or <code>null</code> + */ + public SampleTableBox getSampleTableBox() { + MediaBox mdia = getMediaBox(); + if (mdia != null) { + MediaInformationBox minf = mdia.getMediaInformationBox(); + if (minf != null) { + return minf.getSampleTableBox(); + } + } + return null; + + } + + + public MediaBox getMediaBox() { + for (Box box : boxes) { + if (box instanceof MediaBox) { + return (MediaBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TrackHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackHeaderBox.java new file mode 100644 index 0000000..8816bb9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackHeaderBox.java @@ -0,0 +1,249 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track.<br> + * In the absence of an edit list, the presentation of a track starts at the beginning of the overall presentation. An + * empty edit is used to offset the start time of a track. <br> + * The default value of the track header flags for media tracks is 7 (track_enabled, track_in_movie, + * track_in_preview). If in a presentation all tracks have neither track_in_movie nor track_in_preview set, then all + * tracks shall be treated as if both flags were set on all tracks. Hint tracks should have the track header flags set + * to 0, so that they are ignored for local playback and preview. + */ +public class TrackHeaderBox extends AbstractFullBox { + + public static final String TYPE = "tkhd"; + + private long creationTime; + private long modificationTime; + private long trackId; + private long duration; + private int layer; + private int alternateGroup; + private float volume; + private long[] matrix = new long[]{0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; + private double width; + private double height; + + + public TrackHeaderBox() { + super(TYPE); + + } + + public long getCreationTime() { + return creationTime; + } + + public long getModificationTime() { + return modificationTime; + } + + public long getTrackId() { + return trackId; + } + + public long getDuration() { + return duration; + } + + public int getLayer() { + return layer; + } + + public int getAlternateGroup() { + return alternateGroup; + } + + public float getVolume() { + return volume; + } + + public long[] getMatrix() { + return matrix; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + protected long getContentSize() { + long contentSize = 4; + if (getVersion() == 1) { + contentSize += 32; + } else { + contentSize += 20; + } + contentSize += 60; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + creationTime = IsoTypeReader.readUInt64(content); + modificationTime = IsoTypeReader.readUInt64(content); + trackId = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt64(content); + } else { + creationTime = IsoTypeReader.readUInt32(content); + modificationTime = IsoTypeReader.readUInt32(content); + trackId = IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + duration = IsoTypeReader.readUInt32(content); + } // 196 + IsoTypeReader.readUInt32(content); + IsoTypeReader.readUInt32(content); + layer = IsoTypeReader.readUInt16(content); // 204 + alternateGroup = IsoTypeReader.readUInt16(content); + volume = IsoTypeReader.readFixedPoint88(content); + IsoTypeReader.readUInt16(content); // 212 + matrix = new long[9]; + for (int i = 0; i < 9; i++) { + matrix[i] = IsoTypeReader.readUInt32(content); + } + width = IsoTypeReader.readFixedPoint1616(content); // 248 + height = IsoTypeReader.readFixedPoint1616(content); + } + + public void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, creationTime); + IsoTypeWriter.writeUInt64(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt64(byteBuffer, duration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, creationTime); + IsoTypeWriter.writeUInt32(byteBuffer, modificationTime); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, duration); + } // 196 + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, layer); + IsoTypeWriter.writeUInt16(byteBuffer, alternateGroup); + IsoTypeWriter.writeFixedPont88(byteBuffer, volume); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + for (int i = 0; i < 9; i++) { + IsoTypeWriter.writeUInt32(byteBuffer, matrix[i]); + } + IsoTypeWriter.writeFixedPont1616(byteBuffer, width); + IsoTypeWriter.writeFixedPont1616(byteBuffer, height); + } + + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("TrackHeaderBox["); + result.append("creationTime=").append(getCreationTime()); + result.append(";"); + result.append("modificationTime=").append(getModificationTime()); + result.append(";"); + result.append("trackId=").append(getTrackId()); + result.append(";"); + result.append("duration=").append(getDuration()); + result.append(";"); + result.append("layer=").append(getLayer()); + result.append(";"); + result.append("alternateGroup=").append(getAlternateGroup()); + result.append(";"); + result.append("volume=").append(getVolume()); + for (int i = 0; i < matrix.length; i++) { + result.append(";"); + result.append("matrix").append(i).append("=").append(matrix[i]); + } + result.append(";"); + result.append("width=").append(getWidth()); + result.append(";"); + result.append("height=").append(getHeight()); + result.append("]"); + return result.toString(); + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModificationTime(long modificationTime) { + this.modificationTime = modificationTime; + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setLayer(int layer) { + this.layer = layer; + } + + public void setAlternateGroup(int alternateGroup) { + this.alternateGroup = alternateGroup; + } + + public void setVolume(float volume) { + this.volume = volume; + } + + public void setMatrix(long[] matrix) { + this.matrix = matrix; + } + + public void setWidth(double width) { + this.width = width; + } + + public void setHeight(double height) { + this.height = height; + } + + + public boolean isEnabled() { + return (getFlags() & 1) > 0; + } + + public boolean isInMovie() { + return (getFlags() & 2) > 0; + } + + public boolean isInPreview() { + return (getFlags() & 4) > 0; + } + + public boolean isInPoster() { + return (getFlags() & 8) > 0; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceBox.java new file mode 100644 index 0000000..1b4a7fb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceBox.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * <code> + * Box Type: 'tref'<br> + * Container: {@link TrackBox} ('trak')<br> + * Mandatory: No<br> + * Quantity: Zero or one<br><br> + * </code> + * This box provides a reference from the containing track to another track in the presentation. These references + * are typed. A 'hint' reference links from the containing hint track to the media data that it hints. A content + * description reference 'cdsc' links a descriptive or metadata track to the content which it describes. + * Exactly one Track Reference Box can be contained within the Track Box. + * If this box is not present, the track is not referencing any other track in any way. The reference array is sized + * to fill the reference type box. + */ +public class TrackReferenceBox extends AbstractContainerBox { + public static final String TYPE = "tref"; + + public TrackReferenceBox() { + super(TYPE); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceTypeBox.java new file mode 100644 index 0000000..297932d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/TrackReferenceTypeBox.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * Contains a reference to a track. The type of the box gives the kind of reference. + */ +public class TrackReferenceTypeBox extends AbstractBox { + + public static final String TYPE1 = "hint"; + public static final String TYPE2 = "cdsc"; + + private long[] trackIds; + + public TrackReferenceTypeBox(String type) { + super(type); + } + + public long[] getTrackIds() { + return trackIds; + } + + @Override + public void _parseDetails(ByteBuffer content) { + int count = (int) (content.remaining() / 4); + trackIds = new long[count]; + for (int i = 0; i < count; i++) { + trackIds[i] = IsoTypeReader.readUInt32(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + for (long trackId : trackIds) { + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + } + } + + + protected long getContentSize() { + return trackIds.length * 4; + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("TrackReferenceTypeBox[type=").append(getType()); + for (int i = 0; i < trackIds.length; i++) { + buffer.append(";trackId"); + buffer.append(i); + buffer.append("="); + buffer.append(trackIds[i]); + } + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/UnknownBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/UnknownBox.java new file mode 100644 index 0000000..f76481c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/UnknownBox.java @@ -0,0 +1,59 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * A box unknown to the ISO Parser. If there is no specific Box implementation for a Box this <code>UnknownBox</code> + * will just hold the box's data. + */ +public class UnknownBox extends AbstractBox { + ByteBuffer data; + + public UnknownBox(String type) { + super(type); + } + + @Override + protected long getContentSize() { + return data.limit(); + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = content; + content.position(content.position() + content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + data.rewind(); + byteBuffer.put(data); + } + + public ByteBuffer getData() { + return data; + } + + public void setData(ByteBuffer data) { + this.data = data; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/UserBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/UserBox.java new file mode 100644 index 0000000..db0e741 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/UserBox.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * A user specifc box. See ISO/IEC 14496-12 for details. + */ +public class UserBox extends AbstractBox { + byte[] data; + public static final String TYPE = "uuid"; + + public UserBox(byte[] userType) { + super(TYPE, userType); + } + + + protected long getContentSize() { + return data.length; + } + + public String toString() { + return "UserBox[type=" + (getType()) + + ";userType=" + new String(getUserType()) + + ";contentLength=" + data.length + "]"; + } + + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + @Override + public void _parseDetails(ByteBuffer content) { + data = new byte[content.remaining()]; + content.get(data); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(data); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/UserDataBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/UserDataBox.java new file mode 100644 index 0000000..65c5808 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/UserDataBox.java @@ -0,0 +1,59 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.BoxParser; +import com.googlecode.mp4parser.AbstractContainerBox; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +/** + * This box contains objects that declare user information about the containing box and its data (presentation or + * track).<br> + * The User Data Box is a container box for informative user-data. This user data is formatted as a set of boxes + * with more specific box types, which declare more precisely their content + */ +public class UserDataBox extends AbstractContainerBox { + public static final String TYPE = "udta"; + + @Override + protected long getContentSize() { + return super.getContentSize(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + super.parse(readableByteChannel, header, contentSize, boxParser); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public void _parseDetails(ByteBuffer content) { + super._parseDetails(content); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + super.getContent(byteBuffer); //To change body of overridden methods use File | Settings | File Templates. + } + + public UserDataBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/VideoMediaHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/VideoMediaHeaderBox.java new file mode 100644 index 0000000..421a67d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/VideoMediaHeaderBox.java @@ -0,0 +1,81 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * The video media header contains general presentation information, independent of the coding, for video + * media. Note that the flags field has the value 1. + */ +public class VideoMediaHeaderBox extends AbstractMediaHeaderBox { + private int graphicsmode = 0; + private int[] opcolor = new int[]{0, 0, 0}; + public static final String TYPE = "vmhd"; + + public VideoMediaHeaderBox() { + super(TYPE); + setFlags(1); // 1 is default. + } + + public int getGraphicsmode() { + return graphicsmode; + } + + public int[] getOpcolor() { + return opcolor; + } + + protected long getContentSize() { + return 12; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + graphicsmode = IsoTypeReader.readUInt16(content); + opcolor = new int[3]; + for (int i = 0; i < 3; i++) { + opcolor[i] = IsoTypeReader.readUInt16(content); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, graphicsmode); + for (int anOpcolor : opcolor) { + IsoTypeWriter.writeUInt16(byteBuffer, anOpcolor); + } + } + + public String toString() { + return "VideoMediaHeaderBox[graphicsmode=" + getGraphicsmode() + ";opcolor0=" + getOpcolor()[0] + ";opcolor1=" + getOpcolor()[1] + ";opcolor2=" + getOpcolor()[2] + "]"; + } + + public void setOpcolor(int[] opcolor) { + this.opcolor = opcolor; + } + + public void setGraphicsmode(int graphicsmode) { + this.graphicsmode = graphicsmode; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/WriteListener.java b/isoparser/src/main/java/com/coremedia/iso/boxes/WriteListener.java new file mode 100644 index 0000000..dc22d52 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/WriteListener.java @@ -0,0 +1,10 @@ +package com.coremedia.iso.boxes; + +/** + * The <class>WriteListener</class> is used to get the offset of + * a box before writing the box. This can be used if a box written + * later needs an offset. + */ +public interface WriteListener { + public void beforeWrite(long offset); +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/XmlBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/XmlBox.java new file mode 100644 index 0000000..43727e1 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/XmlBox.java @@ -0,0 +1,51 @@ +package com.coremedia.iso.boxes; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * + */ +public class XmlBox extends AbstractFullBox { + String xml = ""; + public static final String TYPE = "xml "; + + public XmlBox() { + super(TYPE); + } + + public String getXml() { + return xml; + } + + public void setXml(String xml) { + this.xml = xml; + } + + @Override + protected long getContentSize() { + return 4 + Utf8.utf8StringLengthInBytes(xml); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + xml = IsoTypeReader.readString(content, content.remaining()); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(xml)); + } + + @Override + public String toString() { + return "XmlBox{" + + "xml='" + xml + '\'' + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/all-wcprops new file mode 100644 index 0000000..581c9a0 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/all-wcprops @@ -0,0 +1,263 @@ +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple +END +AppleTrackTitleBox.java +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackTitleBox.java +END +AppleCopyrightBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCopyrightBox.java +END +ApplePurchaseDateBox.java +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/ApplePurchaseDateBox.java +END +AppleSortAlbumBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSortAlbumBox.java +END +AppleTvEpisodeNumberBox.java +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeNumberBox.java +END +AppleStoreAccountTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreAccountTypeBox.java +END +AppleStoreCountryCodeBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreCountryCodeBox.java +END +AppleGenericBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGenericBox.java +END +AppleNameBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNameBox.java +END +AppleShowBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleShowBox.java +END +AppleStandardGenreBox.java +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStandardGenreBox.java +END +AppleRatingBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRatingBox.java +END +AppleSynopsisBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSynopsisBox.java +END +AppleNetworkBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNetworkBox.java +END +AppleRecordingYearBox.java +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRecordingYearBox.java +END +AppleReferenceMovieBox.java +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieBox.java +END +AppleTvEpisodeBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeBox.java +END +AppleWaveBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleWaveBox.java +END +AbstractAppleMetaDataBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AbstractAppleMetaDataBox.java +END +AppleGaplessPlaybackBox.java +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGaplessPlaybackBox.java +END +AppleTempBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTempBox.java +END +AppleArtistBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleArtistBox.java +END +AppleDataBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataBox.java +END +AppleTrackNumberBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackNumberBox.java +END +AppleLosslessSpecificBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleLosslessSpecificBox.java +END +AppleCompilationBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCompilationBox.java +END +AppleCoverBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCoverBox.java +END +AppleEncoderBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleEncoderBox.java +END +AppleMeanBox.java +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMeanBox.java +END +AppleMediaTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMediaTypeBox.java +END +AppleDescriptionBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDescriptionBox.java +END +AppleDataRateBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataRateBox.java +END +AppleTrackAuthorBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackAuthorBox.java +END +AppleAlbumArtistBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumArtistBox.java +END +AppleDataReferenceBox.java +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataReferenceBox.java +END +AppleItemListBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleItemListBox.java +END +AppleGroupingBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGroupingBox.java +END +AppleCustomGenreBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCustomGenreBox.java +END +AppleIdBox.java +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleIdBox.java +END +AppleReferenceMovieDescriptorBox.java +K 25 +svn:wc:ra_dav:version-url +V 115 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieDescriptorBox.java +END +AppleAlbumBox.java +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumBox.java +END +AppleCommentBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCommentBox.java +END +AppleTvSeasonBox.java +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/!svn/ver/198/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvSeasonBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/entries new file mode 100644 index 0000000..aadbfac --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/entries @@ -0,0 +1,1490 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/apple +http://mp4parser.googlecode.com/svn + + + +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +AppleTrackTitleBox.java +file + + + + +2012-09-14T17:27:52.037241Z +d00320057c7c9b507bdd9413d190eade +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +302 + +AppleCopyrightBox.java +file + + + + +2012-09-14T17:27:52.037241Z +d10479559734743978d76f30ffc59465 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +323 + +ApplePurchaseDateBox.java +file + + + + +2012-09-14T17:27:52.037241Z +a970bf8322f9e093a3916aec472ea947 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +300 + +AppleSortAlbumBox.java +file + + + + +2012-09-14T17:27:52.037241Z +517e986ff5c8917167163f94bdf507dd +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +293 + +AppleTvEpisodeNumberBox.java +file + + + + +2012-09-14T17:27:52.037241Z +203d82f75cf575c09a2fc51a9de729a1 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +326 + +AppleStoreAccountTypeBox.java +file + + + + +2012-09-14T17:27:52.037241Z +5b6e2900853c7d47daba86a93ab9df6b +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +646 + +AppleStoreCountryCodeBox.java +file + + + + +2012-09-14T17:27:52.037241Z +0e1bb94c09e72b3d9973d376c42c5455 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1772 + +AppleGenericBox.java +file + + + + +2012-09-14T17:27:52.037241Z +290bdaf97d2b67e2f04fec1b5bf251fe +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +279 + +AppleNameBox.java +file + + + + +2012-09-14T17:27:52.037241Z +8e435cf54ce66721515e4cc955be94d5 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1075 + +AppleShowBox.java +file + + + + +2012-09-14T17:27:52.037241Z +47cc10c763e97419f7e57eeaaf469abe +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +284 + +AppleStandardGenreBox.java +file + + + + +2012-09-14T17:27:52.037241Z +849a14b354905fbb51d173ceeb520730 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +301 + +AppleRatingBox.java +file + + + + +2012-09-14T17:27:52.037241Z +fc93688c8546a210349c4b42e916abec +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +308 + +AppleSynopsisBox.java +file + + + + +2012-09-14T17:27:52.037241Z +a0c3dab5469f58afffbb7a26440b4cd3 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +293 + +AppleNetworkBox.java +file + + + + +2012-09-14T17:27:52.037241Z +9af00d5cc53625f084891cd0985219cb +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +291 + +AppleRecordingYearBox.java +file + + + + +2012-09-14T17:27:52.037241Z +14e939016b9c0c909240a680b92d4300 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +302 + +AppleReferenceMovieBox.java +file + + + + +2012-09-14T17:27:52.037241Z +1c577082bb05a1d59ae899bcef5bbce1 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +907 + +AppleTvEpisodeBox.java +file + + + + +2012-09-14T17:27:52.037241Z +a433a5413c9363a190f588ff6af717b2 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +314 + +AppleWaveBox.java +file + + + + +2012-09-14T17:27:52.037241Z +07d6df3c463714a51bd6957fec7b15f5 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +275 + +AbstractAppleMetaDataBox.java +file + + + + +2012-09-14T17:27:52.037241Z +3beb0cfc7e1f245f23ac59adecf6c90b +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +5703 + +AppleGaplessPlaybackBox.java +file + + + + +2012-09-14T17:27:52.037241Z +610b85d8fe94c499ba679e47d7af59aa +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +339 + +AppleTempBox.java +file + + + + +2012-09-14T17:27:52.037241Z +ab1b52b242ac326460a50dafcb4d586b +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +682 + +AppleArtistBox.java +file + + + + +2012-09-14T17:27:52.037241Z +50d2d51ac35d53fa91d596d9fba893c1 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +330 + +AppleDataBox.java +file + + + + +2012-09-14T17:27:52.037241Z +064c87d2b50c91ebaa552f3b53844de2 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2475 + +AppleTrackNumberBox.java +file + + + + +2012-09-14T17:27:52.047241Z +3cf21c036183461f0a26d7812cd54a11 +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1177 + +AppleLosslessSpecificBox.java +file + + + + +2012-09-14T17:27:52.047241Z +3659a7955b976252491eaff784518492 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4638 + +AppleCompilationBox.java +file + + + + +2012-09-14T17:27:52.047241Z +e6bcc185918d8b2d3c449bd1218536c9 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +324 + +AppleCoverBox.java +file + + + + +2012-09-14T17:27:52.047241Z +9d9ec44a18fdc7b3490073454ae6bf8e +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1005 + +AppleEncoderBox.java +file + + + + +2012-09-14T17:27:52.047241Z +aa3191200ee624f2fde12d6d29da22c3 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +324 + +AppleMeanBox.java +file + + + + +2012-09-14T17:27:52.047241Z +d64b8d0e17b59ff76c984d831a36cc85 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1151 + +AppleMediaTypeBox.java +file + + + + +2012-09-14T17:27:52.047241Z +ca121472ac950656cb0158cecb259db9 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1038 + +AppleDescriptionBox.java +file + + + + +2012-09-14T17:27:52.047241Z +21ee5c043816a5117165b95234eadc13 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +298 + +AppleDataRateBox.java +file + + + + +2012-09-14T17:27:52.047241Z +88e0145f42678bb7a380e50bd8ab3157 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1514 + +AppleTrackAuthorBox.java +file + + + + +2012-09-14T17:27:52.047241Z +5a6f88b1189b0d1cd56f336ee6400d80 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +304 + +AppleAlbumArtistBox.java +file + + + + +2012-09-14T17:27:52.047241Z +2595bb2e066cee575a8cd963e6ce648a +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +322 + +AppleDataReferenceBox.java +file + + + + +2012-09-14T17:27:52.047241Z +c47ce167549e9d5b400ed21b64450a4e +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2226 + +AppleItemListBox.java +file + + + + +2012-09-14T17:27:52.047241Z +2e430a7e3bc2d56e975340e9899a05ae +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +310 + +AppleGroupingBox.java +file + + + + +2012-09-14T17:27:52.047241Z +a12a7d1cc3c693cfd8ec5c20df44aa1c +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +326 + +AppleCustomGenreBox.java +file + + + + +2012-09-14T17:27:52.047241Z +2e06c42c89625ea9943c5bca05040844 +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +685 + +AppleIdBox.java +file + + + + +2012-09-14T17:27:52.047241Z +18aecf8082534727517207e0f00df3ba +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +280 + +AppleReferenceMovieDescriptorBox.java +file + + + + +2012-09-14T17:27:52.047241Z +f621253270c3f55828bd412050238d07 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +925 + +AppleAlbumBox.java +file + + + + +2012-09-14T17:27:52.047241Z +4a59cf2bbab9bc17ef1a28da752902e9 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +291 + +AppleCommentBox.java +file + + + + +2012-09-14T17:27:52.047241Z +e0d8d51f0b5f000fcea8ee721c2bf382 +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com +has-props + + + + + + + + + + + + + + + + + + + + +326 + +AppleTvSeasonBox.java +file + + + + +2012-09-14T17:27:52.047241Z +c991f4f5c2998dc6d20404138653705b +2011-08-11T14:33:30.631951Z +198 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +317 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleAlbumArtistBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleAlbumArtistBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleAlbumArtistBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCommentBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCommentBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCommentBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCopyrightBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCopyrightBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleCopyrightBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleEncoderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleEncoderBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleEncoderBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleGroupingBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleGroupingBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleGroupingBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleStoreAccountTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleStoreAccountTypeBox.java.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/prop-base/AppleStoreAccountTypeBox.java.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AbstractAppleMetaDataBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AbstractAppleMetaDataBox.java.svn-base new file mode 100644 index 0000000..fdb7ac9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AbstractAppleMetaDataBox.java.svn-base @@ -0,0 +1,164 @@ +package com.coremedia.iso.boxes.apple; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +/** + * + */ +public abstract class AbstractAppleMetaDataBox extends AbstractBox implements ContainerBox { + private static Logger LOG = Logger.getLogger(AbstractAppleMetaDataBox.class.getName()); + AppleDataBox appleDataBox = new AppleDataBox(); + + public List<Box> getBoxes() { + return Collections.singletonList((Box) appleDataBox); + } + + public void setBoxes(List<Box> boxes) { + if (boxes.size() == 1 && boxes.get(0) instanceof AppleDataBox) { + appleDataBox = (AppleDataBox) boxes.get(0); + } else { + throw new IllegalArgumentException("This box only accepts one AppleDataBox child"); + } + } + + public <T extends Box> List<T> getBoxes(Class<T> clazz) { + return getBoxes(clazz, false); + } + + public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) { + //todo recursive? + if (clazz.isAssignableFrom(appleDataBox.getClass())) { + return (List<T>) Collections.singletonList(appleDataBox); + } + return null; + } + + public AbstractAppleMetaDataBox(String type) { + super(type); + } + + @Override + public void _parseDetails(ByteBuffer content) { + long dataBoxSize = IsoTypeReader.readUInt32(content); + String thisShouldBeData = IsoTypeReader.read4cc(content); + assert "data".equals(thisShouldBeData); + appleDataBox = new AppleDataBox(); + try { + appleDataBox.parse(new ByteBufferByteChannel(content), null, content.remaining(), null); + } catch (IOException e) { + throw new RuntimeException(e); + } + appleDataBox.setParent(this); + } + + + protected long getContentSize() { + return appleDataBox.getSize(); + } + + protected void getContent(ByteBuffer byteBuffer) { + try { + appleDataBox.getBox(new ByteBufferByteChannel(byteBuffer)); + } catch (IOException e) { + throw new RuntimeException("The Channel is based on a ByteBuffer and therefore it shouldn't throw any exception"); + } + } + + public long getNumOfBytesToFirstChild() { + return getSize() - appleDataBox.getSize(); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "appleDataBox=" + getValue() + + '}'; + } + + static long toLong(byte b) { + return b < 0 ? b + 256 : b; + } + + public void setValue(String value) { + if (appleDataBox.getFlags() == 1) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(1); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(Utf8.convert(value)); + } else if (appleDataBox.getFlags() == 21) { + byte[] content = appleDataBox.getData(); + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(21); + appleDataBox.setFourBytes(new byte[4]); + + ByteBuffer bb = ByteBuffer.allocate(content.length); + if (content.length == 1) { + IsoTypeWriter.writeUInt8(bb, (Byte.parseByte(value) & 0xFF)); + } else if (content.length == 2) { + IsoTypeWriter.writeUInt16(bb, Integer.parseInt(value)); + } else if (content.length == 4) { + IsoTypeWriter.writeUInt32(bb, Long.parseLong(value)); + } else if (content.length == 8) { + IsoTypeWriter.writeUInt64(bb, Long.parseLong(value)); + } else { + throw new Error("The content length within the appleDataBox is neither 1, 2, 4 or 8. I can't handle that!"); + } + appleDataBox.setData(bb.array()); + } else if (appleDataBox.getFlags() == 0) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(hexStringToByteArray(value)); + + } else { + LOG.warning("Don't know how to handle appleDataBox with flag=" + appleDataBox.getFlags()); + } + } + + public String getValue() { + if (appleDataBox.getFlags() == 1) { + return Utf8.convert(appleDataBox.getData()); + } else if (appleDataBox.getFlags() == 21) { + byte[] content = appleDataBox.getData(); + long l = 0; + int current = 1; + int length = content.length; + for (byte b : content) { + l += toLong(b) << (8 * (length - current++)); + } + return "" + l; + } else if (appleDataBox.getFlags() == 0) { + return String.format("%x", new BigInteger(appleDataBox.getData())); + } else { + return "unknown"; + } + } + + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumArtistBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumArtistBox.java.svn-base new file mode 100644 index 0000000..5c258b4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumArtistBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public class AppleAlbumArtistBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "aART"; + + + public AppleAlbumArtistBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumBox.java.svn-base new file mode 100644 index 0000000..9e3d5f7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleAlbumBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleAlbumBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9alb"; + + + public AppleAlbumBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleArtistBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleArtistBox.java.svn-base new file mode 100644 index 0000000..627a603 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleArtistBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * iTunes Artist box.
+ */
+public final class AppleArtistBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "\u00a9ART";
+
+
+ public AppleArtistBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getStringAppleDataBox();
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCommentBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCommentBox.java.svn-base new file mode 100644 index 0000000..b58899f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCommentBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleCommentBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9cmt"; + + + public AppleCommentBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCompilationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCompilationBox.java.svn-base new file mode 100644 index 0000000..c8c9bf4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCompilationBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Compilation.
+ */
+public final class AppleCompilationBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "cpil";
+
+
+ public AppleCompilationBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint8AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCopyrightBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCopyrightBox.java.svn-base new file mode 100644 index 0000000..ae44285 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCopyrightBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleCopyrightBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "cprt"; + + + public AppleCopyrightBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCoverBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCoverBox.java.svn-base new file mode 100644 index 0000000..946dd49 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCoverBox.java.svn-base @@ -0,0 +1,44 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.logging.Logger; + +/** + * + */ +public final class AppleCoverBox extends AbstractAppleMetaDataBox { + private static Logger LOG = Logger.getLogger(AppleCoverBox.class.getName()); + public static final String TYPE = "covr"; + + + public AppleCoverBox() { + super(TYPE); + } + + + public void setPng(byte[] pngData) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0xe); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(pngData); + } + + + public void setJpg(byte[] jpgData) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0xd); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(jpgData); + } + + @Override + public void setValue(String value) { + LOG.warning("---"); + } + + @Override + public String getValue() { + return "---"; + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCustomGenreBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCustomGenreBox.java.svn-base new file mode 100644 index 0000000..0c67f97 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleCustomGenreBox.java.svn-base @@ -0,0 +1,28 @@ +package com.coremedia.iso.boxes.apple; + +import com.coremedia.iso.Utf8; + +/** + * + */ +public final class AppleCustomGenreBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9gen"; + + + public AppleCustomGenreBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + public void setGenre(String genre) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(1); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(Utf8.convert(genre)); + } + + public String getGenre() { + return Utf8.convert(appleDataBox.getData()); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataBox.java.svn-base new file mode 100644 index 0000000..ba42629 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataBox.java.svn-base @@ -0,0 +1,92 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Most stupid box of the world. Encapsulates actual data within + */ +public final class AppleDataBox extends AbstractFullBox { + public static final String TYPE = "data"; + + private byte[] fourBytes = new byte[4]; + private byte[] data; + + private static AppleDataBox getEmpty() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFourBytes(new byte[4]); + return appleDataBox; + } + + public static AppleDataBox getStringAppleDataBox() { + AppleDataBox appleDataBox = getEmpty(); + appleDataBox.setFlags(1); + appleDataBox.setData(new byte[]{0}); + return appleDataBox; + } + + public static AppleDataBox getUint8AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0}); + return appleDataBox; + } + + public static AppleDataBox getUint16AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0, 0}); + return appleDataBox; + } + + public static AppleDataBox getUint32AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0, 0, 0, 0}); + return appleDataBox; + } + + public AppleDataBox() { + super(TYPE); + } + + protected long getContentSize() { + return data.length + 8; + } + + public void setData(byte[] data) { + this.data = new byte[data.length]; + System.arraycopy(data, 0, this.data, 0, data.length); + } + + public void setFourBytes(byte[] fourBytes) { + System.arraycopy(fourBytes, 0, this.fourBytes, 0, 4); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + fourBytes = new byte[4]; + content.get(fourBytes); + data = new byte[content.remaining()]; + content.get(data); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(fourBytes, 0, 4); + byteBuffer.put(data); + } + + public byte[] getFourBytes() { + return fourBytes; + } + + public byte[] getData() { + return data; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataRateBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataRateBox.java.svn-base new file mode 100644 index 0000000..e58e550 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataRateBox.java.svn-base @@ -0,0 +1,53 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+public class AppleDataRateBox extends AbstractFullBox {
+ public static final String TYPE = "rmdr";
+ private long dataRate;
+
+ public AppleDataRateBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 8;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ dataRate = IsoTypeReader.readUInt32(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, dataRate);
+ }
+
+
+ public long getDataRate() {
+ return dataRate;
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataReferenceBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataReferenceBox.java.svn-base new file mode 100644 index 0000000..7370c10 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDataReferenceBox.java.svn-base @@ -0,0 +1,71 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+public class AppleDataReferenceBox extends AbstractFullBox {
+ public static final String TYPE = "rdrf";
+ private int dataReferenceSize;
+ private String dataReferenceType;
+ private String dataReference;
+
+ public AppleDataReferenceBox() {
+ super(TYPE);
+ }
+
+
+ protected long getContentSize() {
+ return 12 + dataReferenceSize;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ dataReferenceType = IsoTypeReader.read4cc(content);
+ dataReferenceSize = l2i(IsoTypeReader.readUInt32(content));
+ dataReference = IsoTypeReader.readString(content, dataReferenceSize);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(IsoFile.fourCCtoBytes(dataReferenceType));
+ IsoTypeWriter.writeUInt32(byteBuffer, dataReferenceSize);
+ byteBuffer.put(Utf8.convert(dataReference));
+ }
+
+ public long getDataReferenceSize() {
+ return dataReferenceSize;
+ }
+
+ public String getDataReferenceType() {
+ return dataReferenceType;
+ }
+
+ public String getDataReference() {
+ return dataReference;
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDescriptionBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDescriptionBox.java.svn-base new file mode 100644 index 0000000..e20e0fc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleDescriptionBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleDescriptionBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "desc"; + + + public AppleDescriptionBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleEncoderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleEncoderBox.java.svn-base new file mode 100644 index 0000000..5a59e81 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleEncoderBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleEncoderBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9too"; + + + public AppleEncoderBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGaplessPlaybackBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGaplessPlaybackBox.java.svn-base new file mode 100644 index 0000000..c617a54 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGaplessPlaybackBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Gapless Playback.
+ */
+public final class AppleGaplessPlaybackBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "pgap";
+
+
+ public AppleGaplessPlaybackBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint8AppleDataBox();
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGenericBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGenericBox.java.svn-base new file mode 100644 index 0000000..177a25b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGenericBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * + */ +public final class AppleGenericBox extends AbstractContainerBox { + public static final String TYPE = "----"; + + public AppleGenericBox() { + super(TYPE); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGroupingBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGroupingBox.java.svn-base new file mode 100644 index 0000000..9884298 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleGroupingBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleGroupingBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9grp"; + + + public AppleGroupingBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleIdBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleIdBox.java.svn-base new file mode 100644 index 0000000..08c697e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleIdBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleIdBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "apID"; + + + public AppleIdBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleItemListBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleItemListBox.java.svn-base new file mode 100644 index 0000000..cd26e81 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleItemListBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * undocumented iTunes MetaData Box. + */ +public class AppleItemListBox extends AbstractContainerBox { + public static final String TYPE = "ilst"; + + public AppleItemListBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleLosslessSpecificBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleLosslessSpecificBox.java.svn-base new file mode 100644 index 0000000..781af49 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleLosslessSpecificBox.java.svn-base @@ -0,0 +1,163 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public final class AppleLosslessSpecificBox extends AbstractFullBox {
+
+ public static final String TYPE = "alac";
+ /*
+ Extradata: 32bit size 32bit tag (=alac) 32bit zero?
+ 32bit max sample per frame 8bit ?? (zero?) 8bit sample
+ size 8bit history mult 8bit initial history 8bit kmodifier
+ 8bit channels? 16bit ?? 32bit max coded frame size 32bit
+ bitrate? 32bit samplerate
+ */
+ private long maxSamplePerFrame; // 32bi
+ private int unknown1; // 8bit
+ private int sampleSize; // 8bit
+ private int historyMult; // 8bit
+ private int initialHistory; // 8bit
+ private int kModifier; // 8bit
+ private int channels; // 8bit
+ private int unknown2; // 16bit
+ private long maxCodedFrameSize; // 32bit
+ private long bitRate; // 32bit
+ private long sampleRate; // 32bit
+
+ public long getMaxSamplePerFrame() {
+ return maxSamplePerFrame;
+ }
+
+ public void setMaxSamplePerFrame(int maxSamplePerFrame) {
+ this.maxSamplePerFrame = maxSamplePerFrame;
+ }
+
+ public int getUnknown1() {
+ return unknown1;
+ }
+
+ public void setUnknown1(int unknown1) {
+ this.unknown1 = unknown1;
+ }
+
+ public int getSampleSize() {
+ return sampleSize;
+ }
+
+ public void setSampleSize(int sampleSize) {
+ this.sampleSize = sampleSize;
+ }
+
+ public int getHistoryMult() {
+ return historyMult;
+ }
+
+ public void setHistoryMult(int historyMult) {
+ this.historyMult = historyMult;
+ }
+
+ public int getInitialHistory() {
+ return initialHistory;
+ }
+
+ public void setInitialHistory(int initialHistory) {
+ this.initialHistory = initialHistory;
+ }
+
+ public int getKModifier() {
+ return kModifier;
+ }
+
+ public void setKModifier(int kModifier) {
+ this.kModifier = kModifier;
+ }
+
+ public int getChannels() {
+ return channels;
+ }
+
+ public void setChannels(int channels) {
+ this.channels = channels;
+ }
+
+ public int getUnknown2() {
+ return unknown2;
+ }
+
+ public void setUnknown2(int unknown2) {
+ this.unknown2 = unknown2;
+ }
+
+ public long getMaxCodedFrameSize() {
+ return maxCodedFrameSize;
+ }
+
+ public void setMaxCodedFrameSize(int maxCodedFrameSize) {
+ this.maxCodedFrameSize = maxCodedFrameSize;
+ }
+
+ public long getBitRate() {
+ return bitRate;
+ }
+
+ public void setBitRate(int bitRate) {
+ this.bitRate = bitRate;
+ }
+
+ public long getSampleRate() {
+ return sampleRate;
+ }
+
+ public void setSampleRate(int sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ maxSamplePerFrame = IsoTypeReader.readUInt32(content);
+ unknown1 = IsoTypeReader.readUInt8(content);
+ sampleSize = IsoTypeReader.readUInt8(content);
+ historyMult = IsoTypeReader.readUInt8(content);
+ initialHistory = IsoTypeReader.readUInt8(content);
+ kModifier = IsoTypeReader.readUInt8(content);
+ channels = IsoTypeReader.readUInt8(content);
+ unknown2 = IsoTypeReader.readUInt16(content);
+ maxCodedFrameSize = IsoTypeReader.readUInt32(content);
+ bitRate = IsoTypeReader.readUInt32(content);
+ sampleRate = IsoTypeReader.readUInt32(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxSamplePerFrame);
+ IsoTypeWriter.writeUInt8(byteBuffer, unknown1);
+ IsoTypeWriter.writeUInt8(byteBuffer, sampleSize);
+ IsoTypeWriter.writeUInt8(byteBuffer, historyMult);
+ IsoTypeWriter.writeUInt8(byteBuffer, initialHistory);
+ IsoTypeWriter.writeUInt8(byteBuffer, kModifier);
+ IsoTypeWriter.writeUInt8(byteBuffer, channels);
+ IsoTypeWriter.writeUInt16(byteBuffer, unknown2);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxCodedFrameSize);
+ IsoTypeWriter.writeUInt32(byteBuffer, bitRate);
+ IsoTypeWriter.writeUInt32(byteBuffer, sampleRate);
+ }
+
+ public AppleLosslessSpecificBox() {
+ super("alac");
+ }
+
+ protected long getContentSize() {
+ return 28;
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMeanBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMeanBox.java.svn-base new file mode 100644 index 0000000..3a26f96 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMeanBox.java.svn-base @@ -0,0 +1,47 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Apple Meaning box. Allowed as subbox of "----" box.
+ *
+ * @see com.coremedia.iso.boxes.apple.AppleGenericBox
+ */
+public final class AppleMeanBox extends AbstractFullBox {
+ public static final String TYPE = "mean";
+ private String meaning;
+
+ public AppleMeanBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 4 + Utf8.utf8StringLengthInBytes(meaning);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ meaning = IsoTypeReader.readString(content, content.remaining());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(meaning));
+ }
+
+ public String getMeaning() {
+ return meaning;
+ }
+
+ public void setMeaning(String meaning) {
+ this.meaning = meaning;
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMediaTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMediaTypeBox.java.svn-base new file mode 100644 index 0000000..f4ca98d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleMediaTypeBox.java.svn-base @@ -0,0 +1,39 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.HashMap; +import java.util.Map; + +/** + * itunes MetaData comment box. + */ +public class AppleMediaTypeBox extends AbstractAppleMetaDataBox { + private static Map<String, String> mediaTypes = new HashMap<String, String>(); + + static { + mediaTypes.put("0", "Movie (is now 9)"); + mediaTypes.put("1", "Normal (Music)"); + mediaTypes.put("2", "Audiobook"); + mediaTypes.put("6", "Music Video"); + mediaTypes.put("9", "Movie"); + mediaTypes.put("10", "TV Show"); + mediaTypes.put("11", "Booklet"); + mediaTypes.put("14", "Ringtone"); + } + + public static final String TYPE = "stik"; + + + public AppleMediaTypeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + public String getReadableValue() { + if (mediaTypes.containsKey(getValue())) { + return mediaTypes.get(getValue()); + } else { + return "unknown media type " + getValue(); + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNameBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNameBox.java.svn-base new file mode 100644 index 0000000..5cad249 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNameBox.java.svn-base @@ -0,0 +1,45 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Apple Name box. Allowed as subbox of "----" box.
+ *
+ * @see AppleGenericBox
+ */
+public final class AppleNameBox extends AbstractFullBox {
+ public static final String TYPE = "name";
+ private String name;
+
+ public AppleNameBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 4 + Utf8.convert(name).length;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ name = IsoTypeReader.readString(content, content.remaining());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(name));
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNetworkBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNetworkBox.java.svn-base new file mode 100644 index 0000000..07691b3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleNetworkBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleNetworkBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "tvnn"; + + + public AppleNetworkBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/ApplePurchaseDateBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/ApplePurchaseDateBox.java.svn-base new file mode 100644 index 0000000..eb9807f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/ApplePurchaseDateBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class ApplePurchaseDateBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "purd"; + + + public ApplePurchaseDateBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRatingBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRatingBox.java.svn-base new file mode 100644 index 0000000..71671fc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRatingBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * iTunes Rating Box. + */ +public final class AppleRatingBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "rtng"; + + + public AppleRatingBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRecordingYearBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRecordingYearBox.java.svn-base new file mode 100644 index 0000000..da13300 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleRecordingYearBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public class AppleRecordingYearBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9day"; + + + public AppleRecordingYearBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieBox.java.svn-base new file mode 100644 index 0000000..49c539f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieBox.java.svn-base @@ -0,0 +1,28 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class AppleReferenceMovieBox extends AbstractContainerBox {
+ public static final String TYPE = "rmra";
+
+ public AppleReferenceMovieBox() {
+ super(TYPE);
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieDescriptorBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieDescriptorBox.java.svn-base new file mode 100644 index 0000000..488f01b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleReferenceMovieDescriptorBox.java.svn-base @@ -0,0 +1,27 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class AppleReferenceMovieDescriptorBox extends AbstractContainerBox {
+ public static final String TYPE = "rmda";
+
+ public AppleReferenceMovieDescriptorBox() {
+ super(TYPE);
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleShowBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleShowBox.java.svn-base new file mode 100644 index 0000000..66b0d59 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleShowBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleShowBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "tvsh"; + + + public AppleShowBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSortAlbumBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSortAlbumBox.java.svn-base new file mode 100644 index 0000000..cf74004 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSortAlbumBox.java.svn-base @@ -0,0 +1,14 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleSortAlbumBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "soal"; + + + public AppleSortAlbumBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStandardGenreBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStandardGenreBox.java.svn-base new file mode 100644 index 0000000..21932fa --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStandardGenreBox.java.svn-base @@ -0,0 +1,14 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleStandardGenreBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "gnre"; + + + public AppleStandardGenreBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint16AppleDataBox(); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreAccountTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreAccountTypeBox.java.svn-base new file mode 100644 index 0000000..36ecf4e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreAccountTypeBox.java.svn-base @@ -0,0 +1,27 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public class AppleStoreAccountTypeBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "akID"; + + + public AppleStoreAccountTypeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + public String getReadableValue() { + byte value = this.appleDataBox.getData()[0]; + switch (value) { + case 0: + return "iTunes Account"; + case 1: + return "AOL Account"; + default: + return "unknown Account"; + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreCountryCodeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreCountryCodeBox.java.svn-base new file mode 100644 index 0000000..2c4756a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleStoreCountryCodeBox.java.svn-base @@ -0,0 +1,54 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.HashMap; +import java.util.Map; + +/** + * itunes MetaData comment box. + */ +public class AppleStoreCountryCodeBox extends AbstractAppleMetaDataBox { + private static Map<String, String> countryCodes = new HashMap<String, String>(); + + static { + countryCodes.put("143460", "Australia"); + countryCodes.put("143445", "Austria"); + countryCodes.put("143446", "Belgium"); + countryCodes.put("143455", "Canada"); + countryCodes.put("143458", "Denmark"); + countryCodes.put("143447", "Finland"); + countryCodes.put("143442", "France"); + countryCodes.put("143443", "Germany"); + countryCodes.put("143448", "Greece"); + countryCodes.put("143449", "Ireland"); + countryCodes.put("143450", "Italy"); + countryCodes.put("143462", "Japan"); + countryCodes.put("143451", "Luxembourg"); + countryCodes.put("143452", "Netherlands"); + countryCodes.put("143461", "New Zealand"); + countryCodes.put("143457", "Norway"); + countryCodes.put("143453", "Portugal"); + countryCodes.put("143454", "Spain"); + countryCodes.put("143456", "Sweden"); + countryCodes.put("143459", "Switzerland"); + countryCodes.put("143444", "United Kingdom"); + countryCodes.put("143441", "United States"); + } + + public static final String TYPE = "sfID"; + + + public AppleStoreCountryCodeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint32AppleDataBox(); + } + + + public String getReadableValue() { + if (countryCodes.containsKey(getValue())) { + return countryCodes.get(getValue()); + } else { + return "unknown country code " + getValue(); + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSynopsisBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSynopsisBox.java.svn-base new file mode 100644 index 0000000..cd5c2ab --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleSynopsisBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleSynopsisBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "ldes"; + + + public AppleSynopsisBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTempBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTempBox.java.svn-base new file mode 100644 index 0000000..ef57228 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTempBox.java.svn-base @@ -0,0 +1,28 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Beats per minute.
+ */
+public final class AppleTempBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tmpo";
+
+
+ public AppleTempBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint16AppleDataBox();
+ }
+
+
+ public int getTempo() {
+ return appleDataBox.getData()[1];
+ }
+
+ public void setTempo(int tempo) {
+ appleDataBox = new AppleDataBox();
+ appleDataBox.setVersion(0);
+ appleDataBox.setFlags(21);
+ appleDataBox.setFourBytes(new byte[4]);
+ appleDataBox.setData(new byte[]{0, (byte) (tempo & 0xFF)});
+
+ }
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackAuthorBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackAuthorBox.java.svn-base new file mode 100644 index 0000000..c5b3732 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackAuthorBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackAuthorBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9wrt"; + + + public AppleTrackAuthorBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackNumberBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackNumberBox.java.svn-base new file mode 100644 index 0000000..c073c2f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackNumberBox.java.svn-base @@ -0,0 +1,48 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackNumberBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "trkn"; + + + public AppleTrackNumberBox() { + super(TYPE); + } + + + /** + * @param track the actual track number + * @param of number of tracks overall + */ + public void setTrackNumber(byte track, byte of) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(new byte[]{0, 0, 0, track, 0, of, 0, 0}); + } + + public byte getTrackNumber() { + return appleDataBox.getData()[3]; + } + + public byte getNumberOfTracks() { + return appleDataBox.getData()[5]; + } + + public void setNumberOfTracks(byte numberOfTracks) { + byte[] content = appleDataBox.getData(); + content[5] = numberOfTracks; + appleDataBox.setData(content); + } + + public void setTrackNumber(byte trackNumber) { + byte[] content = appleDataBox.getData(); + content[3] = trackNumber; + appleDataBox.setData(content); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackTitleBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackTitleBox.java.svn-base new file mode 100644 index 0000000..3dd613c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTrackTitleBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackTitleBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9nam"; + + + public AppleTrackTitleBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeBox.java.svn-base new file mode 100644 index 0000000..3b3817b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Episode.
+ */
+public class AppleTvEpisodeBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tves";
+
+
+ public AppleTvEpisodeBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint32AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeNumberBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeNumberBox.java.svn-base new file mode 100644 index 0000000..33cd4e3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvEpisodeNumberBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Episode.
+ */
+public class AppleTvEpisodeNumberBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tven";
+
+
+ public AppleTvEpisodeNumberBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getStringAppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvSeasonBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvSeasonBox.java.svn-base new file mode 100644 index 0000000..9459ea3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleTvSeasonBox.java.svn-base @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Season.
+ */
+public final class AppleTvSeasonBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tvsn";
+
+
+ public AppleTvSeasonBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint32AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleWaveBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleWaveBox.java.svn-base new file mode 100644 index 0000000..65edd38 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/text-base/AppleWaveBox.java.svn-base @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * + */ +public final class AppleWaveBox extends AbstractContainerBox { + public static final String TYPE = "wave"; + + public AppleWaveBox() { + super(TYPE); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AbstractAppleMetaDataBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AbstractAppleMetaDataBox.java new file mode 100644 index 0000000..fdb7ac9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AbstractAppleMetaDataBox.java @@ -0,0 +1,164 @@ +package com.coremedia.iso.boxes.apple; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +/** + * + */ +public abstract class AbstractAppleMetaDataBox extends AbstractBox implements ContainerBox { + private static Logger LOG = Logger.getLogger(AbstractAppleMetaDataBox.class.getName()); + AppleDataBox appleDataBox = new AppleDataBox(); + + public List<Box> getBoxes() { + return Collections.singletonList((Box) appleDataBox); + } + + public void setBoxes(List<Box> boxes) { + if (boxes.size() == 1 && boxes.get(0) instanceof AppleDataBox) { + appleDataBox = (AppleDataBox) boxes.get(0); + } else { + throw new IllegalArgumentException("This box only accepts one AppleDataBox child"); + } + } + + public <T extends Box> List<T> getBoxes(Class<T> clazz) { + return getBoxes(clazz, false); + } + + public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) { + //todo recursive? + if (clazz.isAssignableFrom(appleDataBox.getClass())) { + return (List<T>) Collections.singletonList(appleDataBox); + } + return null; + } + + public AbstractAppleMetaDataBox(String type) { + super(type); + } + + @Override + public void _parseDetails(ByteBuffer content) { + long dataBoxSize = IsoTypeReader.readUInt32(content); + String thisShouldBeData = IsoTypeReader.read4cc(content); + assert "data".equals(thisShouldBeData); + appleDataBox = new AppleDataBox(); + try { + appleDataBox.parse(new ByteBufferByteChannel(content), null, content.remaining(), null); + } catch (IOException e) { + throw new RuntimeException(e); + } + appleDataBox.setParent(this); + } + + + protected long getContentSize() { + return appleDataBox.getSize(); + } + + protected void getContent(ByteBuffer byteBuffer) { + try { + appleDataBox.getBox(new ByteBufferByteChannel(byteBuffer)); + } catch (IOException e) { + throw new RuntimeException("The Channel is based on a ByteBuffer and therefore it shouldn't throw any exception"); + } + } + + public long getNumOfBytesToFirstChild() { + return getSize() - appleDataBox.getSize(); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "appleDataBox=" + getValue() + + '}'; + } + + static long toLong(byte b) { + return b < 0 ? b + 256 : b; + } + + public void setValue(String value) { + if (appleDataBox.getFlags() == 1) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(1); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(Utf8.convert(value)); + } else if (appleDataBox.getFlags() == 21) { + byte[] content = appleDataBox.getData(); + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(21); + appleDataBox.setFourBytes(new byte[4]); + + ByteBuffer bb = ByteBuffer.allocate(content.length); + if (content.length == 1) { + IsoTypeWriter.writeUInt8(bb, (Byte.parseByte(value) & 0xFF)); + } else if (content.length == 2) { + IsoTypeWriter.writeUInt16(bb, Integer.parseInt(value)); + } else if (content.length == 4) { + IsoTypeWriter.writeUInt32(bb, Long.parseLong(value)); + } else if (content.length == 8) { + IsoTypeWriter.writeUInt64(bb, Long.parseLong(value)); + } else { + throw new Error("The content length within the appleDataBox is neither 1, 2, 4 or 8. I can't handle that!"); + } + appleDataBox.setData(bb.array()); + } else if (appleDataBox.getFlags() == 0) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(hexStringToByteArray(value)); + + } else { + LOG.warning("Don't know how to handle appleDataBox with flag=" + appleDataBox.getFlags()); + } + } + + public String getValue() { + if (appleDataBox.getFlags() == 1) { + return Utf8.convert(appleDataBox.getData()); + } else if (appleDataBox.getFlags() == 21) { + byte[] content = appleDataBox.getData(); + long l = 0; + int current = 1; + int length = content.length; + for (byte b : content) { + l += toLong(b) << (8 * (length - current++)); + } + return "" + l; + } else if (appleDataBox.getFlags() == 0) { + return String.format("%x", new BigInteger(appleDataBox.getData())); + } else { + return "unknown"; + } + } + + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumArtistBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumArtistBox.java new file mode 100755 index 0000000..5c258b4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumArtistBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public class AppleAlbumArtistBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "aART"; + + + public AppleAlbumArtistBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumBox.java new file mode 100644 index 0000000..9e3d5f7 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleAlbumBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleAlbumBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9alb"; + + + public AppleAlbumBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleArtistBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleArtistBox.java new file mode 100644 index 0000000..627a603 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleArtistBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * iTunes Artist box.
+ */
+public final class AppleArtistBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "\u00a9ART";
+
+
+ public AppleArtistBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getStringAppleDataBox();
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCommentBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCommentBox.java new file mode 100755 index 0000000..b58899f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCommentBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleCommentBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9cmt"; + + + public AppleCommentBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCompilationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCompilationBox.java new file mode 100644 index 0000000..c8c9bf4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCompilationBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Compilation.
+ */
+public final class AppleCompilationBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "cpil";
+
+
+ public AppleCompilationBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint8AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCopyrightBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCopyrightBox.java new file mode 100755 index 0000000..ae44285 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCopyrightBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleCopyrightBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "cprt"; + + + public AppleCopyrightBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCoverBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCoverBox.java new file mode 100644 index 0000000..946dd49 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCoverBox.java @@ -0,0 +1,44 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.logging.Logger; + +/** + * + */ +public final class AppleCoverBox extends AbstractAppleMetaDataBox { + private static Logger LOG = Logger.getLogger(AppleCoverBox.class.getName()); + public static final String TYPE = "covr"; + + + public AppleCoverBox() { + super(TYPE); + } + + + public void setPng(byte[] pngData) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0xe); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(pngData); + } + + + public void setJpg(byte[] jpgData) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0xd); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(jpgData); + } + + @Override + public void setValue(String value) { + LOG.warning("---"); + } + + @Override + public String getValue() { + return "---"; + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCustomGenreBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCustomGenreBox.java new file mode 100644 index 0000000..0c67f97 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleCustomGenreBox.java @@ -0,0 +1,28 @@ +package com.coremedia.iso.boxes.apple; + +import com.coremedia.iso.Utf8; + +/** + * + */ +public final class AppleCustomGenreBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9gen"; + + + public AppleCustomGenreBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + public void setGenre(String genre) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(1); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(Utf8.convert(genre)); + } + + public String getGenre() { + return Utf8.convert(appleDataBox.getData()); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataBox.java new file mode 100644 index 0000000..ba42629 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataBox.java @@ -0,0 +1,92 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Most stupid box of the world. Encapsulates actual data within + */ +public final class AppleDataBox extends AbstractFullBox { + public static final String TYPE = "data"; + + private byte[] fourBytes = new byte[4]; + private byte[] data; + + private static AppleDataBox getEmpty() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFourBytes(new byte[4]); + return appleDataBox; + } + + public static AppleDataBox getStringAppleDataBox() { + AppleDataBox appleDataBox = getEmpty(); + appleDataBox.setFlags(1); + appleDataBox.setData(new byte[]{0}); + return appleDataBox; + } + + public static AppleDataBox getUint8AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0}); + return appleDataBox; + } + + public static AppleDataBox getUint16AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0, 0}); + return appleDataBox; + } + + public static AppleDataBox getUint32AppleDataBox() { + AppleDataBox appleDataBox = new AppleDataBox(); + appleDataBox.setFlags(21); + appleDataBox.setData(new byte[]{0, 0, 0, 0}); + return appleDataBox; + } + + public AppleDataBox() { + super(TYPE); + } + + protected long getContentSize() { + return data.length + 8; + } + + public void setData(byte[] data) { + this.data = new byte[data.length]; + System.arraycopy(data, 0, this.data, 0, data.length); + } + + public void setFourBytes(byte[] fourBytes) { + System.arraycopy(fourBytes, 0, this.fourBytes, 0, 4); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + fourBytes = new byte[4]; + content.get(fourBytes); + data = new byte[content.remaining()]; + content.get(data); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(fourBytes, 0, 4); + byteBuffer.put(data); + } + + public byte[] getFourBytes() { + return fourBytes; + } + + public byte[] getData() { + return data; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataRateBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataRateBox.java new file mode 100644 index 0000000..e58e550 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataRateBox.java @@ -0,0 +1,53 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+public class AppleDataRateBox extends AbstractFullBox {
+ public static final String TYPE = "rmdr";
+ private long dataRate;
+
+ public AppleDataRateBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 8;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ dataRate = IsoTypeReader.readUInt32(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, dataRate);
+ }
+
+
+ public long getDataRate() {
+ return dataRate;
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataReferenceBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataReferenceBox.java new file mode 100644 index 0000000..7370c10 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDataReferenceBox.java @@ -0,0 +1,71 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+public class AppleDataReferenceBox extends AbstractFullBox {
+ public static final String TYPE = "rdrf";
+ private int dataReferenceSize;
+ private String dataReferenceType;
+ private String dataReference;
+
+ public AppleDataReferenceBox() {
+ super(TYPE);
+ }
+
+
+ protected long getContentSize() {
+ return 12 + dataReferenceSize;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ dataReferenceType = IsoTypeReader.read4cc(content);
+ dataReferenceSize = l2i(IsoTypeReader.readUInt32(content));
+ dataReference = IsoTypeReader.readString(content, dataReferenceSize);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(IsoFile.fourCCtoBytes(dataReferenceType));
+ IsoTypeWriter.writeUInt32(byteBuffer, dataReferenceSize);
+ byteBuffer.put(Utf8.convert(dataReference));
+ }
+
+ public long getDataReferenceSize() {
+ return dataReferenceSize;
+ }
+
+ public String getDataReferenceType() {
+ return dataReferenceType;
+ }
+
+ public String getDataReference() {
+ return dataReference;
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDescriptionBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDescriptionBox.java new file mode 100644 index 0000000..e20e0fc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleDescriptionBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleDescriptionBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "desc"; + + + public AppleDescriptionBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleEncoderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleEncoderBox.java new file mode 100755 index 0000000..5a59e81 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleEncoderBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleEncoderBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9too"; + + + public AppleEncoderBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGaplessPlaybackBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGaplessPlaybackBox.java new file mode 100644 index 0000000..c617a54 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGaplessPlaybackBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Gapless Playback.
+ */
+public final class AppleGaplessPlaybackBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "pgap";
+
+
+ public AppleGaplessPlaybackBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint8AppleDataBox();
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGenericBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGenericBox.java new file mode 100644 index 0000000..177a25b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGenericBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * + */ +public final class AppleGenericBox extends AbstractContainerBox { + public static final String TYPE = "----"; + + public AppleGenericBox() { + super(TYPE); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGroupingBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGroupingBox.java new file mode 100755 index 0000000..9884298 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleGroupingBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public final class AppleGroupingBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9grp"; + + + public AppleGroupingBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleIdBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleIdBox.java new file mode 100644 index 0000000..08c697e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleIdBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleIdBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "apID"; + + + public AppleIdBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleItemListBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleItemListBox.java new file mode 100644 index 0000000..cd26e81 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleItemListBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * undocumented iTunes MetaData Box. + */ +public class AppleItemListBox extends AbstractContainerBox { + public static final String TYPE = "ilst"; + + public AppleItemListBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleLosslessSpecificBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleLosslessSpecificBox.java new file mode 100644 index 0000000..781af49 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleLosslessSpecificBox.java @@ -0,0 +1,163 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public final class AppleLosslessSpecificBox extends AbstractFullBox {
+
+ public static final String TYPE = "alac";
+ /*
+ Extradata: 32bit size 32bit tag (=alac) 32bit zero?
+ 32bit max sample per frame 8bit ?? (zero?) 8bit sample
+ size 8bit history mult 8bit initial history 8bit kmodifier
+ 8bit channels? 16bit ?? 32bit max coded frame size 32bit
+ bitrate? 32bit samplerate
+ */
+ private long maxSamplePerFrame; // 32bi
+ private int unknown1; // 8bit
+ private int sampleSize; // 8bit
+ private int historyMult; // 8bit
+ private int initialHistory; // 8bit
+ private int kModifier; // 8bit
+ private int channels; // 8bit
+ private int unknown2; // 16bit
+ private long maxCodedFrameSize; // 32bit
+ private long bitRate; // 32bit
+ private long sampleRate; // 32bit
+
+ public long getMaxSamplePerFrame() {
+ return maxSamplePerFrame;
+ }
+
+ public void setMaxSamplePerFrame(int maxSamplePerFrame) {
+ this.maxSamplePerFrame = maxSamplePerFrame;
+ }
+
+ public int getUnknown1() {
+ return unknown1;
+ }
+
+ public void setUnknown1(int unknown1) {
+ this.unknown1 = unknown1;
+ }
+
+ public int getSampleSize() {
+ return sampleSize;
+ }
+
+ public void setSampleSize(int sampleSize) {
+ this.sampleSize = sampleSize;
+ }
+
+ public int getHistoryMult() {
+ return historyMult;
+ }
+
+ public void setHistoryMult(int historyMult) {
+ this.historyMult = historyMult;
+ }
+
+ public int getInitialHistory() {
+ return initialHistory;
+ }
+
+ public void setInitialHistory(int initialHistory) {
+ this.initialHistory = initialHistory;
+ }
+
+ public int getKModifier() {
+ return kModifier;
+ }
+
+ public void setKModifier(int kModifier) {
+ this.kModifier = kModifier;
+ }
+
+ public int getChannels() {
+ return channels;
+ }
+
+ public void setChannels(int channels) {
+ this.channels = channels;
+ }
+
+ public int getUnknown2() {
+ return unknown2;
+ }
+
+ public void setUnknown2(int unknown2) {
+ this.unknown2 = unknown2;
+ }
+
+ public long getMaxCodedFrameSize() {
+ return maxCodedFrameSize;
+ }
+
+ public void setMaxCodedFrameSize(int maxCodedFrameSize) {
+ this.maxCodedFrameSize = maxCodedFrameSize;
+ }
+
+ public long getBitRate() {
+ return bitRate;
+ }
+
+ public void setBitRate(int bitRate) {
+ this.bitRate = bitRate;
+ }
+
+ public long getSampleRate() {
+ return sampleRate;
+ }
+
+ public void setSampleRate(int sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ maxSamplePerFrame = IsoTypeReader.readUInt32(content);
+ unknown1 = IsoTypeReader.readUInt8(content);
+ sampleSize = IsoTypeReader.readUInt8(content);
+ historyMult = IsoTypeReader.readUInt8(content);
+ initialHistory = IsoTypeReader.readUInt8(content);
+ kModifier = IsoTypeReader.readUInt8(content);
+ channels = IsoTypeReader.readUInt8(content);
+ unknown2 = IsoTypeReader.readUInt16(content);
+ maxCodedFrameSize = IsoTypeReader.readUInt32(content);
+ bitRate = IsoTypeReader.readUInt32(content);
+ sampleRate = IsoTypeReader.readUInt32(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxSamplePerFrame);
+ IsoTypeWriter.writeUInt8(byteBuffer, unknown1);
+ IsoTypeWriter.writeUInt8(byteBuffer, sampleSize);
+ IsoTypeWriter.writeUInt8(byteBuffer, historyMult);
+ IsoTypeWriter.writeUInt8(byteBuffer, initialHistory);
+ IsoTypeWriter.writeUInt8(byteBuffer, kModifier);
+ IsoTypeWriter.writeUInt8(byteBuffer, channels);
+ IsoTypeWriter.writeUInt16(byteBuffer, unknown2);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxCodedFrameSize);
+ IsoTypeWriter.writeUInt32(byteBuffer, bitRate);
+ IsoTypeWriter.writeUInt32(byteBuffer, sampleRate);
+ }
+
+ public AppleLosslessSpecificBox() {
+ super("alac");
+ }
+
+ protected long getContentSize() {
+ return 28;
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMeanBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMeanBox.java new file mode 100644 index 0000000..3a26f96 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMeanBox.java @@ -0,0 +1,47 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Apple Meaning box. Allowed as subbox of "----" box.
+ *
+ * @see com.coremedia.iso.boxes.apple.AppleGenericBox
+ */
+public final class AppleMeanBox extends AbstractFullBox {
+ public static final String TYPE = "mean";
+ private String meaning;
+
+ public AppleMeanBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 4 + Utf8.utf8StringLengthInBytes(meaning);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ meaning = IsoTypeReader.readString(content, content.remaining());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(meaning));
+ }
+
+ public String getMeaning() {
+ return meaning;
+ }
+
+ public void setMeaning(String meaning) {
+ this.meaning = meaning;
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMediaTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMediaTypeBox.java new file mode 100644 index 0000000..f4ca98d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleMediaTypeBox.java @@ -0,0 +1,39 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.HashMap; +import java.util.Map; + +/** + * itunes MetaData comment box. + */ +public class AppleMediaTypeBox extends AbstractAppleMetaDataBox { + private static Map<String, String> mediaTypes = new HashMap<String, String>(); + + static { + mediaTypes.put("0", "Movie (is now 9)"); + mediaTypes.put("1", "Normal (Music)"); + mediaTypes.put("2", "Audiobook"); + mediaTypes.put("6", "Music Video"); + mediaTypes.put("9", "Movie"); + mediaTypes.put("10", "TV Show"); + mediaTypes.put("11", "Booklet"); + mediaTypes.put("14", "Ringtone"); + } + + public static final String TYPE = "stik"; + + + public AppleMediaTypeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + public String getReadableValue() { + if (mediaTypes.containsKey(getValue())) { + return mediaTypes.get(getValue()); + } else { + return "unknown media type " + getValue(); + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNameBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNameBox.java new file mode 100644 index 0000000..5cad249 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNameBox.java @@ -0,0 +1,45 @@ +package com.coremedia.iso.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Apple Name box. Allowed as subbox of "----" box.
+ *
+ * @see AppleGenericBox
+ */
+public final class AppleNameBox extends AbstractFullBox {
+ public static final String TYPE = "name";
+ private String name;
+
+ public AppleNameBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 4 + Utf8.convert(name).length;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ name = IsoTypeReader.readString(content, content.remaining());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(name));
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNetworkBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNetworkBox.java new file mode 100644 index 0000000..07691b3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleNetworkBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleNetworkBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "tvnn"; + + + public AppleNetworkBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/ApplePurchaseDateBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/ApplePurchaseDateBox.java new file mode 100644 index 0000000..eb9807f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/ApplePurchaseDateBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class ApplePurchaseDateBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "purd"; + + + public ApplePurchaseDateBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRatingBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRatingBox.java new file mode 100644 index 0000000..71671fc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRatingBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * iTunes Rating Box. + */ +public final class AppleRatingBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "rtng"; + + + public AppleRatingBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRecordingYearBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRecordingYearBox.java new file mode 100644 index 0000000..da13300 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleRecordingYearBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public class AppleRecordingYearBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9day"; + + + public AppleRecordingYearBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieBox.java new file mode 100644 index 0000000..49c539f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieBox.java @@ -0,0 +1,28 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class AppleReferenceMovieBox extends AbstractContainerBox {
+ public static final String TYPE = "rmra";
+
+ public AppleReferenceMovieBox() {
+ super(TYPE);
+ }
+
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieDescriptorBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieDescriptorBox.java new file mode 100644 index 0000000..488f01b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleReferenceMovieDescriptorBox.java @@ -0,0 +1,27 @@ +/*
+ * Copyright 2009 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.coremedia.iso.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class AppleReferenceMovieDescriptorBox extends AbstractContainerBox {
+ public static final String TYPE = "rmda";
+
+ public AppleReferenceMovieDescriptorBox() {
+ super(TYPE);
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleShowBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleShowBox.java new file mode 100644 index 0000000..66b0d59 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleShowBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleShowBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "tvsh"; + + + public AppleShowBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSortAlbumBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSortAlbumBox.java new file mode 100644 index 0000000..cf74004 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSortAlbumBox.java @@ -0,0 +1,14 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleSortAlbumBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "soal"; + + + public AppleSortAlbumBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStandardGenreBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStandardGenreBox.java new file mode 100644 index 0000000..21932fa --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStandardGenreBox.java @@ -0,0 +1,14 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleStandardGenreBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "gnre"; + + + public AppleStandardGenreBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint16AppleDataBox(); + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreAccountTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreAccountTypeBox.java new file mode 100755 index 0000000..36ecf4e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreAccountTypeBox.java @@ -0,0 +1,27 @@ +package com.coremedia.iso.boxes.apple; + +/** + * itunes MetaData comment box. + */ +public class AppleStoreAccountTypeBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "akID"; + + + public AppleStoreAccountTypeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint8AppleDataBox(); + } + + public String getReadableValue() { + byte value = this.appleDataBox.getData()[0]; + switch (value) { + case 0: + return "iTunes Account"; + case 1: + return "AOL Account"; + default: + return "unknown Account"; + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreCountryCodeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreCountryCodeBox.java new file mode 100644 index 0000000..2c4756a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleStoreCountryCodeBox.java @@ -0,0 +1,54 @@ +package com.coremedia.iso.boxes.apple; + +import java.util.HashMap; +import java.util.Map; + +/** + * itunes MetaData comment box. + */ +public class AppleStoreCountryCodeBox extends AbstractAppleMetaDataBox { + private static Map<String, String> countryCodes = new HashMap<String, String>(); + + static { + countryCodes.put("143460", "Australia"); + countryCodes.put("143445", "Austria"); + countryCodes.put("143446", "Belgium"); + countryCodes.put("143455", "Canada"); + countryCodes.put("143458", "Denmark"); + countryCodes.put("143447", "Finland"); + countryCodes.put("143442", "France"); + countryCodes.put("143443", "Germany"); + countryCodes.put("143448", "Greece"); + countryCodes.put("143449", "Ireland"); + countryCodes.put("143450", "Italy"); + countryCodes.put("143462", "Japan"); + countryCodes.put("143451", "Luxembourg"); + countryCodes.put("143452", "Netherlands"); + countryCodes.put("143461", "New Zealand"); + countryCodes.put("143457", "Norway"); + countryCodes.put("143453", "Portugal"); + countryCodes.put("143454", "Spain"); + countryCodes.put("143456", "Sweden"); + countryCodes.put("143459", "Switzerland"); + countryCodes.put("143444", "United Kingdom"); + countryCodes.put("143441", "United States"); + } + + public static final String TYPE = "sfID"; + + + public AppleStoreCountryCodeBox() { + super(TYPE); + appleDataBox = AppleDataBox.getUint32AppleDataBox(); + } + + + public String getReadableValue() { + if (countryCodes.containsKey(getValue())) { + return countryCodes.get(getValue()); + } else { + return "unknown country code " + getValue(); + } + + } +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSynopsisBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSynopsisBox.java new file mode 100644 index 0000000..cd5c2ab --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleSynopsisBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleSynopsisBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "ldes"; + + + public AppleSynopsisBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTempBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTempBox.java new file mode 100644 index 0000000..ef57228 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTempBox.java @@ -0,0 +1,28 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Beats per minute.
+ */
+public final class AppleTempBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tmpo";
+
+
+ public AppleTempBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint16AppleDataBox();
+ }
+
+
+ public int getTempo() {
+ return appleDataBox.getData()[1];
+ }
+
+ public void setTempo(int tempo) {
+ appleDataBox = new AppleDataBox();
+ appleDataBox.setVersion(0);
+ appleDataBox.setFlags(21);
+ appleDataBox.setFourBytes(new byte[4]);
+ appleDataBox.setData(new byte[]{0, (byte) (tempo & 0xFF)});
+
+ }
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackAuthorBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackAuthorBox.java new file mode 100644 index 0000000..c5b3732 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackAuthorBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackAuthorBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9wrt"; + + + public AppleTrackAuthorBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackNumberBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackNumberBox.java new file mode 100644 index 0000000..c073c2f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackNumberBox.java @@ -0,0 +1,48 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackNumberBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "trkn"; + + + public AppleTrackNumberBox() { + super(TYPE); + } + + + /** + * @param track the actual track number + * @param of number of tracks overall + */ + public void setTrackNumber(byte track, byte of) { + appleDataBox = new AppleDataBox(); + appleDataBox.setVersion(0); + appleDataBox.setFlags(0); + appleDataBox.setFourBytes(new byte[4]); + appleDataBox.setData(new byte[]{0, 0, 0, track, 0, of, 0, 0}); + } + + public byte getTrackNumber() { + return appleDataBox.getData()[3]; + } + + public byte getNumberOfTracks() { + return appleDataBox.getData()[5]; + } + + public void setNumberOfTracks(byte numberOfTracks) { + byte[] content = appleDataBox.getData(); + content[5] = numberOfTracks; + appleDataBox.setData(content); + } + + public void setTrackNumber(byte trackNumber) { + byte[] content = appleDataBox.getData(); + content[3] = trackNumber; + appleDataBox.setData(content); + } + + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackTitleBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackTitleBox.java new file mode 100644 index 0000000..3dd613c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTrackTitleBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple; + +/** + * + */ +public final class AppleTrackTitleBox extends AbstractAppleMetaDataBox { + public static final String TYPE = "\u00a9nam"; + + + public AppleTrackTitleBox() { + super(TYPE); + appleDataBox = AppleDataBox.getStringAppleDataBox(); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeBox.java new file mode 100644 index 0000000..3b3817b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Episode.
+ */
+public class AppleTvEpisodeBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tves";
+
+
+ public AppleTvEpisodeBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint32AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeNumberBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeNumberBox.java new file mode 100644 index 0000000..33cd4e3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvEpisodeNumberBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Episode.
+ */
+public class AppleTvEpisodeNumberBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tven";
+
+
+ public AppleTvEpisodeNumberBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getStringAppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvSeasonBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvSeasonBox.java new file mode 100644 index 0000000..9459ea3 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleTvSeasonBox.java @@ -0,0 +1,15 @@ +package com.coremedia.iso.boxes.apple;
+
+/**
+ * Tv Season.
+ */
+public final class AppleTvSeasonBox extends AbstractAppleMetaDataBox {
+ public static final String TYPE = "tvsn";
+
+
+ public AppleTvSeasonBox() {
+ super(TYPE);
+ appleDataBox = AppleDataBox.getUint32AppleDataBox();
+ }
+
+}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleWaveBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleWaveBox.java new file mode 100644 index 0000000..65edd38 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/apple/AppleWaveBox.java @@ -0,0 +1,16 @@ +package com.coremedia.iso.boxes.apple; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * + */ +public final class AppleWaveBox extends AbstractContainerBox { + public static final String TYPE = "wave"; + + public AppleWaveBox() { + super(TYPE); + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/all-wcprops new file mode 100644 index 0000000..fb492fe --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/dece +END +TrickPlayBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/dece/TrickPlayBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/entries new file mode 100644 index 0000000..f3d8baf --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/dece +http://mp4parser.googlecode.com/svn + + + +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +TrickPlayBox.java +file + + + + +2012-09-14T17:27:52.607249Z +0afc708ec47fcdf8687d1623014b81a0 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2716 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/text-base/TrickPlayBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/text-base/TrickPlayBox.java.svn-base new file mode 100644 index 0000000..24d5712 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/.svn/text-base/TrickPlayBox.java.svn-base @@ -0,0 +1,108 @@ +package com.coremedia.iso.boxes.dece;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * aligned(8) class TrickPlayBox
+ * extends FullBox(‘trik’, version=0, flags=0)
+ * {
+ * for (i=0; I < sample_count; i++) {
+ * unsigned int(2) pic_type;
+ * unsigned int(6) dependency_level;
+ * }
+ * }
+ */
+public class TrickPlayBox extends AbstractFullBox {
+ public static final String TYPE = "trik";
+
+ private List<Entry> entries = new ArrayList<Entry>();
+
+ public TrickPlayBox() {
+ super(TYPE);
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public static class Entry {
+
+ public Entry() {
+ }
+
+ public Entry(int value) {
+ this.value = value;
+ }
+
+
+ private int value;
+
+ public int getPicType() {
+ return (value >> 6) & 0x03;
+ }
+
+ public void setPicType(int picType) {
+ value = value & (0xff >> 3);
+ value = (picType & 0x03) << 6 | value;
+ }
+
+ public int getDependencyLevel() {
+ return value & 0x3f;
+ }
+
+ public void setDependencyLevel(int dependencyLevel) {
+ value = (dependencyLevel & 0x3f) | value;
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Entry");
+ sb.append("{picType=").append(getPicType());
+ sb.append(",dependencyLevel=").append(getDependencyLevel());
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 4 + entries.size();
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ while (content.remaining() > 0) {
+ entries.add(new Entry(IsoTypeReader.readUInt8(content)));
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ for (Entry entry : entries) {
+ IsoTypeWriter.writeUInt8(byteBuffer, entry.value);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TrickPlayBox");
+ sb.append("{entries=").append(entries);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/dece/TrickPlayBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/TrickPlayBox.java new file mode 100644 index 0000000..24d5712 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/dece/TrickPlayBox.java @@ -0,0 +1,108 @@ +package com.coremedia.iso.boxes.dece;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * aligned(8) class TrickPlayBox
+ * extends FullBox(‘trik’, version=0, flags=0)
+ * {
+ * for (i=0; I < sample_count; i++) {
+ * unsigned int(2) pic_type;
+ * unsigned int(6) dependency_level;
+ * }
+ * }
+ */
+public class TrickPlayBox extends AbstractFullBox {
+ public static final String TYPE = "trik";
+
+ private List<Entry> entries = new ArrayList<Entry>();
+
+ public TrickPlayBox() {
+ super(TYPE);
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public static class Entry {
+
+ public Entry() {
+ }
+
+ public Entry(int value) {
+ this.value = value;
+ }
+
+
+ private int value;
+
+ public int getPicType() {
+ return (value >> 6) & 0x03;
+ }
+
+ public void setPicType(int picType) {
+ value = value & (0xff >> 3);
+ value = (picType & 0x03) << 6 | value;
+ }
+
+ public int getDependencyLevel() {
+ return value & 0x3f;
+ }
+
+ public void setDependencyLevel(int dependencyLevel) {
+ value = (dependencyLevel & 0x3f) | value;
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Entry");
+ sb.append("{picType=").append(getPicType());
+ sb.append(",dependencyLevel=").append(getDependencyLevel());
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 4 + entries.size();
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ while (content.remaining() > 0) {
+ entries.add(new Entry(IsoTypeReader.readUInt8(content)));
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ for (Entry entry : entries) {
+ IsoTypeWriter.writeUInt8(byteBuffer, entry.value);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TrickPlayBox");
+ sb.append("{entries=").append(entries);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/all-wcprops new file mode 100644 index 0000000..4b6b1e0 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/all-wcprops @@ -0,0 +1,89 @@ +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/707/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment +END +MovieFragmentRandomAccessBox.java +K 25 +svn:wc:ra_dav:version-url +V 114 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessBox.java +END +TrackFragmentBaseMediaDecodeTimeBox.java +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBaseMediaDecodeTimeBox.java +END +TrackFragmentBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBox.java +END +TrackRunBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/640/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java +END +MovieExtendsBox.java +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsBox.java +END +TrackFragmentRandomAccessBox.java +K 25 +svn:wc:ra_dav:version-url +V 114 +/svn/!svn/ver/624/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentRandomAccessBox.java +END +MovieFragmentHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 108 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentHeaderBox.java +END +MovieFragmentRandomAccessOffsetBox.java +K 25 +svn:wc:ra_dav:version-url +V 120 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessOffsetBox.java +END +TrackExtendsBox.java +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackExtendsBox.java +END +TrackFragmentHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 108 +/svn/!svn/ver/640/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentHeaderBox.java +END +MovieFragmentBox.java +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/!svn/ver/671/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentBox.java +END +MovieExtendsHeaderBox.java +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/!svn/ver/707/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsHeaderBox.java +END +SegmentTypeBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/613/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SegmentTypeBox.java +END +SampleFlags.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/534/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SampleFlags.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/entries new file mode 100644 index 0000000..6212978 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/entries @@ -0,0 +1,504 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/fragment +http://mp4parser.googlecode.com/svn + + + +2012-07-10T16:32:53.757675Z +707 +michael.stattmann@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +MovieFragmentRandomAccessBox.java +file + + + + +2012-09-14T17:27:52.267244Z +4eabe3aabca1078ceea9af4a4834b0f1 +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +984 + +TrackFragmentBaseMediaDecodeTimeBox.java +file + + + + +2012-09-14T17:27:52.267244Z +af8610f8a9e617ce31f65b03dcc17367 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2190 + +TrackFragmentBox.java +file + + + + +2012-09-14T17:27:52.267244Z +dba2633d9c107e9eddcf3e6eab22c9dd +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1241 + +TrackRunBox.java +file + + + + +2012-09-14T17:27:52.267244Z +c28d12fedd74251d99e0d5c1830c94d3 +2012-05-25T01:59:01.697137Z +640 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +11046 + +MovieExtendsBox.java +file + + + + +2012-09-14T17:27:52.267244Z +dcf05781e764bcbfbb5e15fd788fb0aa +2012-04-21T21:18:31.685061Z +505 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +937 + +TrackFragmentRandomAccessBox.java +file + + + + +2012-09-14T17:27:52.267244Z +45b30b8d197f9815b53fcc90fb31ee95 +2012-05-21T11:57:37.647327Z +624 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +9307 + +MovieFragmentHeaderBox.java +file + + + + +2012-09-14T17:27:52.267244Z +25d305e9e55dfdcf69ae5f31c90b8337 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1914 + +MovieFragmentRandomAccessOffsetBox.java +file + + + + +2012-09-14T17:27:52.267244Z +6d2116a9bd56b10e667a6a51bea18b53 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1720 + +TrackExtendsBox.java +file + + + + +2012-09-14T17:27:52.267244Z +322aa8226e5343046573a005646fc1d2 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3577 + +TrackFragmentHeaderBox.java +file + + + + +2012-09-14T17:27:52.267244Z +984fc3f2f62a36cef43dc93b804accb6 +2012-05-25T01:59:01.697137Z +640 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +7356 + +MovieFragmentBox.java +file + + + + +2012-09-14T17:27:52.267244Z +a3c1c53469581b52f3658b1abeba4e6a +2012-06-10T18:50:38.971172Z +671 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +3033 + +MovieExtendsHeaderBox.java +file + + + + +2012-09-14T17:27:52.267244Z +1b6dca9e192c4e7f9ad26a2be93a2fd8 +2012-07-10T16:32:53.757675Z +707 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +2083 + +SegmentTypeBox.java +file + + + + +2012-09-14T17:27:52.267244Z +0c595f0be955e83b6f9e980455f6719f +2012-05-11T07:48:18.576721Z +613 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +4363 + +SampleFlags.java +file + + + + +2012-09-14T17:27:52.267244Z +d39b07fe798f248be8d054513f809787 +2012-04-27T14:59:11.479630Z +534 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +6723 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsBox.java.svn-base new file mode 100644 index 0000000..5ecd642 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsBox.java.svn-base @@ -0,0 +1,31 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * aligned(8) class MovieExtendsBox extends Box('mvex'){ + * } + */ +public class MovieExtendsBox extends AbstractContainerBox { + public static final String TYPE = "mvex"; + + public MovieExtendsBox() { + super(TYPE); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsHeaderBox.java.svn-base new file mode 100644 index 0000000..8dd58f9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieExtendsHeaderBox.java.svn-base @@ -0,0 +1,71 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieExtendsHeaderBox extends FullBox('mehd', version, 0) { + * if (version==1) { + * unsigned int(64) fragment_duration; + * } else { // version==0 + * unsigned int(32) fragment_duration; + * } + * } + */ +public class MovieExtendsHeaderBox extends AbstractFullBox { + public static final String TYPE = "mehd"; + private long fragmentDuration; + + public MovieExtendsHeaderBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return getVersion() == 1 ? 12 : 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + fragmentDuration = getVersion() == 1 ? IsoTypeReader.readUInt64(content) : IsoTypeReader.readUInt32(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, fragmentDuration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, fragmentDuration); + } + } + + public long getFragmentDuration() { + return fragmentDuration; + } + + public void setFragmentDuration(long fragmentDuration) { + this.fragmentDuration = fragmentDuration; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentBox.java.svn-base new file mode 100644 index 0000000..e92bd53 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentBox.java.svn-base @@ -0,0 +1,100 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.SampleDependencyTypeBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.util.ArrayList; +import java.util.List; + +/** + * aligned(8) class MovieFragmentBox extends Box(moof){ + * } + */ + +public class MovieFragmentBox extends AbstractContainerBox { + public static final String TYPE = "moof"; + + public MovieFragmentBox() { + super(TYPE); + } + + + public List<Long> getSyncSamples(SampleDependencyTypeBox sdtp) { + List<Long> result = new ArrayList<Long>(); + + final List<SampleDependencyTypeBox.Entry> sampleEntries = sdtp.getEntries(); + long i = 1; + for (SampleDependencyTypeBox.Entry sampleEntry : sampleEntries) { + if (sampleEntry.getSampleDependsOn() == 2) { + result.add(i); + } + i++; + } + + return result; + } + + @DoNotParseDetail + public long getOffset() { + Box b = this; + long offset = 0; + while (b.getParent() != null) { + for (Box box : b.getParent().getBoxes()) { + if (b == box) { + break; + } + offset += box.getSize(); + } + b = b.getParent(); + } + return offset; + } + + + public int getTrackCount() { + return getBoxes(TrackFragmentBox.class, false).size(); + } + + /** + * Returns the track numbers associated with this <code>MovieBox</code>. + * + * @return the tracknumbers (IDs) of the tracks in their order of appearance in the file + */ + + public long[] getTrackNumbers() { + + List<TrackFragmentBox> trackBoxes = this.getBoxes(TrackFragmentBox.class, false); + long[] trackNumbers = new long[trackBoxes.size()]; + for (int trackCounter = 0; trackCounter < trackBoxes.size(); trackCounter++) { + TrackFragmentBox trackBoxe = trackBoxes.get(trackCounter); + trackNumbers[trackCounter] = trackBoxe.getTrackFragmentHeaderBox().getTrackId(); + } + return trackNumbers; + } + + public List<TrackFragmentHeaderBox> getTrackFragmentHeaderBoxes() { + return getBoxes(TrackFragmentHeaderBox.class, true); + } + + public List<TrackRunBox> getTrackRunBoxes() { + return getBoxes(TrackRunBox.class, true); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentHeaderBox.java.svn-base new file mode 100644 index 0000000..e58f7a2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentHeaderBox.java.svn-base @@ -0,0 +1,72 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieFragmentHeaderBox + * extends FullBox('mfhd', 0, 0){ + * unsigned int(32) sequence_number; + * } + */ + +public class MovieFragmentHeaderBox extends AbstractFullBox { + public static final String TYPE = "mfhd"; + private long sequenceNumber; + + public MovieFragmentHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, sequenceNumber); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + sequenceNumber = IsoTypeReader.readUInt32(content); + + } + + public long getSequenceNumber() { + return sequenceNumber; + } + + public void setSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + @Override + public String toString() { + return "MovieFragmentHeaderBox{" + + "sequenceNumber=" + sequenceNumber + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessBox.java.svn-base new file mode 100644 index 0000000..86e2c9d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessBox.java.svn-base @@ -0,0 +1,34 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * aligned(8) class MovieFragmentRandomAccessBox + * extends Box('mfra') + * { + * } + */ +public class MovieFragmentRandomAccessBox extends AbstractContainerBox { + public static final String TYPE = "mfra"; + + public MovieFragmentRandomAccessBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessOffsetBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessOffsetBox.java.svn-base new file mode 100644 index 0000000..edbfd66 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/MovieFragmentRandomAccessOffsetBox.java.svn-base @@ -0,0 +1,62 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieFragmentRandomAccessOffsetBox + * extends FullBox('mfro', version, 0) { + * unsigned int(32) size; + * } + */ +public class MovieFragmentRandomAccessOffsetBox extends AbstractFullBox { + public static final String TYPE = "mfro"; + private long mfraSize; + + public MovieFragmentRandomAccessOffsetBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + mfraSize = IsoTypeReader.readUInt32(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, mfraSize); + } + + public long getMfraSize() { + return mfraSize; + } + + public void setMfraSize(long mfraSize) { + this.mfraSize = mfraSize; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SampleFlags.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SampleFlags.java.svn-base new file mode 100644 index 0000000..6caaf1e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SampleFlags.java.svn-base @@ -0,0 +1,207 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * bit(6) reserved=0; + * unsigned int(2) sample_depends_on; + * unsigned int(2) sample_is_depended_on; + * unsigned int(2) sample_has_redundancy; + * bit(3) sample_padding_value; + * bit(1) sample_is_difference_sample; + * // i.e. when 1 signals a non-key or non-sync sample + * unsigned int(16) sample_degradation_priority; + */ +public class SampleFlags { + private int reserved; + private int sampleDependsOn; + private int sampleIsDependedOn; + private int sampleHasRedundancy; + private int samplePaddingValue; + private boolean sampleIsDifferenceSample; + private int sampleDegradationPriority; + + public SampleFlags() { + + } + + public SampleFlags(ByteBuffer bb) { + BitReaderBuffer brb = new BitReaderBuffer(bb); + reserved = brb.readBits(6); + sampleDependsOn = brb.readBits(2); + sampleIsDependedOn = brb.readBits(2); + sampleHasRedundancy = brb.readBits(2); + samplePaddingValue = brb.readBits(3); + sampleIsDifferenceSample = brb.readBits(1) == 1; + sampleDegradationPriority = brb.readBits(16); + } + + + public void getContent(ByteBuffer os) { + BitWriterBuffer bitWriterBuffer = new BitWriterBuffer(os); + bitWriterBuffer.writeBits(reserved, 6); + bitWriterBuffer.writeBits(sampleDependsOn, 2); + bitWriterBuffer.writeBits(sampleIsDependedOn, 2); + bitWriterBuffer.writeBits(sampleHasRedundancy, 2); + bitWriterBuffer.writeBits(samplePaddingValue, 3); + bitWriterBuffer.writeBits(this.sampleIsDifferenceSample ? 1 : 0, 1); + bitWriterBuffer.writeBits(sampleDegradationPriority, 16); + } + + public int getReserved() { + return reserved; + } + + public void setReserved(int reserved) { + this.reserved = reserved; + } + + /** + * @see #setSampleDependsOn(int) + */ + public int getSampleDependsOn() { + return sampleDependsOn; + } + + /** + * sample_depends_on takes one of the following four values: + * <pre> + * 0: the dependency of this sample is unknown; + * 1: this sample does depend on others (not an I picture); + * 2: this sample does not depend on others (I picture); + * 3: reserved + * </pre> + * + */ + public void setSampleDependsOn(int sampleDependsOn) { + this.sampleDependsOn = sampleDependsOn; + } + + /** + * @see #setSampleIsDependedOn(int) + */ + public int getSampleIsDependedOn() { + return sampleIsDependedOn; + } + + /** + * sample_is_depended_on takes one of the following four values: + * <pre> + * 0: the dependency of other samples on this sample is unknown; + * 1: other samples may depend on this one (not disposable); + * 2: no other sample depends on this one (disposable); + * 3: reserved + * </pre> + * + */ + public void setSampleIsDependedOn(int sampleIsDependedOn) { + this.sampleIsDependedOn = sampleIsDependedOn; + } + + /** + * @see #setSampleHasRedundancy(int) + */ + public int getSampleHasRedundancy() { + return sampleHasRedundancy; + } + + /** + * sample_has_redundancy takes one of the following four values: + * <pre> + * 0: it is unknown whether there is redundant coding in this sample; + * 1: there is redundant coding in this sample; + * 2: there is no redundant coding in this sample; + * 3: reserved + * </pre> + */ + public void setSampleHasRedundancy(int sampleHasRedundancy) { + this.sampleHasRedundancy = sampleHasRedundancy; + } + + public int getSamplePaddingValue() { + return samplePaddingValue; + } + + public void setSamplePaddingValue(int samplePaddingValue) { + this.samplePaddingValue = samplePaddingValue; + } + + public boolean isSampleIsDifferenceSample() { + return sampleIsDifferenceSample; + } + + + public void setSampleIsDifferenceSample(boolean sampleIsDifferenceSample) { + this.sampleIsDifferenceSample = sampleIsDifferenceSample; + } + + public int getSampleDegradationPriority() { + return sampleDegradationPriority; + } + + public void setSampleDegradationPriority(int sampleDegradationPriority) { + this.sampleDegradationPriority = sampleDegradationPriority; + } + + @Override + public String toString() { + return "SampleFlags{" + + "reserved=" + reserved + + ", sampleDependsOn=" + sampleDependsOn + + ", sampleHasRedundancy=" + sampleHasRedundancy + + ", samplePaddingValue=" + samplePaddingValue + + ", sampleIsDifferenceSample=" + sampleIsDifferenceSample + + ", sampleDegradationPriority=" + sampleDegradationPriority + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SampleFlags that = (SampleFlags) o; + + if (reserved != that.reserved) return false; + if (sampleDegradationPriority != that.sampleDegradationPriority) return false; + if (sampleDependsOn != that.sampleDependsOn) return false; + if (sampleHasRedundancy != that.sampleHasRedundancy) return false; + if (sampleIsDependedOn != that.sampleIsDependedOn) return false; + if (sampleIsDifferenceSample != that.sampleIsDifferenceSample) return false; + if (samplePaddingValue != that.samplePaddingValue) return false; + + return true; + } + + @Override + public int hashCode() { + int result = reserved; + result = 31 * result + sampleDependsOn; + result = 31 * result + sampleIsDependedOn; + result = 31 * result + sampleHasRedundancy; + result = 31 * result + samplePaddingValue; + result = 31 * result + (sampleIsDifferenceSample ? 1 : 0); + result = 31 * result + sampleDegradationPriority; + return result; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SegmentTypeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SegmentTypeBox.java.svn-base new file mode 100644 index 0000000..5e0d47b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/SegmentTypeBox.java.svn-base @@ -0,0 +1,143 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * This box identifies the specifications to which this file complies. <br> + * Each brand is a printable four-character code, registered with ISO, that + * identifies a precise specification. + */ +public class SegmentTypeBox extends AbstractBox { + public static final String TYPE = "styp"; + + private String majorBrand; + private long minorVersion; + private List<String> compatibleBrands = Collections.emptyList(); + + public SegmentTypeBox() { + super(TYPE); + } + + public SegmentTypeBox(String majorBrand, long minorVersion, List<String> compatibleBrands) { + super(TYPE); + this.majorBrand = majorBrand; + this.minorVersion = minorVersion; + this.compatibleBrands = compatibleBrands; + } + + protected long getContentSize() { + return 8 + compatibleBrands.size() * 4; + + } + + @Override + public void _parseDetails(ByteBuffer content) { + majorBrand = IsoTypeReader.read4cc(content); + minorVersion = IsoTypeReader.readUInt32(content); + int compatibleBrandsCount = content.remaining() / 4; + compatibleBrands = new LinkedList<String>(); + for (int i = 0; i < compatibleBrandsCount; i++) { + compatibleBrands.add(IsoTypeReader.read4cc(content)); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(majorBrand)); + IsoTypeWriter.writeUInt32(byteBuffer, minorVersion); + for (String compatibleBrand : compatibleBrands) { + byteBuffer.put(IsoFile.fourCCtoBytes(compatibleBrand)); + } + + } + + /** + * Gets the brand identifier. + * + * @return the brand identifier + */ + public String getMajorBrand() { + return majorBrand; + } + + /** + * Sets the major brand of the file used to determine an appropriate reader. + * + * @param majorBrand the new major brand + */ + public void setMajorBrand(String majorBrand) { + this.majorBrand = majorBrand; + } + + /** + * Sets the "informative integer for the minor version of the major brand". + * + * @param minorVersion the version number of the major brand + */ + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + /** + * Gets an informative integer for the minor version of the major brand. + * + * @return an informative integer + * @see SegmentTypeBox#getMajorBrand() + */ + public long getMinorVersion() { + return minorVersion; + } + + /** + * Gets an array of 4-cc brands. + * + * @return the compatible brands + */ + public List<String> getCompatibleBrands() { + return compatibleBrands; + } + + public void setCompatibleBrands(List<String> compatibleBrands) { + this.compatibleBrands = compatibleBrands; + } + + @DoNotParseDetail + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("SegmentTypeBox["); + result.append("majorBrand=").append(getMajorBrand()); + result.append(";"); + result.append("minorVersion=").append(getMinorVersion()); + for (String compatibleBrand : compatibleBrands) { + result.append(";"); + result.append("compatibleBrand=").append(compatibleBrand); + } + result.append("]"); + return result.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackExtendsBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackExtendsBox.java.svn-base new file mode 100644 index 0000000..8bba7c1 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackExtendsBox.java.svn-base @@ -0,0 +1,115 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class TrackExtendsBox extends FullBox('trex', 0, 0){ + * unsigned int(32) track_ID; + * unsigned int(32) default_sample_description_index; + * unsigned int(32) default_sample_duration; + * unsigned int(32) default_sample_size; + * unsigned int(32) default_sample_flags + * } + */ +public class TrackExtendsBox extends AbstractFullBox { + public static final String TYPE = "trex"; + private long trackId; + private long defaultSampleDescriptionIndex; + private long defaultSampleDuration; + private long defaultSampleSize; + private SampleFlags defaultSampleFlags; + + public TrackExtendsBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 5 * 4 + 4; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleDescriptionIndex); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleDuration); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleSize); + defaultSampleFlags.getContent(byteBuffer); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + defaultSampleDescriptionIndex = IsoTypeReader.readUInt32(content); + defaultSampleDuration = IsoTypeReader.readUInt32(content); + defaultSampleSize = IsoTypeReader.readUInt32(content); + defaultSampleFlags = new SampleFlags(content); + } + + public long getTrackId() { + return trackId; + } + + public long getDefaultSampleDescriptionIndex() { + return defaultSampleDescriptionIndex; + } + + public long getDefaultSampleDuration() { + return defaultSampleDuration; + } + + public long getDefaultSampleSize() { + return defaultSampleSize; + } + + public SampleFlags getDefaultSampleFlags() { + return defaultSampleFlags; + } + + public String getDefaultSampleFlagsStr() { + return defaultSampleFlags.toString(); + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setDefaultSampleDescriptionIndex(long defaultSampleDescriptionIndex) { + this.defaultSampleDescriptionIndex = defaultSampleDescriptionIndex; + } + + public void setDefaultSampleDuration(long defaultSampleDuration) { + this.defaultSampleDuration = defaultSampleDuration; + } + + public void setDefaultSampleSize(long defaultSampleSize) { + this.defaultSampleSize = defaultSampleSize; + } + + public void setDefaultSampleFlags(SampleFlags defaultSampleFlags) { + this.defaultSampleFlags = defaultSampleFlags; + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBaseMediaDecodeTimeBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBaseMediaDecodeTimeBox.java.svn-base new file mode 100644 index 0000000..06fcf62 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBaseMediaDecodeTimeBox.java.svn-base @@ -0,0 +1,76 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +public class TrackFragmentBaseMediaDecodeTimeBox extends AbstractFullBox { + public static final String TYPE = "tfdt"; + + private long baseMediaDecodeTime; + + public TrackFragmentBaseMediaDecodeTimeBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return getVersion() == 0 ? 8 : 12; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, baseMediaDecodeTime); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, baseMediaDecodeTime); + } + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + baseMediaDecodeTime = IsoTypeReader.readUInt64(content); + } else { + baseMediaDecodeTime = IsoTypeReader.readUInt32(content); + } + + } + + + public long getBaseMediaDecodeTime() { + return baseMediaDecodeTime; + } + + public void setBaseMediaDecodeTime(long baseMediaDecodeTime) { + this.baseMediaDecodeTime = baseMediaDecodeTime; + } + + @Override + public String toString() { + return "TrackFragmentBaseMediaDecodeTimeBox{" + + "baseMediaDecodeTime=" + baseMediaDecodeTime + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBox.java.svn-base new file mode 100644 index 0000000..fde7da5 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentBox.java.svn-base @@ -0,0 +1,43 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; + +/** + * aligned(8) class TrackFragmentBox extends Box('traf'){ + * } + */ +public class TrackFragmentBox extends AbstractContainerBox { + public static final String TYPE = "traf"; + + public TrackFragmentBox() { + super(TYPE); + } + + + public TrackFragmentHeaderBox getTrackFragmentHeaderBox() { + for (Box box : getBoxes()) { + if (box instanceof TrackFragmentHeaderBox) { + return (TrackFragmentHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentHeaderBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentHeaderBox.java.svn-base new file mode 100644 index 0000000..fb9509b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentHeaderBox.java.svn-base @@ -0,0 +1,224 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class TrackFragmentHeaderBox + * extends FullBox('tfhd', 0, tf_flags){ + * unsigned int(32) track_ID; + * // all the following are optional fields + * unsigned int(64) base_data_offset; + * unsigned int(32) sample_description_index; + * unsigned int(32) default_sample_duration; + * unsigned int(32) default_sample_size; + * unsigned int(32) default_sample_flags + * } + */ +public class TrackFragmentHeaderBox extends AbstractFullBox { + public static final String TYPE = "tfhd"; + + private long trackId; + private long baseDataOffset = -1; + private long sampleDescriptionIndex; + private long defaultSampleDuration = -1; + private long defaultSampleSize = -1; + private SampleFlags defaultSampleFlags; + private boolean durationIsEmpty; + + public TrackFragmentHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + long size = 8; + int flags = getFlags(); + if ((flags & 0x1) == 1) { //baseDataOffsetPresent + size += 8; + } + if ((flags & 0x2) == 0x2) { //sampleDescriptionIndexPresent + size += 4; + } + if ((flags & 0x8) == 0x8) { //defaultSampleDurationPresent + size += 4; + } + if ((flags & 0x10) == 0x10) { //defaultSampleSizePresent + size += 4; + } + if ((flags & 0x20) == 0x20) { //defaultSampleFlagsPresent + size += 4; + } + return size; + } + + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + + if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent + IsoTypeWriter.writeUInt64(byteBuffer, getBaseDataOffset()); + } + if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent + IsoTypeWriter.writeUInt32(byteBuffer, getSampleDescriptionIndex()); + } + if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent + IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleDuration()); + } + if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent + IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleSize()); + } + if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent + defaultSampleFlags.getContent(byteBuffer); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent + baseDataOffset = IsoTypeReader.readUInt64(content); + } + if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent + sampleDescriptionIndex = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent + defaultSampleDuration = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent + defaultSampleSize = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent + defaultSampleFlags = new SampleFlags(content); + } + if ((getFlags() & 0x10000) == 0x10000) { //durationIsEmpty + durationIsEmpty = true; + } + } + + public boolean hasBaseDataOffset() { + return (getFlags() & 0x1) != 0; + } + + public boolean hasSampleDescriptionIndex() { + return (getFlags() & 0x2) != 0; + } + + public boolean hasDefaultSampleDuration() { + return (getFlags() & 0x8) != 0; + } + + public boolean hasDefaultSampleSize() { + return (getFlags() & 0x10) != 0; + } + + public boolean hasDefaultSampleFlags() { + return (getFlags() & 0x20) != 0; + } + + public long getTrackId() { + return trackId; + } + + public long getBaseDataOffset() { + return baseDataOffset; + } + + public long getSampleDescriptionIndex() { + return sampleDescriptionIndex; + } + + public long getDefaultSampleDuration() { + return defaultSampleDuration; + } + + public long getDefaultSampleSize() { + return defaultSampleSize; + } + + public SampleFlags getDefaultSampleFlags() { + return defaultSampleFlags; + } + + public boolean isDurationIsEmpty() { + return durationIsEmpty; + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setBaseDataOffset(long baseDataOffset) { + if (baseDataOffset == -1) { + setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x1)); + } else { + setFlags(getFlags() | 0x1); // activate the field + } + this.baseDataOffset = baseDataOffset; + } + + public void setSampleDescriptionIndex(long sampleDescriptionIndex) { + if (sampleDescriptionIndex == -1) { + setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x2)); + } else { + setFlags(getFlags() | 0x2); // activate the field + } + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + public void setDefaultSampleDuration(long defaultSampleDuration) { + setFlags(getFlags() | 0x8); // activate the field + this.defaultSampleDuration = defaultSampleDuration; + } + + public void setDefaultSampleSize(long defaultSampleSize) { + setFlags(getFlags() | 0x10); // activate the field + this.defaultSampleSize = defaultSampleSize; + } + + public void setDefaultSampleFlags(SampleFlags defaultSampleFlags) { + setFlags(getFlags() | 0x20); // activate the field + this.defaultSampleFlags = defaultSampleFlags; + } + + public void setDurationIsEmpty(boolean durationIsEmpty) { + setFlags(getFlags() | 0x10000); // activate the field + this.durationIsEmpty = durationIsEmpty; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("TrackFragmentHeaderBox"); + sb.append("{trackId=").append(trackId); + sb.append(", baseDataOffset=").append(baseDataOffset); + sb.append(", sampleDescriptionIndex=").append(sampleDescriptionIndex); + sb.append(", defaultSampleDuration=").append(defaultSampleDuration); + sb.append(", defaultSampleSize=").append(defaultSampleSize); + sb.append(", defaultSampleFlags=").append(defaultSampleFlags); + sb.append(", durationIsEmpty=").append(durationIsEmpty); + sb.append('}'); + return sb.toString(); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentRandomAccessBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentRandomAccessBox.java.svn-base new file mode 100644 index 0000000..94d24ae --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackFragmentRandomAccessBox.java.svn-base @@ -0,0 +1,294 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeReaderVariable; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.IsoTypeWriterVariable; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * aligned(8) class TrackFragmentRandomAccessBox + * extends FullBox('tfra', version, 0) { + * unsigned int(32) track_ID; + * const unsigned int(26) reserved = 0; + * unsigned int(2) length_size_of_traf_num; + * unsigned int(2) length_size_of_trun_num; + * unsigned int(2) length_size_of_sample_num; + * unsigned int(32) number_of_entry; + * for(i=1; i <= number_of_entry; i++){ + * if(version==1){ + * unsigned int(64) time; + * unsigned int(64) moof_offset; + * }else{ + * unsigned int(32) time; + * unsigned int(32) moof_offset; + * } + * unsigned int((length_size_of_traf_num+1) * 8) traf_number; + * unsigned int((length_size_of_trun_num+1) * 8) trun_number; + * unsigned int((length_size_of_sample_num+1) * 8) sample_number; + * } + * } + */ +public class TrackFragmentRandomAccessBox extends AbstractFullBox { + public static final String TYPE = "tfra"; + + private long trackId; + private int reserved; + private int lengthSizeOfTrafNum = 2; + private int lengthSizeOfTrunNum = 2; + private int lengthSizeOfSampleNum = 2; + private List<Entry> entries = Collections.emptyList(); + + public TrackFragmentRandomAccessBox() { + super(TYPE); + } + + + protected long getContentSize() { + long contentSize = 4; + contentSize += 4 + 4 /*26 + 2 + 2 + 2 */ + 4; + if (getVersion() == 1) { + contentSize += (8 + 8) * entries.size(); + } else { + contentSize += (4 + 4) * entries.size(); + } + contentSize += lengthSizeOfTrafNum * entries.size(); + contentSize += lengthSizeOfTrunNum * entries.size(); + contentSize += lengthSizeOfSampleNum * entries.size(); + return contentSize; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + long temp = IsoTypeReader.readUInt32(content); + reserved = (int) (temp >> 6); + lengthSizeOfTrafNum = ((int) (temp & 0x3F) >> 4) + 1; + lengthSizeOfTrunNum = ((int) (temp & 0xC) >> 2) + 1; + lengthSizeOfSampleNum = ((int) (temp & 0x3)) + 1; + long numberOfEntries = IsoTypeReader.readUInt32(content); + + entries = new ArrayList<Entry>(); + + for (int i = 0; i < numberOfEntries; i++) { + Entry entry = new Entry(); + if (getVersion() == 1) { + entry.time = IsoTypeReader.readUInt64(content); + entry.moofOffset = IsoTypeReader.readUInt64(content); + } else { + entry.time = IsoTypeReader.readUInt32(content); + entry.moofOffset = IsoTypeReader.readUInt32(content); + } + entry.trafNumber = IsoTypeReaderVariable.read(content, lengthSizeOfTrafNum); + entry.trunNumber = IsoTypeReaderVariable.read(content, lengthSizeOfTrunNum); + entry.sampleNumber = IsoTypeReaderVariable.read(content, lengthSizeOfSampleNum); + + entries.add(entry); + } + + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + long temp; + temp = reserved << 6; + temp = temp | (((lengthSizeOfTrafNum - 1) & 0x3) << 4); + temp = temp | (((lengthSizeOfTrunNum - 1) & 0x3) << 2); + temp = temp | ((lengthSizeOfSampleNum - 1) & 0x3); + IsoTypeWriter.writeUInt32(byteBuffer, temp); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + + for (Entry entry : entries) { + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, entry.time); + IsoTypeWriter.writeUInt64(byteBuffer, entry.moofOffset); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, entry.time); + IsoTypeWriter.writeUInt32(byteBuffer, entry.moofOffset); + } + IsoTypeWriterVariable.write(entry.trafNumber, byteBuffer, lengthSizeOfTrafNum); + IsoTypeWriterVariable.write(entry.trunNumber, byteBuffer, lengthSizeOfTrunNum); + IsoTypeWriterVariable.write(entry.sampleNumber, byteBuffer, lengthSizeOfSampleNum); + + } + } + + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setLengthSizeOfTrafNum(int lengthSizeOfTrafNum) { + this.lengthSizeOfTrafNum = lengthSizeOfTrafNum; + } + + public void setLengthSizeOfTrunNum(int lengthSizeOfTrunNum) { + this.lengthSizeOfTrunNum = lengthSizeOfTrunNum; + } + + public void setLengthSizeOfSampleNum(int lengthSizeOfSampleNum) { + this.lengthSizeOfSampleNum = lengthSizeOfSampleNum; + } + + public long getTrackId() { + return trackId; + } + + public int getReserved() { + return reserved; + } + + public int getLengthSizeOfTrafNum() { + return lengthSizeOfTrafNum; + } + + public int getLengthSizeOfTrunNum() { + return lengthSizeOfTrunNum; + } + + public int getLengthSizeOfSampleNum() { + return lengthSizeOfSampleNum; + } + + public long getNumberOfEntries() { + return entries.size(); + } + + public List<Entry> getEntries() { + return Collections.unmodifiableList(entries); + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + public static class Entry { + private long time; + private long moofOffset; + private long trafNumber; + private long trunNumber; + private long sampleNumber; + + public Entry() { + } + + public Entry(long time, long moofOffset, long trafNumber, long trunNumber, long sampleNumber) { + this.moofOffset = moofOffset; + this.sampleNumber = sampleNumber; + this.time = time; + this.trafNumber = trafNumber; + this.trunNumber = trunNumber; + } + + public long getTime() { + return time; + } + + public long getMoofOffset() { + return moofOffset; + } + + public long getTrafNumber() { + return trafNumber; + } + + public long getTrunNumber() { + return trunNumber; + } + + public long getSampleNumber() { + return sampleNumber; + } + + public void setTime(long time) { + this.time = time; + } + + public void setMoofOffset(long moofOffset) { + this.moofOffset = moofOffset; + } + + public void setTrafNumber(long trafNumber) { + this.trafNumber = trafNumber; + } + + public void setTrunNumber(long trunNumber) { + this.trunNumber = trunNumber; + } + + public void setSampleNumber(long sampleNumber) { + this.sampleNumber = sampleNumber; + } + + @Override + public String toString() { + return "Entry{" + + "time=" + time + + ", moofOffset=" + moofOffset + + ", trafNumber=" + trafNumber + + ", trunNumber=" + trunNumber + + ", sampleNumber=" + sampleNumber + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Entry entry = (Entry) o; + + if (moofOffset != entry.moofOffset) return false; + if (sampleNumber != entry.sampleNumber) return false; + if (time != entry.time) return false; + if (trafNumber != entry.trafNumber) return false; + if (trunNumber != entry.trunNumber) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (time ^ (time >>> 32)); + result = 31 * result + (int) (moofOffset ^ (moofOffset >>> 32)); + result = 31 * result + (int) (trafNumber ^ (trafNumber >>> 32)); + result = 31 * result + (int) (trunNumber ^ (trunNumber >>> 32)); + result = 31 * result + (int) (sampleNumber ^ (sampleNumber >>> 32)); + return result; + } + } + + @Override + public String toString() { + return "TrackFragmentRandomAccessBox{" + + "trackId=" + trackId + + ", entries=" + entries + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackRunBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackRunBox.java.svn-base new file mode 100644 index 0000000..fc4faac --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/.svn/text-base/TrackRunBox.java.svn-base @@ -0,0 +1,355 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.MovieBox; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * aligned(8) class TrackRunBox + * extends FullBox('trun', 0, tr_flags) { + * unsigned int(32) sample_count; + * // the following are optional fields + * signed int(32) data_offset; + * unsigned int(32) first_sample_flags; + * // all fields in the following array are optional + * { + * unsigned int(32) sample_duration; + * unsigned int(32) sample_size; + * unsigned int(32) sample_flags + * unsigned int(32) sample_composition_time_offset; + * }[ sample_count ] + * } + */ + +public class TrackRunBox extends AbstractFullBox { + public static final String TYPE = "trun"; + private int dataOffset; + private SampleFlags firstSampleFlags; + private List<Entry> entries = new ArrayList<Entry>(); + + + public List<Entry> getEntries() { + return entries; + } + + public static class Entry { + private long sampleDuration; + private long sampleSize; + private SampleFlags sampleFlags; + private int sampleCompositionTimeOffset; + + public Entry() { + } + + public Entry(long sampleDuration, long sampleSize, SampleFlags sampleFlags, int sampleCompositionTimeOffset) { + this.sampleDuration = sampleDuration; + this.sampleSize = sampleSize; + this.sampleFlags = sampleFlags; + this.sampleCompositionTimeOffset = sampleCompositionTimeOffset; + } + + public long getSampleDuration() { + return sampleDuration; + } + + public long getSampleSize() { + return sampleSize; + } + + public SampleFlags getSampleFlags() { + return sampleFlags; + } + + public int getSampleCompositionTimeOffset() { + return sampleCompositionTimeOffset; + } + + public void setSampleDuration(long sampleDuration) { + this.sampleDuration = sampleDuration; + } + + public void setSampleSize(long sampleSize) { + this.sampleSize = sampleSize; + } + + public void setSampleFlags(SampleFlags sampleFlags) { + this.sampleFlags = sampleFlags; + } + + public void setSampleCompositionTimeOffset(int sampleCompositionTimeOffset) { + this.sampleCompositionTimeOffset = sampleCompositionTimeOffset; + } + + @Override + public String toString() { + return "Entry{" + + "sampleDuration=" + sampleDuration + + ", sampleSize=" + sampleSize + + ", sampleFlags=" + sampleFlags + + ", sampleCompositionTimeOffset=" + sampleCompositionTimeOffset + + '}'; + } + } + + public void setDataOffset(int dataOffset) { + if (dataOffset == -1) { + setFlags(getFlags() & (0xFFFFFF ^ 1)); + } else { + setFlags(getFlags() | 0x1); // turn on dataoffset + } + this.dataOffset = dataOffset; + } + + public long[] getSampleCompositionTimeOffsets() { + if (isSampleCompositionTimeOffsetPresent()) { + long[] result = new long[entries.size()]; + + for (int i = 0; i < result.length; i++) { + result[i] = entries.get(i).getSampleCompositionTimeOffset(); + } + return result; + } + return null; + } + + public TrackExtendsBox getTrackExtendsBox() { + final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) getParent()).getTrackFragmentHeaderBox(); + final List<MovieBox> movieBoxes = tfhd.getIsoFile().getBoxes(MovieBox.class); + if (movieBoxes.size() == 0) { + return null; + } + + final List<TrackExtendsBox> trexBoxes = movieBoxes.get(0).getBoxes(TrackExtendsBox.class, true); + TrackExtendsBox trex = null; + for (TrackExtendsBox aTrex : trexBoxes) { + if (aTrex.getTrackId() == tfhd.getTrackId()) { + trex = aTrex; + } + } + return trex; + } + + public TrackRunBox() { + super(TYPE); + } + + protected long getContentSize() { + long size = 8; + int flags = getFlags(); + + if ((flags & 0x1) == 0x1) { //dataOffsetPresent + size += 4; + } + if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent + size += 4; + } + + long entrySize = 0; + if ((flags & 0x100) == 0x100) { //sampleDurationPresent + entrySize += 4; + } + if ((flags & 0x200) == 0x200) { //sampleSizePresent + entrySize += 4; + } + if ((flags & 0x400) == 0x400) { //sampleFlagsPresent + entrySize += 4; + } + if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + entrySize += 4; + } + size += entrySize * entries.size(); + return size; + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + int flags = getFlags(); + + if ((flags & 0x1) == 1) { //dataOffsetPresent + IsoTypeWriter.writeUInt32(byteBuffer, dataOffset); + } + if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent + firstSampleFlags.getContent(byteBuffer); + } + + for (Entry entry : entries) { + if ((flags & 0x100) == 0x100) { //sampleDurationPresent + IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleDuration); + } + if ((flags & 0x200) == 0x200) { //sampleSizePresent + IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleSize); + } + if ((flags & 0x400) == 0x400) { //sampleFlagsPresent + entry.sampleFlags.getContent(byteBuffer); + } + if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + byteBuffer.putInt(entry.sampleCompositionTimeOffset); + } + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + long sampleCount = IsoTypeReader.readUInt32(content); + + if ((getFlags() & 0x1) == 1) { //dataOffsetPresent + dataOffset = l2i(IsoTypeReader.readUInt32(content)); + } else { + dataOffset = -1; + } + if ((getFlags() & 0x4) == 0x4) { //firstSampleFlagsPresent + firstSampleFlags = new SampleFlags(content); + } + + for (int i = 0; i < sampleCount; i++) { + Entry entry = new Entry(); + if ((getFlags() & 0x100) == 0x100) { //sampleDurationPresent + entry.sampleDuration = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x200) == 0x200) { //sampleSizePresent + entry.sampleSize = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x400) == 0x400) { //sampleFlagsPresent + entry.sampleFlags = new SampleFlags(content); + } + if ((getFlags() & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + entry.sampleCompositionTimeOffset = content.getInt(); + } + entries.add(entry); + } + + } + + public long getSampleCount() { + return entries.size(); + } + + public boolean isDataOffsetPresent() { + return (getFlags() & 0x1) == 1; + } + + public boolean isFirstSampleFlagsPresent() { + return (getFlags() & 0x4) == 0x4; + } + + + public boolean isSampleSizePresent() { + return (getFlags() & 0x200) == 0x200; + } + + public boolean isSampleDurationPresent() { + return (getFlags() & 0x100) == 0x100; + } + + public boolean isSampleFlagsPresent() { + return (getFlags() & 0x400) == 0x400; + } + + public boolean isSampleCompositionTimeOffsetPresent() { + return (getFlags() & 0x800) == 0x800; + } + + public void setDataOffsetPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x01); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x1)); + } + } + + public void setSampleSizePresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x200); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x200)); + } + } + + public void setSampleDurationPresent(boolean v) { + + if (v) { + setFlags(getFlags() | 0x100); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x100)); + } + } + + public void setSampleFlagsPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x400); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x400)); + } + } + + public void setSampleCompositionTimeOffsetPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x800); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x800)); + } + + } + + public int getDataOffset() { + return dataOffset; + } + + public SampleFlags getFirstSampleFlags() { + return firstSampleFlags; + } + + public void setFirstSampleFlags(SampleFlags firstSampleFlags) { + if (firstSampleFlags == null) { + setFlags(getFlags() & (0xFFFFFF ^ 0x4)); + } else { + setFlags(getFlags() | 0x4); + } + this.firstSampleFlags = firstSampleFlags; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("TrackRunBox"); + sb.append("{sampleCount=").append(entries.size()); + sb.append(", dataOffset=").append(dataOffset); + sb.append(", dataOffsetPresent=").append(isDataOffsetPresent()); + sb.append(", sampleSizePresent=").append(isSampleSizePresent()); + sb.append(", sampleDurationPresent=").append(isSampleDurationPresent()); + sb.append(", sampleFlagsPresentPresent=").append(isSampleFlagsPresent()); + sb.append(", sampleCompositionTimeOffsetPresent=").append(isSampleCompositionTimeOffsetPresent()); + sb.append(", firstSampleFlags=").append(firstSampleFlags); + sb.append('}'); + return sb.toString(); + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsBox.java new file mode 100644 index 0000000..5ecd642 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsBox.java @@ -0,0 +1,31 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * aligned(8) class MovieExtendsBox extends Box('mvex'){ + * } + */ +public class MovieExtendsBox extends AbstractContainerBox { + public static final String TYPE = "mvex"; + + public MovieExtendsBox() { + super(TYPE); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsHeaderBox.java new file mode 100644 index 0000000..8dd58f9 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieExtendsHeaderBox.java @@ -0,0 +1,71 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieExtendsHeaderBox extends FullBox('mehd', version, 0) { + * if (version==1) { + * unsigned int(64) fragment_duration; + * } else { // version==0 + * unsigned int(32) fragment_duration; + * } + * } + */ +public class MovieExtendsHeaderBox extends AbstractFullBox { + public static final String TYPE = "mehd"; + private long fragmentDuration; + + public MovieExtendsHeaderBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return getVersion() == 1 ? 12 : 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + fragmentDuration = getVersion() == 1 ? IsoTypeReader.readUInt64(content) : IsoTypeReader.readUInt32(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, fragmentDuration); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, fragmentDuration); + } + } + + public long getFragmentDuration() { + return fragmentDuration; + } + + public void setFragmentDuration(long fragmentDuration) { + this.fragmentDuration = fragmentDuration; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentBox.java new file mode 100644 index 0000000..e92bd53 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentBox.java @@ -0,0 +1,100 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.SampleDependencyTypeBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.util.ArrayList; +import java.util.List; + +/** + * aligned(8) class MovieFragmentBox extends Box(moof){ + * } + */ + +public class MovieFragmentBox extends AbstractContainerBox { + public static final String TYPE = "moof"; + + public MovieFragmentBox() { + super(TYPE); + } + + + public List<Long> getSyncSamples(SampleDependencyTypeBox sdtp) { + List<Long> result = new ArrayList<Long>(); + + final List<SampleDependencyTypeBox.Entry> sampleEntries = sdtp.getEntries(); + long i = 1; + for (SampleDependencyTypeBox.Entry sampleEntry : sampleEntries) { + if (sampleEntry.getSampleDependsOn() == 2) { + result.add(i); + } + i++; + } + + return result; + } + + @DoNotParseDetail + public long getOffset() { + Box b = this; + long offset = 0; + while (b.getParent() != null) { + for (Box box : b.getParent().getBoxes()) { + if (b == box) { + break; + } + offset += box.getSize(); + } + b = b.getParent(); + } + return offset; + } + + + public int getTrackCount() { + return getBoxes(TrackFragmentBox.class, false).size(); + } + + /** + * Returns the track numbers associated with this <code>MovieBox</code>. + * + * @return the tracknumbers (IDs) of the tracks in their order of appearance in the file + */ + + public long[] getTrackNumbers() { + + List<TrackFragmentBox> trackBoxes = this.getBoxes(TrackFragmentBox.class, false); + long[] trackNumbers = new long[trackBoxes.size()]; + for (int trackCounter = 0; trackCounter < trackBoxes.size(); trackCounter++) { + TrackFragmentBox trackBoxe = trackBoxes.get(trackCounter); + trackNumbers[trackCounter] = trackBoxe.getTrackFragmentHeaderBox().getTrackId(); + } + return trackNumbers; + } + + public List<TrackFragmentHeaderBox> getTrackFragmentHeaderBoxes() { + return getBoxes(TrackFragmentHeaderBox.class, true); + } + + public List<TrackRunBox> getTrackRunBoxes() { + return getBoxes(TrackRunBox.class, true); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentHeaderBox.java new file mode 100644 index 0000000..e58f7a2 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentHeaderBox.java @@ -0,0 +1,72 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieFragmentHeaderBox + * extends FullBox('mfhd', 0, 0){ + * unsigned int(32) sequence_number; + * } + */ + +public class MovieFragmentHeaderBox extends AbstractFullBox { + public static final String TYPE = "mfhd"; + private long sequenceNumber; + + public MovieFragmentHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, sequenceNumber); + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + sequenceNumber = IsoTypeReader.readUInt32(content); + + } + + public long getSequenceNumber() { + return sequenceNumber; + } + + public void setSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } + + @Override + public String toString() { + return "MovieFragmentHeaderBox{" + + "sequenceNumber=" + sequenceNumber + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessBox.java new file mode 100644 index 0000000..86e2c9d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessBox.java @@ -0,0 +1,34 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; + +/** + * aligned(8) class MovieFragmentRandomAccessBox + * extends Box('mfra') + * { + * } + */ +public class MovieFragmentRandomAccessBox extends AbstractContainerBox { + public static final String TYPE = "mfra"; + + public MovieFragmentRandomAccessBox() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessOffsetBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessOffsetBox.java new file mode 100644 index 0000000..edbfd66 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/MovieFragmentRandomAccessOffsetBox.java @@ -0,0 +1,62 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class MovieFragmentRandomAccessOffsetBox + * extends FullBox('mfro', version, 0) { + * unsigned int(32) size; + * } + */ +public class MovieFragmentRandomAccessOffsetBox extends AbstractFullBox { + public static final String TYPE = "mfro"; + private long mfraSize; + + public MovieFragmentRandomAccessOffsetBox() { + super(TYPE); + } + + protected long getContentSize() { + return 8; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + mfraSize = IsoTypeReader.readUInt32(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, mfraSize); + } + + public long getMfraSize() { + return mfraSize; + } + + public void setMfraSize(long mfraSize) { + this.mfraSize = mfraSize; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SampleFlags.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SampleFlags.java new file mode 100644 index 0000000..6caaf1e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SampleFlags.java @@ -0,0 +1,207 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * bit(6) reserved=0; + * unsigned int(2) sample_depends_on; + * unsigned int(2) sample_is_depended_on; + * unsigned int(2) sample_has_redundancy; + * bit(3) sample_padding_value; + * bit(1) sample_is_difference_sample; + * // i.e. when 1 signals a non-key or non-sync sample + * unsigned int(16) sample_degradation_priority; + */ +public class SampleFlags { + private int reserved; + private int sampleDependsOn; + private int sampleIsDependedOn; + private int sampleHasRedundancy; + private int samplePaddingValue; + private boolean sampleIsDifferenceSample; + private int sampleDegradationPriority; + + public SampleFlags() { + + } + + public SampleFlags(ByteBuffer bb) { + BitReaderBuffer brb = new BitReaderBuffer(bb); + reserved = brb.readBits(6); + sampleDependsOn = brb.readBits(2); + sampleIsDependedOn = brb.readBits(2); + sampleHasRedundancy = brb.readBits(2); + samplePaddingValue = brb.readBits(3); + sampleIsDifferenceSample = brb.readBits(1) == 1; + sampleDegradationPriority = brb.readBits(16); + } + + + public void getContent(ByteBuffer os) { + BitWriterBuffer bitWriterBuffer = new BitWriterBuffer(os); + bitWriterBuffer.writeBits(reserved, 6); + bitWriterBuffer.writeBits(sampleDependsOn, 2); + bitWriterBuffer.writeBits(sampleIsDependedOn, 2); + bitWriterBuffer.writeBits(sampleHasRedundancy, 2); + bitWriterBuffer.writeBits(samplePaddingValue, 3); + bitWriterBuffer.writeBits(this.sampleIsDifferenceSample ? 1 : 0, 1); + bitWriterBuffer.writeBits(sampleDegradationPriority, 16); + } + + public int getReserved() { + return reserved; + } + + public void setReserved(int reserved) { + this.reserved = reserved; + } + + /** + * @see #setSampleDependsOn(int) + */ + public int getSampleDependsOn() { + return sampleDependsOn; + } + + /** + * sample_depends_on takes one of the following four values: + * <pre> + * 0: the dependency of this sample is unknown; + * 1: this sample does depend on others (not an I picture); + * 2: this sample does not depend on others (I picture); + * 3: reserved + * </pre> + * + */ + public void setSampleDependsOn(int sampleDependsOn) { + this.sampleDependsOn = sampleDependsOn; + } + + /** + * @see #setSampleIsDependedOn(int) + */ + public int getSampleIsDependedOn() { + return sampleIsDependedOn; + } + + /** + * sample_is_depended_on takes one of the following four values: + * <pre> + * 0: the dependency of other samples on this sample is unknown; + * 1: other samples may depend on this one (not disposable); + * 2: no other sample depends on this one (disposable); + * 3: reserved + * </pre> + * + */ + public void setSampleIsDependedOn(int sampleIsDependedOn) { + this.sampleIsDependedOn = sampleIsDependedOn; + } + + /** + * @see #setSampleHasRedundancy(int) + */ + public int getSampleHasRedundancy() { + return sampleHasRedundancy; + } + + /** + * sample_has_redundancy takes one of the following four values: + * <pre> + * 0: it is unknown whether there is redundant coding in this sample; + * 1: there is redundant coding in this sample; + * 2: there is no redundant coding in this sample; + * 3: reserved + * </pre> + */ + public void setSampleHasRedundancy(int sampleHasRedundancy) { + this.sampleHasRedundancy = sampleHasRedundancy; + } + + public int getSamplePaddingValue() { + return samplePaddingValue; + } + + public void setSamplePaddingValue(int samplePaddingValue) { + this.samplePaddingValue = samplePaddingValue; + } + + public boolean isSampleIsDifferenceSample() { + return sampleIsDifferenceSample; + } + + + public void setSampleIsDifferenceSample(boolean sampleIsDifferenceSample) { + this.sampleIsDifferenceSample = sampleIsDifferenceSample; + } + + public int getSampleDegradationPriority() { + return sampleDegradationPriority; + } + + public void setSampleDegradationPriority(int sampleDegradationPriority) { + this.sampleDegradationPriority = sampleDegradationPriority; + } + + @Override + public String toString() { + return "SampleFlags{" + + "reserved=" + reserved + + ", sampleDependsOn=" + sampleDependsOn + + ", sampleHasRedundancy=" + sampleHasRedundancy + + ", samplePaddingValue=" + samplePaddingValue + + ", sampleIsDifferenceSample=" + sampleIsDifferenceSample + + ", sampleDegradationPriority=" + sampleDegradationPriority + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SampleFlags that = (SampleFlags) o; + + if (reserved != that.reserved) return false; + if (sampleDegradationPriority != that.sampleDegradationPriority) return false; + if (sampleDependsOn != that.sampleDependsOn) return false; + if (sampleHasRedundancy != that.sampleHasRedundancy) return false; + if (sampleIsDependedOn != that.sampleIsDependedOn) return false; + if (sampleIsDifferenceSample != that.sampleIsDifferenceSample) return false; + if (samplePaddingValue != that.samplePaddingValue) return false; + + return true; + } + + @Override + public int hashCode() { + int result = reserved; + result = 31 * result + sampleDependsOn; + result = 31 * result + sampleIsDependedOn; + result = 31 * result + sampleHasRedundancy; + result = 31 * result + samplePaddingValue; + result = 31 * result + (sampleIsDifferenceSample ? 1 : 0); + result = 31 * result + sampleDegradationPriority; + return result; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SegmentTypeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SegmentTypeBox.java new file mode 100644 index 0000000..5e0d47b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/SegmentTypeBox.java @@ -0,0 +1,143 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.annotations.DoNotParseDetail; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * This box identifies the specifications to which this file complies. <br> + * Each brand is a printable four-character code, registered with ISO, that + * identifies a precise specification. + */ +public class SegmentTypeBox extends AbstractBox { + public static final String TYPE = "styp"; + + private String majorBrand; + private long minorVersion; + private List<String> compatibleBrands = Collections.emptyList(); + + public SegmentTypeBox() { + super(TYPE); + } + + public SegmentTypeBox(String majorBrand, long minorVersion, List<String> compatibleBrands) { + super(TYPE); + this.majorBrand = majorBrand; + this.minorVersion = minorVersion; + this.compatibleBrands = compatibleBrands; + } + + protected long getContentSize() { + return 8 + compatibleBrands.size() * 4; + + } + + @Override + public void _parseDetails(ByteBuffer content) { + majorBrand = IsoTypeReader.read4cc(content); + minorVersion = IsoTypeReader.readUInt32(content); + int compatibleBrandsCount = content.remaining() / 4; + compatibleBrands = new LinkedList<String>(); + for (int i = 0; i < compatibleBrandsCount; i++) { + compatibleBrands.add(IsoTypeReader.read4cc(content)); + } + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(majorBrand)); + IsoTypeWriter.writeUInt32(byteBuffer, minorVersion); + for (String compatibleBrand : compatibleBrands) { + byteBuffer.put(IsoFile.fourCCtoBytes(compatibleBrand)); + } + + } + + /** + * Gets the brand identifier. + * + * @return the brand identifier + */ + public String getMajorBrand() { + return majorBrand; + } + + /** + * Sets the major brand of the file used to determine an appropriate reader. + * + * @param majorBrand the new major brand + */ + public void setMajorBrand(String majorBrand) { + this.majorBrand = majorBrand; + } + + /** + * Sets the "informative integer for the minor version of the major brand". + * + * @param minorVersion the version number of the major brand + */ + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + /** + * Gets an informative integer for the minor version of the major brand. + * + * @return an informative integer + * @see SegmentTypeBox#getMajorBrand() + */ + public long getMinorVersion() { + return minorVersion; + } + + /** + * Gets an array of 4-cc brands. + * + * @return the compatible brands + */ + public List<String> getCompatibleBrands() { + return compatibleBrands; + } + + public void setCompatibleBrands(List<String> compatibleBrands) { + this.compatibleBrands = compatibleBrands; + } + + @DoNotParseDetail + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("SegmentTypeBox["); + result.append("majorBrand=").append(getMajorBrand()); + result.append(";"); + result.append("minorVersion=").append(getMinorVersion()); + for (String compatibleBrand : compatibleBrands) { + result.append(";"); + result.append("compatibleBrand=").append(compatibleBrand); + } + result.append("]"); + return result.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackExtendsBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackExtendsBox.java new file mode 100644 index 0000000..8bba7c1 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackExtendsBox.java @@ -0,0 +1,115 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class TrackExtendsBox extends FullBox('trex', 0, 0){ + * unsigned int(32) track_ID; + * unsigned int(32) default_sample_description_index; + * unsigned int(32) default_sample_duration; + * unsigned int(32) default_sample_size; + * unsigned int(32) default_sample_flags + * } + */ +public class TrackExtendsBox extends AbstractFullBox { + public static final String TYPE = "trex"; + private long trackId; + private long defaultSampleDescriptionIndex; + private long defaultSampleDuration; + private long defaultSampleSize; + private SampleFlags defaultSampleFlags; + + public TrackExtendsBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return 5 * 4 + 4; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleDescriptionIndex); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleDuration); + IsoTypeWriter.writeUInt32(byteBuffer, defaultSampleSize); + defaultSampleFlags.getContent(byteBuffer); + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + defaultSampleDescriptionIndex = IsoTypeReader.readUInt32(content); + defaultSampleDuration = IsoTypeReader.readUInt32(content); + defaultSampleSize = IsoTypeReader.readUInt32(content); + defaultSampleFlags = new SampleFlags(content); + } + + public long getTrackId() { + return trackId; + } + + public long getDefaultSampleDescriptionIndex() { + return defaultSampleDescriptionIndex; + } + + public long getDefaultSampleDuration() { + return defaultSampleDuration; + } + + public long getDefaultSampleSize() { + return defaultSampleSize; + } + + public SampleFlags getDefaultSampleFlags() { + return defaultSampleFlags; + } + + public String getDefaultSampleFlagsStr() { + return defaultSampleFlags.toString(); + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setDefaultSampleDescriptionIndex(long defaultSampleDescriptionIndex) { + this.defaultSampleDescriptionIndex = defaultSampleDescriptionIndex; + } + + public void setDefaultSampleDuration(long defaultSampleDuration) { + this.defaultSampleDuration = defaultSampleDuration; + } + + public void setDefaultSampleSize(long defaultSampleSize) { + this.defaultSampleSize = defaultSampleSize; + } + + public void setDefaultSampleFlags(SampleFlags defaultSampleFlags) { + this.defaultSampleFlags = defaultSampleFlags; + + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBaseMediaDecodeTimeBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBaseMediaDecodeTimeBox.java new file mode 100644 index 0000000..06fcf62 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBaseMediaDecodeTimeBox.java @@ -0,0 +1,76 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +public class TrackFragmentBaseMediaDecodeTimeBox extends AbstractFullBox { + public static final String TYPE = "tfdt"; + + private long baseMediaDecodeTime; + + public TrackFragmentBaseMediaDecodeTimeBox() { + super(TYPE); + } + + @Override + protected long getContentSize() { + return getVersion() == 0 ? 8 : 12; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, baseMediaDecodeTime); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, baseMediaDecodeTime); + } + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + if (getVersion() == 1) { + baseMediaDecodeTime = IsoTypeReader.readUInt64(content); + } else { + baseMediaDecodeTime = IsoTypeReader.readUInt32(content); + } + + } + + + public long getBaseMediaDecodeTime() { + return baseMediaDecodeTime; + } + + public void setBaseMediaDecodeTime(long baseMediaDecodeTime) { + this.baseMediaDecodeTime = baseMediaDecodeTime; + } + + @Override + public String toString() { + return "TrackFragmentBaseMediaDecodeTimeBox{" + + "baseMediaDecodeTime=" + baseMediaDecodeTime + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBox.java new file mode 100644 index 0000000..fde7da5 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentBox.java @@ -0,0 +1,43 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.googlecode.mp4parser.AbstractContainerBox; +import com.coremedia.iso.boxes.Box; + +/** + * aligned(8) class TrackFragmentBox extends Box('traf'){ + * } + */ +public class TrackFragmentBox extends AbstractContainerBox { + public static final String TYPE = "traf"; + + public TrackFragmentBox() { + super(TYPE); + } + + + public TrackFragmentHeaderBox getTrackFragmentHeaderBox() { + for (Box box : getBoxes()) { + if (box instanceof TrackFragmentHeaderBox) { + return (TrackFragmentHeaderBox) box; + } + } + return null; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentHeaderBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentHeaderBox.java new file mode 100644 index 0000000..fb9509b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentHeaderBox.java @@ -0,0 +1,224 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * aligned(8) class TrackFragmentHeaderBox + * extends FullBox('tfhd', 0, tf_flags){ + * unsigned int(32) track_ID; + * // all the following are optional fields + * unsigned int(64) base_data_offset; + * unsigned int(32) sample_description_index; + * unsigned int(32) default_sample_duration; + * unsigned int(32) default_sample_size; + * unsigned int(32) default_sample_flags + * } + */ +public class TrackFragmentHeaderBox extends AbstractFullBox { + public static final String TYPE = "tfhd"; + + private long trackId; + private long baseDataOffset = -1; + private long sampleDescriptionIndex; + private long defaultSampleDuration = -1; + private long defaultSampleSize = -1; + private SampleFlags defaultSampleFlags; + private boolean durationIsEmpty; + + public TrackFragmentHeaderBox() { + super(TYPE); + } + + protected long getContentSize() { + long size = 8; + int flags = getFlags(); + if ((flags & 0x1) == 1) { //baseDataOffsetPresent + size += 8; + } + if ((flags & 0x2) == 0x2) { //sampleDescriptionIndexPresent + size += 4; + } + if ((flags & 0x8) == 0x8) { //defaultSampleDurationPresent + size += 4; + } + if ((flags & 0x10) == 0x10) { //defaultSampleSizePresent + size += 4; + } + if ((flags & 0x20) == 0x20) { //defaultSampleFlagsPresent + size += 4; + } + return size; + } + + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + + if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent + IsoTypeWriter.writeUInt64(byteBuffer, getBaseDataOffset()); + } + if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent + IsoTypeWriter.writeUInt32(byteBuffer, getSampleDescriptionIndex()); + } + if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent + IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleDuration()); + } + if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent + IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleSize()); + } + if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent + defaultSampleFlags.getContent(byteBuffer); + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent + baseDataOffset = IsoTypeReader.readUInt64(content); + } + if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent + sampleDescriptionIndex = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent + defaultSampleDuration = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent + defaultSampleSize = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent + defaultSampleFlags = new SampleFlags(content); + } + if ((getFlags() & 0x10000) == 0x10000) { //durationIsEmpty + durationIsEmpty = true; + } + } + + public boolean hasBaseDataOffset() { + return (getFlags() & 0x1) != 0; + } + + public boolean hasSampleDescriptionIndex() { + return (getFlags() & 0x2) != 0; + } + + public boolean hasDefaultSampleDuration() { + return (getFlags() & 0x8) != 0; + } + + public boolean hasDefaultSampleSize() { + return (getFlags() & 0x10) != 0; + } + + public boolean hasDefaultSampleFlags() { + return (getFlags() & 0x20) != 0; + } + + public long getTrackId() { + return trackId; + } + + public long getBaseDataOffset() { + return baseDataOffset; + } + + public long getSampleDescriptionIndex() { + return sampleDescriptionIndex; + } + + public long getDefaultSampleDuration() { + return defaultSampleDuration; + } + + public long getDefaultSampleSize() { + return defaultSampleSize; + } + + public SampleFlags getDefaultSampleFlags() { + return defaultSampleFlags; + } + + public boolean isDurationIsEmpty() { + return durationIsEmpty; + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setBaseDataOffset(long baseDataOffset) { + if (baseDataOffset == -1) { + setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x1)); + } else { + setFlags(getFlags() | 0x1); // activate the field + } + this.baseDataOffset = baseDataOffset; + } + + public void setSampleDescriptionIndex(long sampleDescriptionIndex) { + if (sampleDescriptionIndex == -1) { + setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x2)); + } else { + setFlags(getFlags() | 0x2); // activate the field + } + this.sampleDescriptionIndex = sampleDescriptionIndex; + } + + public void setDefaultSampleDuration(long defaultSampleDuration) { + setFlags(getFlags() | 0x8); // activate the field + this.defaultSampleDuration = defaultSampleDuration; + } + + public void setDefaultSampleSize(long defaultSampleSize) { + setFlags(getFlags() | 0x10); // activate the field + this.defaultSampleSize = defaultSampleSize; + } + + public void setDefaultSampleFlags(SampleFlags defaultSampleFlags) { + setFlags(getFlags() | 0x20); // activate the field + this.defaultSampleFlags = defaultSampleFlags; + } + + public void setDurationIsEmpty(boolean durationIsEmpty) { + setFlags(getFlags() | 0x10000); // activate the field + this.durationIsEmpty = durationIsEmpty; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("TrackFragmentHeaderBox"); + sb.append("{trackId=").append(trackId); + sb.append(", baseDataOffset=").append(baseDataOffset); + sb.append(", sampleDescriptionIndex=").append(sampleDescriptionIndex); + sb.append(", defaultSampleDuration=").append(defaultSampleDuration); + sb.append(", defaultSampleSize=").append(defaultSampleSize); + sb.append(", defaultSampleFlags=").append(defaultSampleFlags); + sb.append(", durationIsEmpty=").append(durationIsEmpty); + sb.append('}'); + return sb.toString(); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentRandomAccessBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentRandomAccessBox.java new file mode 100644 index 0000000..94d24ae --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackFragmentRandomAccessBox.java @@ -0,0 +1,294 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeReaderVariable; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.IsoTypeWriterVariable; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * aligned(8) class TrackFragmentRandomAccessBox + * extends FullBox('tfra', version, 0) { + * unsigned int(32) track_ID; + * const unsigned int(26) reserved = 0; + * unsigned int(2) length_size_of_traf_num; + * unsigned int(2) length_size_of_trun_num; + * unsigned int(2) length_size_of_sample_num; + * unsigned int(32) number_of_entry; + * for(i=1; i <= number_of_entry; i++){ + * if(version==1){ + * unsigned int(64) time; + * unsigned int(64) moof_offset; + * }else{ + * unsigned int(32) time; + * unsigned int(32) moof_offset; + * } + * unsigned int((length_size_of_traf_num+1) * 8) traf_number; + * unsigned int((length_size_of_trun_num+1) * 8) trun_number; + * unsigned int((length_size_of_sample_num+1) * 8) sample_number; + * } + * } + */ +public class TrackFragmentRandomAccessBox extends AbstractFullBox { + public static final String TYPE = "tfra"; + + private long trackId; + private int reserved; + private int lengthSizeOfTrafNum = 2; + private int lengthSizeOfTrunNum = 2; + private int lengthSizeOfSampleNum = 2; + private List<Entry> entries = Collections.emptyList(); + + public TrackFragmentRandomAccessBox() { + super(TYPE); + } + + + protected long getContentSize() { + long contentSize = 4; + contentSize += 4 + 4 /*26 + 2 + 2 + 2 */ + 4; + if (getVersion() == 1) { + contentSize += (8 + 8) * entries.size(); + } else { + contentSize += (4 + 4) * entries.size(); + } + contentSize += lengthSizeOfTrafNum * entries.size(); + contentSize += lengthSizeOfTrunNum * entries.size(); + contentSize += lengthSizeOfSampleNum * entries.size(); + return contentSize; + } + + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + trackId = IsoTypeReader.readUInt32(content); + long temp = IsoTypeReader.readUInt32(content); + reserved = (int) (temp >> 6); + lengthSizeOfTrafNum = ((int) (temp & 0x3F) >> 4) + 1; + lengthSizeOfTrunNum = ((int) (temp & 0xC) >> 2) + 1; + lengthSizeOfSampleNum = ((int) (temp & 0x3)) + 1; + long numberOfEntries = IsoTypeReader.readUInt32(content); + + entries = new ArrayList<Entry>(); + + for (int i = 0; i < numberOfEntries; i++) { + Entry entry = new Entry(); + if (getVersion() == 1) { + entry.time = IsoTypeReader.readUInt64(content); + entry.moofOffset = IsoTypeReader.readUInt64(content); + } else { + entry.time = IsoTypeReader.readUInt32(content); + entry.moofOffset = IsoTypeReader.readUInt32(content); + } + entry.trafNumber = IsoTypeReaderVariable.read(content, lengthSizeOfTrafNum); + entry.trunNumber = IsoTypeReaderVariable.read(content, lengthSizeOfTrunNum); + entry.sampleNumber = IsoTypeReaderVariable.read(content, lengthSizeOfSampleNum); + + entries.add(entry); + } + + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, trackId); + long temp; + temp = reserved << 6; + temp = temp | (((lengthSizeOfTrafNum - 1) & 0x3) << 4); + temp = temp | (((lengthSizeOfTrunNum - 1) & 0x3) << 2); + temp = temp | ((lengthSizeOfSampleNum - 1) & 0x3); + IsoTypeWriter.writeUInt32(byteBuffer, temp); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + + for (Entry entry : entries) { + if (getVersion() == 1) { + IsoTypeWriter.writeUInt64(byteBuffer, entry.time); + IsoTypeWriter.writeUInt64(byteBuffer, entry.moofOffset); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, entry.time); + IsoTypeWriter.writeUInt32(byteBuffer, entry.moofOffset); + } + IsoTypeWriterVariable.write(entry.trafNumber, byteBuffer, lengthSizeOfTrafNum); + IsoTypeWriterVariable.write(entry.trunNumber, byteBuffer, lengthSizeOfTrunNum); + IsoTypeWriterVariable.write(entry.sampleNumber, byteBuffer, lengthSizeOfSampleNum); + + } + } + + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public void setLengthSizeOfTrafNum(int lengthSizeOfTrafNum) { + this.lengthSizeOfTrafNum = lengthSizeOfTrafNum; + } + + public void setLengthSizeOfTrunNum(int lengthSizeOfTrunNum) { + this.lengthSizeOfTrunNum = lengthSizeOfTrunNum; + } + + public void setLengthSizeOfSampleNum(int lengthSizeOfSampleNum) { + this.lengthSizeOfSampleNum = lengthSizeOfSampleNum; + } + + public long getTrackId() { + return trackId; + } + + public int getReserved() { + return reserved; + } + + public int getLengthSizeOfTrafNum() { + return lengthSizeOfTrafNum; + } + + public int getLengthSizeOfTrunNum() { + return lengthSizeOfTrunNum; + } + + public int getLengthSizeOfSampleNum() { + return lengthSizeOfSampleNum; + } + + public long getNumberOfEntries() { + return entries.size(); + } + + public List<Entry> getEntries() { + return Collections.unmodifiableList(entries); + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } + + public static class Entry { + private long time; + private long moofOffset; + private long trafNumber; + private long trunNumber; + private long sampleNumber; + + public Entry() { + } + + public Entry(long time, long moofOffset, long trafNumber, long trunNumber, long sampleNumber) { + this.moofOffset = moofOffset; + this.sampleNumber = sampleNumber; + this.time = time; + this.trafNumber = trafNumber; + this.trunNumber = trunNumber; + } + + public long getTime() { + return time; + } + + public long getMoofOffset() { + return moofOffset; + } + + public long getTrafNumber() { + return trafNumber; + } + + public long getTrunNumber() { + return trunNumber; + } + + public long getSampleNumber() { + return sampleNumber; + } + + public void setTime(long time) { + this.time = time; + } + + public void setMoofOffset(long moofOffset) { + this.moofOffset = moofOffset; + } + + public void setTrafNumber(long trafNumber) { + this.trafNumber = trafNumber; + } + + public void setTrunNumber(long trunNumber) { + this.trunNumber = trunNumber; + } + + public void setSampleNumber(long sampleNumber) { + this.sampleNumber = sampleNumber; + } + + @Override + public String toString() { + return "Entry{" + + "time=" + time + + ", moofOffset=" + moofOffset + + ", trafNumber=" + trafNumber + + ", trunNumber=" + trunNumber + + ", sampleNumber=" + sampleNumber + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Entry entry = (Entry) o; + + if (moofOffset != entry.moofOffset) return false; + if (sampleNumber != entry.sampleNumber) return false; + if (time != entry.time) return false; + if (trafNumber != entry.trafNumber) return false; + if (trunNumber != entry.trunNumber) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (time ^ (time >>> 32)); + result = 31 * result + (int) (moofOffset ^ (moofOffset >>> 32)); + result = 31 * result + (int) (trafNumber ^ (trafNumber >>> 32)); + result = 31 * result + (int) (trunNumber ^ (trunNumber >>> 32)); + result = 31 * result + (int) (sampleNumber ^ (sampleNumber >>> 32)); + return result; + } + } + + @Override + public String toString() { + return "TrackFragmentRandomAccessBox{" + + "trackId=" + trackId + + ", entries=" + entries + + '}'; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java new file mode 100644 index 0000000..fc4faac --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java @@ -0,0 +1,355 @@ +/* + * Copyright 2009 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.coremedia.iso.boxes.fragment; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.MovieBox; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * aligned(8) class TrackRunBox + * extends FullBox('trun', 0, tr_flags) { + * unsigned int(32) sample_count; + * // the following are optional fields + * signed int(32) data_offset; + * unsigned int(32) first_sample_flags; + * // all fields in the following array are optional + * { + * unsigned int(32) sample_duration; + * unsigned int(32) sample_size; + * unsigned int(32) sample_flags + * unsigned int(32) sample_composition_time_offset; + * }[ sample_count ] + * } + */ + +public class TrackRunBox extends AbstractFullBox { + public static final String TYPE = "trun"; + private int dataOffset; + private SampleFlags firstSampleFlags; + private List<Entry> entries = new ArrayList<Entry>(); + + + public List<Entry> getEntries() { + return entries; + } + + public static class Entry { + private long sampleDuration; + private long sampleSize; + private SampleFlags sampleFlags; + private int sampleCompositionTimeOffset; + + public Entry() { + } + + public Entry(long sampleDuration, long sampleSize, SampleFlags sampleFlags, int sampleCompositionTimeOffset) { + this.sampleDuration = sampleDuration; + this.sampleSize = sampleSize; + this.sampleFlags = sampleFlags; + this.sampleCompositionTimeOffset = sampleCompositionTimeOffset; + } + + public long getSampleDuration() { + return sampleDuration; + } + + public long getSampleSize() { + return sampleSize; + } + + public SampleFlags getSampleFlags() { + return sampleFlags; + } + + public int getSampleCompositionTimeOffset() { + return sampleCompositionTimeOffset; + } + + public void setSampleDuration(long sampleDuration) { + this.sampleDuration = sampleDuration; + } + + public void setSampleSize(long sampleSize) { + this.sampleSize = sampleSize; + } + + public void setSampleFlags(SampleFlags sampleFlags) { + this.sampleFlags = sampleFlags; + } + + public void setSampleCompositionTimeOffset(int sampleCompositionTimeOffset) { + this.sampleCompositionTimeOffset = sampleCompositionTimeOffset; + } + + @Override + public String toString() { + return "Entry{" + + "sampleDuration=" + sampleDuration + + ", sampleSize=" + sampleSize + + ", sampleFlags=" + sampleFlags + + ", sampleCompositionTimeOffset=" + sampleCompositionTimeOffset + + '}'; + } + } + + public void setDataOffset(int dataOffset) { + if (dataOffset == -1) { + setFlags(getFlags() & (0xFFFFFF ^ 1)); + } else { + setFlags(getFlags() | 0x1); // turn on dataoffset + } + this.dataOffset = dataOffset; + } + + public long[] getSampleCompositionTimeOffsets() { + if (isSampleCompositionTimeOffsetPresent()) { + long[] result = new long[entries.size()]; + + for (int i = 0; i < result.length; i++) { + result[i] = entries.get(i).getSampleCompositionTimeOffset(); + } + return result; + } + return null; + } + + public TrackExtendsBox getTrackExtendsBox() { + final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) getParent()).getTrackFragmentHeaderBox(); + final List<MovieBox> movieBoxes = tfhd.getIsoFile().getBoxes(MovieBox.class); + if (movieBoxes.size() == 0) { + return null; + } + + final List<TrackExtendsBox> trexBoxes = movieBoxes.get(0).getBoxes(TrackExtendsBox.class, true); + TrackExtendsBox trex = null; + for (TrackExtendsBox aTrex : trexBoxes) { + if (aTrex.getTrackId() == tfhd.getTrackId()) { + trex = aTrex; + } + } + return trex; + } + + public TrackRunBox() { + super(TYPE); + } + + protected long getContentSize() { + long size = 8; + int flags = getFlags(); + + if ((flags & 0x1) == 0x1) { //dataOffsetPresent + size += 4; + } + if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent + size += 4; + } + + long entrySize = 0; + if ((flags & 0x100) == 0x100) { //sampleDurationPresent + entrySize += 4; + } + if ((flags & 0x200) == 0x200) { //sampleSizePresent + entrySize += 4; + } + if ((flags & 0x400) == 0x400) { //sampleFlagsPresent + entrySize += 4; + } + if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + entrySize += 4; + } + size += entrySize * entries.size(); + return size; + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); + int flags = getFlags(); + + if ((flags & 0x1) == 1) { //dataOffsetPresent + IsoTypeWriter.writeUInt32(byteBuffer, dataOffset); + } + if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent + firstSampleFlags.getContent(byteBuffer); + } + + for (Entry entry : entries) { + if ((flags & 0x100) == 0x100) { //sampleDurationPresent + IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleDuration); + } + if ((flags & 0x200) == 0x200) { //sampleSizePresent + IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleSize); + } + if ((flags & 0x400) == 0x400) { //sampleFlagsPresent + entry.sampleFlags.getContent(byteBuffer); + } + if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + byteBuffer.putInt(entry.sampleCompositionTimeOffset); + } + } + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + long sampleCount = IsoTypeReader.readUInt32(content); + + if ((getFlags() & 0x1) == 1) { //dataOffsetPresent + dataOffset = l2i(IsoTypeReader.readUInt32(content)); + } else { + dataOffset = -1; + } + if ((getFlags() & 0x4) == 0x4) { //firstSampleFlagsPresent + firstSampleFlags = new SampleFlags(content); + } + + for (int i = 0; i < sampleCount; i++) { + Entry entry = new Entry(); + if ((getFlags() & 0x100) == 0x100) { //sampleDurationPresent + entry.sampleDuration = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x200) == 0x200) { //sampleSizePresent + entry.sampleSize = IsoTypeReader.readUInt32(content); + } + if ((getFlags() & 0x400) == 0x400) { //sampleFlagsPresent + entry.sampleFlags = new SampleFlags(content); + } + if ((getFlags() & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent + entry.sampleCompositionTimeOffset = content.getInt(); + } + entries.add(entry); + } + + } + + public long getSampleCount() { + return entries.size(); + } + + public boolean isDataOffsetPresent() { + return (getFlags() & 0x1) == 1; + } + + public boolean isFirstSampleFlagsPresent() { + return (getFlags() & 0x4) == 0x4; + } + + + public boolean isSampleSizePresent() { + return (getFlags() & 0x200) == 0x200; + } + + public boolean isSampleDurationPresent() { + return (getFlags() & 0x100) == 0x100; + } + + public boolean isSampleFlagsPresent() { + return (getFlags() & 0x400) == 0x400; + } + + public boolean isSampleCompositionTimeOffsetPresent() { + return (getFlags() & 0x800) == 0x800; + } + + public void setDataOffsetPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x01); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x1)); + } + } + + public void setSampleSizePresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x200); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x200)); + } + } + + public void setSampleDurationPresent(boolean v) { + + if (v) { + setFlags(getFlags() | 0x100); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x100)); + } + } + + public void setSampleFlagsPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x400); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x400)); + } + } + + public void setSampleCompositionTimeOffsetPresent(boolean v) { + if (v) { + setFlags(getFlags() | 0x800); + } else { + setFlags(getFlags() & (0xFFFFFF ^ 0x800)); + } + + } + + public int getDataOffset() { + return dataOffset; + } + + public SampleFlags getFirstSampleFlags() { + return firstSampleFlags; + } + + public void setFirstSampleFlags(SampleFlags firstSampleFlags) { + if (firstSampleFlags == null) { + setFlags(getFlags() & (0xFFFFFF ^ 0x4)); + } else { + setFlags(getFlags() | 0x4); + } + this.firstSampleFlags = firstSampleFlags; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("TrackRunBox"); + sb.append("{sampleCount=").append(entries.size()); + sb.append(", dataOffset=").append(dataOffset); + sb.append(", dataOffsetPresent=").append(isDataOffsetPresent()); + sb.append(", sampleSizePresent=").append(isSampleSizePresent()); + sb.append(", sampleDurationPresent=").append(isSampleDurationPresent()); + sb.append(", sampleFlagsPresentPresent=").append(isSampleFlagsPresent()); + sb.append(", sampleCompositionTimeOffsetPresent=").append(isSampleCompositionTimeOffsetPresent()); + sb.append(", firstSampleFlags=").append(firstSampleFlags); + sb.append('}'); + return sb.toString(); + } + + public void setEntries(List<Entry> entries) { + this.entries = entries; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/all-wcprops new file mode 100644 index 0000000..15d84c0 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/!svn/ver/777/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/h264 +END +AvcConfigurationBox.java +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/!svn/ver/777/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/h264/AvcConfigurationBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/entries new file mode 100644 index 0000000..ccf8f72 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/h264 +http://mp4parser.googlecode.com/svn + + + +2012-09-10T14:56:10.036617Z +777 +sebastian.annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +AvcConfigurationBox.java +file + + + + +2012-09-14T17:27:52.727250Z +676ca6ae057828e6b82a8e4fa58caa3e +2012-09-10T14:56:10.036617Z +777 +sebastian.annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +15420 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/text-base/AvcConfigurationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/text-base/AvcConfigurationBox.java.svn-base new file mode 100644 index 0000000..52f3695 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/.svn/text-base/AvcConfigurationBox.java.svn-base @@ -0,0 +1,378 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.h264; + +import com.coremedia.iso.Hex; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer; +import com.googlecode.mp4parser.h264.model.PictureParameterSet; +import com.googlecode.mp4parser.h264.model.SeqParameterSet; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Defined in ISO/IEC 14496-15:2004. + */ +public final class AvcConfigurationBox extends AbstractBox { + public static final String TYPE = "avcC"; + + public AVCDecoderConfigurationRecord avcDecoderConfigurationRecord = new AVCDecoderConfigurationRecord(); + + + public AvcConfigurationBox() { + super(TYPE); + } + + public int getConfigurationVersion() { + return avcDecoderConfigurationRecord.configurationVersion; + } + + public int getAvcProfileIndication() { + return avcDecoderConfigurationRecord.avcProfileIndication; + } + + public int getProfileCompatibility() { + return avcDecoderConfigurationRecord.profileCompatibility; + } + + public int getAvcLevelIndication() { + return avcDecoderConfigurationRecord.avcLevelIndication; + } + + public int getLengthSizeMinusOne() { + return avcDecoderConfigurationRecord.lengthSizeMinusOne; + } + + public List<byte[]> getSequenceParameterSets() { + return Collections.unmodifiableList(avcDecoderConfigurationRecord.sequenceParameterSets); + } + + public List<byte[]> getPictureParameterSets() { + return Collections.unmodifiableList(avcDecoderConfigurationRecord.pictureParameterSets); + } + + public void setConfigurationVersion(int configurationVersion) { + this.avcDecoderConfigurationRecord.configurationVersion = configurationVersion; + } + + public void setAvcProfileIndication(int avcProfileIndication) { + this.avcDecoderConfigurationRecord.avcProfileIndication = avcProfileIndication; + } + + public void setProfileCompatibility(int profileCompatibility) { + this.avcDecoderConfigurationRecord.profileCompatibility = profileCompatibility; + } + + public void setAvcLevelIndication(int avcLevelIndication) { + this.avcDecoderConfigurationRecord.avcLevelIndication = avcLevelIndication; + } + + public void setLengthSizeMinusOne(int lengthSizeMinusOne) { + this.avcDecoderConfigurationRecord.lengthSizeMinusOne = lengthSizeMinusOne; + } + + public void setSequenceParameterSets(List<byte[]> sequenceParameterSets) { + this.avcDecoderConfigurationRecord.sequenceParameterSets = sequenceParameterSets; + } + + public void setPictureParameterSets(List<byte[]> pictureParameterSets) { + this.avcDecoderConfigurationRecord.pictureParameterSets = pictureParameterSets; + } + + public int getChromaFormat() { + return avcDecoderConfigurationRecord.chromaFormat; + } + + public void setChromaFormat(int chromaFormat) { + this.avcDecoderConfigurationRecord.chromaFormat = chromaFormat; + } + + public int getBitDepthLumaMinus8() { + return avcDecoderConfigurationRecord.bitDepthLumaMinus8; + } + + public void setBitDepthLumaMinus8(int bitDepthLumaMinus8) { + this.avcDecoderConfigurationRecord.bitDepthLumaMinus8 = bitDepthLumaMinus8; + } + + public int getBitDepthChromaMinus8() { + return avcDecoderConfigurationRecord.bitDepthChromaMinus8; + } + + public void setBitDepthChromaMinus8(int bitDepthChromaMinus8) { + this.avcDecoderConfigurationRecord.bitDepthChromaMinus8 = bitDepthChromaMinus8; + } + + public List<byte[]> getSequenceParameterSetExts() { + return avcDecoderConfigurationRecord.sequenceParameterSetExts; + } + + public void setSequenceParameterSetExts(List<byte[]> sequenceParameterSetExts) { + this.avcDecoderConfigurationRecord.sequenceParameterSetExts = sequenceParameterSetExts; + } + + public boolean hasExts() { + return avcDecoderConfigurationRecord.hasExts; + } + + public void setHasExts(boolean hasExts) { + this.avcDecoderConfigurationRecord.hasExts = hasExts; + } + + @Override + public void _parseDetails(ByteBuffer content) { + avcDecoderConfigurationRecord = new AVCDecoderConfigurationRecord(content); + } + + + @Override + public long getContentSize() { + return avcDecoderConfigurationRecord.getContentSize(); + } + + + @Override + public void getContent(ByteBuffer byteBuffer) { + avcDecoderConfigurationRecord.getContent(byteBuffer); + } + + // just to display sps in isoviewer no practical use + public String[] getSPS() { + return avcDecoderConfigurationRecord.getSPS(); + } + + public String[] getPPS() { + return avcDecoderConfigurationRecord.getPPS(); + } + + public List<String> getSequenceParameterSetsAsStrings() { + return avcDecoderConfigurationRecord.getSequenceParameterSetsAsStrings(); + } + + public List<String> getSequenceParameterSetExtsAsStrings() { + return avcDecoderConfigurationRecord.getSequenceParameterSetExtsAsStrings(); + } + + public List<String> getPictureParameterSetsAsStrings() { + return avcDecoderConfigurationRecord.getPictureParameterSetsAsStrings(); + } + + public AVCDecoderConfigurationRecord getavcDecoderConfigurationRecord() { + return avcDecoderConfigurationRecord; + } + + + public static class AVCDecoderConfigurationRecord { + public int configurationVersion; + public int avcProfileIndication; + public int profileCompatibility; + public int avcLevelIndication; + public int lengthSizeMinusOne; + public List<byte[]> sequenceParameterSets = new ArrayList<byte[]>(); + public List<byte[]> pictureParameterSets = new ArrayList<byte[]>(); + + public boolean hasExts = true; + public int chromaFormat = 1; + public int bitDepthLumaMinus8 = 0; + public int bitDepthChromaMinus8 = 0; + public List<byte[]> sequenceParameterSetExts = new ArrayList<byte[]>(); + + /** + * Just for non-spec-conform encoders + */ + public int lengthSizeMinusOnePaddingBits = 60; + public int numberOfSequenceParameterSetsPaddingBits = 7; + public int chromaFormatPaddingBits = 31; + public int bitDepthLumaMinus8PaddingBits = 31; + public int bitDepthChromaMinus8PaddingBits = 31; + + public AVCDecoderConfigurationRecord() { + } + + public AVCDecoderConfigurationRecord(ByteBuffer content) { + configurationVersion = IsoTypeReader.readUInt8(content); + avcProfileIndication = IsoTypeReader.readUInt8(content); + profileCompatibility = IsoTypeReader.readUInt8(content); + avcLevelIndication = IsoTypeReader.readUInt8(content); + BitReaderBuffer brb = new BitReaderBuffer(content); + lengthSizeMinusOnePaddingBits = brb.readBits(6); + lengthSizeMinusOne = brb.readBits(2); + numberOfSequenceParameterSetsPaddingBits = brb.readBits(3); + int numberOfSeuqenceParameterSets = brb.readBits(5); + for (int i = 0; i < numberOfSeuqenceParameterSets; i++) { + int sequenceParameterSetLength = IsoTypeReader.readUInt16(content); + + byte[] sequenceParameterSetNALUnit = new byte[sequenceParameterSetLength]; + content.get(sequenceParameterSetNALUnit); + sequenceParameterSets.add(sequenceParameterSetNALUnit); + } + long numberOfPictureParameterSets = IsoTypeReader.readUInt8(content); + for (int i = 0; i < numberOfPictureParameterSets; i++) { + int pictureParameterSetLength = IsoTypeReader.readUInt16(content); + byte[] pictureParameterSetNALUnit = new byte[pictureParameterSetLength]; + content.get(pictureParameterSetNALUnit); + pictureParameterSets.add(pictureParameterSetNALUnit); + } + if (content.remaining() < 4) { + hasExts = false; + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + // actually only some bits are interesting so masking with & x would be good but not all Mp4 creating tools set the reserved bits to 1. + // So we need to store all bits + brb = new BitReaderBuffer(content); + chromaFormatPaddingBits = brb.readBits(6); + chromaFormat = brb.readBits(2); + bitDepthLumaMinus8PaddingBits = brb.readBits(5); + bitDepthLumaMinus8 = brb.readBits(3); + bitDepthChromaMinus8PaddingBits = brb.readBits(5); + bitDepthChromaMinus8 = brb.readBits(3); + long numOfSequenceParameterSetExt = IsoTypeReader.readUInt8(content); + for (int i = 0; i < numOfSequenceParameterSetExt; i++) { + int sequenceParameterSetExtLength = IsoTypeReader.readUInt16(content); + byte[] sequenceParameterSetExtNALUnit = new byte[sequenceParameterSetExtLength]; + content.get(sequenceParameterSetExtNALUnit); + sequenceParameterSetExts.add(sequenceParameterSetExtNALUnit); + } + } else { + chromaFormat = -1; + bitDepthLumaMinus8 = -1; + bitDepthChromaMinus8 = -1; + } + } + + public void getContent(ByteBuffer byteBuffer) { + IsoTypeWriter.writeUInt8(byteBuffer, configurationVersion); + IsoTypeWriter.writeUInt8(byteBuffer, avcProfileIndication); + IsoTypeWriter.writeUInt8(byteBuffer, profileCompatibility); + IsoTypeWriter.writeUInt8(byteBuffer, avcLevelIndication); + BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer); + bwb.writeBits(lengthSizeMinusOnePaddingBits, 6); + bwb.writeBits(lengthSizeMinusOne, 2); + bwb.writeBits(numberOfSequenceParameterSetsPaddingBits, 3); + bwb.writeBits(pictureParameterSets.size(), 5); + for (byte[] sequenceParameterSetNALUnit : sequenceParameterSets) { + IsoTypeWriter.writeUInt16(byteBuffer, sequenceParameterSetNALUnit.length); + byteBuffer.put(sequenceParameterSetNALUnit); + } + IsoTypeWriter.writeUInt8(byteBuffer, pictureParameterSets.size()); + for (byte[] pictureParameterSetNALUnit : pictureParameterSets) { + IsoTypeWriter.writeUInt16(byteBuffer, pictureParameterSetNALUnit.length); + byteBuffer.put(pictureParameterSetNALUnit); + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + + bwb = new BitWriterBuffer(byteBuffer); + bwb.writeBits(chromaFormatPaddingBits, 6); + bwb.writeBits(chromaFormat, 2); + bwb.writeBits(bitDepthLumaMinus8PaddingBits, 5); + bwb.writeBits(bitDepthLumaMinus8, 3); + bwb.writeBits(bitDepthChromaMinus8PaddingBits, 5); + bwb.writeBits(bitDepthChromaMinus8, 3); + for (byte[] sequenceParameterSetExtNALUnit : sequenceParameterSetExts) { + IsoTypeWriter.writeUInt16(byteBuffer, sequenceParameterSetExtNALUnit.length); + byteBuffer.put(sequenceParameterSetExtNALUnit); + } + } + } + + public long getContentSize() { + long size = 5; + size += 1; // sequenceParamsetLength + for (byte[] sequenceParameterSetNALUnit : sequenceParameterSets) { + size += 2; //lengthSizeMinusOne field + size += sequenceParameterSetNALUnit.length; + } + size += 1; // pictureParamsetLength + for (byte[] pictureParameterSetNALUnit : pictureParameterSets) { + size += 2; //lengthSizeMinusOne field + size += pictureParameterSetNALUnit.length; + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + size += 4; + for (byte[] sequenceParameterSetExtNALUnit : sequenceParameterSetExts) { + size += 2; + size += sequenceParameterSetExtNALUnit.length; + } + } + + return size; + } + + public String[] getPPS() { + ArrayList<String> l = new ArrayList<String>(); + for (byte[] pictureParameterSet : pictureParameterSets) { + String details = "not parsable"; + try { + details = PictureParameterSet.read(pictureParameterSet).toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + l.add(details); + } + return l.toArray(new String[l.size()]); + } + + public String[] getSPS() { + ArrayList<String> l = new ArrayList<String>(); + for (byte[] sequenceParameterSet : sequenceParameterSets) { + String detail = "not parsable"; + try { + detail = SeqParameterSet.read(new ByteArrayInputStream(sequenceParameterSet)).toString(); + } catch (IOException e) { + + } + l.add(detail); + } + return l.toArray(new String[l.size()]); + } + + public List<String> getSequenceParameterSetsAsStrings() { + List <String> result = new ArrayList<String>(sequenceParameterSets.size()); + for (byte[] parameterSet : sequenceParameterSets) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + public List<String> getSequenceParameterSetExtsAsStrings() { + List <String> result = new ArrayList<String>(sequenceParameterSetExts.size()); + for (byte[] parameterSet : sequenceParameterSetExts) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + public List<String> getPictureParameterSetsAsStrings() { + List <String> result = new ArrayList<String>(pictureParameterSets.size()); + for (byte[] parameterSet : pictureParameterSets) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + } +} + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/h264/AvcConfigurationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/AvcConfigurationBox.java new file mode 100644 index 0000000..52f3695 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/h264/AvcConfigurationBox.java @@ -0,0 +1,378 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.h264; + +import com.coremedia.iso.Hex; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer; +import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer; +import com.googlecode.mp4parser.h264.model.PictureParameterSet; +import com.googlecode.mp4parser.h264.model.SeqParameterSet; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Defined in ISO/IEC 14496-15:2004. + */ +public final class AvcConfigurationBox extends AbstractBox { + public static final String TYPE = "avcC"; + + public AVCDecoderConfigurationRecord avcDecoderConfigurationRecord = new AVCDecoderConfigurationRecord(); + + + public AvcConfigurationBox() { + super(TYPE); + } + + public int getConfigurationVersion() { + return avcDecoderConfigurationRecord.configurationVersion; + } + + public int getAvcProfileIndication() { + return avcDecoderConfigurationRecord.avcProfileIndication; + } + + public int getProfileCompatibility() { + return avcDecoderConfigurationRecord.profileCompatibility; + } + + public int getAvcLevelIndication() { + return avcDecoderConfigurationRecord.avcLevelIndication; + } + + public int getLengthSizeMinusOne() { + return avcDecoderConfigurationRecord.lengthSizeMinusOne; + } + + public List<byte[]> getSequenceParameterSets() { + return Collections.unmodifiableList(avcDecoderConfigurationRecord.sequenceParameterSets); + } + + public List<byte[]> getPictureParameterSets() { + return Collections.unmodifiableList(avcDecoderConfigurationRecord.pictureParameterSets); + } + + public void setConfigurationVersion(int configurationVersion) { + this.avcDecoderConfigurationRecord.configurationVersion = configurationVersion; + } + + public void setAvcProfileIndication(int avcProfileIndication) { + this.avcDecoderConfigurationRecord.avcProfileIndication = avcProfileIndication; + } + + public void setProfileCompatibility(int profileCompatibility) { + this.avcDecoderConfigurationRecord.profileCompatibility = profileCompatibility; + } + + public void setAvcLevelIndication(int avcLevelIndication) { + this.avcDecoderConfigurationRecord.avcLevelIndication = avcLevelIndication; + } + + public void setLengthSizeMinusOne(int lengthSizeMinusOne) { + this.avcDecoderConfigurationRecord.lengthSizeMinusOne = lengthSizeMinusOne; + } + + public void setSequenceParameterSets(List<byte[]> sequenceParameterSets) { + this.avcDecoderConfigurationRecord.sequenceParameterSets = sequenceParameterSets; + } + + public void setPictureParameterSets(List<byte[]> pictureParameterSets) { + this.avcDecoderConfigurationRecord.pictureParameterSets = pictureParameterSets; + } + + public int getChromaFormat() { + return avcDecoderConfigurationRecord.chromaFormat; + } + + public void setChromaFormat(int chromaFormat) { + this.avcDecoderConfigurationRecord.chromaFormat = chromaFormat; + } + + public int getBitDepthLumaMinus8() { + return avcDecoderConfigurationRecord.bitDepthLumaMinus8; + } + + public void setBitDepthLumaMinus8(int bitDepthLumaMinus8) { + this.avcDecoderConfigurationRecord.bitDepthLumaMinus8 = bitDepthLumaMinus8; + } + + public int getBitDepthChromaMinus8() { + return avcDecoderConfigurationRecord.bitDepthChromaMinus8; + } + + public void setBitDepthChromaMinus8(int bitDepthChromaMinus8) { + this.avcDecoderConfigurationRecord.bitDepthChromaMinus8 = bitDepthChromaMinus8; + } + + public List<byte[]> getSequenceParameterSetExts() { + return avcDecoderConfigurationRecord.sequenceParameterSetExts; + } + + public void setSequenceParameterSetExts(List<byte[]> sequenceParameterSetExts) { + this.avcDecoderConfigurationRecord.sequenceParameterSetExts = sequenceParameterSetExts; + } + + public boolean hasExts() { + return avcDecoderConfigurationRecord.hasExts; + } + + public void setHasExts(boolean hasExts) { + this.avcDecoderConfigurationRecord.hasExts = hasExts; + } + + @Override + public void _parseDetails(ByteBuffer content) { + avcDecoderConfigurationRecord = new AVCDecoderConfigurationRecord(content); + } + + + @Override + public long getContentSize() { + return avcDecoderConfigurationRecord.getContentSize(); + } + + + @Override + public void getContent(ByteBuffer byteBuffer) { + avcDecoderConfigurationRecord.getContent(byteBuffer); + } + + // just to display sps in isoviewer no practical use + public String[] getSPS() { + return avcDecoderConfigurationRecord.getSPS(); + } + + public String[] getPPS() { + return avcDecoderConfigurationRecord.getPPS(); + } + + public List<String> getSequenceParameterSetsAsStrings() { + return avcDecoderConfigurationRecord.getSequenceParameterSetsAsStrings(); + } + + public List<String> getSequenceParameterSetExtsAsStrings() { + return avcDecoderConfigurationRecord.getSequenceParameterSetExtsAsStrings(); + } + + public List<String> getPictureParameterSetsAsStrings() { + return avcDecoderConfigurationRecord.getPictureParameterSetsAsStrings(); + } + + public AVCDecoderConfigurationRecord getavcDecoderConfigurationRecord() { + return avcDecoderConfigurationRecord; + } + + + public static class AVCDecoderConfigurationRecord { + public int configurationVersion; + public int avcProfileIndication; + public int profileCompatibility; + public int avcLevelIndication; + public int lengthSizeMinusOne; + public List<byte[]> sequenceParameterSets = new ArrayList<byte[]>(); + public List<byte[]> pictureParameterSets = new ArrayList<byte[]>(); + + public boolean hasExts = true; + public int chromaFormat = 1; + public int bitDepthLumaMinus8 = 0; + public int bitDepthChromaMinus8 = 0; + public List<byte[]> sequenceParameterSetExts = new ArrayList<byte[]>(); + + /** + * Just for non-spec-conform encoders + */ + public int lengthSizeMinusOnePaddingBits = 60; + public int numberOfSequenceParameterSetsPaddingBits = 7; + public int chromaFormatPaddingBits = 31; + public int bitDepthLumaMinus8PaddingBits = 31; + public int bitDepthChromaMinus8PaddingBits = 31; + + public AVCDecoderConfigurationRecord() { + } + + public AVCDecoderConfigurationRecord(ByteBuffer content) { + configurationVersion = IsoTypeReader.readUInt8(content); + avcProfileIndication = IsoTypeReader.readUInt8(content); + profileCompatibility = IsoTypeReader.readUInt8(content); + avcLevelIndication = IsoTypeReader.readUInt8(content); + BitReaderBuffer brb = new BitReaderBuffer(content); + lengthSizeMinusOnePaddingBits = brb.readBits(6); + lengthSizeMinusOne = brb.readBits(2); + numberOfSequenceParameterSetsPaddingBits = brb.readBits(3); + int numberOfSeuqenceParameterSets = brb.readBits(5); + for (int i = 0; i < numberOfSeuqenceParameterSets; i++) { + int sequenceParameterSetLength = IsoTypeReader.readUInt16(content); + + byte[] sequenceParameterSetNALUnit = new byte[sequenceParameterSetLength]; + content.get(sequenceParameterSetNALUnit); + sequenceParameterSets.add(sequenceParameterSetNALUnit); + } + long numberOfPictureParameterSets = IsoTypeReader.readUInt8(content); + for (int i = 0; i < numberOfPictureParameterSets; i++) { + int pictureParameterSetLength = IsoTypeReader.readUInt16(content); + byte[] pictureParameterSetNALUnit = new byte[pictureParameterSetLength]; + content.get(pictureParameterSetNALUnit); + pictureParameterSets.add(pictureParameterSetNALUnit); + } + if (content.remaining() < 4) { + hasExts = false; + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + // actually only some bits are interesting so masking with & x would be good but not all Mp4 creating tools set the reserved bits to 1. + // So we need to store all bits + brb = new BitReaderBuffer(content); + chromaFormatPaddingBits = brb.readBits(6); + chromaFormat = brb.readBits(2); + bitDepthLumaMinus8PaddingBits = brb.readBits(5); + bitDepthLumaMinus8 = brb.readBits(3); + bitDepthChromaMinus8PaddingBits = brb.readBits(5); + bitDepthChromaMinus8 = brb.readBits(3); + long numOfSequenceParameterSetExt = IsoTypeReader.readUInt8(content); + for (int i = 0; i < numOfSequenceParameterSetExt; i++) { + int sequenceParameterSetExtLength = IsoTypeReader.readUInt16(content); + byte[] sequenceParameterSetExtNALUnit = new byte[sequenceParameterSetExtLength]; + content.get(sequenceParameterSetExtNALUnit); + sequenceParameterSetExts.add(sequenceParameterSetExtNALUnit); + } + } else { + chromaFormat = -1; + bitDepthLumaMinus8 = -1; + bitDepthChromaMinus8 = -1; + } + } + + public void getContent(ByteBuffer byteBuffer) { + IsoTypeWriter.writeUInt8(byteBuffer, configurationVersion); + IsoTypeWriter.writeUInt8(byteBuffer, avcProfileIndication); + IsoTypeWriter.writeUInt8(byteBuffer, profileCompatibility); + IsoTypeWriter.writeUInt8(byteBuffer, avcLevelIndication); + BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer); + bwb.writeBits(lengthSizeMinusOnePaddingBits, 6); + bwb.writeBits(lengthSizeMinusOne, 2); + bwb.writeBits(numberOfSequenceParameterSetsPaddingBits, 3); + bwb.writeBits(pictureParameterSets.size(), 5); + for (byte[] sequenceParameterSetNALUnit : sequenceParameterSets) { + IsoTypeWriter.writeUInt16(byteBuffer, sequenceParameterSetNALUnit.length); + byteBuffer.put(sequenceParameterSetNALUnit); + } + IsoTypeWriter.writeUInt8(byteBuffer, pictureParameterSets.size()); + for (byte[] pictureParameterSetNALUnit : pictureParameterSets) { + IsoTypeWriter.writeUInt16(byteBuffer, pictureParameterSetNALUnit.length); + byteBuffer.put(pictureParameterSetNALUnit); + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + + bwb = new BitWriterBuffer(byteBuffer); + bwb.writeBits(chromaFormatPaddingBits, 6); + bwb.writeBits(chromaFormat, 2); + bwb.writeBits(bitDepthLumaMinus8PaddingBits, 5); + bwb.writeBits(bitDepthLumaMinus8, 3); + bwb.writeBits(bitDepthChromaMinus8PaddingBits, 5); + bwb.writeBits(bitDepthChromaMinus8, 3); + for (byte[] sequenceParameterSetExtNALUnit : sequenceParameterSetExts) { + IsoTypeWriter.writeUInt16(byteBuffer, sequenceParameterSetExtNALUnit.length); + byteBuffer.put(sequenceParameterSetExtNALUnit); + } + } + } + + public long getContentSize() { + long size = 5; + size += 1; // sequenceParamsetLength + for (byte[] sequenceParameterSetNALUnit : sequenceParameterSets) { + size += 2; //lengthSizeMinusOne field + size += sequenceParameterSetNALUnit.length; + } + size += 1; // pictureParamsetLength + for (byte[] pictureParameterSetNALUnit : pictureParameterSets) { + size += 2; //lengthSizeMinusOne field + size += pictureParameterSetNALUnit.length; + } + if (hasExts && (avcProfileIndication == 100 || avcProfileIndication == 110 || avcProfileIndication == 122 || avcProfileIndication == 144)) { + size += 4; + for (byte[] sequenceParameterSetExtNALUnit : sequenceParameterSetExts) { + size += 2; + size += sequenceParameterSetExtNALUnit.length; + } + } + + return size; + } + + public String[] getPPS() { + ArrayList<String> l = new ArrayList<String>(); + for (byte[] pictureParameterSet : pictureParameterSets) { + String details = "not parsable"; + try { + details = PictureParameterSet.read(pictureParameterSet).toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + l.add(details); + } + return l.toArray(new String[l.size()]); + } + + public String[] getSPS() { + ArrayList<String> l = new ArrayList<String>(); + for (byte[] sequenceParameterSet : sequenceParameterSets) { + String detail = "not parsable"; + try { + detail = SeqParameterSet.read(new ByteArrayInputStream(sequenceParameterSet)).toString(); + } catch (IOException e) { + + } + l.add(detail); + } + return l.toArray(new String[l.size()]); + } + + public List<String> getSequenceParameterSetsAsStrings() { + List <String> result = new ArrayList<String>(sequenceParameterSets.size()); + for (byte[] parameterSet : sequenceParameterSets) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + public List<String> getSequenceParameterSetExtsAsStrings() { + List <String> result = new ArrayList<String>(sequenceParameterSetExts.size()); + for (byte[] parameterSet : sequenceParameterSetExts) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + public List<String> getPictureParameterSetsAsStrings() { + List <String> result = new ArrayList<String>(pictureParameterSets.size()); + for (byte[] parameterSet : pictureParameterSets) { + result.add(Hex.encodeHex(parameterSet)); + } + return result; + } + + } +} + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/all-wcprops new file mode 100644 index 0000000..238325a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/!svn/ver/772/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/mdat +END +MediaDataBox.java +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/!svn/ver/772/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/MediaDataBox.java +END +DummyMap.java +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/DummyMap.java +END +SampleList.java +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/671/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/SampleList.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/entries new file mode 100644 index 0000000..7dc6a8e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/mdat +http://mp4parser.googlecode.com/svn + + + +2012-09-01T02:22:41.253285Z +772 +michael.stattmann@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +MediaDataBox.java +file + + + + +2012-09-14T17:27:52.567248Z +9805155611e85fdee88d368ada02bbdb +2012-09-01T02:22:41.253285Z +772 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +7442 + +DummyMap.java +file + + + + +2012-09-14T17:27:52.567248Z +911189888371eb0f2ae03f4e019d33c5 +2012-03-05T23:28:24.666173Z +377 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1722 + +SampleList.java +file + + + + +2012-09-14T17:27:52.567248Z +1986183baf9f90328a4a7131cf21897d +2012-06-10T18:50:38.971172Z +671 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +9770 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/DummyMap.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/DummyMap.java.svn-base new file mode 100644 index 0000000..ab96023 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/DummyMap.java.svn-base @@ -0,0 +1,84 @@ +package com.coremedia.iso.boxes.mdat; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * A SortedSet that contains just one value. + */ +public class DummyMap<K, V> implements Map<K, V> { + HashSet<K> keys = new HashSet<K>(); + V value; + + public DummyMap(V value) { + this.value = value; + } + + public Comparator<? super K> comparator() { + return null; // I don't have any + } + + public void addKeys(K[] keys) { + Collections.addAll(this.keys, keys); + + } + + public int size() { + return keys.size(); + } + + public boolean isEmpty() { + return keys.isEmpty(); + } + + public boolean containsKey(Object key) { + return keys.contains(key); + } + + public boolean containsValue(Object value) { + return this.value == value; + } + + public V get(Object key) { + return keys.contains(key) ? value : null; + } + + public V put(K key, V value) { + assert this.value == value; + keys.add(key); + return this.value; + } + + public V remove(Object key) { + V v = get(key); + keys.remove(key); + return v; + } + + public void putAll(Map<? extends K, ? extends V> m) { + for (K k : m.keySet()) { + assert m.get(k) == value; + this.keys.add(k); + } + } + + public void clear() { + keys.clear(); + } + + public Set<K> keySet() { + return keys; + } + + public Collection<V> values() { + throw new UnsupportedOperationException(); + } + + public Set<Entry<K, V>> entrySet() { + throw new UnsupportedOperationException(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/MediaDataBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/MediaDataBox.java.svn-base new file mode 100644 index 0000000..5075a15 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/MediaDataBox.java.svn-base @@ -0,0 +1,189 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.mdat; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.ChannelHelper; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.AbstractBox; + +import java.io.IOException; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box contains the media data. In video tracks, this box would contain video frames. A presentation may + * contain zero or more Media Data Boxes. The actual media data follows the type field; its structure is described + * by the metadata (see {@link com.coremedia.iso.boxes.SampleTableBox}).<br> + * In large presentations, it may be desirable to have more data in this box than a 32-bit size would permit. In this + * case, the large variant of the size field is used.<br> + * There may be any number of these boxes in the file (including zero, if all the media data is in other files). The + * metadata refers to media data by its absolute offset within the file (see {@link com.coremedia.iso.boxes.StaticChunkOffsetBox}); + * so Media Data Box headers and free space may easily be skipped, and files without any box structure may + * also be referenced and used. + */ +public final class MediaDataBox implements Box { + private static Logger LOG = Logger.getLogger(MediaDataBox.class.getName()); + + public static final String TYPE = "mdat"; + public static final int BUFFER_SIZE = 10 * 1024 * 1024; + ContainerBox parent; + + ByteBuffer header; + + // These fields are for the special case of a FileChannel as input. + private FileChannel fileChannel; + private long startPosition; + private long contentSize; + + + private Map<Long, Reference<ByteBuffer>> cache = new HashMap<Long, Reference<ByteBuffer>>(); + + + /** + * If the whole content is just in one mapped buffer keep a strong reference to it so it is + * not evicted from the cache. + */ + private ByteBuffer content; + + public ContainerBox getParent() { + return parent; + } + + public void setParent(ContainerBox parent) { + this.parent = parent; + } + + public String getType() { + return TYPE; + } + + private static void transfer(FileChannel from, long position, long count, WritableByteChannel to) throws IOException { + long maxCount = (64 * 1024 * 1024) - (32 * 1024); + // Transfer data in chunks a bit less than 64MB + // People state that this is a kind of magic number on Windows. + // I don't care. The size seems reasonable. + long offset = 0; + while (offset < count) { + offset += from.transferTo(position + offset, Math.min(maxCount, count - offset), to); + } + } + + public void getBox(WritableByteChannel writableByteChannel) throws IOException { + if (fileChannel != null) { + assert checkStillOk(); + transfer(fileChannel, startPosition - header.limit(), contentSize + header.limit(), writableByteChannel); + } else { + header.rewind(); + writableByteChannel.write(header); + writableByteChannel.write(content); + } + } + + /** + * If someone use the same file as source and sink it could the case that + * inserting a few bytes before the mdat results in overwrting data we still + * need to write this mdat here. This method just makes sure that we haven't already + * overwritten the mdat contents. + * + * @return true if ok + */ + private boolean checkStillOk() { + try { + fileChannel.position(startPosition - header.limit()); + ByteBuffer h2 = ByteBuffer.allocate(header.limit()); + fileChannel.read(h2); + header.rewind(); + h2.rewind(); + assert h2.equals(header) : "It seems that the content I want to read has already been overwritten."; + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + } + + + public long getSize() { + long size = header.limit(); + size += contentSize; + return size; + } + + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + this.header = header; + this.contentSize = contentSize; + + if (readableByteChannel instanceof FileChannel && (contentSize > AbstractBox.MEM_MAP_THRESHOLD)) { + this.fileChannel = ((FileChannel) readableByteChannel); + this.startPosition = ((FileChannel) readableByteChannel).position(); + ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); + } else { + content = ChannelHelper.readFully(readableByteChannel, l2i(contentSize)); + cache.put(0l, new SoftReference<ByteBuffer>(content)); + } + } + + public synchronized ByteBuffer getContent(long offset, int length) { + + for (Long chacheEntryOffset : cache.keySet()) { + if (chacheEntryOffset <= offset && offset <= chacheEntryOffset + BUFFER_SIZE) { + ByteBuffer cacheEntry = cache.get(chacheEntryOffset).get(); + if ((cacheEntry != null) && ((chacheEntryOffset + cacheEntry.limit()) >= (offset + length))) { + // CACHE HIT + cacheEntry.position((int) (offset - chacheEntryOffset)); + ByteBuffer cachedSample = cacheEntry.slice(); + cachedSample.limit(length); + return cachedSample; + } + } + } + // CACHE MISS + ByteBuffer cacheEntry; + try { + // Just mapping 10MB at a time. Seems reasonable. + cacheEntry = fileChannel.map(FileChannel.MapMode.READ_ONLY, startPosition + offset, Math.min(BUFFER_SIZE, contentSize - offset)); + } catch (IOException e1) { + LOG.fine("Even mapping just 10MB of the source file into the memory failed. " + e1); + throw new RuntimeException( + "Delayed reading of mdat content failed. Make sure not to close " + + "the FileChannel that has been used to create the IsoFile!", e1); + } + cache.put(offset, new SoftReference<ByteBuffer>(cacheEntry)); + cacheEntry.position(0); + ByteBuffer cachedSample = cacheEntry.slice(); + cachedSample.limit(length); + return cachedSample; + } + + + public ByteBuffer getHeader() { + return header; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/SampleList.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/SampleList.java.svn-base new file mode 100644 index 0000000..a7f7b59 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/.svn/text-base/SampleList.java.svn-base @@ -0,0 +1,227 @@ +package com.coremedia.iso.boxes.mdat; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.boxes.*; +import com.coremedia.iso.boxes.fragment.*; + +import java.nio.ByteBuffer; +import java.util.*; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Creates a list of <code>ByteBuffer</code>s that represent the samples of a given track. + */ +public class SampleList extends AbstractList<ByteBuffer> { + + + long[] offsets; + long[] sizes; + + IsoFile isoFile; + HashMap<MediaDataBox, Long> mdatStartCache = new HashMap<MediaDataBox, Long>(); + HashMap<MediaDataBox, Long> mdatEndCache = new HashMap<MediaDataBox, Long>(); + MediaDataBox[] mdats; + + /** + * Gets a sorted random access optimized list of all sample offsets. + * Basically it is a map from sample number to sample offset. + * + * @return the sorted list of sample offsets + */ + public long[] getOffsetKeys() { + return offsets; + } + + + public SampleList(TrackBox trackBox) { + initIsoFile(trackBox.getIsoFile()); // where are we? + + // first we get all sample from the 'normal' MP4 part. + // if there are none - no problem. + SampleSizeBox sampleSizeBox = trackBox.getSampleTableBox().getSampleSizeBox(); + ChunkOffsetBox chunkOffsetBox = trackBox.getSampleTableBox().getChunkOffsetBox(); + SampleToChunkBox sampleToChunkBox = trackBox.getSampleTableBox().getSampleToChunkBox(); + + + final long[] chunkOffsets = chunkOffsetBox != null ? chunkOffsetBox.getChunkOffsets() : new long[0]; + if (sampleToChunkBox != null && sampleToChunkBox.getEntries().size() > 0 && + chunkOffsets.length > 0 && sampleSizeBox != null && sampleSizeBox.getSampleCount() > 0) { + long[] numberOfSamplesInChunk = sampleToChunkBox.blowup(chunkOffsets.length); + + int sampleIndex = 0; + + if (sampleSizeBox.getSampleSize() > 0) { + sizes = new long[l2i(sampleSizeBox.getSampleCount())]; + Arrays.fill(sizes, sampleSizeBox.getSampleSize()); + } else { + sizes = sampleSizeBox.getSampleSizes(); + } + offsets = new long[sizes.length]; + + for (int i = 0; i < numberOfSamplesInChunk.length; i++) { + long thisChunksNumberOfSamples = numberOfSamplesInChunk[i]; + long sampleOffset = chunkOffsets[i]; + for (int j = 0; j < thisChunksNumberOfSamples; j++) { + long sampleSize = sizes[sampleIndex]; + offsets[sampleIndex] = sampleOffset; + sampleOffset += sampleSize; + sampleIndex++; + } + } + + } + + // Next we add all samples from the fragments + // in most cases - I've never seen it different it's either normal or fragmented. + List<MovieExtendsBox> movieExtendsBoxes = trackBox.getParent().getBoxes(MovieExtendsBox.class); + + if (movieExtendsBoxes.size() > 0) { + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + List<TrackExtendsBox> trackExtendsBoxes = movieExtendsBoxes.get(0).getBoxes(TrackExtendsBox.class); + for (TrackExtendsBox trackExtendsBox : trackExtendsBoxes) { + if (trackExtendsBox.getTrackId() == trackBox.getTrackHeaderBox().getTrackId()) { + for (MovieFragmentBox movieFragmentBox : trackBox.getIsoFile().getBoxes(MovieFragmentBox.class)) { + offsets2Sizes.putAll(getOffsets(movieFragmentBox, trackBox.getTrackHeaderBox().getTrackId(), trackExtendsBox)); + } + } + } + + if (sizes == null || offsets == null) { + sizes = new long[0]; + offsets = new long[0]; + } + + splitToArrays(offsets2Sizes); + } + + // We have now a map from all sample offsets to their sizes + } + + private void splitToArrays(Map<Long, Long> offsets2Sizes) { + List<Long> keys = new ArrayList<Long>(offsets2Sizes.keySet()); + Collections.sort(keys); + + long[] nuSizes = new long[sizes.length + keys.size()]; + System.arraycopy(sizes, 0, nuSizes, 0, sizes.length); + long[] nuOffsets = new long[offsets.length + keys.size()]; + System.arraycopy(offsets, 0, nuOffsets, 0, offsets.length); + for (int i = 0; i < keys.size(); i++) { + nuOffsets[i + offsets.length] = keys.get(i); + nuSizes[i + sizes.length] = offsets2Sizes.get(keys.get(i)); + } + sizes = nuSizes; + offsets = nuOffsets; + } + + public SampleList(TrackFragmentBox traf) { + sizes = new long[0]; + offsets = new long[0]; + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + initIsoFile(traf.getIsoFile()); + + final List<MovieFragmentBox> movieFragmentBoxList = isoFile.getBoxes(MovieFragmentBox.class); + + final long trackId = traf.getTrackFragmentHeaderBox().getTrackId(); + for (MovieFragmentBox moof : movieFragmentBoxList) { + final List<TrackFragmentHeaderBox> trackFragmentHeaderBoxes = moof.getTrackFragmentHeaderBoxes(); + for (TrackFragmentHeaderBox tfhd : trackFragmentHeaderBoxes) { + if (tfhd.getTrackId() == trackId) { + offsets2Sizes.putAll(getOffsets(moof, trackId, null)); + } + } + } + splitToArrays(offsets2Sizes); + } + + private void initIsoFile(IsoFile isoFile) { + this.isoFile = isoFile; + // find all mdats first to be able to use them later with explicitly looking them up + long currentOffset = 0; + LinkedList<MediaDataBox> mdats = new LinkedList<MediaDataBox>(); + for (Box b : this.isoFile.getBoxes()) { + long currentSize = b.getSize(); + if ("mdat".equals(b.getType())) { + if (b instanceof MediaDataBox) { + long contentOffset = currentOffset + ((MediaDataBox) b).getHeader().limit(); + mdatStartCache.put((MediaDataBox) b, contentOffset); + mdatEndCache.put((MediaDataBox) b, contentOffset + currentSize); + mdats.add((MediaDataBox) b); + } else { + throw new RuntimeException("Sample need to be in mdats and mdats need to be instanceof MediaDataBox"); + } + } + currentOffset += currentSize; + } + this.mdats = mdats.toArray(new MediaDataBox[mdats.size()]); + } + + + @Override + public int size() { + return sizes.length; + } + + + @Override + public ByteBuffer get(int index) { + // it is a two stage lookup: from index to offset to size + long offset = offsets[index]; + int sampleSize = l2i(sizes[index]); + + for (MediaDataBox mediaDataBox : mdats) { + long start = mdatStartCache.get(mediaDataBox); + long end = mdatEndCache.get(mediaDataBox); + if ((start <= offset) && (offset + sampleSize <= end)) { + return mediaDataBox.getContent(offset - start, sampleSize); + } + } + + throw new RuntimeException("The sample with offset " + offset + " and size " + sampleSize + " is NOT located within an mdat"); + } + + Map<Long, Long> getOffsets(MovieFragmentBox moof, long trackId, TrackExtendsBox trex) { + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + List<TrackFragmentBox> traf = moof.getBoxes(TrackFragmentBox.class); + for (TrackFragmentBox trackFragmentBox : traf) { + if (trackFragmentBox.getTrackFragmentHeaderBox().getTrackId() == trackId) { + long baseDataOffset; + if (trackFragmentBox.getTrackFragmentHeaderBox().hasBaseDataOffset()) { + baseDataOffset = trackFragmentBox.getTrackFragmentHeaderBox().getBaseDataOffset(); + } else { + baseDataOffset = moof.getOffset(); + } + + for (TrackRunBox trun : trackFragmentBox.getBoxes(TrackRunBox.class)) { + long sampleBaseOffset = baseDataOffset + trun.getDataOffset(); + final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) trun.getParent()).getTrackFragmentHeaderBox(); + + long offset = 0; + for (TrackRunBox.Entry entry : trun.getEntries()) { + final long sampleSize; + if (trun.isSampleSizePresent()) { + sampleSize = entry.getSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } else { + if (tfhd.hasDefaultSampleSize()) { + sampleSize = tfhd.getDefaultSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } else { + if (trex == null) { + throw new RuntimeException("File doesn't contain trex box but track fragments aren't fully self contained. Cannot determine sample size."); + } + sampleSize = trex.getDefaultSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } + } + } + } + } + } + return offsets2Sizes; + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/DummyMap.java b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/DummyMap.java new file mode 100644 index 0000000..ab96023 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/DummyMap.java @@ -0,0 +1,84 @@ +package com.coremedia.iso.boxes.mdat; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * A SortedSet that contains just one value. + */ +public class DummyMap<K, V> implements Map<K, V> { + HashSet<K> keys = new HashSet<K>(); + V value; + + public DummyMap(V value) { + this.value = value; + } + + public Comparator<? super K> comparator() { + return null; // I don't have any + } + + public void addKeys(K[] keys) { + Collections.addAll(this.keys, keys); + + } + + public int size() { + return keys.size(); + } + + public boolean isEmpty() { + return keys.isEmpty(); + } + + public boolean containsKey(Object key) { + return keys.contains(key); + } + + public boolean containsValue(Object value) { + return this.value == value; + } + + public V get(Object key) { + return keys.contains(key) ? value : null; + } + + public V put(K key, V value) { + assert this.value == value; + keys.add(key); + return this.value; + } + + public V remove(Object key) { + V v = get(key); + keys.remove(key); + return v; + } + + public void putAll(Map<? extends K, ? extends V> m) { + for (K k : m.keySet()) { + assert m.get(k) == value; + this.keys.add(k); + } + } + + public void clear() { + keys.clear(); + } + + public Set<K> keySet() { + return keys; + } + + public Collection<V> values() { + throw new UnsupportedOperationException(); + } + + public Set<Entry<K, V>> entrySet() { + throw new UnsupportedOperationException(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/MediaDataBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/MediaDataBox.java new file mode 100644 index 0000000..5075a15 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/MediaDataBox.java @@ -0,0 +1,189 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.mdat; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.ChannelHelper; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.AbstractBox; + +import java.io.IOException; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * This box contains the media data. In video tracks, this box would contain video frames. A presentation may + * contain zero or more Media Data Boxes. The actual media data follows the type field; its structure is described + * by the metadata (see {@link com.coremedia.iso.boxes.SampleTableBox}).<br> + * In large presentations, it may be desirable to have more data in this box than a 32-bit size would permit. In this + * case, the large variant of the size field is used.<br> + * There may be any number of these boxes in the file (including zero, if all the media data is in other files). The + * metadata refers to media data by its absolute offset within the file (see {@link com.coremedia.iso.boxes.StaticChunkOffsetBox}); + * so Media Data Box headers and free space may easily be skipped, and files without any box structure may + * also be referenced and used. + */ +public final class MediaDataBox implements Box { + private static Logger LOG = Logger.getLogger(MediaDataBox.class.getName()); + + public static final String TYPE = "mdat"; + public static final int BUFFER_SIZE = 10 * 1024 * 1024; + ContainerBox parent; + + ByteBuffer header; + + // These fields are for the special case of a FileChannel as input. + private FileChannel fileChannel; + private long startPosition; + private long contentSize; + + + private Map<Long, Reference<ByteBuffer>> cache = new HashMap<Long, Reference<ByteBuffer>>(); + + + /** + * If the whole content is just in one mapped buffer keep a strong reference to it so it is + * not evicted from the cache. + */ + private ByteBuffer content; + + public ContainerBox getParent() { + return parent; + } + + public void setParent(ContainerBox parent) { + this.parent = parent; + } + + public String getType() { + return TYPE; + } + + private static void transfer(FileChannel from, long position, long count, WritableByteChannel to) throws IOException { + long maxCount = (64 * 1024 * 1024) - (32 * 1024); + // Transfer data in chunks a bit less than 64MB + // People state that this is a kind of magic number on Windows. + // I don't care. The size seems reasonable. + long offset = 0; + while (offset < count) { + offset += from.transferTo(position + offset, Math.min(maxCount, count - offset), to); + } + } + + public void getBox(WritableByteChannel writableByteChannel) throws IOException { + if (fileChannel != null) { + assert checkStillOk(); + transfer(fileChannel, startPosition - header.limit(), contentSize + header.limit(), writableByteChannel); + } else { + header.rewind(); + writableByteChannel.write(header); + writableByteChannel.write(content); + } + } + + /** + * If someone use the same file as source and sink it could the case that + * inserting a few bytes before the mdat results in overwrting data we still + * need to write this mdat here. This method just makes sure that we haven't already + * overwritten the mdat contents. + * + * @return true if ok + */ + private boolean checkStillOk() { + try { + fileChannel.position(startPosition - header.limit()); + ByteBuffer h2 = ByteBuffer.allocate(header.limit()); + fileChannel.read(h2); + header.rewind(); + h2.rewind(); + assert h2.equals(header) : "It seems that the content I want to read has already been overwritten."; + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + } + + + public long getSize() { + long size = header.limit(); + size += contentSize; + return size; + } + + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + this.header = header; + this.contentSize = contentSize; + + if (readableByteChannel instanceof FileChannel && (contentSize > AbstractBox.MEM_MAP_THRESHOLD)) { + this.fileChannel = ((FileChannel) readableByteChannel); + this.startPosition = ((FileChannel) readableByteChannel).position(); + ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); + } else { + content = ChannelHelper.readFully(readableByteChannel, l2i(contentSize)); + cache.put(0l, new SoftReference<ByteBuffer>(content)); + } + } + + public synchronized ByteBuffer getContent(long offset, int length) { + + for (Long chacheEntryOffset : cache.keySet()) { + if (chacheEntryOffset <= offset && offset <= chacheEntryOffset + BUFFER_SIZE) { + ByteBuffer cacheEntry = cache.get(chacheEntryOffset).get(); + if ((cacheEntry != null) && ((chacheEntryOffset + cacheEntry.limit()) >= (offset + length))) { + // CACHE HIT + cacheEntry.position((int) (offset - chacheEntryOffset)); + ByteBuffer cachedSample = cacheEntry.slice(); + cachedSample.limit(length); + return cachedSample; + } + } + } + // CACHE MISS + ByteBuffer cacheEntry; + try { + // Just mapping 10MB at a time. Seems reasonable. + cacheEntry = fileChannel.map(FileChannel.MapMode.READ_ONLY, startPosition + offset, Math.min(BUFFER_SIZE, contentSize - offset)); + } catch (IOException e1) { + LOG.fine("Even mapping just 10MB of the source file into the memory failed. " + e1); + throw new RuntimeException( + "Delayed reading of mdat content failed. Make sure not to close " + + "the FileChannel that has been used to create the IsoFile!", e1); + } + cache.put(offset, new SoftReference<ByteBuffer>(cacheEntry)); + cacheEntry.position(0); + ByteBuffer cachedSample = cacheEntry.slice(); + cachedSample.limit(length); + return cachedSample; + } + + + public ByteBuffer getHeader() { + return header; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/SampleList.java b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/SampleList.java new file mode 100644 index 0000000..a7f7b59 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/mdat/SampleList.java @@ -0,0 +1,227 @@ +package com.coremedia.iso.boxes.mdat; + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.boxes.*; +import com.coremedia.iso.boxes.fragment.*; + +import java.nio.ByteBuffer; +import java.util.*; + +import static com.googlecode.mp4parser.util.CastUtils.l2i; + +/** + * Creates a list of <code>ByteBuffer</code>s that represent the samples of a given track. + */ +public class SampleList extends AbstractList<ByteBuffer> { + + + long[] offsets; + long[] sizes; + + IsoFile isoFile; + HashMap<MediaDataBox, Long> mdatStartCache = new HashMap<MediaDataBox, Long>(); + HashMap<MediaDataBox, Long> mdatEndCache = new HashMap<MediaDataBox, Long>(); + MediaDataBox[] mdats; + + /** + * Gets a sorted random access optimized list of all sample offsets. + * Basically it is a map from sample number to sample offset. + * + * @return the sorted list of sample offsets + */ + public long[] getOffsetKeys() { + return offsets; + } + + + public SampleList(TrackBox trackBox) { + initIsoFile(trackBox.getIsoFile()); // where are we? + + // first we get all sample from the 'normal' MP4 part. + // if there are none - no problem. + SampleSizeBox sampleSizeBox = trackBox.getSampleTableBox().getSampleSizeBox(); + ChunkOffsetBox chunkOffsetBox = trackBox.getSampleTableBox().getChunkOffsetBox(); + SampleToChunkBox sampleToChunkBox = trackBox.getSampleTableBox().getSampleToChunkBox(); + + + final long[] chunkOffsets = chunkOffsetBox != null ? chunkOffsetBox.getChunkOffsets() : new long[0]; + if (sampleToChunkBox != null && sampleToChunkBox.getEntries().size() > 0 && + chunkOffsets.length > 0 && sampleSizeBox != null && sampleSizeBox.getSampleCount() > 0) { + long[] numberOfSamplesInChunk = sampleToChunkBox.blowup(chunkOffsets.length); + + int sampleIndex = 0; + + if (sampleSizeBox.getSampleSize() > 0) { + sizes = new long[l2i(sampleSizeBox.getSampleCount())]; + Arrays.fill(sizes, sampleSizeBox.getSampleSize()); + } else { + sizes = sampleSizeBox.getSampleSizes(); + } + offsets = new long[sizes.length]; + + for (int i = 0; i < numberOfSamplesInChunk.length; i++) { + long thisChunksNumberOfSamples = numberOfSamplesInChunk[i]; + long sampleOffset = chunkOffsets[i]; + for (int j = 0; j < thisChunksNumberOfSamples; j++) { + long sampleSize = sizes[sampleIndex]; + offsets[sampleIndex] = sampleOffset; + sampleOffset += sampleSize; + sampleIndex++; + } + } + + } + + // Next we add all samples from the fragments + // in most cases - I've never seen it different it's either normal or fragmented. + List<MovieExtendsBox> movieExtendsBoxes = trackBox.getParent().getBoxes(MovieExtendsBox.class); + + if (movieExtendsBoxes.size() > 0) { + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + List<TrackExtendsBox> trackExtendsBoxes = movieExtendsBoxes.get(0).getBoxes(TrackExtendsBox.class); + for (TrackExtendsBox trackExtendsBox : trackExtendsBoxes) { + if (trackExtendsBox.getTrackId() == trackBox.getTrackHeaderBox().getTrackId()) { + for (MovieFragmentBox movieFragmentBox : trackBox.getIsoFile().getBoxes(MovieFragmentBox.class)) { + offsets2Sizes.putAll(getOffsets(movieFragmentBox, trackBox.getTrackHeaderBox().getTrackId(), trackExtendsBox)); + } + } + } + + if (sizes == null || offsets == null) { + sizes = new long[0]; + offsets = new long[0]; + } + + splitToArrays(offsets2Sizes); + } + + // We have now a map from all sample offsets to their sizes + } + + private void splitToArrays(Map<Long, Long> offsets2Sizes) { + List<Long> keys = new ArrayList<Long>(offsets2Sizes.keySet()); + Collections.sort(keys); + + long[] nuSizes = new long[sizes.length + keys.size()]; + System.arraycopy(sizes, 0, nuSizes, 0, sizes.length); + long[] nuOffsets = new long[offsets.length + keys.size()]; + System.arraycopy(offsets, 0, nuOffsets, 0, offsets.length); + for (int i = 0; i < keys.size(); i++) { + nuOffsets[i + offsets.length] = keys.get(i); + nuSizes[i + sizes.length] = offsets2Sizes.get(keys.get(i)); + } + sizes = nuSizes; + offsets = nuOffsets; + } + + public SampleList(TrackFragmentBox traf) { + sizes = new long[0]; + offsets = new long[0]; + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + initIsoFile(traf.getIsoFile()); + + final List<MovieFragmentBox> movieFragmentBoxList = isoFile.getBoxes(MovieFragmentBox.class); + + final long trackId = traf.getTrackFragmentHeaderBox().getTrackId(); + for (MovieFragmentBox moof : movieFragmentBoxList) { + final List<TrackFragmentHeaderBox> trackFragmentHeaderBoxes = moof.getTrackFragmentHeaderBoxes(); + for (TrackFragmentHeaderBox tfhd : trackFragmentHeaderBoxes) { + if (tfhd.getTrackId() == trackId) { + offsets2Sizes.putAll(getOffsets(moof, trackId, null)); + } + } + } + splitToArrays(offsets2Sizes); + } + + private void initIsoFile(IsoFile isoFile) { + this.isoFile = isoFile; + // find all mdats first to be able to use them later with explicitly looking them up + long currentOffset = 0; + LinkedList<MediaDataBox> mdats = new LinkedList<MediaDataBox>(); + for (Box b : this.isoFile.getBoxes()) { + long currentSize = b.getSize(); + if ("mdat".equals(b.getType())) { + if (b instanceof MediaDataBox) { + long contentOffset = currentOffset + ((MediaDataBox) b).getHeader().limit(); + mdatStartCache.put((MediaDataBox) b, contentOffset); + mdatEndCache.put((MediaDataBox) b, contentOffset + currentSize); + mdats.add((MediaDataBox) b); + } else { + throw new RuntimeException("Sample need to be in mdats and mdats need to be instanceof MediaDataBox"); + } + } + currentOffset += currentSize; + } + this.mdats = mdats.toArray(new MediaDataBox[mdats.size()]); + } + + + @Override + public int size() { + return sizes.length; + } + + + @Override + public ByteBuffer get(int index) { + // it is a two stage lookup: from index to offset to size + long offset = offsets[index]; + int sampleSize = l2i(sizes[index]); + + for (MediaDataBox mediaDataBox : mdats) { + long start = mdatStartCache.get(mediaDataBox); + long end = mdatEndCache.get(mediaDataBox); + if ((start <= offset) && (offset + sampleSize <= end)) { + return mediaDataBox.getContent(offset - start, sampleSize); + } + } + + throw new RuntimeException("The sample with offset " + offset + " and size " + sampleSize + " is NOT located within an mdat"); + } + + Map<Long, Long> getOffsets(MovieFragmentBox moof, long trackId, TrackExtendsBox trex) { + Map<Long, Long> offsets2Sizes = new HashMap<Long, Long>(); + List<TrackFragmentBox> traf = moof.getBoxes(TrackFragmentBox.class); + for (TrackFragmentBox trackFragmentBox : traf) { + if (trackFragmentBox.getTrackFragmentHeaderBox().getTrackId() == trackId) { + long baseDataOffset; + if (trackFragmentBox.getTrackFragmentHeaderBox().hasBaseDataOffset()) { + baseDataOffset = trackFragmentBox.getTrackFragmentHeaderBox().getBaseDataOffset(); + } else { + baseDataOffset = moof.getOffset(); + } + + for (TrackRunBox trun : trackFragmentBox.getBoxes(TrackRunBox.class)) { + long sampleBaseOffset = baseDataOffset + trun.getDataOffset(); + final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) trun.getParent()).getTrackFragmentHeaderBox(); + + long offset = 0; + for (TrackRunBox.Entry entry : trun.getEntries()) { + final long sampleSize; + if (trun.isSampleSizePresent()) { + sampleSize = entry.getSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } else { + if (tfhd.hasDefaultSampleSize()) { + sampleSize = tfhd.getDefaultSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } else { + if (trex == null) { + throw new RuntimeException("File doesn't contain trex box but track fragments aren't fully self contained. Cannot determine sample size."); + } + sampleSize = trex.getDefaultSampleSize(); + offsets2Sizes.put(offset + sampleBaseOffset, sampleSize); + offset += sampleSize; + } + } + } + } + } + } + return offsets2Sizes; + } + +}
\ No newline at end of file diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/odf-boxes.zip b/isoparser/src/main/java/com/coremedia/iso/boxes/odf-boxes.zip Binary files differnew file mode 100644 index 0000000..04e0e5e --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/odf-boxes.zip diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/rtp-boxes.zip b/isoparser/src/main/java/com/coremedia/iso/boxes/rtp-boxes.zip Binary files differnew file mode 100644 index 0000000..be1a167 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/rtp-boxes.zip diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/all-wcprops new file mode 100644 index 0000000..8a5b647 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/all-wcprops @@ -0,0 +1,53 @@ +K 25 +svn:wc:ra_dav:version-url +V 83 +/svn/!svn/ver/757/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry +END +SubtitleSampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 108 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SubtitleSampleEntry.java +END +Ovc1VisualSampleEntryImpl.java +K 25 +svn:wc:ra_dav:version-url +V 114 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/Ovc1VisualSampleEntryImpl.java +END +SampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/745/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SampleEntry.java +END +AudioSampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/!svn/ver/757/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AudioSampleEntry.java +END +VisualSampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/!svn/ver/745/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/VisualSampleEntry.java +END +TextSampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/TextSampleEntry.java +END +MpegSampleEntry.java +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/MpegSampleEntry.java +END +AmrSpecificBox.java +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AmrSpecificBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/entries new file mode 100644 index 0000000..3891d06 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/entries @@ -0,0 +1,300 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry +http://mp4parser.googlecode.com/svn + + + +2012-08-17T05:55:12.215481Z +757 +michael.stattmann@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +SubtitleSampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +a1d02883384ec405c3d62e1a4d157b5e +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2055 + +Ovc1VisualSampleEntryImpl.java +file + + + + +2012-09-14T17:27:52.647249Z +c92067b340193f4ffa776fd1e449dcf5 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1018 + +SampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +8d726941a0af28eaa7b3cc9abcf4bd55 +2012-08-14T19:18:50.777750Z +745 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +5020 + +AudioSampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +3ee1365e9bd772c4e77c3011765ae58a +2012-08-17T05:55:12.215481Z +757 +michael.stattmann@gmail.com + + + + + + + + + + + + + + + + + + + + + +8585 + +VisualSampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +5616cce8d163f57f4e105fd3dbf34e61 +2012-08-14T19:18:50.777750Z +745 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +6899 + +TextSampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +96794e77ef63fbcc1cb861b25ddbb784 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +9126 + +MpegSampleEntry.java +file + + + + +2012-09-14T17:27:52.647249Z +97170f2c4511a4f03915f73d5690cb4d +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1079 + +AmrSpecificBox.java +file + + + + +2012-09-14T17:27:52.647249Z +c306ac7445479a0a2642022bb8428d8f +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2974 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AmrSpecificBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AmrSpecificBox.java.svn-base new file mode 100644 index 0000000..f69de7b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AmrSpecificBox.java.svn-base @@ -0,0 +1,101 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * AMR audio format specific subbox of an audio sample entry. + * + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + */ +public class AmrSpecificBox extends AbstractBox { + public static final String TYPE = "damr"; + + private String vendor; + private int decoderVersion; + private int modeSet; + private int modeChangePeriod; + private int framesPerSample; + + public AmrSpecificBox() { + super(TYPE); + } + + public String getVendor() { + return vendor; + } + + public int getDecoderVersion() { + return decoderVersion; + } + + public int getModeSet() { + return modeSet; + } + + public int getModeChangePeriod() { + return modeChangePeriod; + } + + public int getFramesPerSample() { + return framesPerSample; + } + + protected long getContentSize() { + return 9; + } + + @Override + public void _parseDetails(ByteBuffer content) { + byte[] v = new byte[4]; + content.get(v); + vendor = IsoFile.bytesToFourCC(v); + + decoderVersion = IsoTypeReader.readUInt8(content); + modeSet = IsoTypeReader.readUInt16(content); + modeChangePeriod = IsoTypeReader.readUInt8(content); + framesPerSample = IsoTypeReader.readUInt8(content); + + } + + + public void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(vendor)); + IsoTypeWriter.writeUInt8(byteBuffer, decoderVersion); + IsoTypeWriter.writeUInt16(byteBuffer, modeSet); + IsoTypeWriter.writeUInt8(byteBuffer, modeChangePeriod); + IsoTypeWriter.writeUInt8(byteBuffer, framesPerSample); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("AmrSpecificBox[vendor=").append(getVendor()); + buffer.append(";decoderVersion=").append(getDecoderVersion()); + buffer.append(";modeSet=").append(getModeSet()); + buffer.append(";modeChangePeriod=").append(getModeChangePeriod()); + buffer.append(";framesPerSample=").append(getFramesPerSample()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AudioSampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AudioSampleEntry.java.svn-base new file mode 100644 index 0000000..69aeb79 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/AudioSampleEntry.java.svn-base @@ -0,0 +1,278 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.nio.ByteBuffer; + +/** + * Contains basic information about the audio samples in this track. Format-specific information + * is appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. + */ +public class AudioSampleEntry extends SampleEntry implements ContainerBox { + + public static final String TYPE1 = "samr"; + public static final String TYPE2 = "sawb"; + public static final String TYPE3 = "mp4a"; + public static final String TYPE4 = "drms"; + public static final String TYPE5 = "alac"; + public static final String TYPE7 = "owma"; + public static final String TYPE8 = "ac-3"; /* ETSI TS 102 366 1.2.1 Annex F */ + public static final String TYPE9 = "ec-3"; /* ETSI TS 102 366 1.2.1 Annex F */ + public static final String TYPE10 = "mlpa"; + public static final String TYPE11 = "dtsl"; + public static final String TYPE12 = "dtsh"; + public static final String TYPE13 = "dtse"; + + /** + * Identifier for an encrypted audio track. + * + * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox + */ + public static final String TYPE_ENCRYPTED = "enca"; + + private int channelCount; + private int sampleSize; + private long sampleRate; + private int soundVersion; + private int compressionId; + private int packetSize; + private long samplesPerPacket; + private long bytesPerPacket; + private long bytesPerFrame; + private long bytesPerSample; + + private int reserved1; + private long reserved2; + private byte[] soundVersion2Data; + private BoxParser boxParser; + + public AudioSampleEntry(String type) { + super(type); + } + + public int getChannelCount() { + return channelCount; + } + + public int getSampleSize() { + return sampleSize; + } + + public long getSampleRate() { + return sampleRate; + } + + public int getSoundVersion() { + return soundVersion; + } + + public int getCompressionId() { + return compressionId; + } + + public int getPacketSize() { + return packetSize; + } + + public long getSamplesPerPacket() { + return samplesPerPacket; + } + + public long getBytesPerPacket() { + return bytesPerPacket; + } + + public long getBytesPerFrame() { + return bytesPerFrame; + } + + public long getBytesPerSample() { + return bytesPerSample; + } + + public byte[] getSoundVersion2Data() { + return soundVersion2Data; + } + + public int getReserved1() { + return reserved1; + } + + public long getReserved2() { + return reserved2; + } + + public void setChannelCount(int channelCount) { + this.channelCount = channelCount; + } + + public void setSampleSize(int sampleSize) { + this.sampleSize = sampleSize; + } + + public void setSampleRate(long sampleRate) { + this.sampleRate = sampleRate; + } + + public void setSoundVersion(int soundVersion) { + this.soundVersion = soundVersion; + } + + public void setCompressionId(int compressionId) { + this.compressionId = compressionId; + } + + public void setPacketSize(int packetSize) { + this.packetSize = packetSize; + } + + public void setSamplesPerPacket(long samplesPerPacket) { + this.samplesPerPacket = samplesPerPacket; + } + + public void setBytesPerPacket(long bytesPerPacket) { + this.bytesPerPacket = bytesPerPacket; + } + + public void setBytesPerFrame(long bytesPerFrame) { + this.bytesPerFrame = bytesPerFrame; + } + + public void setBytesPerSample(long bytesPerSample) { + this.bytesPerSample = bytesPerSample; + } + + public void setReserved1(int reserved1) { + this.reserved1 = reserved1; + } + + public void setReserved2(long reserved2) { + this.reserved2 = reserved2; + } + + public void setSoundVersion2Data(byte[] soundVersion2Data) { + this.soundVersion2Data = soundVersion2Data; + } + + public void setBoxParser(BoxParser boxParser) { + this.boxParser = boxParser; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); //parses the six reserved bytes and dataReferenceIndex + // 8 bytes already parsed + //reserved bits - used by qt + soundVersion = IsoTypeReader.readUInt16(content); + + //reserved + reserved1 = IsoTypeReader.readUInt16(content); + reserved2 = IsoTypeReader.readUInt32(content); + + channelCount = IsoTypeReader.readUInt16(content); + sampleSize = IsoTypeReader.readUInt16(content); + //reserved bits - used by qt + compressionId = IsoTypeReader.readUInt16(content); + //reserved bits - used by qt + packetSize = IsoTypeReader.readUInt16(content); + //sampleRate = in.readFixedPoint1616(); + sampleRate = IsoTypeReader.readUInt32(content); + if (!type.equals("mlpa")) { + sampleRate = sampleRate >>> 16; + } + + //more qt stuff - see http://mp4v2.googlecode.com/svn-history/r388/trunk/src/atom_sound.cpp + if (soundVersion > 0) { + samplesPerPacket = IsoTypeReader.readUInt32(content); + bytesPerPacket = IsoTypeReader.readUInt32(content); + bytesPerFrame = IsoTypeReader.readUInt32(content); + bytesPerSample = IsoTypeReader.readUInt32(content); + } + if (soundVersion == 2) { + + soundVersion2Data = new byte[20]; + content.get(20); + } + _parseChildBoxes(content); + + } + + + @Override + protected long getContentSize() { + long contentSize = 28; + contentSize += soundVersion > 0 ? 16 : 0; + contentSize += soundVersion == 2 ? 20 : 0; + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + @Override + public String toString() { + return "AudioSampleEntry{" + + "bytesPerSample=" + bytesPerSample + + ", bytesPerFrame=" + bytesPerFrame + + ", bytesPerPacket=" + bytesPerPacket + + ", samplesPerPacket=" + samplesPerPacket + + ", packetSize=" + packetSize + + ", compressionId=" + compressionId + + ", soundVersion=" + soundVersion + + ", sampleRate=" + sampleRate + + ", sampleSize=" + sampleSize + + ", channelCount=" + channelCount + + ", boxes=" + getBoxes() + + '}'; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, soundVersion); + IsoTypeWriter.writeUInt16(byteBuffer, reserved1); + IsoTypeWriter.writeUInt32(byteBuffer, reserved2); + IsoTypeWriter.writeUInt16(byteBuffer, channelCount); + IsoTypeWriter.writeUInt16(byteBuffer, sampleSize); + IsoTypeWriter.writeUInt16(byteBuffer, compressionId); + IsoTypeWriter.writeUInt16(byteBuffer, packetSize); + //isos.writeFixedPont1616(getSampleRate()); + if (type.equals("mlpa")) { + IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate()); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate() << 16); + } + + if (soundVersion > 0) { + IsoTypeWriter.writeUInt32(byteBuffer, samplesPerPacket); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerPacket); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerFrame); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerSample); + } + + if (soundVersion == 2) { + byteBuffer.put(soundVersion2Data); + } + _writeChildBoxes(byteBuffer); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/MpegSampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/MpegSampleEntry.java.svn-base new file mode 100644 index 0000000..e4a33dc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/MpegSampleEntry.java.svn-base @@ -0,0 +1,43 @@ +package com.coremedia.iso.boxes.sampleentry;
+
+import com.coremedia.iso.BoxParser;
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.ContainerBox;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+public class MpegSampleEntry extends SampleEntry implements ContainerBox {
+
+ private BoxParser boxParser;
+
+ public MpegSampleEntry(String type) {
+ super(type);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ _parseChildBoxes(content);
+
+ }
+
+ @Override
+ protected long getContentSize() {
+ long contentSize = 8;
+ for (Box boxe : boxes) {
+ contentSize += boxe.getSize();
+ }
+ return contentSize;
+ }
+
+ public String toString() {
+ return "MpegSampleEntry" + Arrays.asList(getBoxes());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/Ovc1VisualSampleEntryImpl.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/Ovc1VisualSampleEntryImpl.java.svn-base new file mode 100644 index 0000000..56b8adb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/Ovc1VisualSampleEntryImpl.java.svn-base @@ -0,0 +1,45 @@ +package com.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; + +import java.nio.ByteBuffer; + + +public class Ovc1VisualSampleEntryImpl extends SampleEntry { + private byte[] vc1Content; + public static final String TYPE = "ovc1"; + + + @Override + protected long getContentSize() { + long size = 8; + + for (Box box : boxes) { + size += box.getSize(); + } + size += vc1Content.length; + return size; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + vc1Content = new byte[content.remaining()]; + content.get(vc1Content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(new byte[6]); + IsoTypeWriter.writeUInt16(byteBuffer, getDataReferenceIndex()); + byteBuffer.put(vc1Content); + } + + + protected Ovc1VisualSampleEntryImpl() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SampleEntry.java.svn-base new file mode 100644 index 0000000..a1a5486 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SampleEntry.java.svn-base @@ -0,0 +1,159 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract base class for all sample entries. + * + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.TextSampleEntry + */ +public abstract class SampleEntry extends AbstractBox implements ContainerBox { + + + private int dataReferenceIndex = 1; + protected List<Box> boxes = new LinkedList<Box>(); + private BoxParser boxParser; + + + protected SampleEntry(String type) { + super(type); + } + + public void setType(String type) { + this.type = type; + } + + public int getDataReferenceIndex() { + return dataReferenceIndex; + } + + public void setDataReferenceIndex(int dataReferenceIndex) { + this.dataReferenceIndex = dataReferenceIndex; + } + + public void setBoxes(List<Box> boxes) { + this.boxes = new LinkedList<Box>(boxes); + } + + public void addBox(Box b) { + b.setParent(this); + boxes.add(b); + } + + public boolean removeBox(Box b) { + b.setParent(this); + return boxes.remove(b); + } + + public List<Box> getBoxes() { + return boxes; + } + + @SuppressWarnings("unchecked") + public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) { + List<T> boxesToBeReturned = new ArrayList<T>(2); + for (Box boxe : boxes) { //clazz.isInstance(boxe) / clazz == boxe.getClass()? + if (clazz == boxe.getClass()) { + boxesToBeReturned.add((T) boxe); + } + + if (recursive && boxe instanceof ContainerBox) { + boxesToBeReturned.addAll(((ContainerBox) boxe).getBoxes(clazz, recursive)); + } + } + // Optimize here! Spare object creation work on arrays directly! System.arrayCopy + return boxesToBeReturned; + //return (T[]) boxesToBeReturned.toArray(); + } + + @SuppressWarnings("unchecked") + public <T extends Box> List<T> getBoxes(Class<T> clazz) { + return getBoxes(clazz, false); + } + + @Override + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + super.parse(readableByteChannel, header, contentSize, boxParser); + this.boxParser = boxParser; + } + + + public void _parseReservedAndDataReferenceIndex(ByteBuffer content) { + content.get(new byte[6]); // ignore 6 reserved bytes; + dataReferenceIndex = IsoTypeReader.readUInt16(content); + } + + public void _parseChildBoxes(ByteBuffer content) { + while (content.remaining() > 8) { + try { + boxes.add(boxParser.parseBox(new ByteBufferByteChannel(content), this)); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + setDeadBytes(content.slice()); + } + + public void _writeReservedAndDataReferenceIndex(ByteBuffer bb) { + bb.put(new byte[6]); + IsoTypeWriter.writeUInt16(bb, dataReferenceIndex); + } + + public void _writeChildBoxes(ByteBuffer bb) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + WritableByteChannel wbc = Channels.newChannel(baos); + try { + for (Box box : boxes) { + box.getBox(wbc); + } + wbc.close(); + } catch (IOException e) { + throw new RuntimeException("Cannot happen. Everything should be in memory and therefore no exceptions."); + } + bb.put(baos.toByteArray()); + } + + public long getNumOfBytesToFirstChild() { + long sizeOfChildren = 0; + for (Box box : boxes) { + sizeOfChildren += box.getSize(); + } + return getSize() - sizeOfChildren; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SubtitleSampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SubtitleSampleEntry.java.svn-base new file mode 100644 index 0000000..21d0cc4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/SubtitleSampleEntry.java.svn-base @@ -0,0 +1,76 @@ +package com.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * Created by IntelliJ IDEA. + * User: magnus + * Date: 2012-03-08 + * Time: 11:36 + * To change this template use File | Settings | File Templates. + */ +public class SubtitleSampleEntry extends SampleEntry { + + public static final String TYPE1 = "stpp"; + + public static final String TYPE_ENCRYPTED = ""; // This is not known! + + private String namespace; + private String schemaLocation; + private String imageMimeType; + + public SubtitleSampleEntry(String type) { + super(type); + } + + @Override + protected long getContentSize() { + long contentSize = 8 + namespace.length() + schemaLocation.length() + imageMimeType.length() + 3; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + namespace = IsoTypeReader.readString(content); + schemaLocation = IsoTypeReader.readString(content); + imageMimeType = IsoTypeReader.readString(content); + _parseChildBoxes(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUtf8String(byteBuffer, namespace); + IsoTypeWriter.writeUtf8String(byteBuffer, schemaLocation); + IsoTypeWriter.writeUtf8String(byteBuffer, imageMimeType); + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getSchemaLocation() { + return schemaLocation; + } + + public void setSchemaLocation(String schemaLocation) { + this.schemaLocation = schemaLocation; + } + + public String getImageMimeType() { + return imageMimeType; + } + + public void setImageMimeType(String imageMimeType) { + this.imageMimeType = imageMimeType; + } +} + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/TextSampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/TextSampleEntry.java.svn-base new file mode 100644 index 0000000..3a0b83a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/TextSampleEntry.java.svn-base @@ -0,0 +1,305 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Entry type for timed text samples defined in the timed text specification (ISO/IEC 14496-17). + */ +public class TextSampleEntry extends SampleEntry { + + public static final String TYPE1 = "tx3g"; + + public static final String TYPE_ENCRYPTED = "enct"; + +/* class TextSampleEntry() extends SampleEntry ('tx3g') { + unsigned int(32) displayFlags; + signed int(8) horizontal-justification; + signed int(8) vertical-justification; + unsigned int(8) background-color-rgba[4]; + BoxRecord default-text-box; + StyleRecord default-style; + FontTableBox font-table; + } + */ + + private long displayFlags; // 32 bits + private int horizontalJustification; // 8 bit + private int verticalJustification; // 8 bit + private int[] backgroundColorRgba = new int[4]; // 4 bytes + private BoxRecord boxRecord = new BoxRecord(); + private StyleRecord styleRecord = new StyleRecord(); + + public TextSampleEntry(String type) { + super(type); + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + displayFlags = IsoTypeReader.readUInt32(content); + horizontalJustification = IsoTypeReader.readUInt8(content); + verticalJustification = IsoTypeReader.readUInt8(content); + backgroundColorRgba = new int[4]; + backgroundColorRgba[0] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[1] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[2] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[3] = IsoTypeReader.readUInt8(content); + boxRecord = new BoxRecord(); + boxRecord.parse(content); + + styleRecord = new StyleRecord(); + styleRecord.parse(content); + _parseChildBoxes(content); + } + + + protected long getContentSize() { + long contentSize = 18; + contentSize += boxRecord.getSize(); + contentSize += styleRecord.getSize(); + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + public String toString() { + return "TextSampleEntry"; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, displayFlags); + IsoTypeWriter.writeUInt8(byteBuffer, horizontalJustification); + IsoTypeWriter.writeUInt8(byteBuffer, verticalJustification); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[0]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[1]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[2]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[3]); + boxRecord.getContent(byteBuffer); + styleRecord.getContent(byteBuffer); + + _writeChildBoxes(byteBuffer); + } + + public BoxRecord getBoxRecord() { + return boxRecord; + } + + public void setBoxRecord(BoxRecord boxRecord) { + this.boxRecord = boxRecord; + } + + public StyleRecord getStyleRecord() { + return styleRecord; + } + + public void setStyleRecord(StyleRecord styleRecord) { + this.styleRecord = styleRecord; + } + + public boolean isScrollIn() { + return (displayFlags & 0x00000020) == 0x00000020; + } + + public void setScrollIn(boolean scrollIn) { + if (scrollIn) { + displayFlags |= 0x00000020; + } else { + displayFlags &= ~0x00000020; + } + } + + public boolean isScrollOut() { + return (displayFlags & 0x00000040) == 0x00000040; + } + + public void setScrollOut(boolean scrollOutIn) { + if (scrollOutIn) { + displayFlags |= 0x00000040; + } else { + displayFlags &= ~0x00000040; + } + } + + public boolean isScrollDirection() { + return (displayFlags & 0x00000180) == 0x00000180; + } + + public void setScrollDirection(boolean scrollOutIn) { + if (scrollOutIn) { + displayFlags |= 0x00000180; + } else { + displayFlags &= ~0x00000180; + } + } + + public boolean isContinuousKaraoke() { + return (displayFlags & 0x00000800) == 0x00000800; + } + + public void setContinuousKaraoke(boolean continuousKaraoke) { + if (continuousKaraoke) { + displayFlags |= 0x00000800; + } else { + displayFlags &= ~0x00000800; + } + } + + public boolean isWriteTextVertically() { + return (displayFlags & 0x00020000) == 0x00020000; + } + + public void setWriteTextVertically(boolean writeTextVertically) { + if (writeTextVertically) { + displayFlags |= 0x00020000; + } else { + displayFlags &= ~0x00020000; + } + } + + + public boolean isFillTextRegion() { + return (displayFlags & 0x00040000) == 0x00040000; + } + + public void setFillTextRegion(boolean fillTextRegion) { + if (fillTextRegion) { + displayFlags |= 0x00040000; + } else { + displayFlags &= ~0x00040000; + } + } + + + public int getHorizontalJustification() { + return horizontalJustification; + } + + public void setHorizontalJustification(int horizontalJustification) { + this.horizontalJustification = horizontalJustification; + } + + public int getVerticalJustification() { + return verticalJustification; + } + + public void setVerticalJustification(int verticalJustification) { + this.verticalJustification = verticalJustification; + } + + public int[] getBackgroundColorRgba() { + return backgroundColorRgba; + } + + public void setBackgroundColorRgba(int[] backgroundColorRgba) { + this.backgroundColorRgba = backgroundColorRgba; + } + + public static class BoxRecord { + int top; + int left; + int bottom; + int right; + + public void parse(ByteBuffer in) { + top = IsoTypeReader.readUInt16(in); + left = IsoTypeReader.readUInt16(in); + bottom = IsoTypeReader.readUInt16(in); + right = IsoTypeReader.readUInt16(in); + } + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, top); + IsoTypeWriter.writeUInt16(bb, left); + IsoTypeWriter.writeUInt16(bb, bottom); + IsoTypeWriter.writeUInt16(bb, right); + } + + public int getSize() { + return 8; + } + } + + /* + class FontRecord { + unsigned int(16) font-ID; + unsigned int(8) font-name-length; + unsigned int(8) font[font-name-length]; +} + */ + + + /* + aligned(8) class StyleRecord { + unsigned int(16) startChar; + unsigned int(16) endChar; + unsigned int(16) font-ID; + unsigned int(8) face-style-flags; + unsigned int(8) font-size; + unsigned int(8) text-color-rgba[4]; +} + */ + public static class StyleRecord { + int startChar; + int endChar; + int fontId; + int faceStyleFlags; + int fontSize; + int[] textColor = new int[]{0xff, 0xff, 0xff, 0xff}; + + public void parse(ByteBuffer in) { + startChar = IsoTypeReader.readUInt16(in); + endChar = IsoTypeReader.readUInt16(in); + fontId = IsoTypeReader.readUInt16(in); + faceStyleFlags = IsoTypeReader.readUInt8(in); + fontSize = IsoTypeReader.readUInt8(in); + textColor = new int[4]; + textColor[0] = IsoTypeReader.readUInt8(in); + textColor[1] = IsoTypeReader.readUInt8(in); + textColor[2] = IsoTypeReader.readUInt8(in); + textColor[3] = IsoTypeReader.readUInt8(in); + } + + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, startChar); + IsoTypeWriter.writeUInt16(bb, endChar); + IsoTypeWriter.writeUInt16(bb, fontId); + IsoTypeWriter.writeUInt8(bb, faceStyleFlags); + IsoTypeWriter.writeUInt8(bb, fontSize); + IsoTypeWriter.writeUInt8(bb, textColor[0]); + IsoTypeWriter.writeUInt8(bb, textColor[1]); + IsoTypeWriter.writeUInt8(bb, textColor[2]); + IsoTypeWriter.writeUInt8(bb, textColor[3]); + } + + public int getSize() { + return 12; + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/VisualSampleEntry.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/VisualSampleEntry.java.svn-base new file mode 100644 index 0000000..407e79f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/.svn/text-base/VisualSampleEntry.java.svn-base @@ -0,0 +1,213 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.nio.ByteBuffer; + +/** + * Contains information common to all visual tracks. + * <code> + * <pre> + * class VisualSampleEntry(codingname) extends SampleEntry (codingname){ + * unsigned int(16) pre_defined = 0; + * const unsigned int(16) reserved = 0; + * unsigned int(32)[3] pre_defined = 0; + * unsigned int(16) width; + * unsigned int(16) height; + * template unsigned int(32) horizresolution = 0x00480000; // 72 dpi + * template unsigned int(32) vertresolution = 0x00480000; // 72 dpi + * const unsigned int(32) reserved = 0; + * template unsigned int(16) frame_count = 1; + * string[32] compressorname; + * template unsigned int(16) depth = 0x0018; + * int(16) pre_defined = -1; + * }<br> + * </pre> + * </code> + * <p/> + * Format-specific informationis appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. + */ +public class VisualSampleEntry extends SampleEntry implements ContainerBox { + public static final String TYPE1 = "mp4v"; + public static final String TYPE2 = "s263"; + public static final String TYPE3 = "avc1"; + + + /** + * Identifier for an encrypted video track. + * + * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox + */ + public static final String TYPE_ENCRYPTED = "encv"; + + + private int width; + private int height; + private double horizresolution = 72; + private double vertresolution = 72; + private int frameCount = 1; + private String compressorname; + private int depth = 24; + + private long[] predefined = new long[3]; + + public VisualSampleEntry(String type) { + super(type); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public double getHorizresolution() { + return horizresolution; + } + + public double getVertresolution() { + return vertresolution; + } + + public int getFrameCount() { + return frameCount; + } + + public String getCompressorname() { + return compressorname; + } + + public int getDepth() { + return depth; + } + + public void setCompressorname(String compressorname) { + this.compressorname = compressorname; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setHorizresolution(double horizresolution) { + this.horizresolution = horizresolution; + } + + public void setVertresolution(double vertresolution) { + this.vertresolution = vertresolution; + } + + public void setFrameCount(int frameCount) { + this.frameCount = frameCount; + } + + public void setDepth(int depth) { + this.depth = depth; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + long tmp = IsoTypeReader.readUInt16(content); + assert 0 == tmp : "reserved byte not 0"; + tmp = IsoTypeReader.readUInt16(content); + assert 0 == tmp : "reserved byte not 0"; + predefined[0] = IsoTypeReader.readUInt32(content); // should be zero + predefined[1] = IsoTypeReader.readUInt32(content); // should be zero + predefined[2] = IsoTypeReader.readUInt32(content); // should be zero + width = IsoTypeReader.readUInt16(content); + height = IsoTypeReader.readUInt16(content); + horizresolution = IsoTypeReader.readFixedPoint1616(content); + vertresolution = IsoTypeReader.readFixedPoint1616(content); + tmp = IsoTypeReader.readUInt32(content); + assert 0 == tmp : "reserved byte not 0"; + frameCount = IsoTypeReader.readUInt16(content); + int compressornameDisplayAbleData = IsoTypeReader.readUInt8(content); + if (compressornameDisplayAbleData > 31) { + System.out.println("invalid compressor name displayable data: " + compressornameDisplayAbleData); + compressornameDisplayAbleData = 31; + } + byte[] bytes = new byte[compressornameDisplayAbleData]; + content.get(bytes); + compressorname = Utf8.convert(bytes); + if (compressornameDisplayAbleData < 31) { + byte[] zeros = new byte[31 - compressornameDisplayAbleData]; + content.get(zeros); + //assert Arrays.equals(zeros, new byte[zeros.length]) : "The compressor name length was not filled up with zeros"; + } + depth = IsoTypeReader.readUInt16(content); + tmp = IsoTypeReader.readUInt16(content); + assert 0xFFFF == tmp; + + _parseChildBoxes(content); + + } + + + protected long getContentSize() { + long contentSize = 78; + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[0]); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[1]); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[2]); + + IsoTypeWriter.writeUInt16(byteBuffer, getWidth()); + IsoTypeWriter.writeUInt16(byteBuffer, getHeight()); + + IsoTypeWriter.writeFixedPont1616(byteBuffer, getHorizresolution()); + IsoTypeWriter.writeFixedPont1616(byteBuffer, getVertresolution()); + + + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, getFrameCount()); + IsoTypeWriter.writeUInt8(byteBuffer, Utf8.utf8StringLengthInBytes(getCompressorname())); + byteBuffer.put(Utf8.convert(getCompressorname())); + int a = Utf8.utf8StringLengthInBytes(getCompressorname()); + while (a < 31) { + a++; + byteBuffer.put((byte) 0); + } + IsoTypeWriter.writeUInt16(byteBuffer, getDepth()); + IsoTypeWriter.writeUInt16(byteBuffer, 0xFFFF); + + _writeChildBoxes(byteBuffer); + + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AmrSpecificBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AmrSpecificBox.java new file mode 100644 index 0000000..f69de7b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AmrSpecificBox.java @@ -0,0 +1,101 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + + +import com.coremedia.iso.IsoFile; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; + +import java.nio.ByteBuffer; + +/** + * AMR audio format specific subbox of an audio sample entry. + * + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + */ +public class AmrSpecificBox extends AbstractBox { + public static final String TYPE = "damr"; + + private String vendor; + private int decoderVersion; + private int modeSet; + private int modeChangePeriod; + private int framesPerSample; + + public AmrSpecificBox() { + super(TYPE); + } + + public String getVendor() { + return vendor; + } + + public int getDecoderVersion() { + return decoderVersion; + } + + public int getModeSet() { + return modeSet; + } + + public int getModeChangePeriod() { + return modeChangePeriod; + } + + public int getFramesPerSample() { + return framesPerSample; + } + + protected long getContentSize() { + return 9; + } + + @Override + public void _parseDetails(ByteBuffer content) { + byte[] v = new byte[4]; + content.get(v); + vendor = IsoFile.bytesToFourCC(v); + + decoderVersion = IsoTypeReader.readUInt8(content); + modeSet = IsoTypeReader.readUInt16(content); + modeChangePeriod = IsoTypeReader.readUInt8(content); + framesPerSample = IsoTypeReader.readUInt8(content); + + } + + + public void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(IsoFile.fourCCtoBytes(vendor)); + IsoTypeWriter.writeUInt8(byteBuffer, decoderVersion); + IsoTypeWriter.writeUInt16(byteBuffer, modeSet); + IsoTypeWriter.writeUInt8(byteBuffer, modeChangePeriod); + IsoTypeWriter.writeUInt8(byteBuffer, framesPerSample); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("AmrSpecificBox[vendor=").append(getVendor()); + buffer.append(";decoderVersion=").append(getDecoderVersion()); + buffer.append(";modeSet=").append(getModeSet()); + buffer.append(";modeChangePeriod=").append(getModeChangePeriod()); + buffer.append(";framesPerSample=").append(getFramesPerSample()); + buffer.append("]"); + return buffer.toString(); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AudioSampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AudioSampleEntry.java new file mode 100644 index 0000000..69aeb79 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/AudioSampleEntry.java @@ -0,0 +1,278 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.nio.ByteBuffer; + +/** + * Contains basic information about the audio samples in this track. Format-specific information + * is appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. + */ +public class AudioSampleEntry extends SampleEntry implements ContainerBox { + + public static final String TYPE1 = "samr"; + public static final String TYPE2 = "sawb"; + public static final String TYPE3 = "mp4a"; + public static final String TYPE4 = "drms"; + public static final String TYPE5 = "alac"; + public static final String TYPE7 = "owma"; + public static final String TYPE8 = "ac-3"; /* ETSI TS 102 366 1.2.1 Annex F */ + public static final String TYPE9 = "ec-3"; /* ETSI TS 102 366 1.2.1 Annex F */ + public static final String TYPE10 = "mlpa"; + public static final String TYPE11 = "dtsl"; + public static final String TYPE12 = "dtsh"; + public static final String TYPE13 = "dtse"; + + /** + * Identifier for an encrypted audio track. + * + * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox + */ + public static final String TYPE_ENCRYPTED = "enca"; + + private int channelCount; + private int sampleSize; + private long sampleRate; + private int soundVersion; + private int compressionId; + private int packetSize; + private long samplesPerPacket; + private long bytesPerPacket; + private long bytesPerFrame; + private long bytesPerSample; + + private int reserved1; + private long reserved2; + private byte[] soundVersion2Data; + private BoxParser boxParser; + + public AudioSampleEntry(String type) { + super(type); + } + + public int getChannelCount() { + return channelCount; + } + + public int getSampleSize() { + return sampleSize; + } + + public long getSampleRate() { + return sampleRate; + } + + public int getSoundVersion() { + return soundVersion; + } + + public int getCompressionId() { + return compressionId; + } + + public int getPacketSize() { + return packetSize; + } + + public long getSamplesPerPacket() { + return samplesPerPacket; + } + + public long getBytesPerPacket() { + return bytesPerPacket; + } + + public long getBytesPerFrame() { + return bytesPerFrame; + } + + public long getBytesPerSample() { + return bytesPerSample; + } + + public byte[] getSoundVersion2Data() { + return soundVersion2Data; + } + + public int getReserved1() { + return reserved1; + } + + public long getReserved2() { + return reserved2; + } + + public void setChannelCount(int channelCount) { + this.channelCount = channelCount; + } + + public void setSampleSize(int sampleSize) { + this.sampleSize = sampleSize; + } + + public void setSampleRate(long sampleRate) { + this.sampleRate = sampleRate; + } + + public void setSoundVersion(int soundVersion) { + this.soundVersion = soundVersion; + } + + public void setCompressionId(int compressionId) { + this.compressionId = compressionId; + } + + public void setPacketSize(int packetSize) { + this.packetSize = packetSize; + } + + public void setSamplesPerPacket(long samplesPerPacket) { + this.samplesPerPacket = samplesPerPacket; + } + + public void setBytesPerPacket(long bytesPerPacket) { + this.bytesPerPacket = bytesPerPacket; + } + + public void setBytesPerFrame(long bytesPerFrame) { + this.bytesPerFrame = bytesPerFrame; + } + + public void setBytesPerSample(long bytesPerSample) { + this.bytesPerSample = bytesPerSample; + } + + public void setReserved1(int reserved1) { + this.reserved1 = reserved1; + } + + public void setReserved2(long reserved2) { + this.reserved2 = reserved2; + } + + public void setSoundVersion2Data(byte[] soundVersion2Data) { + this.soundVersion2Data = soundVersion2Data; + } + + public void setBoxParser(BoxParser boxParser) { + this.boxParser = boxParser; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); //parses the six reserved bytes and dataReferenceIndex + // 8 bytes already parsed + //reserved bits - used by qt + soundVersion = IsoTypeReader.readUInt16(content); + + //reserved + reserved1 = IsoTypeReader.readUInt16(content); + reserved2 = IsoTypeReader.readUInt32(content); + + channelCount = IsoTypeReader.readUInt16(content); + sampleSize = IsoTypeReader.readUInt16(content); + //reserved bits - used by qt + compressionId = IsoTypeReader.readUInt16(content); + //reserved bits - used by qt + packetSize = IsoTypeReader.readUInt16(content); + //sampleRate = in.readFixedPoint1616(); + sampleRate = IsoTypeReader.readUInt32(content); + if (!type.equals("mlpa")) { + sampleRate = sampleRate >>> 16; + } + + //more qt stuff - see http://mp4v2.googlecode.com/svn-history/r388/trunk/src/atom_sound.cpp + if (soundVersion > 0) { + samplesPerPacket = IsoTypeReader.readUInt32(content); + bytesPerPacket = IsoTypeReader.readUInt32(content); + bytesPerFrame = IsoTypeReader.readUInt32(content); + bytesPerSample = IsoTypeReader.readUInt32(content); + } + if (soundVersion == 2) { + + soundVersion2Data = new byte[20]; + content.get(20); + } + _parseChildBoxes(content); + + } + + + @Override + protected long getContentSize() { + long contentSize = 28; + contentSize += soundVersion > 0 ? 16 : 0; + contentSize += soundVersion == 2 ? 20 : 0; + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + @Override + public String toString() { + return "AudioSampleEntry{" + + "bytesPerSample=" + bytesPerSample + + ", bytesPerFrame=" + bytesPerFrame + + ", bytesPerPacket=" + bytesPerPacket + + ", samplesPerPacket=" + samplesPerPacket + + ", packetSize=" + packetSize + + ", compressionId=" + compressionId + + ", soundVersion=" + soundVersion + + ", sampleRate=" + sampleRate + + ", sampleSize=" + sampleSize + + ", channelCount=" + channelCount + + ", boxes=" + getBoxes() + + '}'; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, soundVersion); + IsoTypeWriter.writeUInt16(byteBuffer, reserved1); + IsoTypeWriter.writeUInt32(byteBuffer, reserved2); + IsoTypeWriter.writeUInt16(byteBuffer, channelCount); + IsoTypeWriter.writeUInt16(byteBuffer, sampleSize); + IsoTypeWriter.writeUInt16(byteBuffer, compressionId); + IsoTypeWriter.writeUInt16(byteBuffer, packetSize); + //isos.writeFixedPont1616(getSampleRate()); + if (type.equals("mlpa")) { + IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate()); + } else { + IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate() << 16); + } + + if (soundVersion > 0) { + IsoTypeWriter.writeUInt32(byteBuffer, samplesPerPacket); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerPacket); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerFrame); + IsoTypeWriter.writeUInt32(byteBuffer, bytesPerSample); + } + + if (soundVersion == 2) { + byteBuffer.put(soundVersion2Data); + } + _writeChildBoxes(byteBuffer); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/MpegSampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/MpegSampleEntry.java new file mode 100644 index 0000000..e4a33dc --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/MpegSampleEntry.java @@ -0,0 +1,43 @@ +package com.coremedia.iso.boxes.sampleentry;
+
+import com.coremedia.iso.BoxParser;
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.ContainerBox;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+public class MpegSampleEntry extends SampleEntry implements ContainerBox {
+
+ private BoxParser boxParser;
+
+ public MpegSampleEntry(String type) {
+ super(type);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ _parseChildBoxes(content);
+
+ }
+
+ @Override
+ protected long getContentSize() {
+ long contentSize = 8;
+ for (Box boxe : boxes) {
+ contentSize += boxe.getSize();
+ }
+ return contentSize;
+ }
+
+ public String toString() {
+ return "MpegSampleEntry" + Arrays.asList(getBoxes());
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/Ovc1VisualSampleEntryImpl.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/Ovc1VisualSampleEntryImpl.java new file mode 100644 index 0000000..56b8adb --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/Ovc1VisualSampleEntryImpl.java @@ -0,0 +1,45 @@ +package com.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; + +import java.nio.ByteBuffer; + + +public class Ovc1VisualSampleEntryImpl extends SampleEntry { + private byte[] vc1Content; + public static final String TYPE = "ovc1"; + + + @Override + protected long getContentSize() { + long size = 8; + + for (Box box : boxes) { + size += box.getSize(); + } + size += vc1Content.length; + return size; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + vc1Content = new byte[content.remaining()]; + content.get(vc1Content); + + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + byteBuffer.put(new byte[6]); + IsoTypeWriter.writeUInt16(byteBuffer, getDataReferenceIndex()); + byteBuffer.put(vc1Content); + } + + + protected Ovc1VisualSampleEntryImpl() { + super(TYPE); + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SampleEntry.java new file mode 100644 index 0000000..a1a5486 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SampleEntry.java @@ -0,0 +1,159 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.BoxParser; +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.googlecode.mp4parser.AbstractBox; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; +import com.googlecode.mp4parser.util.ByteBufferByteChannel; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract base class for all sample entries. + * + * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry + * @see com.coremedia.iso.boxes.sampleentry.TextSampleEntry + */ +public abstract class SampleEntry extends AbstractBox implements ContainerBox { + + + private int dataReferenceIndex = 1; + protected List<Box> boxes = new LinkedList<Box>(); + private BoxParser boxParser; + + + protected SampleEntry(String type) { + super(type); + } + + public void setType(String type) { + this.type = type; + } + + public int getDataReferenceIndex() { + return dataReferenceIndex; + } + + public void setDataReferenceIndex(int dataReferenceIndex) { + this.dataReferenceIndex = dataReferenceIndex; + } + + public void setBoxes(List<Box> boxes) { + this.boxes = new LinkedList<Box>(boxes); + } + + public void addBox(Box b) { + b.setParent(this); + boxes.add(b); + } + + public boolean removeBox(Box b) { + b.setParent(this); + return boxes.remove(b); + } + + public List<Box> getBoxes() { + return boxes; + } + + @SuppressWarnings("unchecked") + public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) { + List<T> boxesToBeReturned = new ArrayList<T>(2); + for (Box boxe : boxes) { //clazz.isInstance(boxe) / clazz == boxe.getClass()? + if (clazz == boxe.getClass()) { + boxesToBeReturned.add((T) boxe); + } + + if (recursive && boxe instanceof ContainerBox) { + boxesToBeReturned.addAll(((ContainerBox) boxe).getBoxes(clazz, recursive)); + } + } + // Optimize here! Spare object creation work on arrays directly! System.arrayCopy + return boxesToBeReturned; + //return (T[]) boxesToBeReturned.toArray(); + } + + @SuppressWarnings("unchecked") + public <T extends Box> List<T> getBoxes(Class<T> clazz) { + return getBoxes(clazz, false); + } + + @Override + public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { + super.parse(readableByteChannel, header, contentSize, boxParser); + this.boxParser = boxParser; + } + + + public void _parseReservedAndDataReferenceIndex(ByteBuffer content) { + content.get(new byte[6]); // ignore 6 reserved bytes; + dataReferenceIndex = IsoTypeReader.readUInt16(content); + } + + public void _parseChildBoxes(ByteBuffer content) { + while (content.remaining() > 8) { + try { + boxes.add(boxParser.parseBox(new ByteBufferByteChannel(content), this)); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + setDeadBytes(content.slice()); + } + + public void _writeReservedAndDataReferenceIndex(ByteBuffer bb) { + bb.put(new byte[6]); + IsoTypeWriter.writeUInt16(bb, dataReferenceIndex); + } + + public void _writeChildBoxes(ByteBuffer bb) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + WritableByteChannel wbc = Channels.newChannel(baos); + try { + for (Box box : boxes) { + box.getBox(wbc); + } + wbc.close(); + } catch (IOException e) { + throw new RuntimeException("Cannot happen. Everything should be in memory and therefore no exceptions."); + } + bb.put(baos.toByteArray()); + } + + public long getNumOfBytesToFirstChild() { + long sizeOfChildren = 0; + for (Box box : boxes) { + sizeOfChildren += box.getSize(); + } + return getSize() - sizeOfChildren; + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SubtitleSampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SubtitleSampleEntry.java new file mode 100644 index 0000000..21d0cc4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/SubtitleSampleEntry.java @@ -0,0 +1,76 @@ +package com.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; + +import java.nio.ByteBuffer; + +/** + * Created by IntelliJ IDEA. + * User: magnus + * Date: 2012-03-08 + * Time: 11:36 + * To change this template use File | Settings | File Templates. + */ +public class SubtitleSampleEntry extends SampleEntry { + + public static final String TYPE1 = "stpp"; + + public static final String TYPE_ENCRYPTED = ""; // This is not known! + + private String namespace; + private String schemaLocation; + private String imageMimeType; + + public SubtitleSampleEntry(String type) { + super(type); + } + + @Override + protected long getContentSize() { + long contentSize = 8 + namespace.length() + schemaLocation.length() + imageMimeType.length() + 3; + return contentSize; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + namespace = IsoTypeReader.readString(content); + schemaLocation = IsoTypeReader.readString(content); + imageMimeType = IsoTypeReader.readString(content); + _parseChildBoxes(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUtf8String(byteBuffer, namespace); + IsoTypeWriter.writeUtf8String(byteBuffer, schemaLocation); + IsoTypeWriter.writeUtf8String(byteBuffer, imageMimeType); + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getSchemaLocation() { + return schemaLocation; + } + + public void setSchemaLocation(String schemaLocation) { + this.schemaLocation = schemaLocation; + } + + public String getImageMimeType() { + return imageMimeType; + } + + public void setImageMimeType(String imageMimeType) { + this.imageMimeType = imageMimeType; + } +} + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/TextSampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/TextSampleEntry.java new file mode 100644 index 0000000..3a0b83a --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/TextSampleEntry.java @@ -0,0 +1,305 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.boxes.Box; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Entry type for timed text samples defined in the timed text specification (ISO/IEC 14496-17). + */ +public class TextSampleEntry extends SampleEntry { + + public static final String TYPE1 = "tx3g"; + + public static final String TYPE_ENCRYPTED = "enct"; + +/* class TextSampleEntry() extends SampleEntry ('tx3g') { + unsigned int(32) displayFlags; + signed int(8) horizontal-justification; + signed int(8) vertical-justification; + unsigned int(8) background-color-rgba[4]; + BoxRecord default-text-box; + StyleRecord default-style; + FontTableBox font-table; + } + */ + + private long displayFlags; // 32 bits + private int horizontalJustification; // 8 bit + private int verticalJustification; // 8 bit + private int[] backgroundColorRgba = new int[4]; // 4 bytes + private BoxRecord boxRecord = new BoxRecord(); + private StyleRecord styleRecord = new StyleRecord(); + + public TextSampleEntry(String type) { + super(type); + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + displayFlags = IsoTypeReader.readUInt32(content); + horizontalJustification = IsoTypeReader.readUInt8(content); + verticalJustification = IsoTypeReader.readUInt8(content); + backgroundColorRgba = new int[4]; + backgroundColorRgba[0] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[1] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[2] = IsoTypeReader.readUInt8(content); + backgroundColorRgba[3] = IsoTypeReader.readUInt8(content); + boxRecord = new BoxRecord(); + boxRecord.parse(content); + + styleRecord = new StyleRecord(); + styleRecord.parse(content); + _parseChildBoxes(content); + } + + + protected long getContentSize() { + long contentSize = 18; + contentSize += boxRecord.getSize(); + contentSize += styleRecord.getSize(); + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + public String toString() { + return "TextSampleEntry"; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt32(byteBuffer, displayFlags); + IsoTypeWriter.writeUInt8(byteBuffer, horizontalJustification); + IsoTypeWriter.writeUInt8(byteBuffer, verticalJustification); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[0]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[1]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[2]); + IsoTypeWriter.writeUInt8(byteBuffer, backgroundColorRgba[3]); + boxRecord.getContent(byteBuffer); + styleRecord.getContent(byteBuffer); + + _writeChildBoxes(byteBuffer); + } + + public BoxRecord getBoxRecord() { + return boxRecord; + } + + public void setBoxRecord(BoxRecord boxRecord) { + this.boxRecord = boxRecord; + } + + public StyleRecord getStyleRecord() { + return styleRecord; + } + + public void setStyleRecord(StyleRecord styleRecord) { + this.styleRecord = styleRecord; + } + + public boolean isScrollIn() { + return (displayFlags & 0x00000020) == 0x00000020; + } + + public void setScrollIn(boolean scrollIn) { + if (scrollIn) { + displayFlags |= 0x00000020; + } else { + displayFlags &= ~0x00000020; + } + } + + public boolean isScrollOut() { + return (displayFlags & 0x00000040) == 0x00000040; + } + + public void setScrollOut(boolean scrollOutIn) { + if (scrollOutIn) { + displayFlags |= 0x00000040; + } else { + displayFlags &= ~0x00000040; + } + } + + public boolean isScrollDirection() { + return (displayFlags & 0x00000180) == 0x00000180; + } + + public void setScrollDirection(boolean scrollOutIn) { + if (scrollOutIn) { + displayFlags |= 0x00000180; + } else { + displayFlags &= ~0x00000180; + } + } + + public boolean isContinuousKaraoke() { + return (displayFlags & 0x00000800) == 0x00000800; + } + + public void setContinuousKaraoke(boolean continuousKaraoke) { + if (continuousKaraoke) { + displayFlags |= 0x00000800; + } else { + displayFlags &= ~0x00000800; + } + } + + public boolean isWriteTextVertically() { + return (displayFlags & 0x00020000) == 0x00020000; + } + + public void setWriteTextVertically(boolean writeTextVertically) { + if (writeTextVertically) { + displayFlags |= 0x00020000; + } else { + displayFlags &= ~0x00020000; + } + } + + + public boolean isFillTextRegion() { + return (displayFlags & 0x00040000) == 0x00040000; + } + + public void setFillTextRegion(boolean fillTextRegion) { + if (fillTextRegion) { + displayFlags |= 0x00040000; + } else { + displayFlags &= ~0x00040000; + } + } + + + public int getHorizontalJustification() { + return horizontalJustification; + } + + public void setHorizontalJustification(int horizontalJustification) { + this.horizontalJustification = horizontalJustification; + } + + public int getVerticalJustification() { + return verticalJustification; + } + + public void setVerticalJustification(int verticalJustification) { + this.verticalJustification = verticalJustification; + } + + public int[] getBackgroundColorRgba() { + return backgroundColorRgba; + } + + public void setBackgroundColorRgba(int[] backgroundColorRgba) { + this.backgroundColorRgba = backgroundColorRgba; + } + + public static class BoxRecord { + int top; + int left; + int bottom; + int right; + + public void parse(ByteBuffer in) { + top = IsoTypeReader.readUInt16(in); + left = IsoTypeReader.readUInt16(in); + bottom = IsoTypeReader.readUInt16(in); + right = IsoTypeReader.readUInt16(in); + } + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, top); + IsoTypeWriter.writeUInt16(bb, left); + IsoTypeWriter.writeUInt16(bb, bottom); + IsoTypeWriter.writeUInt16(bb, right); + } + + public int getSize() { + return 8; + } + } + + /* + class FontRecord { + unsigned int(16) font-ID; + unsigned int(8) font-name-length; + unsigned int(8) font[font-name-length]; +} + */ + + + /* + aligned(8) class StyleRecord { + unsigned int(16) startChar; + unsigned int(16) endChar; + unsigned int(16) font-ID; + unsigned int(8) face-style-flags; + unsigned int(8) font-size; + unsigned int(8) text-color-rgba[4]; +} + */ + public static class StyleRecord { + int startChar; + int endChar; + int fontId; + int faceStyleFlags; + int fontSize; + int[] textColor = new int[]{0xff, 0xff, 0xff, 0xff}; + + public void parse(ByteBuffer in) { + startChar = IsoTypeReader.readUInt16(in); + endChar = IsoTypeReader.readUInt16(in); + fontId = IsoTypeReader.readUInt16(in); + faceStyleFlags = IsoTypeReader.readUInt8(in); + fontSize = IsoTypeReader.readUInt8(in); + textColor = new int[4]; + textColor[0] = IsoTypeReader.readUInt8(in); + textColor[1] = IsoTypeReader.readUInt8(in); + textColor[2] = IsoTypeReader.readUInt8(in); + textColor[3] = IsoTypeReader.readUInt8(in); + } + + + public void getContent(ByteBuffer bb) { + IsoTypeWriter.writeUInt16(bb, startChar); + IsoTypeWriter.writeUInt16(bb, endChar); + IsoTypeWriter.writeUInt16(bb, fontId); + IsoTypeWriter.writeUInt8(bb, faceStyleFlags); + IsoTypeWriter.writeUInt8(bb, fontSize); + IsoTypeWriter.writeUInt8(bb, textColor[0]); + IsoTypeWriter.writeUInt8(bb, textColor[1]); + IsoTypeWriter.writeUInt8(bb, textColor[2]); + IsoTypeWriter.writeUInt8(bb, textColor[3]); + } + + public int getSize() { + return 12; + } + } + + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/VisualSampleEntry.java b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/VisualSampleEntry.java new file mode 100644 index 0000000..407e79f --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/sampleentry/VisualSampleEntry.java @@ -0,0 +1,213 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.sampleentry; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.coremedia.iso.boxes.Box; +import com.coremedia.iso.boxes.ContainerBox; + +import java.nio.ByteBuffer; + +/** + * Contains information common to all visual tracks. + * <code> + * <pre> + * class VisualSampleEntry(codingname) extends SampleEntry (codingname){ + * unsigned int(16) pre_defined = 0; + * const unsigned int(16) reserved = 0; + * unsigned int(32)[3] pre_defined = 0; + * unsigned int(16) width; + * unsigned int(16) height; + * template unsigned int(32) horizresolution = 0x00480000; // 72 dpi + * template unsigned int(32) vertresolution = 0x00480000; // 72 dpi + * const unsigned int(32) reserved = 0; + * template unsigned int(16) frame_count = 1; + * string[32] compressorname; + * template unsigned int(16) depth = 0x0018; + * int(16) pre_defined = -1; + * }<br> + * </pre> + * </code> + * <p/> + * Format-specific informationis appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. + */ +public class VisualSampleEntry extends SampleEntry implements ContainerBox { + public static final String TYPE1 = "mp4v"; + public static final String TYPE2 = "s263"; + public static final String TYPE3 = "avc1"; + + + /** + * Identifier for an encrypted video track. + * + * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox + */ + public static final String TYPE_ENCRYPTED = "encv"; + + + private int width; + private int height; + private double horizresolution = 72; + private double vertresolution = 72; + private int frameCount = 1; + private String compressorname; + private int depth = 24; + + private long[] predefined = new long[3]; + + public VisualSampleEntry(String type) { + super(type); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public double getHorizresolution() { + return horizresolution; + } + + public double getVertresolution() { + return vertresolution; + } + + public int getFrameCount() { + return frameCount; + } + + public String getCompressorname() { + return compressorname; + } + + public int getDepth() { + return depth; + } + + public void setCompressorname(String compressorname) { + this.compressorname = compressorname; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setHorizresolution(double horizresolution) { + this.horizresolution = horizresolution; + } + + public void setVertresolution(double vertresolution) { + this.vertresolution = vertresolution; + } + + public void setFrameCount(int frameCount) { + this.frameCount = frameCount; + } + + public void setDepth(int depth) { + this.depth = depth; + } + + @Override + public void _parseDetails(ByteBuffer content) { + _parseReservedAndDataReferenceIndex(content); + long tmp = IsoTypeReader.readUInt16(content); + assert 0 == tmp : "reserved byte not 0"; + tmp = IsoTypeReader.readUInt16(content); + assert 0 == tmp : "reserved byte not 0"; + predefined[0] = IsoTypeReader.readUInt32(content); // should be zero + predefined[1] = IsoTypeReader.readUInt32(content); // should be zero + predefined[2] = IsoTypeReader.readUInt32(content); // should be zero + width = IsoTypeReader.readUInt16(content); + height = IsoTypeReader.readUInt16(content); + horizresolution = IsoTypeReader.readFixedPoint1616(content); + vertresolution = IsoTypeReader.readFixedPoint1616(content); + tmp = IsoTypeReader.readUInt32(content); + assert 0 == tmp : "reserved byte not 0"; + frameCount = IsoTypeReader.readUInt16(content); + int compressornameDisplayAbleData = IsoTypeReader.readUInt8(content); + if (compressornameDisplayAbleData > 31) { + System.out.println("invalid compressor name displayable data: " + compressornameDisplayAbleData); + compressornameDisplayAbleData = 31; + } + byte[] bytes = new byte[compressornameDisplayAbleData]; + content.get(bytes); + compressorname = Utf8.convert(bytes); + if (compressornameDisplayAbleData < 31) { + byte[] zeros = new byte[31 - compressornameDisplayAbleData]; + content.get(zeros); + //assert Arrays.equals(zeros, new byte[zeros.length]) : "The compressor name length was not filled up with zeros"; + } + depth = IsoTypeReader.readUInt16(content); + tmp = IsoTypeReader.readUInt16(content); + assert 0xFFFF == tmp; + + _parseChildBoxes(content); + + } + + + protected long getContentSize() { + long contentSize = 78; + for (Box boxe : boxes) { + contentSize += boxe.getSize(); + } + return contentSize; + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + _writeReservedAndDataReferenceIndex(byteBuffer); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, 0); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[0]); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[1]); + IsoTypeWriter.writeUInt32(byteBuffer, predefined[2]); + + IsoTypeWriter.writeUInt16(byteBuffer, getWidth()); + IsoTypeWriter.writeUInt16(byteBuffer, getHeight()); + + IsoTypeWriter.writeFixedPont1616(byteBuffer, getHorizresolution()); + IsoTypeWriter.writeFixedPont1616(byteBuffer, getVertresolution()); + + + IsoTypeWriter.writeUInt32(byteBuffer, 0); + IsoTypeWriter.writeUInt16(byteBuffer, getFrameCount()); + IsoTypeWriter.writeUInt8(byteBuffer, Utf8.utf8StringLengthInBytes(getCompressorname())); + byteBuffer.put(Utf8.convert(getCompressorname())); + int a = Utf8.utf8StringLengthInBytes(getCompressorname()); + while (a < 31) { + a++; + byteBuffer.put((byte) 0); + } + IsoTypeWriter.writeUInt16(byteBuffer, getDepth()); + IsoTypeWriter.writeUInt16(byteBuffer, 0xFFFF); + + _writeChildBoxes(byteBuffer); + + } + +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/all-wcprops new file mode 100644 index 0000000..da12da8 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244 +END +LocationInformationBox.java +K 25 +svn:wc:ra_dav:version-url +V 113 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/LocationInformationBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/entries new file mode 100644 index 0000000..b3a35ea --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244 +http://mp4parser.googlecode.com/svn + + + +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +LocationInformationBox.java +file + + + + +2012-09-14T17:27:52.867252Z +e71dfcd8b93af51a55331fb161d8cb88 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +3428 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/text-base/LocationInformationBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/text-base/LocationInformationBox.java.svn-base new file mode 100644 index 0000000..089d97b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/.svn/text-base/LocationInformationBox.java.svn-base @@ -0,0 +1,126 @@ +package com.coremedia.iso.boxes.threegpp26244; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Location Information Box as specified in TS 26.244. + */ +public class LocationInformationBox extends AbstractFullBox { + public static final String TYPE = "loci"; + + private String language; + private String name = ""; + private int role; + private double longitude; + private double latitude; + private double altitude; + private String astronomicalBody = ""; + private String additionalNotes = ""; + + public LocationInformationBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getRole() { + return role; + } + + public void setRole(int role) { + this.role = role; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getAltitude() { + return altitude; + } + + public void setAltitude(double altitude) { + this.altitude = altitude; + } + + public String getAstronomicalBody() { + return astronomicalBody; + } + + public void setAstronomicalBody(String astronomicalBody) { + this.astronomicalBody = astronomicalBody; + } + + public String getAdditionalNotes() { + return additionalNotes; + } + + public void setAdditionalNotes(String additionalNotes) { + this.additionalNotes = additionalNotes; + } + + protected long getContentSize() { + return 22 + Utf8.convert(name).length + Utf8.convert(astronomicalBody).length + Utf8.convert(additionalNotes).length; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + name = IsoTypeReader.readString(content); + role = IsoTypeReader.readUInt8(content); + longitude = IsoTypeReader.readFixedPoint1616(content); + latitude = IsoTypeReader.readFixedPoint1616(content); + altitude = IsoTypeReader.readFixedPoint1616(content); + astronomicalBody = IsoTypeReader.readString(content); + additionalNotes = IsoTypeReader.readString(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(name)); + byteBuffer.put((byte) 0); + IsoTypeWriter.writeUInt8(byteBuffer, role); + IsoTypeWriter.writeFixedPont1616(byteBuffer, longitude); + IsoTypeWriter.writeFixedPont1616(byteBuffer, latitude); + IsoTypeWriter.writeFixedPont1616(byteBuffer, altitude); + byteBuffer.put(Utf8.convert(astronomicalBody)); + byteBuffer.put((byte) 0); + byteBuffer.put(Utf8.convert(additionalNotes)); + byteBuffer.put((byte) 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/LocationInformationBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/LocationInformationBox.java new file mode 100644 index 0000000..089d97b --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/threegpp26244/LocationInformationBox.java @@ -0,0 +1,126 @@ +package com.coremedia.iso.boxes.threegpp26244; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Location Information Box as specified in TS 26.244. + */ +public class LocationInformationBox extends AbstractFullBox { + public static final String TYPE = "loci"; + + private String language; + private String name = ""; + private int role; + private double longitude; + private double latitude; + private double altitude; + private String astronomicalBody = ""; + private String additionalNotes = ""; + + public LocationInformationBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getRole() { + return role; + } + + public void setRole(int role) { + this.role = role; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getAltitude() { + return altitude; + } + + public void setAltitude(double altitude) { + this.altitude = altitude; + } + + public String getAstronomicalBody() { + return astronomicalBody; + } + + public void setAstronomicalBody(String astronomicalBody) { + this.astronomicalBody = astronomicalBody; + } + + public String getAdditionalNotes() { + return additionalNotes; + } + + public void setAdditionalNotes(String additionalNotes) { + this.additionalNotes = additionalNotes; + } + + protected long getContentSize() { + return 22 + Utf8.convert(name).length + Utf8.convert(astronomicalBody).length + Utf8.convert(additionalNotes).length; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + name = IsoTypeReader.readString(content); + role = IsoTypeReader.readUInt8(content); + longitude = IsoTypeReader.readFixedPoint1616(content); + latitude = IsoTypeReader.readFixedPoint1616(content); + altitude = IsoTypeReader.readFixedPoint1616(content); + astronomicalBody = IsoTypeReader.readString(content); + additionalNotes = IsoTypeReader.readString(content); + } + + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(name)); + byteBuffer.put((byte) 0); + IsoTypeWriter.writeUInt8(byteBuffer, role); + IsoTypeWriter.writeFixedPont1616(byteBuffer, longitude); + IsoTypeWriter.writeFixedPont1616(byteBuffer, latitude); + IsoTypeWriter.writeFixedPont1616(byteBuffer, altitude); + byteBuffer.put(Utf8.convert(astronomicalBody)); + byteBuffer.put((byte) 0); + byteBuffer.put(Utf8.convert(additionalNotes)); + byteBuffer.put((byte) 0); + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/all-wcprops new file mode 100644 index 0000000..b46dee4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/all-wcprops @@ -0,0 +1,29 @@ +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone +END +AlbumArtistBox.java +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/AlbumArtistBox.java +END +CoverUriBox.java +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/CoverUriBox.java +END +ContentDistributorIdBox.java +K 25 +svn:wc:ra_dav:version-url +V 109 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/ContentDistributorIdBox.java +END +LyricsUriBox.java +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/LyricsUriBox.java +END diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/entries new file mode 100644 index 0000000..15f0da6 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/entries @@ -0,0 +1,164 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone +http://mp4parser.googlecode.com/svn + + + +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + +AlbumArtistBox.java +file + + + + +2012-09-14T17:27:52.067241Z +973d28c2a51998190028321bb407ac03 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2322 + +CoverUriBox.java +file + + + + +2012-09-14T17:27:52.067241Z +142d0171f6ace065d723ff0f1ca68101 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1753 + +ContentDistributorIdBox.java +file + + + + +2012-09-14T17:27:52.067241Z +5e3e0bf310b779bd3c23bf4a100f1dc8 +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +2091 + +LyricsUriBox.java +file + + + + +2012-09-14T17:27:52.067241Z +7aebcd173c05102c97a5bb61874f260d +2012-04-21T22:05:38.425329Z +507 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + + + + + + + + +1873 + diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/AlbumArtistBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/AlbumArtistBox.java.svn-base new file mode 100644 index 0000000..aba12a4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/AlbumArtistBox.java.svn-base @@ -0,0 +1,78 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Special box used by Vodafone in their DCF containing information about the artist. Mainly used for OMA DCF files + * containing music. Resides in the {@link com.coremedia.iso.boxes.UserDataBox}. + */ +public class AlbumArtistBox extends AbstractFullBox { + public static final String TYPE = "albr"; + + private String language; + private String albumArtist; + + public AlbumArtistBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getAlbumArtist() { + return albumArtist; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAlbumArtist(String albumArtist) { + this.albumArtist = albumArtist; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(albumArtist) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + albumArtist = IsoTypeReader.readString(content); + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(albumArtist)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "AlbumArtistBox[language=" + getLanguage() + ";albumArtist=" + getAlbumArtist() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/ContentDistributorIdBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/ContentDistributorIdBox.java.svn-base new file mode 100644 index 0000000..dc36f45 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/ContentDistributorIdBox.java.svn-base @@ -0,0 +1,70 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Vodafone specific box. Usage unclear. + */ +public class ContentDistributorIdBox extends AbstractFullBox { + public static final String TYPE = "cdis"; + + private String language; + private String contentDistributorId; + + public ContentDistributorIdBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getContentDistributorId() { + return contentDistributorId; + } + + protected long getContentSize() { + return 2 + Utf8.utf8StringLengthInBytes(contentDistributorId) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + contentDistributorId = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(contentDistributorId)); + byteBuffer.put((byte) 0); + + } + + public String toString() { + return "ContentDistributorIdBox[language=" + getLanguage() + ";contentDistributorId=" + getContentDistributorId() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/CoverUriBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/CoverUriBox.java.svn-base new file mode 100644 index 0000000..0e78b25 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/CoverUriBox.java.svn-base @@ -0,0 +1,66 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * A vodafone specific box. + */ +public class CoverUriBox extends AbstractFullBox { + public static final String TYPE = "cvru"; + + private String coverUri; + + public CoverUriBox() { + super(TYPE); + } + + public String getCoverUri() { + return coverUri; + } + + public void setCoverUri(String coverUri) { + this.coverUri = coverUri; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(coverUri) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + coverUri = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(coverUri)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + return "CoverUriBox[coverUri=" + getCoverUri() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/LyricsUriBox.java.svn-base b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/LyricsUriBox.java.svn-base new file mode 100644 index 0000000..fbfc243 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/.svn/text-base/LyricsUriBox.java.svn-base @@ -0,0 +1,66 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * A box in the {@link com.coremedia.iso.boxes.UserDataBox} containing information about the lyric location. + * Invented by Vodafone. + */ +public class LyricsUriBox extends AbstractFullBox { + public static final String TYPE = "lrcu"; + + private String lyricsUri; + + public LyricsUriBox() { + super(TYPE); + } + + public String getLyricsUri() { + return lyricsUri; + } + + public void setLyricsUri(String lyricsUri) { + this.lyricsUri = lyricsUri; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(lyricsUri) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + lyricsUri = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(lyricsUri)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "LyricsUriBox[lyricsUri=" + getLyricsUri() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/AlbumArtistBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/AlbumArtistBox.java new file mode 100644 index 0000000..aba12a4 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/AlbumArtistBox.java @@ -0,0 +1,78 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Special box used by Vodafone in their DCF containing information about the artist. Mainly used for OMA DCF files + * containing music. Resides in the {@link com.coremedia.iso.boxes.UserDataBox}. + */ +public class AlbumArtistBox extends AbstractFullBox { + public static final String TYPE = "albr"; + + private String language; + private String albumArtist; + + public AlbumArtistBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getAlbumArtist() { + return albumArtist; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setAlbumArtist(String albumArtist) { + this.albumArtist = albumArtist; + } + + protected long getContentSize() { + return 6 + Utf8.utf8StringLengthInBytes(albumArtist) + 1; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + albumArtist = IsoTypeReader.readString(content); + } + + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(albumArtist)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "AlbumArtistBox[language=" + getLanguage() + ";albumArtist=" + getAlbumArtist() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/ContentDistributorIdBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/ContentDistributorIdBox.java new file mode 100644 index 0000000..dc36f45 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/ContentDistributorIdBox.java @@ -0,0 +1,70 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.IsoTypeWriter; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * Vodafone specific box. Usage unclear. + */ +public class ContentDistributorIdBox extends AbstractFullBox { + public static final String TYPE = "cdis"; + + private String language; + private String contentDistributorId; + + public ContentDistributorIdBox() { + super(TYPE); + } + + public String getLanguage() { + return language; + } + + public String getContentDistributorId() { + return contentDistributorId; + } + + protected long getContentSize() { + return 2 + Utf8.utf8StringLengthInBytes(contentDistributorId) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + language = IsoTypeReader.readIso639(content); + contentDistributorId = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + IsoTypeWriter.writeIso639(byteBuffer, language); + byteBuffer.put(Utf8.convert(contentDistributorId)); + byteBuffer.put((byte) 0); + + } + + public String toString() { + return "ContentDistributorIdBox[language=" + getLanguage() + ";contentDistributorId=" + getContentDistributorId() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/CoverUriBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/CoverUriBox.java new file mode 100644 index 0000000..0e78b25 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/CoverUriBox.java @@ -0,0 +1,66 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * A vodafone specific box. + */ +public class CoverUriBox extends AbstractFullBox { + public static final String TYPE = "cvru"; + + private String coverUri; + + public CoverUriBox() { + super(TYPE); + } + + public String getCoverUri() { + return coverUri; + } + + public void setCoverUri(String coverUri) { + this.coverUri = coverUri; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(coverUri) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + coverUri = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(coverUri)); + byteBuffer.put((byte) 0); + } + + + public String toString() { + return "CoverUriBox[coverUri=" + getCoverUri() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/LyricsUriBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/LyricsUriBox.java new file mode 100644 index 0000000..fbfc243 --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/boxes/vodafone/LyricsUriBox.java @@ -0,0 +1,66 @@ +/* + * Copyright 2008 CoreMedia AG, 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.coremedia.iso.boxes.vodafone; + +import com.coremedia.iso.IsoTypeReader; +import com.coremedia.iso.Utf8; +import com.googlecode.mp4parser.AbstractFullBox; + +import java.nio.ByteBuffer; + +/** + * A box in the {@link com.coremedia.iso.boxes.UserDataBox} containing information about the lyric location. + * Invented by Vodafone. + */ +public class LyricsUriBox extends AbstractFullBox { + public static final String TYPE = "lrcu"; + + private String lyricsUri; + + public LyricsUriBox() { + super(TYPE); + } + + public String getLyricsUri() { + return lyricsUri; + } + + public void setLyricsUri(String lyricsUri) { + this.lyricsUri = lyricsUri; + } + + protected long getContentSize() { + return Utf8.utf8StringLengthInBytes(lyricsUri) + 5; + } + + @Override + public void _parseDetails(ByteBuffer content) { + parseVersionAndFlags(content); + lyricsUri = IsoTypeReader.readString(content); + } + + @Override + protected void getContent(ByteBuffer byteBuffer) { + writeVersionAndFlags(byteBuffer); + byteBuffer.put(Utf8.convert(lyricsUri)); + byteBuffer.put((byte) 0); + } + + public String toString() { + return "LyricsUriBox[lyricsUri=" + getLyricsUri() + "]"; + } +} diff --git a/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/all-wcprops b/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/all-wcprops new file mode 100644 index 0000000..2f92d3c --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 70 +/svn/!svn/ver/178/trunk/isoparser/src/main/java/com/coremedia/iso/mdta +END diff --git a/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/entries b/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/entries new file mode 100644 index 0000000..081f87d --- /dev/null +++ b/isoparser/src/main/java/com/coremedia/iso/mdta/.svn/entries @@ -0,0 +1,28 @@ +10 + +dir +778 +http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/coremedia/iso/mdta +http://mp4parser.googlecode.com/svn + + + +2011-07-11T20:39:14.277970Z +178 +Sebastian.Annies@gmail.com + + + + + + + + + + + + + + +7decde4b-c250-0410-a0da-51896bc88be6 + |