summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/googlecode/mp4parser/boxes
diff options
context:
space:
mode:
Diffstat (limited to 'isoparser/src/main/java/com/googlecode/mp4parser/boxes')
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/all-wcprops47
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/entries293
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/prop-base/mp4-boxes.zip.svn-base5
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AC3SpecificBox.java.svn-base119
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractSampleEncryptionBox.java.svn-base350
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractTrackEncryptionBox.java.svn-base93
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/DTSSpecificBox.java.svn-base217
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/EC3SpecificBox.java.svn-base140
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/MLPSpecificBox.java.svn-base76
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/mp4-boxes.zip.svn-basebin0 -> 62700 bytes
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/AC3SpecificBox.java119
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractSampleEncryptionBox.java350
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractTrackEncryptionBox.java93
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/DTSSpecificBox.java217
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/EC3SpecificBox.java140
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/MLPSpecificBox.java76
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/all-wcprops11
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/entries62
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/text-base/ActionMessageFormat0SampleEntryBox.java.svn-base38
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/ActionMessageFormat0SampleEntryBox.java38
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/all-wcprops41
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/entries232
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/BaseMediaInfoAtom.java.svn-base110
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderAtom.java.svn-base28
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderTextAtom.java.svn-base130
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/QuicktimeTextSampleEntry.java.svn-base237
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TaptAtom.java.svn-base16
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TimeCodeBox.java.svn-base54
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/BaseMediaInfoAtom.java110
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderAtom.java28
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderTextAtom.java130
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/QuicktimeTextSampleEntry.java237
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TaptAtom.java16
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TimeCodeBox.java54
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/all-wcprops23
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/entries130
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/AvcNalUnitStorageBox.java.svn-base97
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/SampleEncryptionBox.java.svn-base24
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/TrackEncryptionBox.java.svn-base12
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/AvcNalUnitStorageBox.java97
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/SampleEncryptionBox.java24
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/TrackEncryptionBox.java12
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/all-wcprops11
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/entries62
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/text-base/ProtectionSystemSpecificHeaderBox.java.svn-base89
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/ProtectionSystemSpecificHeaderBox.java89
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4-boxes.zipbin0 -> 62700 bytes
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/all-wcprops23
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/entries136
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/AbstractDescriptorBox.java.svn-base84
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ESDescriptorBox.java.svn-base36
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ObjectDescriptorBox.java.svn-base46
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/AbstractDescriptorBox.java84
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ESDescriptorBox.java36
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ObjectDescriptorBox.java46
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/all-wcprops107
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/entries606
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/AudioSpecificConfig.java.svn-base1176
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BaseDescriptor.java.svn-base99
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitReaderBuffer.java.svn-base51
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitWriterBuffer.java.svn-base36
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderConfigDescriptor.java.svn-base262
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderSpecificInfo.java.svn-base85
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/Descriptor.java.svn-base39
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ESDescriptor.java.svn-base376
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionDescriptor.java.svn-base73
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionProfileLevelDescriptor.java.svn-base51
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/InitialObjectDescriptor.java.svn-base136
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptor.java_bak.svn-base104
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorBase.java.svn-base27
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorFactory.java.svn-base189
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ProfileLevelIndicationDescriptor.java.svn-base70
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/SLConfigDescriptor.java.svn-base119
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/UnknownDescriptor.java.svn-base42
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/AudioSpecificConfig.java1176
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BaseDescriptor.java99
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitReaderBuffer.java51
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitWriterBuffer.java36
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderConfigDescriptor.java262
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderSpecificInfo.java85
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/Descriptor.java39
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ESDescriptor.java376
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionDescriptor.java73
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionProfileLevelDescriptor.java51
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/InitialObjectDescriptor.java136
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptor.java_bak104
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorBase.java27
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorFactory.java189
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ProfileLevelIndicationDescriptor.java70
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/SLConfigDescriptor.java119
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/UnknownDescriptor.java42
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/all-wcprops59
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/entries334
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/CencSampleEncryptionInformationGroupEntry.java.svn-base125
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/GroupEntry.java.svn-base28
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RateShareEntry.java.svn-base246
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RollRecoveryEntry.java.svn-base77
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleGroupDescriptionBox.java.svn-base200
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleToGroupBox.java.svn-base174
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/TemporalLevelEntry.java.svn-base82
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/UnknownEntry.java.svn-base83
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/VisualRandomAccessEntry.java.svn-base94
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/CencSampleEncryptionInformationGroupEntry.java125
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/GroupEntry.java28
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RateShareEntry.java246
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RollRecoveryEntry.java77
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleGroupDescriptionBox.java200
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleToGroupBox.java174
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/TemporalLevelEntry.java82
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/UnknownEntry.java83
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/VisualRandomAccessEntry.java94
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/all-wcprops47
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/entries266
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffSampleEncryptionBox.java.svn-base45
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffTrackEncryptionBox.java.svn-base34
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PlayReadyHeader.java.svn-base253
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/ProtectionSpecificHeader.java.svn-base79
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfrfBox.java.svn-base129
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfxdBox.java.svn-base85
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/UuidBasedProtectionSystemSpecificHeaderBox.java.svn-base106
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffSampleEncryptionBox.java45
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffTrackEncryptionBox.java34
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PlayReadyHeader.java253
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/ProtectionSpecificHeader.java79
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfrfBox.java129
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfxdBox.java85
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/UuidBasedProtectionSystemSpecificHeaderBox.java106
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/all-wcprops11
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/entries62
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/text-base/SegmentIndexBox.java.svn-base283
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/SegmentIndexBox.java283
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/all-wcprops11
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/entries62
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/text-base/FontTableBox.java.svn-base95
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/FontTableBox.java95
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/all-wcprops17
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/entries96
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/AssetInformationBox.java.svn-base75
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/BaseLocationBox.java.svn-base103
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/AssetInformationBox.java75
-rw-r--r--isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/BaseLocationBox.java103
141 files changed, 17408 insertions, 0 deletions
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/all-wcprops
new file mode 100644
index 0000000..b39616d
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/all-wcprops
@@ -0,0 +1,47 @@
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes
+END
+mp4-boxes.zip
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4-boxes.zip
+END
+AC3SpecificBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AC3SpecificBox.java
+END
+MLPSpecificBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/MLPSpecificBox.java
+END
+DTSSpecificBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/DTSSpecificBox.java
+END
+EC3SpecificBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svn/!svn/ver/755/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/EC3SpecificBox.java
+END
+AbstractSampleEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/svn/!svn/ver/744/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractSampleEncryptionBox.java
+END
+AbstractTrackEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractTrackEncryptionBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/entries
new file mode 100644
index 0000000..46c357c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/entries
@@ -0,0 +1,293 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+mp4-boxes.zip
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+03585a21ffb96d2fec7af185e1a9d11b
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+62700
+
+threegpp26244
+dir
+
+threegpp26245
+dir
+
+basemediaformat
+dir
+
+piff
+dir
+
+MLPSpecificBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+f98e12a419f1111e27ea55eca285239b
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1868
+
+DTSSpecificBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+7e647845ba17be37607c41420f886df0
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5730
+
+AbstractTrackEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+4621f8e06000ce397b5aae869fce1857
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2588
+
+mp4
+dir
+
+apple
+dir
+
+AC3SpecificBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+3f4c28d22ec46abb5263d756387a4d5f
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2661
+
+cenc
+dir
+
+EC3SpecificBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+80bcdd2db3972a22acdfa12a536dd1a5
+2012-08-17T01:13:17.213046Z
+755
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3860
+
+AbstractSampleEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+b729f787e78562982c5f5cf998c58e06
+2012-08-14T13:54:34.186978Z
+744
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10292
+
+ultraviolet
+dir
+
+adobe
+dir
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/prop-base/mp4-boxes.zip.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/prop-base/mp4-boxes.zip.svn-base
new file mode 100644
index 0000000..5e9587e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/prop-base/mp4-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/googlecode/mp4parser/boxes/.svn/text-base/AC3SpecificBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AC3SpecificBox.java.svn-base
new file mode 100644
index 0000000..a3006cd
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AC3SpecificBox.java.svn-base
@@ -0,0 +1,119 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+
+public class AC3SpecificBox extends AbstractBox {
+ int fscod;
+ int bsid;
+ int bsmod;
+ int acmod;
+ int lfeon;
+ int bitRateCode;
+ int reserved;
+
+ public AC3SpecificBox() {
+ super("dac3");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 3;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ fscod = brb.readBits(2);
+ bsid = brb.readBits(5);
+ bsmod = brb.readBits(3);
+ acmod = brb.readBits(3);
+ lfeon = brb.readBits(1);
+ bitRateCode = brb.readBits(5);
+ reserved = brb.readBits(5);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(fscod, 2);
+ bwb.writeBits(bsid, 5);
+ bwb.writeBits(bsmod, 3);
+ bwb.writeBits(acmod, 3);
+ bwb.writeBits(lfeon, 1);
+ bwb.writeBits(bitRateCode, 5);
+ bwb.writeBits(reserved, 5);
+ }
+
+ public int getFscod() {
+ return fscod;
+ }
+
+ public void setFscod(int fscod) {
+ this.fscod = fscod;
+ }
+
+ public int getBsid() {
+ return bsid;
+ }
+
+ public void setBsid(int bsid) {
+ this.bsid = bsid;
+ }
+
+ public int getBsmod() {
+ return bsmod;
+ }
+
+ public void setBsmod(int bsmod) {
+ this.bsmod = bsmod;
+ }
+
+ public int getAcmod() {
+ return acmod;
+ }
+
+ public void setAcmod(int acmod) {
+ this.acmod = acmod;
+ }
+
+ public int getLfeon() {
+ return lfeon;
+ }
+
+ public void setLfeon(int lfeon) {
+ this.lfeon = lfeon;
+ }
+
+ public int getBitRateCode() {
+ return bitRateCode;
+ }
+
+ public void setBitRateCode(int bitRateCode) {
+ this.bitRateCode = bitRateCode;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "AC3SpecificBox{" +
+ "fscod=" + fscod +
+ ", bsid=" + bsid +
+ ", bsmod=" + bsmod +
+ ", acmod=" + acmod +
+ ", lfeon=" + lfeon +
+ ", bitRateCode=" + bitRateCode +
+ ", reserved=" + reserved +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractSampleEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractSampleEncryptionBox.java.svn-base
new file mode 100644
index 0000000..7ac4bba
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractSampleEncryptionBox.java.svn-base
@@ -0,0 +1,350 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.TrackHeaderBox;
+import com.coremedia.iso.boxes.fragment.TrackFragmentHeaderBox;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.basemediaformat.TrackEncryptionBox;
+import com.googlecode.mp4parser.util.Path;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public abstract class AbstractSampleEncryptionBox extends AbstractFullBox {
+ int algorithmId = -1;
+ int ivSize = -1;
+ byte[] kid = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ List<Entry> entries = new LinkedList<Entry>();
+
+ protected AbstractSampleEncryptionBox(String type) {
+ super(type);
+ }
+
+ public int getOffsetToFirstIV() {
+ int offset = (getSize() > (1l << 32) ? 16 : 8);
+ offset += isOverrideTrackEncryptionBoxParameters() ? 20 : 0;
+ offset += 4; //num entries
+ return offset;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ int useThisIvSize = -1;
+ if ((getFlags() & 0x1) > 0) {
+ algorithmId = IsoTypeReader.readUInt24(content);
+ ivSize = IsoTypeReader.readUInt8(content);
+ useThisIvSize = ivSize;
+ kid = new byte[16];
+ content.get(kid);
+ } else {
+ List<Box> tkhds = Path.getPaths(this, "/moov[0]/trak/tkhd");
+ for (Box tkhd : tkhds) {
+ if (((TrackHeaderBox) tkhd).getTrackId() == this.getParent().getBoxes(TrackFragmentHeaderBox.class).get(0).getTrackId()) {
+ AbstractTrackEncryptionBox tenc = (AbstractTrackEncryptionBox) Path.getPath(tkhd, "../mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schi[0]/tenc[0]");
+ if (tenc == null) {
+ tenc = (AbstractTrackEncryptionBox) Path.getPath(tkhd, "../mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schi[0]/uuid[0]");
+ }
+ useThisIvSize = tenc.getDefaultIvSize();
+ }
+ }
+ }
+ long numOfEntries = IsoTypeReader.readUInt32(content);
+
+ while (numOfEntries-- > 0) {
+ Entry e = new Entry();
+ e.iv = new byte[useThisIvSize < 0 ? 8 : useThisIvSize]; // default to 8
+ content.get(e.iv);
+ if ((getFlags() & 0x2) > 0) {
+ int numOfPairs = IsoTypeReader.readUInt16(content);
+ e.pairs = new LinkedList<Entry.Pair>();
+ while (numOfPairs-- > 0) {
+ e.pairs.add(e.createPair(IsoTypeReader.readUInt16(content), IsoTypeReader.readUInt32(content)));
+ }
+ }
+ entries.add(e);
+
+ }
+ }
+
+
+ public int getSampleCount() {
+ return entries.size();
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public int getAlgorithmId() {
+ return algorithmId;
+ }
+
+ public void setAlgorithmId(int algorithmId) {
+ this.algorithmId = algorithmId;
+ }
+
+ public int getIvSize() {
+ return ivSize;
+ }
+
+ public void setIvSize(int ivSize) {
+ this.ivSize = ivSize;
+ }
+
+ public byte[] getKid() {
+ return kid;
+ }
+
+ public void setKid(byte[] kid) {
+ this.kid = kid;
+ }
+
+
+ public boolean isSubSampleEncryption() {
+ return (getFlags() & 0x2) > 0;
+ }
+
+ public boolean isOverrideTrackEncryptionBoxParameters() {
+ return (getFlags() & 0x1) > 0;
+ }
+
+ public void setSubSampleEncryption(boolean b) {
+ if (b) {
+ setFlags(getFlags() | 0x2);
+ } else {
+ setFlags(getFlags() & (0xffffff ^ 0x2));
+ }
+ }
+
+ public void setOverrideTrackEncryptionBoxParameters(boolean b) {
+ if (b) {
+ setFlags(getFlags() | 0x1);
+ } else {
+ setFlags(getFlags() & (0xffffff ^ 0x1));
+ }
+ }
+
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ IsoTypeWriter.writeUInt24(byteBuffer, algorithmId);
+ IsoTypeWriter.writeUInt8(byteBuffer, ivSize);
+ byteBuffer.put(kid);
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ byte[] ivFull = new byte[ivSize];
+ System.arraycopy(entry.iv, 0, ivFull, ivSize - entry.iv.length, entry.iv.length);
+ byteBuffer.put(ivFull);
+ } else {
+ // just put the iv - i don't know any better
+ byteBuffer.put(entry.iv);
+ }
+ if (isSubSampleEncryption()) {
+ IsoTypeWriter.writeUInt16(byteBuffer, entry.pairs.size());
+ for (Entry.Pair pair : entry.pairs) {
+ IsoTypeWriter.writeUInt16(byteBuffer, pair.clear);
+ IsoTypeWriter.writeUInt32(byteBuffer, pair.encrypted);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected long getContentSize() {
+ long contentSize = 4;
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ contentSize += 4;
+ contentSize += kid.length;
+ }
+ contentSize += 4;
+ for (Entry entry : entries) {
+ contentSize += entry.getSize();
+ }
+ return contentSize;
+ }
+
+ @Override
+ public void getBox(WritableByteChannel os) throws IOException {
+ super.getBox(os);
+ }
+
+ public Entry createEntry() {
+ return new Entry();
+ }
+
+ public class Entry {
+ public byte[] iv;
+ public List<Pair> pairs = new LinkedList<Pair>();
+
+ public int getSize() {
+ int size = 0;
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ size = ivSize;
+ } else {
+ size = iv.length;
+ }
+
+
+ if (isSubSampleEncryption()) {
+ size += 2;
+ for (Entry.Pair pair : pairs) {
+ size += 6;
+ }
+ }
+ return size;
+ }
+
+ public Pair createPair(int clear, long encrypted) {
+ return new Pair(clear, encrypted);
+ }
+
+
+ public class Pair {
+ public int clear;
+ public long encrypted;
+
+ public Pair(int clear, long encrypted) {
+ this.clear = clear;
+ this.encrypted = encrypted;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Pair pair = (Pair) o;
+
+ if (clear != pair.clear) {
+ return false;
+ }
+ if (encrypted != pair.encrypted) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = clear;
+ result = 31 * result + (int) (encrypted ^ (encrypted >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "clr:" + clear + " enc:" + encrypted;
+ }
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (!new BigInteger(iv).equals(new BigInteger(entry.iv))) {
+ return false;
+ }
+ if (pairs != null ? !pairs.equals(entry.pairs) : entry.pairs != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = iv != null ? Arrays.hashCode(iv) : 0;
+ result = 31 * result + (pairs != null ? pairs.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "iv=" + Hex.encodeHex(iv) +
+ ", pairs=" + pairs +
+ '}';
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ AbstractSampleEncryptionBox that = (AbstractSampleEncryptionBox) o;
+
+ if (algorithmId != that.algorithmId) {
+ return false;
+ }
+ if (ivSize != that.ivSize) {
+ return false;
+ }
+ if (entries != null ? !entries.equals(that.entries) : that.entries != null) {
+ return false;
+ }
+ if (!Arrays.equals(kid, that.kid)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = algorithmId;
+ result = 31 * result + ivSize;
+ result = 31 * result + (kid != null ? Arrays.hashCode(kid) : 0);
+ result = 31 * result + (entries != null ? entries.hashCode() : 0);
+ return result;
+ }
+
+ public List<Short> getEntrySizes() {
+ List<Short> entrySizes = new ArrayList<Short>(entries.size());
+ for (Entry entry : entries) {
+ short size = (short) entry.iv.length;
+ if (isSubSampleEncryption()) {
+ size += 2; //numPairs
+ size += entry.pairs.size() * 6;
+ }
+ entrySizes.add(size);
+ }
+ return entrySizes;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractTrackEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractTrackEncryptionBox.java.svn-base
new file mode 100644
index 0000000..fe35fde
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/AbstractTrackEncryptionBox.java.svn-base
@@ -0,0 +1,93 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ *
+ */
+public abstract class AbstractTrackEncryptionBox extends AbstractFullBox {
+ int defaultAlgorithmId;
+ int defaultIvSize;
+ byte[] default_KID;
+
+ protected AbstractTrackEncryptionBox(String type) {
+ super(type);
+ }
+
+ public int getDefaultAlgorithmId() {
+ return defaultAlgorithmId;
+ }
+
+ public void setDefaultAlgorithmId(int defaultAlgorithmId) {
+ this.defaultAlgorithmId = defaultAlgorithmId;
+ }
+
+ public int getDefaultIvSize() {
+ return defaultIvSize;
+ }
+
+ public void setDefaultIvSize(int defaultIvSize) {
+ this.defaultIvSize = defaultIvSize;
+ }
+
+ public String getDefault_KID() {
+ ByteBuffer b = ByteBuffer.wrap(default_KID);
+ b.order(ByteOrder.BIG_ENDIAN);
+ return new UUID(b.getLong(), b.getLong()).toString();
+ }
+
+ public void setDefault_KID(byte[] default_KID) {
+ this.default_KID = default_KID;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ defaultAlgorithmId = IsoTypeReader.readUInt24(content);
+ defaultIvSize = IsoTypeReader.readUInt8(content);
+ default_KID = new byte[16];
+ content.get(default_KID);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt24(byteBuffer, defaultAlgorithmId);
+ IsoTypeWriter.writeUInt8(byteBuffer, defaultIvSize);
+ byteBuffer.put(default_KID);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AbstractTrackEncryptionBox that = (AbstractTrackEncryptionBox) o;
+
+ if (defaultAlgorithmId != that.defaultAlgorithmId) return false;
+ if (defaultIvSize != that.defaultIvSize) return false;
+ if (!Arrays.equals(default_KID, that.default_KID)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = defaultAlgorithmId;
+ result = 31 * result + defaultIvSize;
+ result = 31 * result + (default_KID != null ? Arrays.hashCode(default_KID) : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/DTSSpecificBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/DTSSpecificBox.java.svn-base
new file mode 100644
index 0000000..a4cb346
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/DTSSpecificBox.java.svn-base
@@ -0,0 +1,217 @@
+package com.googlecode.mp4parser.boxes;
+
+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 java.nio.ByteBuffer;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: magnus
+ * Date: 2012-03-09
+ * Time: 16:11
+ * To change this template use File | Settings | File Templates.
+ */
+public class DTSSpecificBox extends AbstractBox {
+
+ long DTSSamplingFrequency;
+ long maxBitRate;
+ long avgBitRate;
+ int pcmSampleDepth;
+ int frameDuration;
+ int streamConstruction;
+ int coreLFEPresent;
+ int coreLayout;
+ int coreSize;
+ int stereoDownmix;
+ int representationType;
+ int channelLayout;
+ int multiAssetFlag;
+ int LBRDurationMod;
+ int reservedBoxPresent;
+ int reserved;
+
+ public DTSSpecificBox() {
+ super("ddts");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 20;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ DTSSamplingFrequency = IsoTypeReader.readUInt32(content);
+ maxBitRate = IsoTypeReader.readUInt32(content);
+ avgBitRate = IsoTypeReader.readUInt32(content);
+ pcmSampleDepth = IsoTypeReader.readUInt8(content);
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ frameDuration = brb.readBits(2);
+ streamConstruction = brb.readBits(5);
+ coreLFEPresent = brb.readBits(1);
+ coreLayout = brb.readBits(6);
+ coreSize = brb.readBits(14);
+ stereoDownmix = brb.readBits(1);
+ representationType = brb.readBits(3);
+ channelLayout = brb.readBits(16);
+ multiAssetFlag = brb.readBits(1);
+ LBRDurationMod = brb.readBits(1);
+ reservedBoxPresent = brb.readBits(1);
+ reserved = brb.readBits(5);
+
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ IsoTypeWriter.writeUInt32(byteBuffer, DTSSamplingFrequency);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxBitRate);
+ IsoTypeWriter.writeUInt32(byteBuffer, avgBitRate);
+ IsoTypeWriter.writeUInt8(byteBuffer, pcmSampleDepth);
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(frameDuration, 2);
+ bwb.writeBits(streamConstruction, 5);
+ bwb.writeBits(coreLFEPresent, 1);
+ bwb.writeBits(coreLayout, 6);
+ bwb.writeBits(coreSize, 14);
+ bwb.writeBits(stereoDownmix, 1);
+ bwb.writeBits(representationType, 3);
+ bwb.writeBits(channelLayout, 16);
+ bwb.writeBits(multiAssetFlag, 1);
+ bwb.writeBits(LBRDurationMod, 1);
+ bwb.writeBits(reservedBoxPresent, 1);
+ bwb.writeBits(reserved, 5);
+
+ }
+
+ public long getAvgBitRate() {
+ return avgBitRate;
+ }
+
+ public void setAvgBitRate(long avgBitRate) {
+ this.avgBitRate = avgBitRate;
+ }
+
+ public long getDTSSamplingFrequency() {
+ return DTSSamplingFrequency;
+ }
+
+ public void setDTSSamplingFrequency(long DTSSamplingFrequency) {
+ this.DTSSamplingFrequency = DTSSamplingFrequency;
+ }
+
+ public long getMaxBitRate() {
+ return maxBitRate;
+ }
+
+ public void setMaxBitRate(long maxBitRate) {
+ this.maxBitRate = maxBitRate;
+ }
+
+ public int getPcmSampleDepth() {
+ return pcmSampleDepth;
+ }
+
+ public void setPcmSampleDepth(int pcmSampleDepth) {
+ this.pcmSampleDepth = pcmSampleDepth;
+ }
+
+ public int getFrameDuration() {
+ return frameDuration;
+ }
+
+ public void setFrameDuration(int frameDuration) {
+ this.frameDuration = frameDuration;
+ }
+
+ public int getStreamConstruction() {
+ return streamConstruction;
+ }
+
+ public void setStreamConstruction(int streamConstruction) {
+ this.streamConstruction = streamConstruction;
+ }
+
+ public int getCoreLFEPresent() {
+ return coreLFEPresent;
+ }
+
+ public void setCoreLFEPresent(int coreLFEPresent) {
+ this.coreLFEPresent = coreLFEPresent;
+ }
+
+ public int getCoreLayout() {
+ return coreLayout;
+ }
+
+ public void setCoreLayout(int coreLayout) {
+ this.coreLayout = coreLayout;
+ }
+
+ public int getCoreSize() {
+ return coreSize;
+ }
+
+ public void setCoreSize(int coreSize) {
+ this.coreSize = coreSize;
+ }
+
+ public int getStereoDownmix() {
+ return stereoDownmix;
+ }
+
+ public void setStereoDownmix(int stereoDownmix) {
+ this.stereoDownmix = stereoDownmix;
+ }
+
+ public int getRepresentationType() {
+ return representationType;
+ }
+
+ public void setRepresentationType(int representationType) {
+ this.representationType = representationType;
+ }
+
+ public int getChannelLayout() {
+ return channelLayout;
+ }
+
+ public void setChannelLayout(int channelLayout) {
+ this.channelLayout = channelLayout;
+ }
+
+ public int getMultiAssetFlag() {
+ return multiAssetFlag;
+ }
+
+ public void setMultiAssetFlag(int multiAssetFlag) {
+ this.multiAssetFlag = multiAssetFlag;
+ }
+
+ public int getLBRDurationMod() {
+ return LBRDurationMod;
+ }
+
+ public void setLBRDurationMod(int LBRDurationMod) {
+ this.LBRDurationMod = LBRDurationMod;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public int getReservedBoxPresent() {
+ return reservedBoxPresent;
+ }
+
+ public void setReservedBoxPresent(int reservedBoxPresent) {
+ this.reservedBoxPresent = reservedBoxPresent;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/EC3SpecificBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/EC3SpecificBox.java.svn-base
new file mode 100644
index 0000000..412db04
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/EC3SpecificBox.java.svn-base
@@ -0,0 +1,140 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class EC3SpecificBox extends AbstractBox {
+ List<Entry> entries = new LinkedList<Entry>();
+ int dataRate;
+ int numIndSub;
+
+ public EC3SpecificBox() {
+ super("dec3");
+ }
+
+ @Override
+ public long getContentSize() {
+ long size = 2;
+ for (Entry entry : entries) {
+ if (entry.num_dep_sub > 0) {
+ size += 4;
+ } else {
+ size += 3;
+ }
+ }
+ return size;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ dataRate = brb.readBits(13);
+ numIndSub = brb.readBits(3) + 1;
+ // This field indicates the number of independent substreams that are present in the Enhanced AC-3 bitstream. The value
+ // of this field is one less than the number of independent substreams present.
+
+
+ for (int i = 0; i < numIndSub; i++) {
+ Entry e = new Entry();
+ e.fscod = brb.readBits(2);
+ e.bsid = brb.readBits(5);
+ e.bsmod = brb.readBits(5);
+ e.acmod = brb.readBits(3);
+ e.lfeon = brb.readBits(1);
+ e.reserved = brb.readBits(3);
+ e.num_dep_sub = brb.readBits(4);
+ if (e.num_dep_sub > 0) {
+ e.chan_loc = brb.readBits(9);
+ } else {
+ e.reserved2 = brb.readBits(1);
+ }
+ entries.add(e);
+ }
+ }
+
+ @Override
+ public void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(dataRate, 13);
+ bwb.writeBits(entries.size() - 1, 3);
+ for (Entry e : entries) {
+ bwb.writeBits(e.fscod, 2);
+ bwb.writeBits(e.bsid, 5);
+ bwb.writeBits(e.bsmod, 5);
+ bwb.writeBits(e.acmod, 3);
+ bwb.writeBits(e.lfeon, 1);
+ bwb.writeBits(e.reserved, 3);
+ bwb.writeBits(e.num_dep_sub, 4);
+ if (e.num_dep_sub > 0) {
+ bwb.writeBits(e.chan_loc, 9);
+ } else {
+ bwb.writeBits(e.reserved2, 1);
+ }
+ }
+ }
+
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public void addEntry(Entry entry) {
+ this.entries.add(entry);
+ }
+
+ public int getDataRate() {
+ return dataRate;
+ }
+
+ public void setDataRate(int dataRate) {
+ this.dataRate = dataRate;
+ }
+
+ public int getNumIndSub() {
+ return numIndSub;
+ }
+
+ public void setNumIndSub(int numIndSub) {
+ this.numIndSub = numIndSub;
+ }
+
+ public static class Entry {
+ public int fscod;
+ public int bsid;
+ public int bsmod;
+ public int acmod;
+ public int lfeon;
+ public int reserved;
+ public int num_dep_sub;
+ public int chan_loc;
+ public int reserved2;
+
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "fscod=" + fscod +
+ ", bsid=" + bsid +
+ ", bsmod=" + bsmod +
+ ", acmod=" + acmod +
+ ", lfeon=" + lfeon +
+ ", reserved=" + reserved +
+ ", num_dep_sub=" + num_dep_sub +
+ ", chan_loc=" + chan_loc +
+ ", reserved2=" + reserved2 +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/MLPSpecificBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/MLPSpecificBox.java.svn-base
new file mode 100644
index 0000000..fe6f0d8
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/MLPSpecificBox.java.svn-base
@@ -0,0 +1,76 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+
+
+public class MLPSpecificBox extends AbstractBox {
+
+ int format_info;
+ int peak_data_rate;
+ int reserved;
+ int reserved2;
+
+ public MLPSpecificBox() {
+ super("dmlp");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 10;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ format_info = brb.readBits(32);
+ peak_data_rate = brb.readBits(15);
+ reserved = brb.readBits(1);
+ reserved2 = brb.readBits(32);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(format_info, 32);
+ bwb.writeBits(peak_data_rate, 15);
+ bwb.writeBits(reserved, 1);
+ bwb.writeBits(reserved2, 32);
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getFormat_info() {
+ return format_info;
+ }
+
+ public void setFormat_info(int format_info) {
+ this.format_info = format_info;
+ }
+
+ public int getPeak_data_rate() {
+ return peak_data_rate;
+ }
+
+ public void setPeak_data_rate(int peak_data_rate) {
+ this.peak_data_rate = peak_data_rate;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public int getReserved2() {
+ return reserved2;
+ }
+
+ public void setReserved2(int reserved2) {
+ this.reserved2 = reserved2;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/mp4-boxes.zip.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/mp4-boxes.zip.svn-base
new file mode 100644
index 0000000..c9bcf8b
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/.svn/text-base/mp4-boxes.zip.svn-base
Binary files differ
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AC3SpecificBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AC3SpecificBox.java
new file mode 100644
index 0000000..a3006cd
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AC3SpecificBox.java
@@ -0,0 +1,119 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+
+public class AC3SpecificBox extends AbstractBox {
+ int fscod;
+ int bsid;
+ int bsmod;
+ int acmod;
+ int lfeon;
+ int bitRateCode;
+ int reserved;
+
+ public AC3SpecificBox() {
+ super("dac3");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 3;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ fscod = brb.readBits(2);
+ bsid = brb.readBits(5);
+ bsmod = brb.readBits(3);
+ acmod = brb.readBits(3);
+ lfeon = brb.readBits(1);
+ bitRateCode = brb.readBits(5);
+ reserved = brb.readBits(5);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(fscod, 2);
+ bwb.writeBits(bsid, 5);
+ bwb.writeBits(bsmod, 3);
+ bwb.writeBits(acmod, 3);
+ bwb.writeBits(lfeon, 1);
+ bwb.writeBits(bitRateCode, 5);
+ bwb.writeBits(reserved, 5);
+ }
+
+ public int getFscod() {
+ return fscod;
+ }
+
+ public void setFscod(int fscod) {
+ this.fscod = fscod;
+ }
+
+ public int getBsid() {
+ return bsid;
+ }
+
+ public void setBsid(int bsid) {
+ this.bsid = bsid;
+ }
+
+ public int getBsmod() {
+ return bsmod;
+ }
+
+ public void setBsmod(int bsmod) {
+ this.bsmod = bsmod;
+ }
+
+ public int getAcmod() {
+ return acmod;
+ }
+
+ public void setAcmod(int acmod) {
+ this.acmod = acmod;
+ }
+
+ public int getLfeon() {
+ return lfeon;
+ }
+
+ public void setLfeon(int lfeon) {
+ this.lfeon = lfeon;
+ }
+
+ public int getBitRateCode() {
+ return bitRateCode;
+ }
+
+ public void setBitRateCode(int bitRateCode) {
+ this.bitRateCode = bitRateCode;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "AC3SpecificBox{" +
+ "fscod=" + fscod +
+ ", bsid=" + bsid +
+ ", bsmod=" + bsmod +
+ ", acmod=" + acmod +
+ ", lfeon=" + lfeon +
+ ", bitRateCode=" + bitRateCode +
+ ", reserved=" + reserved +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractSampleEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractSampleEncryptionBox.java
new file mode 100644
index 0000000..7ac4bba
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractSampleEncryptionBox.java
@@ -0,0 +1,350 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.TrackHeaderBox;
+import com.coremedia.iso.boxes.fragment.TrackFragmentHeaderBox;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.basemediaformat.TrackEncryptionBox;
+import com.googlecode.mp4parser.util.Path;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public abstract class AbstractSampleEncryptionBox extends AbstractFullBox {
+ int algorithmId = -1;
+ int ivSize = -1;
+ byte[] kid = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ List<Entry> entries = new LinkedList<Entry>();
+
+ protected AbstractSampleEncryptionBox(String type) {
+ super(type);
+ }
+
+ public int getOffsetToFirstIV() {
+ int offset = (getSize() > (1l << 32) ? 16 : 8);
+ offset += isOverrideTrackEncryptionBoxParameters() ? 20 : 0;
+ offset += 4; //num entries
+ return offset;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ int useThisIvSize = -1;
+ if ((getFlags() & 0x1) > 0) {
+ algorithmId = IsoTypeReader.readUInt24(content);
+ ivSize = IsoTypeReader.readUInt8(content);
+ useThisIvSize = ivSize;
+ kid = new byte[16];
+ content.get(kid);
+ } else {
+ List<Box> tkhds = Path.getPaths(this, "/moov[0]/trak/tkhd");
+ for (Box tkhd : tkhds) {
+ if (((TrackHeaderBox) tkhd).getTrackId() == this.getParent().getBoxes(TrackFragmentHeaderBox.class).get(0).getTrackId()) {
+ AbstractTrackEncryptionBox tenc = (AbstractTrackEncryptionBox) Path.getPath(tkhd, "../mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schi[0]/tenc[0]");
+ if (tenc == null) {
+ tenc = (AbstractTrackEncryptionBox) Path.getPath(tkhd, "../mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schi[0]/uuid[0]");
+ }
+ useThisIvSize = tenc.getDefaultIvSize();
+ }
+ }
+ }
+ long numOfEntries = IsoTypeReader.readUInt32(content);
+
+ while (numOfEntries-- > 0) {
+ Entry e = new Entry();
+ e.iv = new byte[useThisIvSize < 0 ? 8 : useThisIvSize]; // default to 8
+ content.get(e.iv);
+ if ((getFlags() & 0x2) > 0) {
+ int numOfPairs = IsoTypeReader.readUInt16(content);
+ e.pairs = new LinkedList<Entry.Pair>();
+ while (numOfPairs-- > 0) {
+ e.pairs.add(e.createPair(IsoTypeReader.readUInt16(content), IsoTypeReader.readUInt32(content)));
+ }
+ }
+ entries.add(e);
+
+ }
+ }
+
+
+ public int getSampleCount() {
+ return entries.size();
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public int getAlgorithmId() {
+ return algorithmId;
+ }
+
+ public void setAlgorithmId(int algorithmId) {
+ this.algorithmId = algorithmId;
+ }
+
+ public int getIvSize() {
+ return ivSize;
+ }
+
+ public void setIvSize(int ivSize) {
+ this.ivSize = ivSize;
+ }
+
+ public byte[] getKid() {
+ return kid;
+ }
+
+ public void setKid(byte[] kid) {
+ this.kid = kid;
+ }
+
+
+ public boolean isSubSampleEncryption() {
+ return (getFlags() & 0x2) > 0;
+ }
+
+ public boolean isOverrideTrackEncryptionBoxParameters() {
+ return (getFlags() & 0x1) > 0;
+ }
+
+ public void setSubSampleEncryption(boolean b) {
+ if (b) {
+ setFlags(getFlags() | 0x2);
+ } else {
+ setFlags(getFlags() & (0xffffff ^ 0x2));
+ }
+ }
+
+ public void setOverrideTrackEncryptionBoxParameters(boolean b) {
+ if (b) {
+ setFlags(getFlags() | 0x1);
+ } else {
+ setFlags(getFlags() & (0xffffff ^ 0x1));
+ }
+ }
+
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ IsoTypeWriter.writeUInt24(byteBuffer, algorithmId);
+ IsoTypeWriter.writeUInt8(byteBuffer, ivSize);
+ byteBuffer.put(kid);
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ byte[] ivFull = new byte[ivSize];
+ System.arraycopy(entry.iv, 0, ivFull, ivSize - entry.iv.length, entry.iv.length);
+ byteBuffer.put(ivFull);
+ } else {
+ // just put the iv - i don't know any better
+ byteBuffer.put(entry.iv);
+ }
+ if (isSubSampleEncryption()) {
+ IsoTypeWriter.writeUInt16(byteBuffer, entry.pairs.size());
+ for (Entry.Pair pair : entry.pairs) {
+ IsoTypeWriter.writeUInt16(byteBuffer, pair.clear);
+ IsoTypeWriter.writeUInt32(byteBuffer, pair.encrypted);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected long getContentSize() {
+ long contentSize = 4;
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ contentSize += 4;
+ contentSize += kid.length;
+ }
+ contentSize += 4;
+ for (Entry entry : entries) {
+ contentSize += entry.getSize();
+ }
+ return contentSize;
+ }
+
+ @Override
+ public void getBox(WritableByteChannel os) throws IOException {
+ super.getBox(os);
+ }
+
+ public Entry createEntry() {
+ return new Entry();
+ }
+
+ public class Entry {
+ public byte[] iv;
+ public List<Pair> pairs = new LinkedList<Pair>();
+
+ public int getSize() {
+ int size = 0;
+ if (isOverrideTrackEncryptionBoxParameters()) {
+ size = ivSize;
+ } else {
+ size = iv.length;
+ }
+
+
+ if (isSubSampleEncryption()) {
+ size += 2;
+ for (Entry.Pair pair : pairs) {
+ size += 6;
+ }
+ }
+ return size;
+ }
+
+ public Pair createPair(int clear, long encrypted) {
+ return new Pair(clear, encrypted);
+ }
+
+
+ public class Pair {
+ public int clear;
+ public long encrypted;
+
+ public Pair(int clear, long encrypted) {
+ this.clear = clear;
+ this.encrypted = encrypted;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Pair pair = (Pair) o;
+
+ if (clear != pair.clear) {
+ return false;
+ }
+ if (encrypted != pair.encrypted) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = clear;
+ result = 31 * result + (int) (encrypted ^ (encrypted >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "clr:" + clear + " enc:" + encrypted;
+ }
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (!new BigInteger(iv).equals(new BigInteger(entry.iv))) {
+ return false;
+ }
+ if (pairs != null ? !pairs.equals(entry.pairs) : entry.pairs != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = iv != null ? Arrays.hashCode(iv) : 0;
+ result = 31 * result + (pairs != null ? pairs.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "iv=" + Hex.encodeHex(iv) +
+ ", pairs=" + pairs +
+ '}';
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ AbstractSampleEncryptionBox that = (AbstractSampleEncryptionBox) o;
+
+ if (algorithmId != that.algorithmId) {
+ return false;
+ }
+ if (ivSize != that.ivSize) {
+ return false;
+ }
+ if (entries != null ? !entries.equals(that.entries) : that.entries != null) {
+ return false;
+ }
+ if (!Arrays.equals(kid, that.kid)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = algorithmId;
+ result = 31 * result + ivSize;
+ result = 31 * result + (kid != null ? Arrays.hashCode(kid) : 0);
+ result = 31 * result + (entries != null ? entries.hashCode() : 0);
+ return result;
+ }
+
+ public List<Short> getEntrySizes() {
+ List<Short> entrySizes = new ArrayList<Short>(entries.size());
+ for (Entry entry : entries) {
+ short size = (short) entry.iv.length;
+ if (isSubSampleEncryption()) {
+ size += 2; //numPairs
+ size += entry.pairs.size() * 6;
+ }
+ entrySizes.add(size);
+ }
+ return entrySizes;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractTrackEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractTrackEncryptionBox.java
new file mode 100644
index 0000000..fe35fde
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/AbstractTrackEncryptionBox.java
@@ -0,0 +1,93 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ *
+ */
+public abstract class AbstractTrackEncryptionBox extends AbstractFullBox {
+ int defaultAlgorithmId;
+ int defaultIvSize;
+ byte[] default_KID;
+
+ protected AbstractTrackEncryptionBox(String type) {
+ super(type);
+ }
+
+ public int getDefaultAlgorithmId() {
+ return defaultAlgorithmId;
+ }
+
+ public void setDefaultAlgorithmId(int defaultAlgorithmId) {
+ this.defaultAlgorithmId = defaultAlgorithmId;
+ }
+
+ public int getDefaultIvSize() {
+ return defaultIvSize;
+ }
+
+ public void setDefaultIvSize(int defaultIvSize) {
+ this.defaultIvSize = defaultIvSize;
+ }
+
+ public String getDefault_KID() {
+ ByteBuffer b = ByteBuffer.wrap(default_KID);
+ b.order(ByteOrder.BIG_ENDIAN);
+ return new UUID(b.getLong(), b.getLong()).toString();
+ }
+
+ public void setDefault_KID(byte[] default_KID) {
+ this.default_KID = default_KID;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ defaultAlgorithmId = IsoTypeReader.readUInt24(content);
+ defaultIvSize = IsoTypeReader.readUInt8(content);
+ default_KID = new byte[16];
+ content.get(default_KID);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt24(byteBuffer, defaultAlgorithmId);
+ IsoTypeWriter.writeUInt8(byteBuffer, defaultIvSize);
+ byteBuffer.put(default_KID);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AbstractTrackEncryptionBox that = (AbstractTrackEncryptionBox) o;
+
+ if (defaultAlgorithmId != that.defaultAlgorithmId) return false;
+ if (defaultIvSize != that.defaultIvSize) return false;
+ if (!Arrays.equals(default_KID, that.default_KID)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = defaultAlgorithmId;
+ result = 31 * result + defaultIvSize;
+ result = 31 * result + (default_KID != null ? Arrays.hashCode(default_KID) : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/DTSSpecificBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/DTSSpecificBox.java
new file mode 100644
index 0000000..a4cb346
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/DTSSpecificBox.java
@@ -0,0 +1,217 @@
+package com.googlecode.mp4parser.boxes;
+
+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 java.nio.ByteBuffer;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: magnus
+ * Date: 2012-03-09
+ * Time: 16:11
+ * To change this template use File | Settings | File Templates.
+ */
+public class DTSSpecificBox extends AbstractBox {
+
+ long DTSSamplingFrequency;
+ long maxBitRate;
+ long avgBitRate;
+ int pcmSampleDepth;
+ int frameDuration;
+ int streamConstruction;
+ int coreLFEPresent;
+ int coreLayout;
+ int coreSize;
+ int stereoDownmix;
+ int representationType;
+ int channelLayout;
+ int multiAssetFlag;
+ int LBRDurationMod;
+ int reservedBoxPresent;
+ int reserved;
+
+ public DTSSpecificBox() {
+ super("ddts");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 20;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ DTSSamplingFrequency = IsoTypeReader.readUInt32(content);
+ maxBitRate = IsoTypeReader.readUInt32(content);
+ avgBitRate = IsoTypeReader.readUInt32(content);
+ pcmSampleDepth = IsoTypeReader.readUInt8(content);
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ frameDuration = brb.readBits(2);
+ streamConstruction = brb.readBits(5);
+ coreLFEPresent = brb.readBits(1);
+ coreLayout = brb.readBits(6);
+ coreSize = brb.readBits(14);
+ stereoDownmix = brb.readBits(1);
+ representationType = brb.readBits(3);
+ channelLayout = brb.readBits(16);
+ multiAssetFlag = brb.readBits(1);
+ LBRDurationMod = brb.readBits(1);
+ reservedBoxPresent = brb.readBits(1);
+ reserved = brb.readBits(5);
+
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ IsoTypeWriter.writeUInt32(byteBuffer, DTSSamplingFrequency);
+ IsoTypeWriter.writeUInt32(byteBuffer, maxBitRate);
+ IsoTypeWriter.writeUInt32(byteBuffer, avgBitRate);
+ IsoTypeWriter.writeUInt8(byteBuffer, pcmSampleDepth);
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(frameDuration, 2);
+ bwb.writeBits(streamConstruction, 5);
+ bwb.writeBits(coreLFEPresent, 1);
+ bwb.writeBits(coreLayout, 6);
+ bwb.writeBits(coreSize, 14);
+ bwb.writeBits(stereoDownmix, 1);
+ bwb.writeBits(representationType, 3);
+ bwb.writeBits(channelLayout, 16);
+ bwb.writeBits(multiAssetFlag, 1);
+ bwb.writeBits(LBRDurationMod, 1);
+ bwb.writeBits(reservedBoxPresent, 1);
+ bwb.writeBits(reserved, 5);
+
+ }
+
+ public long getAvgBitRate() {
+ return avgBitRate;
+ }
+
+ public void setAvgBitRate(long avgBitRate) {
+ this.avgBitRate = avgBitRate;
+ }
+
+ public long getDTSSamplingFrequency() {
+ return DTSSamplingFrequency;
+ }
+
+ public void setDTSSamplingFrequency(long DTSSamplingFrequency) {
+ this.DTSSamplingFrequency = DTSSamplingFrequency;
+ }
+
+ public long getMaxBitRate() {
+ return maxBitRate;
+ }
+
+ public void setMaxBitRate(long maxBitRate) {
+ this.maxBitRate = maxBitRate;
+ }
+
+ public int getPcmSampleDepth() {
+ return pcmSampleDepth;
+ }
+
+ public void setPcmSampleDepth(int pcmSampleDepth) {
+ this.pcmSampleDepth = pcmSampleDepth;
+ }
+
+ public int getFrameDuration() {
+ return frameDuration;
+ }
+
+ public void setFrameDuration(int frameDuration) {
+ this.frameDuration = frameDuration;
+ }
+
+ public int getStreamConstruction() {
+ return streamConstruction;
+ }
+
+ public void setStreamConstruction(int streamConstruction) {
+ this.streamConstruction = streamConstruction;
+ }
+
+ public int getCoreLFEPresent() {
+ return coreLFEPresent;
+ }
+
+ public void setCoreLFEPresent(int coreLFEPresent) {
+ this.coreLFEPresent = coreLFEPresent;
+ }
+
+ public int getCoreLayout() {
+ return coreLayout;
+ }
+
+ public void setCoreLayout(int coreLayout) {
+ this.coreLayout = coreLayout;
+ }
+
+ public int getCoreSize() {
+ return coreSize;
+ }
+
+ public void setCoreSize(int coreSize) {
+ this.coreSize = coreSize;
+ }
+
+ public int getStereoDownmix() {
+ return stereoDownmix;
+ }
+
+ public void setStereoDownmix(int stereoDownmix) {
+ this.stereoDownmix = stereoDownmix;
+ }
+
+ public int getRepresentationType() {
+ return representationType;
+ }
+
+ public void setRepresentationType(int representationType) {
+ this.representationType = representationType;
+ }
+
+ public int getChannelLayout() {
+ return channelLayout;
+ }
+
+ public void setChannelLayout(int channelLayout) {
+ this.channelLayout = channelLayout;
+ }
+
+ public int getMultiAssetFlag() {
+ return multiAssetFlag;
+ }
+
+ public void setMultiAssetFlag(int multiAssetFlag) {
+ this.multiAssetFlag = multiAssetFlag;
+ }
+
+ public int getLBRDurationMod() {
+ return LBRDurationMod;
+ }
+
+ public void setLBRDurationMod(int LBRDurationMod) {
+ this.LBRDurationMod = LBRDurationMod;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public int getReservedBoxPresent() {
+ return reservedBoxPresent;
+ }
+
+ public void setReservedBoxPresent(int reservedBoxPresent) {
+ this.reservedBoxPresent = reservedBoxPresent;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/EC3SpecificBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/EC3SpecificBox.java
new file mode 100644
index 0000000..412db04
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/EC3SpecificBox.java
@@ -0,0 +1,140 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class EC3SpecificBox extends AbstractBox {
+ List<Entry> entries = new LinkedList<Entry>();
+ int dataRate;
+ int numIndSub;
+
+ public EC3SpecificBox() {
+ super("dec3");
+ }
+
+ @Override
+ public long getContentSize() {
+ long size = 2;
+ for (Entry entry : entries) {
+ if (entry.num_dep_sub > 0) {
+ size += 4;
+ } else {
+ size += 3;
+ }
+ }
+ return size;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ dataRate = brb.readBits(13);
+ numIndSub = brb.readBits(3) + 1;
+ // This field indicates the number of independent substreams that are present in the Enhanced AC-3 bitstream. The value
+ // of this field is one less than the number of independent substreams present.
+
+
+ for (int i = 0; i < numIndSub; i++) {
+ Entry e = new Entry();
+ e.fscod = brb.readBits(2);
+ e.bsid = brb.readBits(5);
+ e.bsmod = brb.readBits(5);
+ e.acmod = brb.readBits(3);
+ e.lfeon = brb.readBits(1);
+ e.reserved = brb.readBits(3);
+ e.num_dep_sub = brb.readBits(4);
+ if (e.num_dep_sub > 0) {
+ e.chan_loc = brb.readBits(9);
+ } else {
+ e.reserved2 = brb.readBits(1);
+ }
+ entries.add(e);
+ }
+ }
+
+ @Override
+ public void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(dataRate, 13);
+ bwb.writeBits(entries.size() - 1, 3);
+ for (Entry e : entries) {
+ bwb.writeBits(e.fscod, 2);
+ bwb.writeBits(e.bsid, 5);
+ bwb.writeBits(e.bsmod, 5);
+ bwb.writeBits(e.acmod, 3);
+ bwb.writeBits(e.lfeon, 1);
+ bwb.writeBits(e.reserved, 3);
+ bwb.writeBits(e.num_dep_sub, 4);
+ if (e.num_dep_sub > 0) {
+ bwb.writeBits(e.chan_loc, 9);
+ } else {
+ bwb.writeBits(e.reserved2, 1);
+ }
+ }
+ }
+
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public void addEntry(Entry entry) {
+ this.entries.add(entry);
+ }
+
+ public int getDataRate() {
+ return dataRate;
+ }
+
+ public void setDataRate(int dataRate) {
+ this.dataRate = dataRate;
+ }
+
+ public int getNumIndSub() {
+ return numIndSub;
+ }
+
+ public void setNumIndSub(int numIndSub) {
+ this.numIndSub = numIndSub;
+ }
+
+ public static class Entry {
+ public int fscod;
+ public int bsid;
+ public int bsmod;
+ public int acmod;
+ public int lfeon;
+ public int reserved;
+ public int num_dep_sub;
+ public int chan_loc;
+ public int reserved2;
+
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "fscod=" + fscod +
+ ", bsid=" + bsid +
+ ", bsmod=" + bsmod +
+ ", acmod=" + acmod +
+ ", lfeon=" + lfeon +
+ ", reserved=" + reserved +
+ ", num_dep_sub=" + num_dep_sub +
+ ", chan_loc=" + chan_loc +
+ ", reserved2=" + reserved2 +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/MLPSpecificBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/MLPSpecificBox.java
new file mode 100644
index 0000000..fe6f0d8
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/MLPSpecificBox.java
@@ -0,0 +1,76 @@
+package com.googlecode.mp4parser.boxes;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+
+
+public class MLPSpecificBox extends AbstractBox {
+
+ int format_info;
+ int peak_data_rate;
+ int reserved;
+ int reserved2;
+
+ public MLPSpecificBox() {
+ super("dmlp");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 10;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ BitReaderBuffer brb = new BitReaderBuffer(content);
+ format_info = brb.readBits(32);
+ peak_data_rate = brb.readBits(15);
+ reserved = brb.readBits(1);
+ reserved2 = brb.readBits(32);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ BitWriterBuffer bwb = new BitWriterBuffer(byteBuffer);
+ bwb.writeBits(format_info, 32);
+ bwb.writeBits(peak_data_rate, 15);
+ bwb.writeBits(reserved, 1);
+ bwb.writeBits(reserved2, 32);
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getFormat_info() {
+ return format_info;
+ }
+
+ public void setFormat_info(int format_info) {
+ this.format_info = format_info;
+ }
+
+ public int getPeak_data_rate() {
+ return peak_data_rate;
+ }
+
+ public void setPeak_data_rate(int peak_data_rate) {
+ this.peak_data_rate = peak_data_rate;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public int getReserved2() {
+ return reserved2;
+ }
+
+ public void setReserved2(int reserved2) {
+ this.reserved2 = reserved2;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/all-wcprops
new file mode 100644
index 0000000..d4678d2
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe
+END
+ActionMessageFormat0SampleEntryBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 124
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/ActionMessageFormat0SampleEntryBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/entries
new file mode 100644
index 0000000..c291f28
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+ActionMessageFormat0SampleEntryBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.297230Z
+cf327bd01b68a2d3801d58c67ba3a500
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+901
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/text-base/ActionMessageFormat0SampleEntryBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/text-base/ActionMessageFormat0SampleEntryBox.java.svn-base
new file mode 100644
index 0000000..483dd8f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/.svn/text-base/ActionMessageFormat0SampleEntryBox.java.svn-base
@@ -0,0 +1,38 @@
+package com.googlecode.mp4parser.boxes.adobe;
+
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Sample Entry as used for Action Message Format tracks.
+ */
+public class ActionMessageFormat0SampleEntryBox extends SampleEntry {
+ public ActionMessageFormat0SampleEntryBox() {
+ super("amf0");
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 8;
+ for (Box box : boxes) {
+ size += box.getSize();
+ }
+
+ return size;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ _parseChildBoxes(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/ActionMessageFormat0SampleEntryBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/ActionMessageFormat0SampleEntryBox.java
new file mode 100644
index 0000000..483dd8f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/adobe/ActionMessageFormat0SampleEntryBox.java
@@ -0,0 +1,38 @@
+package com.googlecode.mp4parser.boxes.adobe;
+
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Sample Entry as used for Action Message Format tracks.
+ */
+public class ActionMessageFormat0SampleEntryBox extends SampleEntry {
+ public ActionMessageFormat0SampleEntryBox() {
+ super("amf0");
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 8;
+ for (Box box : boxes) {
+ size += box.getSize();
+ }
+
+ return size;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ _parseChildBoxes(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/all-wcprops
new file mode 100644
index 0000000..458d104
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/!svn/ver/727/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple
+END
+TimeCodeBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/svn/!svn/ver/684/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TimeCodeBox.java
+END
+QuicktimeTextSampleEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/svn/!svn/ver/690/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/QuicktimeTextSampleEntry.java
+END
+GenericMediaHeaderAtom.java
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/svn/!svn/ver/684/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderAtom.java
+END
+BaseMediaInfoAtom.java
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/svn/!svn/ver/687/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/BaseMediaInfoAtom.java
+END
+TaptAtom.java
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svn/!svn/ver/727/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TaptAtom.java
+END
+GenericMediaHeaderTextAtom.java
+K 25
+svn:wc:ra_dav:version-url
+V 116
+/svn/!svn/ver/685/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderTextAtom.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/entries
new file mode 100644
index 0000000..ad474c2
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/entries
@@ -0,0 +1,232 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-08-08T07:05:08.133759Z
+727
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+TimeCodeBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.197229Z
+c584657a6b97bbddc67e006ea6425bb6
+2012-06-24T14:45:45.932648Z
+684
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1498
+
+QuicktimeTextSampleEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.197229Z
+9fb53b7189ae88149477c073fb987599
+2012-06-24T21:27:52.519961Z
+690
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6202
+
+GenericMediaHeaderAtom.java
+file
+
+
+
+
+2012-09-14T17:27:51.207229Z
+2eba5114788056352adb0e5e7d8cee33
+2012-06-24T14:45:45.932648Z
+684
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+890
+
+BaseMediaInfoAtom.java
+file
+
+
+
+
+2012-09-14T17:27:51.207229Z
+6119ba316b09d48ed85824b96f2b68b1
+2012-06-24T19:53:06.650023Z
+687
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2695
+
+TaptAtom.java
+file
+
+
+
+
+2012-09-14T17:27:51.207229Z
+9eed1655d1a9f0c187071c0bf6ff61bc
+2012-08-08T07:05:08.133759Z
+727
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+327
+
+GenericMediaHeaderTextAtom.java
+file
+
+
+
+
+2012-09-14T17:27:51.207229Z
+b06b279065c7b8475ade9558fa8227c9
+2012-06-24T15:08:14.651658Z
+685
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2866
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/BaseMediaInfoAtom.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/BaseMediaInfoAtom.java.svn-base
new file mode 100644
index 0000000..706569e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/BaseMediaInfoAtom.java.svn-base
@@ -0,0 +1,110 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+public class BaseMediaInfoAtom extends AbstractFullBox {
+ public static final String TYPE = "gmin";
+
+ short graphicsMode = 64;
+ int opColorR = 32768;
+ int opColorG = 32768;
+ int opColorB = 32768;
+ short balance;
+ short reserved;
+
+ public BaseMediaInfoAtom() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 16;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.putShort(graphicsMode);
+ IsoTypeWriter.writeUInt16(byteBuffer, opColorR);
+ IsoTypeWriter.writeUInt16(byteBuffer,opColorG );
+ IsoTypeWriter.writeUInt16(byteBuffer,opColorB );
+ byteBuffer.putShort(balance);
+ byteBuffer.putShort(reserved);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ graphicsMode = content.getShort();
+ opColorR = IsoTypeReader.readUInt16(content);
+ opColorG = IsoTypeReader.readUInt16(content);
+ opColorB = IsoTypeReader.readUInt16(content);
+ balance = content.getShort();
+ reserved = content.getShort();
+
+ }
+
+ public short getGraphicsMode() {
+ return graphicsMode;
+ }
+
+ public void setGraphicsMode(short graphicsMode) {
+ this.graphicsMode = graphicsMode;
+ }
+
+ public int getOpColorR() {
+ return opColorR;
+ }
+
+ public void setOpColorR(int opColorR) {
+ this.opColorR = opColorR;
+ }
+
+ public int getOpColorG() {
+ return opColorG;
+ }
+
+ public void setOpColorG(int opColorG) {
+ this.opColorG = opColorG;
+ }
+
+ public int getOpColorB() {
+ return opColorB;
+ }
+
+ public void setOpColorB(int opColorB) {
+ this.opColorB = opColorB;
+ }
+
+ public short getBalance() {
+ return balance;
+ }
+
+ public void setBalance(short balance) {
+ this.balance = balance;
+ }
+
+ public short getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(short reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseMediaInfoAtom{" +
+ "graphicsMode=" + graphicsMode +
+ ", opColorR=" + opColorR +
+ ", opColorG=" + opColorG +
+ ", opColorB=" + opColorB +
+ ", balance=" + balance +
+ ", reserved=" + reserved +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderAtom.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderAtom.java.svn-base
new file mode 100644
index 0000000..ac2033f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderAtom.java.svn-base
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class GenericMediaHeaderAtom extends AbstractContainerBox {
+
+ public static final String TYPE = "gmhd";
+
+ public GenericMediaHeaderAtom() {
+ super(TYPE);
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderTextAtom.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderTextAtom.java.svn-base
new file mode 100644
index 0000000..fd52dc9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/GenericMediaHeaderTextAtom.java.svn-base
@@ -0,0 +1,130 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Undocumented atom in the gmhd atom of text tracks.
+ */
+public class GenericMediaHeaderTextAtom extends AbstractBox {
+
+ public static final String TYPE = "text";
+
+ int unknown_1 = 65536;
+ int unknown_2;
+ int unknown_3;
+ int unknown_4;
+ int unknown_5 = 65536;
+ int unknown_6;
+ int unknown_7;
+ int unknown_8;
+ int unknown_9 = 1073741824;
+
+ public GenericMediaHeaderTextAtom() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 36;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ byteBuffer.putInt(unknown_1);
+ byteBuffer.putInt(unknown_2);
+ byteBuffer.putInt(unknown_3);
+ byteBuffer.putInt(unknown_4);
+ byteBuffer.putInt(unknown_5);
+ byteBuffer.putInt(unknown_6);
+ byteBuffer.putInt(unknown_7);
+ byteBuffer.putInt(unknown_8);
+ byteBuffer.putInt(unknown_9);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ unknown_1 = content.getInt();
+ unknown_2 = content.getInt();
+ unknown_3 = content.getInt();
+ unknown_4 = content.getInt();
+ unknown_5 = content.getInt();
+ unknown_6 = content.getInt();
+ unknown_7 = content.getInt();
+ unknown_8 = content.getInt();
+ unknown_9 = content.getInt();
+ }
+
+ public int getUnknown_1() {
+ return unknown_1;
+ }
+
+ public void setUnknown_1(int unknown_1) {
+ this.unknown_1 = unknown_1;
+ }
+
+ public int getUnknown_2() {
+ return unknown_2;
+ }
+
+ public void setUnknown_2(int unknown_2) {
+ this.unknown_2 = unknown_2;
+ }
+
+ public int getUnknown_3() {
+ return unknown_3;
+ }
+
+ public void setUnknown_3(int unknown_3) {
+ this.unknown_3 = unknown_3;
+ }
+
+ public int getUnknown_4() {
+ return unknown_4;
+ }
+
+ public void setUnknown_4(int unknown_4) {
+ this.unknown_4 = unknown_4;
+ }
+
+ public int getUnknown_5() {
+ return unknown_5;
+ }
+
+ public void setUnknown_5(int unknown_5) {
+ this.unknown_5 = unknown_5;
+ }
+
+ public int getUnknown_6() {
+ return unknown_6;
+ }
+
+ public void setUnknown_6(int unknown_6) {
+ this.unknown_6 = unknown_6;
+ }
+
+ public int getUnknown_7() {
+ return unknown_7;
+ }
+
+ public void setUnknown_7(int unknown_7) {
+ this.unknown_7 = unknown_7;
+ }
+
+ public int getUnknown_8() {
+ return unknown_8;
+ }
+
+ public void setUnknown_8(int unknown_8) {
+ this.unknown_8 = unknown_8;
+ }
+
+ public int getUnknown_9() {
+ return unknown_9;
+ }
+
+ public void setUnknown_9(int unknown_9) {
+ this.unknown_9 = unknown_9;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/QuicktimeTextSampleEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/QuicktimeTextSampleEntry.java.svn-base
new file mode 100644
index 0000000..8784fc6
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/QuicktimeTextSampleEntry.java.svn-base
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Entry type for timed text samples defined in the timed text specification (ISO/IEC 14496-17).
+ */
+public class QuicktimeTextSampleEntry extends SampleEntry {
+
+ public static final String TYPE = "text";
+
+ int displayFlags;
+ int textJustification;
+
+ int backgroundR;
+ int backgroundG;
+ int backgroundB;
+
+ long defaultTextBox;
+ long reserved1;
+
+ short fontNumber;
+ short fontFace;
+ byte reserved2;
+ short reserved3;
+
+ int foregroundR = 65535;
+ int foregroundG = 65535;
+ int foregroundB = 65535;
+
+ String fontName = "";
+
+ public QuicktimeTextSampleEntry() {
+ super(TYPE);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+
+ displayFlags = content.getInt();
+ textJustification = content.getInt();
+ backgroundR = IsoTypeReader.readUInt16(content);
+ backgroundG = IsoTypeReader.readUInt16(content);
+ backgroundB = IsoTypeReader.readUInt16(content);
+ defaultTextBox = IsoTypeReader.readUInt64(content);
+ reserved1 = IsoTypeReader.readUInt64(content);
+ fontNumber = content.getShort();
+ fontFace = content.getShort();
+ reserved2 = content.get();
+ reserved3 = content.getShort();
+ foregroundR = IsoTypeReader.readUInt16(content);
+ foregroundG = IsoTypeReader.readUInt16(content);
+ foregroundB = IsoTypeReader.readUInt16(content);
+
+ if (content.remaining() > 0) {
+ int length = IsoTypeReader.readUInt8(content);
+ byte[] myFontName = new byte[length];
+ content.get(myFontName);
+ fontName = new String(myFontName);
+ } else {
+ fontName = null;
+ }
+ }
+
+
+ protected long getContentSize() {
+ return 52 + (fontName != null ? fontName.length() : 0);
+ }
+
+
+ public int getDisplayFlags() {
+ return displayFlags;
+ }
+
+ public void setDisplayFlags(int displayFlags) {
+ this.displayFlags = displayFlags;
+ }
+
+ public int getTextJustification() {
+ return textJustification;
+ }
+
+ public void setTextJustification(int textJustification) {
+ this.textJustification = textJustification;
+ }
+
+ public int getBackgroundR() {
+ return backgroundR;
+ }
+
+ public void setBackgroundR(int backgroundR) {
+ this.backgroundR = backgroundR;
+ }
+
+ public int getBackgroundG() {
+ return backgroundG;
+ }
+
+ public void setBackgroundG(int backgroundG) {
+ this.backgroundG = backgroundG;
+ }
+
+ public int getBackgroundB() {
+ return backgroundB;
+ }
+
+ public void setBackgroundB(int backgroundB) {
+ this.backgroundB = backgroundB;
+ }
+
+ public long getDefaultTextBox() {
+ return defaultTextBox;
+ }
+
+ public void setDefaultTextBox(long defaultTextBox) {
+ this.defaultTextBox = defaultTextBox;
+ }
+
+ public long getReserved1() {
+ return reserved1;
+ }
+
+ public void setReserved1(long reserved1) {
+ this.reserved1 = reserved1;
+ }
+
+ public short getFontNumber() {
+ return fontNumber;
+ }
+
+ public void setFontNumber(short fontNumber) {
+ this.fontNumber = fontNumber;
+ }
+
+ public short getFontFace() {
+ return fontFace;
+ }
+
+ public void setFontFace(short fontFace) {
+ this.fontFace = fontFace;
+ }
+
+ public byte getReserved2() {
+ return reserved2;
+ }
+
+ public void setReserved2(byte reserved2) {
+ this.reserved2 = reserved2;
+ }
+
+ public short getReserved3() {
+ return reserved3;
+ }
+
+ public void setReserved3(short reserved3) {
+ this.reserved3 = reserved3;
+ }
+
+ public int getForegroundR() {
+ return foregroundR;
+ }
+
+ public void setForegroundR(int foregroundR) {
+ this.foregroundR = foregroundR;
+ }
+
+ public int getForegroundG() {
+ return foregroundG;
+ }
+
+ public void setForegroundG(int foregroundG) {
+ this.foregroundG = foregroundG;
+ }
+
+ public int getForegroundB() {
+ return foregroundB;
+ }
+
+ public void setForegroundB(int foregroundB) {
+ this.foregroundB = foregroundB;
+ }
+
+ public String getFontName() {
+ return fontName;
+ }
+
+ public void setFontName(String fontName) {
+ this.fontName = fontName;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ byteBuffer.putInt(displayFlags);
+ byteBuffer.putInt(textJustification);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundR);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundG);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundB);
+ IsoTypeWriter.writeUInt64(byteBuffer, defaultTextBox);
+ IsoTypeWriter.writeUInt64(byteBuffer, reserved1);
+ byteBuffer.putShort(fontNumber);
+ byteBuffer.putShort(fontFace);
+ byteBuffer.put(reserved2);
+ byteBuffer.putShort(reserved3);
+
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundR);
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundG);
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundB);
+ if (fontName != null) {
+ IsoTypeWriter.writeUInt8(byteBuffer, fontName.length());
+ byteBuffer.put(fontName.getBytes());
+ }
+
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TaptAtom.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TaptAtom.java.svn-base
new file mode 100644
index 0000000..4fcea56
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TaptAtom.java.svn-base
@@ -0,0 +1,16 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+/**
+ * Don't know what it is but it is obviously a container box.
+ */
+public class TaptAtom extends AbstractContainerBox {
+ public static final String TYPE = "tapt";
+
+ public TaptAtom() {
+ super(TYPE);
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TimeCodeBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TimeCodeBox.java.svn-base
new file mode 100644
index 0000000..e15c9f0
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/.svn/text-base/TimeCodeBox.java.svn-base
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+public class TimeCodeBox extends SampleEntry {
+ byte[] data;
+
+
+ public TimeCodeBox() {
+ super("tmcd");
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 26;
+ for (Box box : boxes) {
+ size += box.getSize();
+ }
+ return size;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ data = new byte[18];
+ content.get(data);
+ _parseChildBoxes(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ byteBuffer.put(data);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/BaseMediaInfoAtom.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/BaseMediaInfoAtom.java
new file mode 100644
index 0000000..706569e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/BaseMediaInfoAtom.java
@@ -0,0 +1,110 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+public class BaseMediaInfoAtom extends AbstractFullBox {
+ public static final String TYPE = "gmin";
+
+ short graphicsMode = 64;
+ int opColorR = 32768;
+ int opColorG = 32768;
+ int opColorB = 32768;
+ short balance;
+ short reserved;
+
+ public BaseMediaInfoAtom() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 16;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.putShort(graphicsMode);
+ IsoTypeWriter.writeUInt16(byteBuffer, opColorR);
+ IsoTypeWriter.writeUInt16(byteBuffer,opColorG );
+ IsoTypeWriter.writeUInt16(byteBuffer,opColorB );
+ byteBuffer.putShort(balance);
+ byteBuffer.putShort(reserved);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ graphicsMode = content.getShort();
+ opColorR = IsoTypeReader.readUInt16(content);
+ opColorG = IsoTypeReader.readUInt16(content);
+ opColorB = IsoTypeReader.readUInt16(content);
+ balance = content.getShort();
+ reserved = content.getShort();
+
+ }
+
+ public short getGraphicsMode() {
+ return graphicsMode;
+ }
+
+ public void setGraphicsMode(short graphicsMode) {
+ this.graphicsMode = graphicsMode;
+ }
+
+ public int getOpColorR() {
+ return opColorR;
+ }
+
+ public void setOpColorR(int opColorR) {
+ this.opColorR = opColorR;
+ }
+
+ public int getOpColorG() {
+ return opColorG;
+ }
+
+ public void setOpColorG(int opColorG) {
+ this.opColorG = opColorG;
+ }
+
+ public int getOpColorB() {
+ return opColorB;
+ }
+
+ public void setOpColorB(int opColorB) {
+ this.opColorB = opColorB;
+ }
+
+ public short getBalance() {
+ return balance;
+ }
+
+ public void setBalance(short balance) {
+ this.balance = balance;
+ }
+
+ public short getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(short reserved) {
+ this.reserved = reserved;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseMediaInfoAtom{" +
+ "graphicsMode=" + graphicsMode +
+ ", opColorR=" + opColorR +
+ ", opColorG=" + opColorG +
+ ", opColorB=" + opColorB +
+ ", balance=" + balance +
+ ", reserved=" + reserved +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderAtom.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderAtom.java
new file mode 100644
index 0000000..ac2033f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderAtom.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+public class GenericMediaHeaderAtom extends AbstractContainerBox {
+
+ public static final String TYPE = "gmhd";
+
+ public GenericMediaHeaderAtom() {
+ super(TYPE);
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderTextAtom.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderTextAtom.java
new file mode 100644
index 0000000..fd52dc9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/GenericMediaHeaderTextAtom.java
@@ -0,0 +1,130 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Undocumented atom in the gmhd atom of text tracks.
+ */
+public class GenericMediaHeaderTextAtom extends AbstractBox {
+
+ public static final String TYPE = "text";
+
+ int unknown_1 = 65536;
+ int unknown_2;
+ int unknown_3;
+ int unknown_4;
+ int unknown_5 = 65536;
+ int unknown_6;
+ int unknown_7;
+ int unknown_8;
+ int unknown_9 = 1073741824;
+
+ public GenericMediaHeaderTextAtom() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 36;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ byteBuffer.putInt(unknown_1);
+ byteBuffer.putInt(unknown_2);
+ byteBuffer.putInt(unknown_3);
+ byteBuffer.putInt(unknown_4);
+ byteBuffer.putInt(unknown_5);
+ byteBuffer.putInt(unknown_6);
+ byteBuffer.putInt(unknown_7);
+ byteBuffer.putInt(unknown_8);
+ byteBuffer.putInt(unknown_9);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ unknown_1 = content.getInt();
+ unknown_2 = content.getInt();
+ unknown_3 = content.getInt();
+ unknown_4 = content.getInt();
+ unknown_5 = content.getInt();
+ unknown_6 = content.getInt();
+ unknown_7 = content.getInt();
+ unknown_8 = content.getInt();
+ unknown_9 = content.getInt();
+ }
+
+ public int getUnknown_1() {
+ return unknown_1;
+ }
+
+ public void setUnknown_1(int unknown_1) {
+ this.unknown_1 = unknown_1;
+ }
+
+ public int getUnknown_2() {
+ return unknown_2;
+ }
+
+ public void setUnknown_2(int unknown_2) {
+ this.unknown_2 = unknown_2;
+ }
+
+ public int getUnknown_3() {
+ return unknown_3;
+ }
+
+ public void setUnknown_3(int unknown_3) {
+ this.unknown_3 = unknown_3;
+ }
+
+ public int getUnknown_4() {
+ return unknown_4;
+ }
+
+ public void setUnknown_4(int unknown_4) {
+ this.unknown_4 = unknown_4;
+ }
+
+ public int getUnknown_5() {
+ return unknown_5;
+ }
+
+ public void setUnknown_5(int unknown_5) {
+ this.unknown_5 = unknown_5;
+ }
+
+ public int getUnknown_6() {
+ return unknown_6;
+ }
+
+ public void setUnknown_6(int unknown_6) {
+ this.unknown_6 = unknown_6;
+ }
+
+ public int getUnknown_7() {
+ return unknown_7;
+ }
+
+ public void setUnknown_7(int unknown_7) {
+ this.unknown_7 = unknown_7;
+ }
+
+ public int getUnknown_8() {
+ return unknown_8;
+ }
+
+ public void setUnknown_8(int unknown_8) {
+ this.unknown_8 = unknown_8;
+ }
+
+ public int getUnknown_9() {
+ return unknown_9;
+ }
+
+ public void setUnknown_9(int unknown_9) {
+ this.unknown_9 = unknown_9;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/QuicktimeTextSampleEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/QuicktimeTextSampleEntry.java
new file mode 100644
index 0000000..8784fc6
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/QuicktimeTextSampleEntry.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Entry type for timed text samples defined in the timed text specification (ISO/IEC 14496-17).
+ */
+public class QuicktimeTextSampleEntry extends SampleEntry {
+
+ public static final String TYPE = "text";
+
+ int displayFlags;
+ int textJustification;
+
+ int backgroundR;
+ int backgroundG;
+ int backgroundB;
+
+ long defaultTextBox;
+ long reserved1;
+
+ short fontNumber;
+ short fontFace;
+ byte reserved2;
+ short reserved3;
+
+ int foregroundR = 65535;
+ int foregroundG = 65535;
+ int foregroundB = 65535;
+
+ String fontName = "";
+
+ public QuicktimeTextSampleEntry() {
+ super(TYPE);
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+
+ displayFlags = content.getInt();
+ textJustification = content.getInt();
+ backgroundR = IsoTypeReader.readUInt16(content);
+ backgroundG = IsoTypeReader.readUInt16(content);
+ backgroundB = IsoTypeReader.readUInt16(content);
+ defaultTextBox = IsoTypeReader.readUInt64(content);
+ reserved1 = IsoTypeReader.readUInt64(content);
+ fontNumber = content.getShort();
+ fontFace = content.getShort();
+ reserved2 = content.get();
+ reserved3 = content.getShort();
+ foregroundR = IsoTypeReader.readUInt16(content);
+ foregroundG = IsoTypeReader.readUInt16(content);
+ foregroundB = IsoTypeReader.readUInt16(content);
+
+ if (content.remaining() > 0) {
+ int length = IsoTypeReader.readUInt8(content);
+ byte[] myFontName = new byte[length];
+ content.get(myFontName);
+ fontName = new String(myFontName);
+ } else {
+ fontName = null;
+ }
+ }
+
+
+ protected long getContentSize() {
+ return 52 + (fontName != null ? fontName.length() : 0);
+ }
+
+
+ public int getDisplayFlags() {
+ return displayFlags;
+ }
+
+ public void setDisplayFlags(int displayFlags) {
+ this.displayFlags = displayFlags;
+ }
+
+ public int getTextJustification() {
+ return textJustification;
+ }
+
+ public void setTextJustification(int textJustification) {
+ this.textJustification = textJustification;
+ }
+
+ public int getBackgroundR() {
+ return backgroundR;
+ }
+
+ public void setBackgroundR(int backgroundR) {
+ this.backgroundR = backgroundR;
+ }
+
+ public int getBackgroundG() {
+ return backgroundG;
+ }
+
+ public void setBackgroundG(int backgroundG) {
+ this.backgroundG = backgroundG;
+ }
+
+ public int getBackgroundB() {
+ return backgroundB;
+ }
+
+ public void setBackgroundB(int backgroundB) {
+ this.backgroundB = backgroundB;
+ }
+
+ public long getDefaultTextBox() {
+ return defaultTextBox;
+ }
+
+ public void setDefaultTextBox(long defaultTextBox) {
+ this.defaultTextBox = defaultTextBox;
+ }
+
+ public long getReserved1() {
+ return reserved1;
+ }
+
+ public void setReserved1(long reserved1) {
+ this.reserved1 = reserved1;
+ }
+
+ public short getFontNumber() {
+ return fontNumber;
+ }
+
+ public void setFontNumber(short fontNumber) {
+ this.fontNumber = fontNumber;
+ }
+
+ public short getFontFace() {
+ return fontFace;
+ }
+
+ public void setFontFace(short fontFace) {
+ this.fontFace = fontFace;
+ }
+
+ public byte getReserved2() {
+ return reserved2;
+ }
+
+ public void setReserved2(byte reserved2) {
+ this.reserved2 = reserved2;
+ }
+
+ public short getReserved3() {
+ return reserved3;
+ }
+
+ public void setReserved3(short reserved3) {
+ this.reserved3 = reserved3;
+ }
+
+ public int getForegroundR() {
+ return foregroundR;
+ }
+
+ public void setForegroundR(int foregroundR) {
+ this.foregroundR = foregroundR;
+ }
+
+ public int getForegroundG() {
+ return foregroundG;
+ }
+
+ public void setForegroundG(int foregroundG) {
+ this.foregroundG = foregroundG;
+ }
+
+ public int getForegroundB() {
+ return foregroundB;
+ }
+
+ public void setForegroundB(int foregroundB) {
+ this.foregroundB = foregroundB;
+ }
+
+ public String getFontName() {
+ return fontName;
+ }
+
+ public void setFontName(String fontName) {
+ this.fontName = fontName;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ byteBuffer.putInt(displayFlags);
+ byteBuffer.putInt(textJustification);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundR);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundG);
+ IsoTypeWriter.writeUInt16(byteBuffer, backgroundB);
+ IsoTypeWriter.writeUInt64(byteBuffer, defaultTextBox);
+ IsoTypeWriter.writeUInt64(byteBuffer, reserved1);
+ byteBuffer.putShort(fontNumber);
+ byteBuffer.putShort(fontFace);
+ byteBuffer.put(reserved2);
+ byteBuffer.putShort(reserved3);
+
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundR);
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundG);
+ IsoTypeWriter.writeUInt16(byteBuffer, foregroundB);
+ if (fontName != null) {
+ IsoTypeWriter.writeUInt8(byteBuffer, fontName.length());
+ byteBuffer.put(fontName.getBytes());
+ }
+
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TaptAtom.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TaptAtom.java
new file mode 100644
index 0000000..4fcea56
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TaptAtom.java
@@ -0,0 +1,16 @@
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.googlecode.mp4parser.AbstractContainerBox;
+
+/**
+ * Don't know what it is but it is obviously a container box.
+ */
+public class TaptAtom extends AbstractContainerBox {
+ public static final String TYPE = "tapt";
+
+ public TaptAtom() {
+ super(TYPE);
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TimeCodeBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TimeCodeBox.java
new file mode 100644
index 0000000..e15c9f0
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/apple/TimeCodeBox.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.apple;
+
+import com.coremedia.iso.boxes.Box;
+import com.coremedia.iso.boxes.sampleentry.SampleEntry;
+
+import java.nio.ByteBuffer;
+
+public class TimeCodeBox extends SampleEntry {
+ byte[] data;
+
+
+ public TimeCodeBox() {
+ super("tmcd");
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 26;
+ for (Box box : boxes) {
+ size += box.getSize();
+ }
+ return size;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ _parseReservedAndDataReferenceIndex(content);
+ data = new byte[18];
+ content.get(data);
+ _parseChildBoxes(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ _writeReservedAndDataReferenceIndex(byteBuffer);
+ byteBuffer.put(data);
+ _writeChildBoxes(byteBuffer);
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/all-wcprops
new file mode 100644
index 0000000..f4b1c1b
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/svn/!svn/ver/671/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat
+END
+AvcNalUnitStorageBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/svn/!svn/ver/671/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/AvcNalUnitStorageBox.java
+END
+SampleEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 119
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/SampleEncryptionBox.java
+END
+TrackEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/svn/!svn/ver/276/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/TrackEncryptionBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/entries
new file mode 100644
index 0000000..6af5ffa
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-06-10T18:50:38.971172Z
+671
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+AvcNalUnitStorageBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.667221Z
+fa9f9cda733943c6af5e690156163dcb
+2012-06-10T18:50:38.971172Z
+671
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3290
+
+SampleEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.667221Z
+b451a1521659345d7712cbb874eec98f
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+618
+
+TrackEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.667221Z
+9ab827bee01e8abfe68167428df756dc
+2011-11-22T18:13:22.290919Z
+276
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+269
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/AvcNalUnitStorageBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/AvcNalUnitStorageBox.java.svn-base
new file mode 100644
index 0000000..7182eca
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/AvcNalUnitStorageBox.java.svn-base
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.coremedia.iso.boxes.h264.AvcConfigurationBox;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * The AVC NAL Unit Storage Box SHALL contain an AVCDecoderConfigurationRecord,
+ * as defined in section 5.2.4.1 of the ISO 14496-12.
+ */
+public class AvcNalUnitStorageBox extends AbstractBox {
+ AvcConfigurationBox.AVCDecoderConfigurationRecord avcDecoderConfigurationRecord;
+
+ public AvcNalUnitStorageBox() {
+ super("avcn");
+ }
+
+ public AvcNalUnitStorageBox(AvcConfigurationBox avcConfigurationBox) {
+ super("avcn");
+ this.avcDecoderConfigurationRecord = avcConfigurationBox.getavcDecoderConfigurationRecord();
+ }
+
+ public AvcConfigurationBox.AVCDecoderConfigurationRecord getAvcDecoderConfigurationRecord() {
+ return avcDecoderConfigurationRecord;
+ }
+
+ // just to display sps in isoviewer no practical use
+ public int getLengthSizeMinusOne() {
+ return avcDecoderConfigurationRecord.lengthSizeMinusOne;
+ }
+
+ 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();
+ }
+
+ @Override
+ protected long getContentSize() {
+ return avcDecoderConfigurationRecord.getContentSize();
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ this.avcDecoderConfigurationRecord = new AvcConfigurationBox.AVCDecoderConfigurationRecord(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ this.avcDecoderConfigurationRecord.getContent(byteBuffer);
+ }
+
+ @Override
+ public String toString() {
+ return "AvcNalUnitStorageBox{" +
+ "SPS=" + avcDecoderConfigurationRecord.getSequenceParameterSetsAsStrings() +
+ ",PPS=" + avcDecoderConfigurationRecord.getPictureParameterSetsAsStrings() +
+ ",lengthSize=" + (avcDecoderConfigurationRecord.lengthSizeMinusOne + 1) +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/SampleEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/SampleEncryptionBox.java.svn-base
new file mode 100644
index 0000000..3430818
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/SampleEncryptionBox.java.svn-base
@@ -0,0 +1,24 @@
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.boxes.AbstractSampleEncryptionBox;
+
+/**
+ * aligned(8) class AbstractSampleEncryptionBox extends FullBox(‘uuid’, extended_type= 0xA2394F52-5A9B-4f14-A244-6C427C648DF4, version=0, flags=0)
+ * {
+ * <p/>
+ * unsigned int (32) sample_count;
+ * {
+ * unsigned int(16) InitializationVector;
+ * }[ sample_count ]
+ * }
+ */
+public class SampleEncryptionBox extends AbstractSampleEncryptionBox {
+
+ /**
+ * Creates a SampleEncryptionBox for non-h264 tracks.
+ */
+ public SampleEncryptionBox() {
+ super("senc");
+
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/TrackEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/TrackEncryptionBox.java.svn-base
new file mode 100644
index 0000000..dd93a12
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/.svn/text-base/TrackEncryptionBox.java.svn-base
@@ -0,0 +1,12 @@
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.boxes.AbstractTrackEncryptionBox;
+
+/**
+ *
+ */
+public class TrackEncryptionBox extends AbstractTrackEncryptionBox {
+ public TrackEncryptionBox() {
+ super("tenc");
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/AvcNalUnitStorageBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/AvcNalUnitStorageBox.java
new file mode 100644
index 0000000..7182eca
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/AvcNalUnitStorageBox.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.AbstractBox;
+import com.coremedia.iso.boxes.h264.AvcConfigurationBox;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * The AVC NAL Unit Storage Box SHALL contain an AVCDecoderConfigurationRecord,
+ * as defined in section 5.2.4.1 of the ISO 14496-12.
+ */
+public class AvcNalUnitStorageBox extends AbstractBox {
+ AvcConfigurationBox.AVCDecoderConfigurationRecord avcDecoderConfigurationRecord;
+
+ public AvcNalUnitStorageBox() {
+ super("avcn");
+ }
+
+ public AvcNalUnitStorageBox(AvcConfigurationBox avcConfigurationBox) {
+ super("avcn");
+ this.avcDecoderConfigurationRecord = avcConfigurationBox.getavcDecoderConfigurationRecord();
+ }
+
+ public AvcConfigurationBox.AVCDecoderConfigurationRecord getAvcDecoderConfigurationRecord() {
+ return avcDecoderConfigurationRecord;
+ }
+
+ // just to display sps in isoviewer no practical use
+ public int getLengthSizeMinusOne() {
+ return avcDecoderConfigurationRecord.lengthSizeMinusOne;
+ }
+
+ 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();
+ }
+
+ @Override
+ protected long getContentSize() {
+ return avcDecoderConfigurationRecord.getContentSize();
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ this.avcDecoderConfigurationRecord = new AvcConfigurationBox.AVCDecoderConfigurationRecord(content);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ this.avcDecoderConfigurationRecord.getContent(byteBuffer);
+ }
+
+ @Override
+ public String toString() {
+ return "AvcNalUnitStorageBox{" +
+ "SPS=" + avcDecoderConfigurationRecord.getSequenceParameterSetsAsStrings() +
+ ",PPS=" + avcDecoderConfigurationRecord.getPictureParameterSetsAsStrings() +
+ ",lengthSize=" + (avcDecoderConfigurationRecord.lengthSizeMinusOne + 1) +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/SampleEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/SampleEncryptionBox.java
new file mode 100644
index 0000000..3430818
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/SampleEncryptionBox.java
@@ -0,0 +1,24 @@
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.boxes.AbstractSampleEncryptionBox;
+
+/**
+ * aligned(8) class AbstractSampleEncryptionBox extends FullBox(‘uuid’, extended_type= 0xA2394F52-5A9B-4f14-A244-6C427C648DF4, version=0, flags=0)
+ * {
+ * <p/>
+ * unsigned int (32) sample_count;
+ * {
+ * unsigned int(16) InitializationVector;
+ * }[ sample_count ]
+ * }
+ */
+public class SampleEncryptionBox extends AbstractSampleEncryptionBox {
+
+ /**
+ * Creates a SampleEncryptionBox for non-h264 tracks.
+ */
+ public SampleEncryptionBox() {
+ super("senc");
+
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/TrackEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/TrackEncryptionBox.java
new file mode 100644
index 0000000..dd93a12
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/basemediaformat/TrackEncryptionBox.java
@@ -0,0 +1,12 @@
+package com.googlecode.mp4parser.boxes.basemediaformat;
+
+import com.googlecode.mp4parser.boxes.AbstractTrackEncryptionBox;
+
+/**
+ *
+ */
+public class TrackEncryptionBox extends AbstractTrackEncryptionBox {
+ public TrackEncryptionBox() {
+ super("tenc");
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/all-wcprops
new file mode 100644
index 0000000..54b03df
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/!svn/ver/728/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc
+END
+ProtectionSystemSpecificHeaderBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/svn/!svn/ver/728/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/ProtectionSystemSpecificHeaderBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/entries
new file mode 100644
index 0000000..c96b178
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-08-08T11:39:22.997932Z
+728
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+ProtectionSystemSpecificHeaderBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.237229Z
+5722926350b47a524ba4c38adeafe5bd
+2012-08-08T11:39:22.997932Z
+728
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3203
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/text-base/ProtectionSystemSpecificHeaderBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/text-base/ProtectionSystemSpecificHeaderBox.java.svn-base
new file mode 100644
index 0000000..d6b653c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/.svn/text-base/ProtectionSystemSpecificHeaderBox.java.svn-base
@@ -0,0 +1,89 @@
+package com.googlecode.mp4parser.boxes.cenc;
+
+import com.coremedia.iso.BoxParser;
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.Box;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.util.UUIDConverter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+
+
+/**
+ * This box contains information needed by a Content Protection System to play back the content. The
+ * data format is specified by the system identified by the ‘pssh’ parameter SystemID, and is considered
+ * opaque for the purposes of this specification.
+ * <p/>
+ * The data encapsulated in the Data field may be read by the identified Content Protection System to
+ * enable decryption key acquisition and decryption of media data. For license/rights-based systems, the
+ * header information may include data such as the URL of license server(s) or rights issuer(s) used,
+ * embedded licenses/rights, and/or other protection system specific metadata.
+ * <p/>
+ * A single file may be constructed to be playable by multiple key and digital rights management (DRM)
+ * systems, by including one Protection System-Specific Header box for each system supported. Readers
+ * that process such presentations must match the SystemID field in this box to the SystemID(s) of the
+ * DRM System(s) they support, and select or create the matching Protection System-Specific Header
+ * box(es) for storage and retrieval of Protection-Specific information interpreted or created by that DRM
+ * system.
+ */
+public class ProtectionSystemSpecificHeaderBox extends AbstractFullBox {
+ public static final String TYPE = "pssh";
+
+ public static byte[] OMA2_SYSTEM_ID = UUIDConverter.convert(UUID.fromString("A2B55680-6F43-11E0-9A3F-0002A5D5C51B"));
+ public static byte[] PLAYREADY_SYSTEM_ID = UUIDConverter.convert(UUID.fromString("9A04F079-9840-4286-AB92-E65BE0885F95"));
+
+ byte[] content;
+ byte[] systemId;
+
+
+ public byte[] getSystemId() {
+ return systemId;
+ }
+
+ public void setSystemId(byte[] systemId) {
+ assert systemId.length == 16;
+ this.systemId = systemId;
+ }
+
+ public byte[] getContent() {
+ return content;
+ }
+
+ public void setContent(byte[] content) {
+ this.content = content;
+ }
+
+ public ProtectionSystemSpecificHeaderBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24 + content.length;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ assert systemId.length == 16;
+ byteBuffer.put(systemId, 0, 16);
+ IsoTypeWriter.writeUInt32(byteBuffer, content.length);
+ byteBuffer.put(content);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ systemId = new byte[16];
+ content.get(systemId);
+ long length = IsoTypeReader.readUInt32(content);
+ this.content = new byte[content.remaining()];
+ content.get(this.content);
+ assert length == this.content.length;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/ProtectionSystemSpecificHeaderBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/ProtectionSystemSpecificHeaderBox.java
new file mode 100644
index 0000000..d6b653c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/cenc/ProtectionSystemSpecificHeaderBox.java
@@ -0,0 +1,89 @@
+package com.googlecode.mp4parser.boxes.cenc;
+
+import com.coremedia.iso.BoxParser;
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.Box;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.util.UUIDConverter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+
+
+/**
+ * This box contains information needed by a Content Protection System to play back the content. The
+ * data format is specified by the system identified by the ‘pssh’ parameter SystemID, and is considered
+ * opaque for the purposes of this specification.
+ * <p/>
+ * The data encapsulated in the Data field may be read by the identified Content Protection System to
+ * enable decryption key acquisition and decryption of media data. For license/rights-based systems, the
+ * header information may include data such as the URL of license server(s) or rights issuer(s) used,
+ * embedded licenses/rights, and/or other protection system specific metadata.
+ * <p/>
+ * A single file may be constructed to be playable by multiple key and digital rights management (DRM)
+ * systems, by including one Protection System-Specific Header box for each system supported. Readers
+ * that process such presentations must match the SystemID field in this box to the SystemID(s) of the
+ * DRM System(s) they support, and select or create the matching Protection System-Specific Header
+ * box(es) for storage and retrieval of Protection-Specific information interpreted or created by that DRM
+ * system.
+ */
+public class ProtectionSystemSpecificHeaderBox extends AbstractFullBox {
+ public static final String TYPE = "pssh";
+
+ public static byte[] OMA2_SYSTEM_ID = UUIDConverter.convert(UUID.fromString("A2B55680-6F43-11E0-9A3F-0002A5D5C51B"));
+ public static byte[] PLAYREADY_SYSTEM_ID = UUIDConverter.convert(UUID.fromString("9A04F079-9840-4286-AB92-E65BE0885F95"));
+
+ byte[] content;
+ byte[] systemId;
+
+
+ public byte[] getSystemId() {
+ return systemId;
+ }
+
+ public void setSystemId(byte[] systemId) {
+ assert systemId.length == 16;
+ this.systemId = systemId;
+ }
+
+ public byte[] getContent() {
+ return content;
+ }
+
+ public void setContent(byte[] content) {
+ this.content = content;
+ }
+
+ public ProtectionSystemSpecificHeaderBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24 + content.length;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ assert systemId.length == 16;
+ byteBuffer.put(systemId, 0, 16);
+ IsoTypeWriter.writeUInt32(byteBuffer, content.length);
+ byteBuffer.put(content);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ systemId = new byte[16];
+ content.get(systemId);
+ long length = IsoTypeReader.readUInt32(content);
+ this.content = new byte[content.remaining()];
+ content.get(this.content);
+ assert length == this.content.length;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4-boxes.zip b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4-boxes.zip
new file mode 100644
index 0000000..c9bcf8b
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4-boxes.zip
Binary files differ
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/all-wcprops
new file mode 100644
index 0000000..b552219
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4
+END
+ESDescriptorBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ESDescriptorBox.java
+END
+AbstractDescriptorBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/AbstractDescriptorBox.java
+END
+ObjectDescriptorBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ObjectDescriptorBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/entries
new file mode 100644
index 0000000..be8f9d8
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/entries
@@ -0,0 +1,136 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+ESDescriptorBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+3938742e971cd377b37592461870d872
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1021
+
+objectdescriptors
+dir
+
+AbstractDescriptorBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+3361124b1437f844ab4727c8dea81e3d
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2487
+
+samplegrouping
+dir
+
+ObjectDescriptorBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+b81e2d3876ef2af7ba17bf2d8bd6e504
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1983
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/AbstractDescriptorBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/AbstractDescriptorBox.java.svn-base
new file mode 100644
index 0000000..7d614e2
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/AbstractDescriptorBox.java.svn-base
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BaseDescriptor;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ObjectDescriptorFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * ES Descriptor Box.
+ */
+public class AbstractDescriptorBox extends AbstractFullBox {
+ private static Logger log = Logger.getLogger(AbstractDescriptorBox.class.getName());
+
+
+ public BaseDescriptor descriptor;
+ public ByteBuffer data;
+
+ public AbstractDescriptorBox(String type) {
+ super(type);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ data.rewind(); // has been fforwarded by parsing
+ byteBuffer.put(data);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 4 + data.limit();
+ }
+
+ public BaseDescriptor getDescriptor() {
+ return descriptor;
+ }
+
+ public String getDescriptorAsString() {
+ return descriptor.toString();
+ }
+
+ public void setData(ByteBuffer data) {
+ this.data = data;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ data = content.slice();
+ content.position(content.position() + content.remaining());
+ try {
+ data.rewind();
+ descriptor = ObjectDescriptorFactory.createFrom(-1, data);
+ } catch (IOException e) {
+ log.log(Level.WARNING, "Error parsing ObjectDescriptor", e);
+ //that's why we copied it ;)
+ } catch (IndexOutOfBoundsException e) {
+ log.log(Level.WARNING, "Error parsing ObjectDescriptor", e);
+ //that's why we copied it ;)
+ }
+
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ESDescriptorBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ESDescriptorBox.java.svn-base
new file mode 100644
index 0000000..5d9d591
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ESDescriptorBox.java.svn-base
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor;
+
+/**
+ * ES Descriptor Box.
+ */
+public class ESDescriptorBox extends AbstractDescriptorBox {
+ public static final String TYPE = "esds";
+
+ public ESDescriptorBox() {
+ super(TYPE);
+ }
+
+ public ESDescriptor getEsDescriptor() {
+ return (ESDescriptor) super.getDescriptor();
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ObjectDescriptorBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ObjectDescriptorBox.java.svn-base
new file mode 100644
index 0000000..c9e7493
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/.svn/text-base/ObjectDescriptorBox.java.svn-base
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+/**
+ * This object contains an Object Descriptor or an Initial Object Descriptor.
+ * There are a number of possible file types based on usage, depending on the descriptor:
+ * <ul>
+ * <li>Presentation, contains IOD which contains a BIFS stream (MP4 file);
+ * <li>Sub-part of a presentation, contains an IOD without a BIFS stream (MP4 file);</li>
+ * <li>Sub-part of a presentation, contains an OD (MP4 file);</li>
+ * <li>Free-form file, referenced by MP4 data references (free-format);</li>
+ * <li>Sub-part of a presentation, referenced by an ES URL.</li>
+ * </ul>
+ * NOTE: <br/>
+ * The first three are MP4 files, a file referenced by a data reference is not necessarily an MP4 file, as it is
+ * free-format. Files referenced by ES URLs, by data references, or intended as input to an editing process, need not have
+ * an Object Descriptor Box. <br/>
+ * An OD URL may point to an MP4 file. Implicitly, the target of such a URL is the OD/IOD located in the 'iods'
+ * atom in that file.</br/>
+ * If an MP4 file contains several object descriptors, only the OD/IOD in the 'iods' atom can be addressed using
+ * an OD URL from a remote MPEG-4 presentation.
+ */
+public class ObjectDescriptorBox extends AbstractDescriptorBox {
+ public static final String TYPE = "iods";
+
+ public ObjectDescriptorBox() {
+ super(TYPE);
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/AbstractDescriptorBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/AbstractDescriptorBox.java
new file mode 100644
index 0000000..7d614e2
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/AbstractDescriptorBox.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BaseDescriptor;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ObjectDescriptorFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * ES Descriptor Box.
+ */
+public class AbstractDescriptorBox extends AbstractFullBox {
+ private static Logger log = Logger.getLogger(AbstractDescriptorBox.class.getName());
+
+
+ public BaseDescriptor descriptor;
+ public ByteBuffer data;
+
+ public AbstractDescriptorBox(String type) {
+ super(type);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ data.rewind(); // has been fforwarded by parsing
+ byteBuffer.put(data);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 4 + data.limit();
+ }
+
+ public BaseDescriptor getDescriptor() {
+ return descriptor;
+ }
+
+ public String getDescriptorAsString() {
+ return descriptor.toString();
+ }
+
+ public void setData(ByteBuffer data) {
+ this.data = data;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ data = content.slice();
+ content.position(content.position() + content.remaining());
+ try {
+ data.rewind();
+ descriptor = ObjectDescriptorFactory.createFrom(-1, data);
+ } catch (IOException e) {
+ log.log(Level.WARNING, "Error parsing ObjectDescriptor", e);
+ //that's why we copied it ;)
+ } catch (IndexOutOfBoundsException e) {
+ log.log(Level.WARNING, "Error parsing ObjectDescriptor", e);
+ //that's why we copied it ;)
+ }
+
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ESDescriptorBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ESDescriptorBox.java
new file mode 100644
index 0000000..5d9d591
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ESDescriptorBox.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor;
+
+/**
+ * ES Descriptor Box.
+ */
+public class ESDescriptorBox extends AbstractDescriptorBox {
+ public static final String TYPE = "esds";
+
+ public ESDescriptorBox() {
+ super(TYPE);
+ }
+
+ public ESDescriptor getEsDescriptor() {
+ return (ESDescriptor) super.getDescriptor();
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ObjectDescriptorBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ObjectDescriptorBox.java
new file mode 100644
index 0000000..c9e7493
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/ObjectDescriptorBox.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Sebastian Annies, Hamburg
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4;
+
+/**
+ * This object contains an Object Descriptor or an Initial Object Descriptor.
+ * There are a number of possible file types based on usage, depending on the descriptor:
+ * <ul>
+ * <li>Presentation, contains IOD which contains a BIFS stream (MP4 file);
+ * <li>Sub-part of a presentation, contains an IOD without a BIFS stream (MP4 file);</li>
+ * <li>Sub-part of a presentation, contains an OD (MP4 file);</li>
+ * <li>Free-form file, referenced by MP4 data references (free-format);</li>
+ * <li>Sub-part of a presentation, referenced by an ES URL.</li>
+ * </ul>
+ * NOTE: <br/>
+ * The first three are MP4 files, a file referenced by a data reference is not necessarily an MP4 file, as it is
+ * free-format. Files referenced by ES URLs, by data references, or intended as input to an editing process, need not have
+ * an Object Descriptor Box. <br/>
+ * An OD URL may point to an MP4 file. Implicitly, the target of such a URL is the OD/IOD located in the 'iods'
+ * atom in that file.</br/>
+ * If an MP4 file contains several object descriptors, only the OD/IOD in the 'iods' atom can be addressed using
+ * an OD URL from a remote MPEG-4 presentation.
+ */
+public class ObjectDescriptorBox extends AbstractDescriptorBox {
+ public static final String TYPE = "iods";
+
+ public ObjectDescriptorBox() {
+ super(TYPE);
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/all-wcprops
new file mode 100644
index 0000000..5e1798f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/all-wcprops
@@ -0,0 +1,107 @@
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors
+END
+ObjectDescriptorBase.java
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorBase.java
+END
+SLConfigDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 124
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/SLConfigDescriptor.java
+END
+BitWriterBuffer.java
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/svn/!svn/ver/683/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitWriterBuffer.java
+END
+ESDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ESDescriptor.java
+END
+BaseDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BaseDescriptor.java
+END
+ExtensionDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 125
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionDescriptor.java
+END
+Descriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 116
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/Descriptor.java
+END
+InitialObjectDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/InitialObjectDescriptor.java
+END
+ObjectDescriptor.java_bak
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptor.java_bak
+END
+ExtensionProfileLevelDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 137
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionProfileLevelDescriptor.java
+END
+DecoderSpecificInfo.java
+K 25
+svn:wc:ra_dav:version-url
+V 125
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderSpecificInfo.java
+END
+ProfileLevelIndicationDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 138
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ProfileLevelIndicationDescriptor.java
+END
+DecoderConfigDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/svn/!svn/ver/501/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderConfigDescriptor.java
+END
+BitReaderBuffer.java
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/svn/!svn/ver/501/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitReaderBuffer.java
+END
+AudioSpecificConfig.java
+K 25
+svn:wc:ra_dav:version-url
+V 125
+/svn/!svn/ver/712/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/AudioSpecificConfig.java
+END
+ObjectDescriptorFactory.java
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorFactory.java
+END
+UnknownDescriptor.java
+K 25
+svn:wc:ra_dav:version-url
+V 123
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/UnknownDescriptor.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/entries
new file mode 100644
index 0000000..b150321
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/entries
@@ -0,0 +1,606 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+ObjectDescriptorBase.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+830afc294b0cc9e0fec5d733e021863c
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+961
+
+SLConfigDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+a0907a19df5c0cc9764689f9c6e3baa3
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3338
+
+BitWriterBuffer.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+771f8d900c6ff640d51fbb5dd4e933af
+2012-06-23T08:51:59.024275Z
+683
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1304
+
+ESDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+98f2c06a445b6b1d9836a6d3017da884
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12845
+
+BaseDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+c74bfdd283a75b2a57aa1b7ebc71c178
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2811
+
+ExtensionDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+907c329cba88c885e4b4b4a751facc6d
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2973
+
+Descriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+ac97c8117fd734f9dd22172d9a9a3a42
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1228
+
+InitialObjectDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+9f15d54d46b6644e1beb981b4d8fcee6
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5237
+
+ObjectDescriptor.java_bak
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+e77953ffb3ced634e03955f8eb0db522
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3666
+
+ExtensionProfileLevelDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+e7e0a38947f89d9285ddfdef6205c843
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1626
+
+DecoderSpecificInfo.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+f1faa43de84eaf3219495512761b4521
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2292
+
+ProfileLevelIndicationDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+6c76abf5466eb8aa9dded6ea17e66588
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2143
+
+DecoderConfigDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+ead55e14a62664da9869cb3a092d4fc2
+2012-04-20T14:18:38.758800Z
+501
+hoemmagnus@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9508
+
+BitReaderBuffer.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+9a0bad29e63d974899749007d890b027
+2012-04-20T14:18:38.758800Z
+501
+hoemmagnus@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1241
+
+ObjectDescriptorFactory.java
+file
+
+
+
+
+2012-09-14T17:27:50.997226Z
+cd9f2bc6eb85a79c6148d91099bbe300
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7011
+
+AudioSpecificConfig.java
+file
+
+
+
+
+2012-09-14T17:27:51.007226Z
+79095f48595f6573c76ec69e5717cdfe
+2012-07-12T22:44:00.389345Z
+712
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+40856
+
+UnknownDescriptor.java
+file
+
+
+
+
+2012-09-14T17:27:51.007226Z
+66e3ecf5b31e50a1a4f80d08e4643af9
+2012-02-27T13:49:22.148513Z
+351
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1467
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/AudioSpecificConfig.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/AudioSpecificConfig.java.svn-base
new file mode 100644
index 0000000..86e319e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/AudioSpecificConfig.java.svn-base
@@ -0,0 +1,1176 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+
+//
+//GetAudioObjectType()
+//{
+//audioObjectType; 5 uimsbf
+//if (audioObjectType == 31) {
+//audioObjectType = 32 + audioObjectTypeExt; 6 uimsbf
+//}
+//return audioObjectType;
+//}
+//AudioSpecificConfig ()
+//{
+//audioObjectType = GetAudioObjectType();
+//samplingFrequencyIndex; 4 bslbf
+//if ( samplingFrequencyIndex == 0xf ) {
+//samplingFrequency; 24 uimsbf
+//}
+//channelConfiguration; 4 bslbf
+//sbrPresentFlag = -1;
+//psPresentFlag = -1;
+//if ( audioObjectType == 5 ||
+//audioObjectType == 29 ) {
+//extensionAudioObjectType = 5;
+//sbrPresentFlag = 1;
+//if ( audioObjectType == 29 ) {
+//psPresentFlag = 1;
+//}
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf )
+//extensionSamplingFrequency; 24 uimsbf
+//audioObjectType = GetAudioObjectType();
+//if ( audioObjectType == 22 )
+//extensionChannelConfiguration; 4 uimsbf
+//}
+//else {
+//extensionAudioObjectType = 0;
+//}
+//switch (audioObjectType) {
+//case 1:
+//case 2:
+//case 3:
+//case 4:
+//case 6:
+//case 7:
+//case 17:
+//case 19:
+//case 20:
+//case 21:
+//case 22:
+//case 23:
+//GASpecificConfig();
+//break:
+//case 8:
+//CelpSpecificConfig();
+//break;
+//case 9:
+//HvxcSpecificConfig();
+//break:
+//case 12:
+//TTSSpecificConfig();
+//break;
+//case 13:
+//case 14:
+//case 15:
+//case 16:
+//StructuredAudioSpecificConfig();
+//break;
+//case 24:
+//ErrorResilientCelpSpecificConfig();
+//break;
+//case 25:
+//ErrorResilientHvxcSpecificConfig();
+//break;
+//case 26:
+//case 27:
+//ParametricSpecificConfig();
+//break;
+// case 28:
+//SSCSpecificConfig();
+//break;
+//case 30:
+//sacPayloadEmbedding; 1 uimsbf
+//SpatialSpecificConfig();
+//break;
+//case 32:
+//case 33:
+//case 34:
+//MPEG_1_2_SpecificConfig();
+//break;
+//case 35:
+//DSTSpecificConfig();
+//break;
+//case 36:
+//fillBits; 5 bslbf
+//ALSSpecificConfig();
+//break;
+//case 37:
+//case 38:
+//SLSSpecificConfig();
+//break;
+//case 39:
+//ELDSpecificConfig(channelConfiguration);
+//break:
+//case 40:
+//case 41:
+//SymbolicMusicSpecificConfig();
+//break;
+//default:
+///* reserved */
+//}
+//switch (audioObjectType) {
+//case 17:
+//case 19:
+//case 20:
+//case 21:
+//case 22:
+//case 23:
+//case 24:
+//case 25:
+//case 26:
+//case 27:
+//case 39:
+//epConfig; 2 bslbf
+//if ( epConfig == 2 || epConfig == 3 ) {
+//ErrorProtectionSpecificConfig();
+//}
+//if ( epConfig == 3 ) {
+//directMapping; 1 bslbf
+//if ( ! directMapping ) {
+///* tbd */
+//}
+//}
+//}
+//if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) {
+//syncExtensionType; 11 bslbf
+//if (syncExtensionType == 0x2b7) {
+// extensionAudioObjectType = GetAudioObjectType();
+//if ( extensionAudioObjectType == 5 ) {
+//sbrPresentFlag; 1 uimsbf
+//if (sbrPresentFlag == 1) {
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf ) {
+//extensionSamplingFrequency; 24 uimsbf
+//}
+//if ( bits_to_decode() >= 12 ) {
+//syncExtensionType; 11 bslbf
+//if (syncExtesionType == 0x548) {
+//psPresentFlag; 1 uimsbf
+//}
+//}
+//}
+//}
+//if ( extensionAudioObjectType == 22 ) {
+//sbrPresentFlag; 1 uimsbf
+//if (sbrPresentFlag == 1) {
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf ) {
+//extensionSamplingFrequency; 24 uimsbf
+//}
+//}
+//extensionChannelConfiguration; 4 uimsbf
+//}
+//}
+//}
+//}
+// }
+//
+// TFCodingType
+//0x0 AAC scaleable
+//0x1 BSAC
+//0x2 TwinVQ
+//0x3 AAC non scaleable (i.e. multichannel)
+//
+// class TFSpecificConfig( uint(4) samplingFrequencyIndex, uint(4) channelConfiguration ) {
+//uint(2) TFCodingType;
+//uint(1) frameLength;
+//uint(1) dependsOnCoreCoder;
+//if (dependsOnCoreCoder == 1){
+//uint(14)coreCoderDelay
+//}
+//if (TFCodingType==BSAC) {
+//uint(11) lslayer_length
+//}
+//uint (1) extensionFlag;
+//if (channelConfiguration == 0 ){
+//program_config_element();
+//}
+//if (extensionFlag==1){
+//<to be defined in mpeg4 phase 2>
+//}
+//}
+//
+//program_config_element()
+//{
+//element_instance_tag 4 uimsbf
+//profile 2 uimsbf
+//sampling_frequency_index 4 uimsbf
+//num_front_channel_elements 4 uimsbf
+//num_side_channel_elements 4 uimsbf
+//num_back_channel_elements 4 uimsbf
+// num_lfe_channel_elements 2 uimsbf
+//num_assoc_data_elements 3 uimsbf
+//num_valid_cc_elements 4 uimsbf
+//mono_mixdown_present 1 uimsbf
+//if ( mono_mixdown_present == 1 )
+//mono_mixdown_element_number 4 uimsbf
+//stereo_mixdown_present 1 uimsbf
+//if ( stereo_mixdown_present == 1 )
+//stereo_mixdown_element_number 4 uimsbf
+//matrix_mixdown_idx_present 1 uimsbf
+//if ( matrix_mixdown_idx_present == 1 ) {
+//matrix_mixdown_idx 2 uimsbf
+//pseudo_surround_enable 1 uimsbf
+//}
+//for ( i = 0; i < num_front_channel_elements; i++) {
+//front_element_is_cpe[i]; 1 bslbf
+//front_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_side_channel_elements; i++) {
+//side_element_is_cpe[i]; 1 bslbf
+//side_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_back_channel_elements; i++) {
+//back_element_is_cpe[i]; 1 bslbf
+//back_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_lfe_channel_elements; i++)
+//lfe_element_tag_select[i]; 4 uimsbf
+//for ( i = 0; i < num_assoc_data_elements; i++)
+//assoc_data_element_tag_select[i]; 4 uimsbf
+//for ( i = 0; i < num_valid_cc_elements; i++) {
+//cc_element_is_ind_sw[i]; 1 uimsbf
+//valid_cc_element_tag_select[i]; 4 uimsbf
+//}
+//byte_alignment()
+//comment_field_bytes 8 uimsbf
+//for ( i = 0; i < comment_field_bytes; i++)
+//comment_field_data[i]; 8 uimsbf
+//}
+
+@Descriptor(tags = 0x5, objectTypeIndication = 0x40)
+public class AudioSpecificConfig extends BaseDescriptor {
+ byte[] configBytes;
+
+ public static Map<Integer, Integer> samplingFrequencyIndexMap = new HashMap<Integer, Integer>();
+ public static Map<Integer, String> audioObjectTypeMap = new HashMap<Integer, String>();
+ int audioObjectType;
+ int samplingFrequencyIndex;
+ int samplingFrequency;
+ int channelConfiguration;
+ int extensionAudioObjectType;
+ int sbrPresentFlag;
+ int psPresentFlag;
+ int extensionSamplingFrequencyIndex;
+ int extensionSamplingFrequency;
+ int extensionChannelConfiguration;
+ int sacPayloadEmbedding;
+ int fillBits;
+ int epConfig;
+ int directMapping;
+ int syncExtensionType;
+
+ //GASpecificConfig
+ int frameLengthFlag;
+ int dependsOnCoreCoder;
+ int coreCoderDelay;
+ int extensionFlag;
+ int layerNr;
+ int numOfSubFrame;
+ int layer_length;
+ int aacSectionDataResilienceFlag;
+ int aacScalefactorDataResilienceFlag;
+ int aacSpectralDataResilienceFlag;
+ int extensionFlag3;
+ boolean gaSpecificConfig;
+
+ //ParametricSpecificConfig
+ int isBaseLayer;
+ int paraMode;
+ int paraExtensionFlag;
+ int hvxcVarMode;
+ int hvxcRateMode;
+ int erHvxcExtensionFlag;
+ int var_ScalableFlag;
+ int hilnQuantMode;
+ int hilnMaxNumLine;
+ int hilnSampleRateCode;
+ int hilnFrameLength;
+ int hilnContMode;
+ int hilnEnhaLayer;
+ int hilnEnhaQuantMode;
+ boolean parametricSpecificConfig;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ ByteBuffer configBytes = bb.slice();
+ configBytes.limit(sizeOfInstance);
+ bb.position(bb.position() + sizeOfInstance);
+
+ //copy original bytes to internal array for constructing codec config strings (todo until writing of the config is supported)
+ this.configBytes = new byte[sizeOfInstance];
+ configBytes.get(this.configBytes);
+ configBytes.rewind();
+
+ BitReaderBuffer bitReaderBuffer = new BitReaderBuffer(configBytes);
+ audioObjectType = getAudioObjectType(bitReaderBuffer);
+ samplingFrequencyIndex = bitReaderBuffer.readBits(4);
+
+ if (samplingFrequencyIndex == 0xf) {
+ samplingFrequency = bitReaderBuffer.readBits(24);
+ }
+
+ channelConfiguration = bitReaderBuffer.readBits(4);
+
+ if (audioObjectType == 5 ||
+ audioObjectType == 29) {
+ extensionAudioObjectType = 5;
+ sbrPresentFlag = 1;
+ if (audioObjectType == 29) {
+ psPresentFlag = 1;
+ }
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf)
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ audioObjectType = getAudioObjectType(bitReaderBuffer);
+ if (audioObjectType == 22)
+ extensionChannelConfiguration = bitReaderBuffer.readBits(4);
+ } else {
+ extensionAudioObjectType = 0;
+ }
+
+ switch (audioObjectType) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 6:
+ case 7:
+ case 17:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ parseGaSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
+ //GASpecificConfig();
+ break;
+ case 8:
+ throw new UnsupportedOperationException("can't parse CelpSpecificConfig yet");
+ //CelpSpecificConfig();
+ //break;
+ case 9:
+ throw new UnsupportedOperationException("can't parse HvxcSpecificConfig yet");
+ //HvxcSpecificConfig();
+ //break;
+ case 12:
+ throw new UnsupportedOperationException("can't parse TTSSpecificConfig yet");
+ //TTSSpecificConfig();
+ //break;
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ throw new UnsupportedOperationException("can't parse StructuredAudioSpecificConfig yet");
+ //StructuredAudioSpecificConfig();
+ //break;
+ case 24:
+ throw new UnsupportedOperationException("can't parse ErrorResilientCelpSpecificConfig yet");
+ //ErrorResilientCelpSpecificConfig();
+ //break;
+ case 25:
+ throw new UnsupportedOperationException("can't parse ErrorResilientHvxcSpecificConfig yet");
+ //ErrorResilientHvxcSpecificConfig();
+ //break;
+ case 26:
+ case 27:
+ parseParametricSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
+ //ParametricSpecificConfig();
+ break;
+ case 28:
+ throw new UnsupportedOperationException("can't parse SSCSpecificConfig yet");
+ //SSCSpecificConfig();
+ //break;
+ case 30:
+ sacPayloadEmbedding = bitReaderBuffer.readBits(1);
+ throw new UnsupportedOperationException("can't parse SpatialSpecificConfig yet");
+ //SpatialSpecificConfig();
+ //break;
+ case 32:
+ case 33:
+ case 34:
+ throw new UnsupportedOperationException("can't parse MPEG_1_2_SpecificConfig yet");
+ //MPEG_1_2_SpecificConfig();
+ //break;
+ case 35:
+ throw new UnsupportedOperationException("can't parse DSTSpecificConfig yet");
+ //DSTSpecificConfig();
+ //break;
+ case 36:
+ fillBits = bitReaderBuffer.readBits(5);
+ throw new UnsupportedOperationException("can't parse ALSSpecificConfig yet");
+ //ALSSpecificConfig();
+ //break;
+ case 37:
+ case 38:
+ throw new UnsupportedOperationException("can't parse SLSSpecificConfig yet");
+ //SLSSpecificConfig();
+ //break;
+ case 39:
+ throw new UnsupportedOperationException("can't parse ELDSpecificConfig yet");
+ //ELDSpecificConfig(channelConfiguration);
+ //break;
+ case 40:
+ case 41:
+ throw new UnsupportedOperationException("can't parse SymbolicMusicSpecificConfig yet");
+ //SymbolicMusicSpecificConfig();
+ //break;
+ default:
+ /* reserved */
+ }
+
+ switch (audioObjectType) {
+ case 17:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 39:
+ epConfig = bitReaderBuffer.readBits(2);
+ if (epConfig == 2 || epConfig == 3) {
+ throw new UnsupportedOperationException("can't parse ErrorProtectionSpecificConfig yet");
+ //ErrorProtectionSpecificConfig();
+ }
+ if (epConfig == 3) {
+ directMapping = bitReaderBuffer.readBits(1);
+ if (directMapping == 0) {
+ /* tbd */
+ throw new RuntimeException("not implemented");
+ }
+ }
+ }
+
+ if (extensionAudioObjectType != 5 && bitReaderBuffer.remainingBits() >= 16) {
+ syncExtensionType = bitReaderBuffer.readBits(11);
+ if (syncExtensionType == 0x2b7) {
+ extensionAudioObjectType = getAudioObjectType(bitReaderBuffer);
+ if (extensionAudioObjectType == 5) {
+ sbrPresentFlag = bitReaderBuffer.readBits(1);
+ if (sbrPresentFlag == 1) {
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf) {
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ }
+ if (bitReaderBuffer.remainingBits() >= 12) {
+ syncExtensionType = bitReaderBuffer.readBits(11); //10101001000
+ if (syncExtensionType == 0x548) {
+ psPresentFlag = bitReaderBuffer.readBits(1);
+ }
+ }
+ }
+ }
+ if (extensionAudioObjectType == 22) {
+ sbrPresentFlag = bitReaderBuffer.readBits(1);
+ if (sbrPresentFlag == 1) {
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf) {
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ }
+ }
+ extensionChannelConfiguration = bitReaderBuffer.readBits(4);
+ }
+ }
+ }
+ }
+
+ private int gaSpecificConfigSize() {
+ return 0;
+ }
+
+ public int serializedSize() {
+ int out = 4;
+ if (audioObjectType == 2) {
+ out += gaSpecificConfigSize();
+ } else {
+ throw new UnsupportedOperationException("can't serialize that yet");
+ }
+ return out;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize());
+ IsoTypeWriter.writeUInt8(out, 5);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
+ BitWriterBuffer bwb = new BitWriterBuffer(out);
+ bwb.writeBits(audioObjectType, 5);
+ bwb.writeBits(samplingFrequencyIndex, 4);
+ if (samplingFrequencyIndex == 0xf) {
+ throw new UnsupportedOperationException("can't serialize that yet");
+ }
+ bwb.writeBits(channelConfiguration, 4);
+
+ // Don't support any extensions, unusual GASpecificConfig other than the default or anything...
+
+ return out;
+ }
+
+ private int getAudioObjectType(BitReaderBuffer in) throws IOException {
+ int audioObjectType = in.readBits(5);
+ if (audioObjectType == 31) {
+ audioObjectType = 32 + in.readBits(6);
+ }
+ return audioObjectType;
+ }
+
+ private void parseGaSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+// GASpecificConfig (samplingFrequencyIndex,
+// channelConfiguration,
+// audioObjectType)
+// {
+ frameLengthFlag = in.readBits(1);
+ dependsOnCoreCoder = in.readBits(1);
+ if (dependsOnCoreCoder == 1) {
+ coreCoderDelay = in.readBits(14);
+ }
+ extensionFlag = in.readBits(1);
+ if (channelConfiguration == 0) {
+ throw new UnsupportedOperationException("can't parse program_config_element yet");
+ //program_config_element ();
+ }
+ if ((audioObjectType == 6) || (audioObjectType == 20)) {
+ layerNr = in.readBits(3);
+ }
+ if (extensionFlag == 1) {
+ if (audioObjectType == 22) {
+ numOfSubFrame = in.readBits(5);
+ layer_length = in.readBits(11);
+ }
+ if (audioObjectType == 17 || audioObjectType == 19 ||
+ audioObjectType == 20 || audioObjectType == 23) {
+ aacSectionDataResilienceFlag = in.readBits(1);
+ aacScalefactorDataResilienceFlag = in.readBits(1);
+ aacSpectralDataResilienceFlag = in.readBits(1);
+ }
+ extensionFlag3 = in.readBits(1);
+ if (extensionFlag3 == 1) {
+ /* tbd in version 3 */
+ }
+ }
+// }
+ gaSpecificConfig = true;
+ }
+
+ private void parseParametricSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ ParametricSpecificConfig() {
+ isBaseLayer; 1 uimsbf
+ if (isBaseLayer) {
+ PARAconfig();
+ } else {
+ HILNenexConfig();
+ }
+ }
+ */
+ isBaseLayer = in.readBits(1);
+ if (isBaseLayer == 1) {
+ parseParaConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ } else {
+ parseHilnEnexConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+ }
+
+ private void parseParaConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ PARAconfig()
+ {
+ PARAmode; 2 uimsbf
+ if (PARAmode != 1) {
+ ErHVXCconfig();
+ }
+ if (PARAmode != 0) {
+ HILNconfig();
+ }
+ PARAextensionFlag; 1 uimsbf
+ if (PARAextensionFlag) {
+ // to be defined in MPEG-4 Phase 3
+ }
+ }
+ */
+ paraMode = in.readBits(2);
+
+ if (paraMode != 1) {
+ parseErHvxcConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+ if (paraMode != 0) {
+ parseHilnConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+
+ paraExtensionFlag = in.readBits(1);
+ parametricSpecificConfig = true;
+ }
+
+ private void parseErHvxcConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ ErHVXCconfig()
+ {
+ HVXCvarMode; 1 uimsbf
+ HVXCrateMode; 2 uimsbf
+ extensionFlag; 1 uimsbf
+ if (extensionFlag) {
+ var_ScalableFlag; 1 uimsbf
+ }
+ }
+ */
+ hvxcVarMode = in.readBits(1);
+ hvxcRateMode = in.readBits(2);
+ erHvxcExtensionFlag = in.readBits(1);
+
+ if (erHvxcExtensionFlag == 1) {
+ var_ScalableFlag = in.readBits(1);
+ }
+ }
+
+ private void parseHilnConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ HILNconfig()
+ {
+ HILNquantMode; 1 uimsbf
+ HILNmaxNumLine; 8 uimsbf
+ HILNsampleRateCode; 4 uimsbf
+ HILNframeLength; 12 uimsbf
+ HILNcontMode; 2 uimsbf
+ }
+ */
+ hilnQuantMode = in.readBits(1);
+ hilnMaxNumLine = in.readBits(8);
+ hilnSampleRateCode = in.readBits(4);
+ hilnFrameLength = in.readBits(12);
+ hilnContMode = in.readBits(2);
+ }
+
+ private void parseHilnEnexConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ HILNenexConfig()
+ {
+ HILNenhaLayer; 1 uimsbf
+ if (HILNenhaLayer) {
+ HILNenhaQuantMode; 2 uimsbf
+ }
+ }
+ */
+ hilnEnhaLayer = in.readBits(1);
+ if (hilnEnhaLayer == 1) {
+ hilnEnhaQuantMode = in.readBits(2);
+ }
+ }
+
+ public byte[] getConfigBytes() {
+ return configBytes;
+ }
+
+ public int getAudioObjectType() {
+ return audioObjectType;
+ }
+
+ public int getExtensionAudioObjectType() {
+ return extensionAudioObjectType;
+ }
+
+ public int getSbrPresentFlag() {
+ return sbrPresentFlag;
+ }
+
+ public int getPsPresentFlag() {
+ return psPresentFlag;
+ }
+
+ public void setAudioObjectType(int audioObjectType) {
+ this.audioObjectType = audioObjectType;
+ }
+
+ public void setSamplingFrequencyIndex(int samplingFrequencyIndex) {
+ this.samplingFrequencyIndex = samplingFrequencyIndex;
+ }
+
+ public void setSamplingFrequency(int samplingFrequency) {
+ this.samplingFrequency = samplingFrequency;
+ }
+
+ public void setChannelConfiguration(int channelConfiguration) {
+ this.channelConfiguration = channelConfiguration;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("AudioSpecificConfig");
+ sb.append("{configBytes=").append(Hex.encodeHex(configBytes));
+ sb.append(", audioObjectType=").append(audioObjectType).append(" (").append(audioObjectTypeMap.get(audioObjectType)).append(")");
+ sb.append(", samplingFrequencyIndex=").append(samplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(samplingFrequencyIndex)).append(")");
+ sb.append(", samplingFrequency=").append(samplingFrequency);
+ sb.append(", channelConfiguration=").append(channelConfiguration);
+ if (extensionAudioObjectType > 0) {
+ sb.append(", extensionAudioObjectType=").append(extensionAudioObjectType).append(" (").append(audioObjectTypeMap.get(extensionAudioObjectType)).append(")");
+ sb.append(", sbrPresentFlag=").append(sbrPresentFlag);
+ sb.append(", psPresentFlag=").append(psPresentFlag);
+ sb.append(", extensionSamplingFrequencyIndex=").append(extensionSamplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(extensionSamplingFrequencyIndex)).append(")");
+ sb.append(", extensionSamplingFrequency=").append(extensionSamplingFrequency);
+ sb.append(", extensionChannelConfiguration=").append(extensionChannelConfiguration);
+ }
+// sb.append(", sacPayloadEmbedding=").append(sacPayloadEmbedding);
+// sb.append(", fillBits=").append(fillBits);
+// sb.append(", epConfig=").append(epConfig);
+// sb.append(", directMapping=").append(directMapping);
+ sb.append(", syncExtensionType=").append(syncExtensionType);
+ if (gaSpecificConfig) {
+ sb.append(", frameLengthFlag=").append(frameLengthFlag);
+ sb.append(", dependsOnCoreCoder=").append(dependsOnCoreCoder);
+ sb.append(", coreCoderDelay=").append(coreCoderDelay);
+ sb.append(", extensionFlag=").append(extensionFlag);
+ sb.append(", layerNr=").append(layerNr);
+ sb.append(", numOfSubFrame=").append(numOfSubFrame);
+ sb.append(", layer_length=").append(layer_length);
+ sb.append(", aacSectionDataResilienceFlag=").append(aacSectionDataResilienceFlag);
+ sb.append(", aacScalefactorDataResilienceFlag=").append(aacScalefactorDataResilienceFlag);
+ sb.append(", aacSpectralDataResilienceFlag=").append(aacSpectralDataResilienceFlag);
+ sb.append(", extensionFlag3=").append(extensionFlag3);
+ }
+ if (parametricSpecificConfig) {
+ sb.append(", isBaseLayer=").append(isBaseLayer);
+ sb.append(", paraMode=").append(paraMode);
+ sb.append(", paraExtensionFlag=").append(paraExtensionFlag);
+ sb.append(", hvxcVarMode=").append(hvxcVarMode);
+ sb.append(", hvxcRateMode=").append(hvxcRateMode);
+ sb.append(", erHvxcExtensionFlag=").append(erHvxcExtensionFlag);
+ sb.append(", var_ScalableFlag=").append(var_ScalableFlag);
+ sb.append(", hilnQuantMode=").append(hilnQuantMode);
+ sb.append(", hilnMaxNumLine=").append(hilnMaxNumLine);
+ sb.append(", hilnSampleRateCode=").append(hilnSampleRateCode);
+ sb.append(", hilnFrameLength=").append(hilnFrameLength);
+ sb.append(", hilnContMode=").append(hilnContMode);
+ sb.append(", hilnEnhaLayer=").append(hilnEnhaLayer);
+ sb.append(", hilnEnhaQuantMode=").append(hilnEnhaQuantMode);
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ static {
+ // sampling_frequency_index sampling frequeny
+//0x0 96000
+//0x1 88200
+//0x2 64000
+//0x3 48000
+//0x4 44100
+//0x5 32000
+//0x6 24000
+//0x7 22050
+//0x8 16000
+//0x9 12000
+//0xa 11025
+//0xb 8000
+//0xc reserved
+//0xd reserved
+//0xe reserved
+//0xf reserved
+ samplingFrequencyIndexMap.put(0x0, 96000);
+ samplingFrequencyIndexMap.put(0x1, 88200);
+ samplingFrequencyIndexMap.put(0x2, 64000);
+ samplingFrequencyIndexMap.put(0x3, 48000);
+ samplingFrequencyIndexMap.put(0x4, 44100);
+ samplingFrequencyIndexMap.put(0x5, 32000);
+ samplingFrequencyIndexMap.put(0x6, 24000);
+ samplingFrequencyIndexMap.put(0x7, 22050);
+ samplingFrequencyIndexMap.put(0x8, 16000);
+ samplingFrequencyIndexMap.put(0x9, 12000);
+ samplingFrequencyIndexMap.put(0xa, 11025);
+ samplingFrequencyIndexMap.put(0xb, 8000);
+
+ /* audioObjectType IDs
+ 0 Null
+ 1 AAC main X X
+ 2 AAC LC X X X X X X X
+ 3 AAC SSR X X
+ 4 AAC LTP X X X X
+ 5 SBR X X
+ 6 AAC Scalable X X X X
+ 7 TwinVQ X X X
+ 8 CELP X X X X X X
+ 9 HVXC X X X X X
+ 10 (reserved)
+ 11 (reserved)
+ 12 TTSI X X X X X X
+ 13 Main synthetic X X
+ 14 Wavetable synthesis X* X*
+ 15 General MIDI X* X*
+ 16 Algorithmic Synthesis and Audio FX X* X*
+ 17 ER AAC LC X X X
+ 18 (reserved)
+ 19 ER AAC LTP X X
+ 20 ER AAC Scalable X X X
+ 21 ER TwinVQ X X
+ 22 ER BSAC X X
+ 23 ER AAC LD X X X X
+ 24 ER CELP X X X
+ 25 ER HVXC X X
+ 26 ER HILN X
+ 27 ER Parametric X
+ 28 SSC
+ 29 PS X
+ 30 MPEG Surround
+ 31 (escape)
+ 32 Layer-1
+ 33 Layer-2
+ 34 Layer-3
+ 35 DST
+ 36 ALS
+ 37 SLS
+ 38 SLS non-core
+ 39 ER AAC ELD
+ 40 SMR Simple
+ 41 SMR Main
+ */
+ audioObjectTypeMap.put(1, "AAC main");
+ audioObjectTypeMap.put(2, "AAC LC");
+ audioObjectTypeMap.put(3, "AAC SSR");
+ audioObjectTypeMap.put(4, "AAC LTP");
+ audioObjectTypeMap.put(5, "SBR");
+ audioObjectTypeMap.put(6, "AAC Scalable");
+ audioObjectTypeMap.put(7, "TwinVQ");
+ audioObjectTypeMap.put(8, "CELP");
+ audioObjectTypeMap.put(9, "HVXC");
+ audioObjectTypeMap.put(10, "(reserved)");
+ audioObjectTypeMap.put(11, "(reserved)");
+ audioObjectTypeMap.put(12, "TTSI");
+ audioObjectTypeMap.put(13, "Main synthetic");
+ audioObjectTypeMap.put(14, "Wavetable synthesis");
+ audioObjectTypeMap.put(15, "General MIDI");
+ audioObjectTypeMap.put(16, "Algorithmic Synthesis and Audio FX");
+ audioObjectTypeMap.put(17, "ER AAC LC");
+ audioObjectTypeMap.put(18, "(reserved)");
+ audioObjectTypeMap.put(19, "ER AAC LTP");
+ audioObjectTypeMap.put(20, "ER AAC Scalable");
+ audioObjectTypeMap.put(21, "ER TwinVQ");
+ audioObjectTypeMap.put(22, "ER BSAC");
+ audioObjectTypeMap.put(23, "ER AAC LD");
+ audioObjectTypeMap.put(24, "ER CELP");
+ audioObjectTypeMap.put(25, "ER HVXC");
+ audioObjectTypeMap.put(26, "ER HILN");
+ audioObjectTypeMap.put(27, "ER Parametric");
+ audioObjectTypeMap.put(28, "SSC");
+ audioObjectTypeMap.put(29, "PS");
+ audioObjectTypeMap.put(30, "MPEG Surround");
+ audioObjectTypeMap.put(31, "(escape)");
+ audioObjectTypeMap.put(32, "Layer-1");
+ audioObjectTypeMap.put(33, "Layer-2");
+ audioObjectTypeMap.put(34, "Layer-3");
+ audioObjectTypeMap.put(35, "DST");
+ audioObjectTypeMap.put(36, "ALS");
+ audioObjectTypeMap.put(37, "SLS");
+ audioObjectTypeMap.put(38, "SLS non-core");
+ audioObjectTypeMap.put(39, "ER AAC ELD");
+ audioObjectTypeMap.put(40, "SMR Simple");
+ audioObjectTypeMap.put(41, "SMR Main");
+
+ /* profileLevelIds
+ 0x00 Reserved for ISO use -
+ 0x01 Main Audio Profile L1
+ 0x02 Main Audio Profile L2
+ 0x03 Main Audio Profile L3
+ 0x04 Main Audio Profile L4
+ 0x05 Scalable Audio Profile L1
+ 0x06 Scalable Audio Profile L2
+ 0x07 Scalable Audio Profile L3
+ 0x08 Scalable Audio Profile L4
+ 0x09 Speech Audio Profile L1
+ 0x0A Speech Audio Profile L2
+ 0x0B Synthetic Audio Profile L1
+ 0x0C Synthetic Audio Profile L2
+ 0x0D Synthetic Audio Profile L3
+ 0x0E High Quality Audio Profile L1
+ 0x0F High Quality Audio Profile L2
+ 0x10 High Quality Audio Profile L3
+ 0x11 High Quality Audio Profile L4
+ 0x12 High Quality Audio Profile L5
+ 0x13 High Quality Audio Profile L6
+ 0x14 High Quality Audio Profile L7
+ 0x15 High Quality Audio Profile L8
+ 0x16 Low Delay Audio Profile L1
+ 0x17 Low Delay Audio Profile L2
+ 0x18 Low Delay Audio Profile L3
+ 0x19 Low Delay Audio Profile L4
+ 0x1A Low Delay Audio Profile L5
+ 0x1B Low Delay Audio Profile L6
+ 0x1C Low Delay Audio Profile L7
+ 0x1D Low Delay Audio Profile L8
+ 0x1E Natural Audio Profile L1
+ 0x1F Natural Audio Profile L2
+ 0x20 Natural Audio Profile L3
+ 0x21 Natural Audio Profile L4
+ 0x22 Mobile Audio Internetworking Profile L1
+ 0x23 Mobile Audio Internetworking Profile L2
+ 0x24 Mobile Audio Internetworking Profile L3
+ 0x25 Mobile Audio Internetworking Profile L4
+ 0x26 Mobile Audio Internetworking Profile L5
+ 0x27 Mobile Audio Internetworking Profile L6
+ 0x28 AAC Profile L1
+ 0x29 AAC Profile L2
+ 0x2A AAC Profile L4
+ 0x2B AAC Profile L5
+ 0x2C High Efficiency AAC Profile L2
+ 0x2D High Efficiency AAC Profile L3
+ 0x2E High Efficiency AAC Profile L4
+ 0x2F High Efficiency AAC Profile L5
+ 0x30 High Efficiency AAC v2 Profile L2
+ 0x31 High Efficiency AAC v2 Profile L3
+ 0x32 High Efficiency AAC v2 Profile L4
+ 0x33 High Efficiency AAC v2 Profile L5
+ 0x34 Low Delay AAC Profile L1
+ 0x35 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L1
+ 0x36 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L2
+ 0x37 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L3
+ 0x38 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L4
+ 0c39 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L5
+ 0x3A Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L6
+ 0x3B - 0x7F reserved for ISO use -
+ 0x80 - 0xFD user private -
+ 0xFE no audio profile specified -
+ 0xFF no audio capability required -
+
+ */
+ }
+
+
+ public int getSamplingFrequency() {
+ return samplingFrequencyIndex == 0xf ? samplingFrequency : samplingFrequencyIndexMap.get(samplingFrequencyIndex);
+ }
+
+ public int getChannelConfiguration() {
+ return channelConfiguration;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ AudioSpecificConfig that = (AudioSpecificConfig) o;
+
+ if (aacScalefactorDataResilienceFlag != that.aacScalefactorDataResilienceFlag) {
+ return false;
+ }
+ if (aacSectionDataResilienceFlag != that.aacSectionDataResilienceFlag) {
+ return false;
+ }
+ if (aacSpectralDataResilienceFlag != that.aacSpectralDataResilienceFlag) {
+ return false;
+ }
+ if (audioObjectType != that.audioObjectType) {
+ return false;
+ }
+ if (channelConfiguration != that.channelConfiguration) {
+ return false;
+ }
+ if (coreCoderDelay != that.coreCoderDelay) {
+ return false;
+ }
+ if (dependsOnCoreCoder != that.dependsOnCoreCoder) {
+ return false;
+ }
+ if (directMapping != that.directMapping) {
+ return false;
+ }
+ if (epConfig != that.epConfig) {
+ return false;
+ }
+ if (erHvxcExtensionFlag != that.erHvxcExtensionFlag) {
+ return false;
+ }
+ if (extensionAudioObjectType != that.extensionAudioObjectType) {
+ return false;
+ }
+ if (extensionChannelConfiguration != that.extensionChannelConfiguration) {
+ return false;
+ }
+ if (extensionFlag != that.extensionFlag) {
+ return false;
+ }
+ if (extensionFlag3 != that.extensionFlag3) {
+ return false;
+ }
+ if (extensionSamplingFrequency != that.extensionSamplingFrequency) {
+ return false;
+ }
+ if (extensionSamplingFrequencyIndex != that.extensionSamplingFrequencyIndex) {
+ return false;
+ }
+ if (fillBits != that.fillBits) {
+ return false;
+ }
+ if (frameLengthFlag != that.frameLengthFlag) {
+ return false;
+ }
+ if (gaSpecificConfig != that.gaSpecificConfig) {
+ return false;
+ }
+ if (hilnContMode != that.hilnContMode) {
+ return false;
+ }
+ if (hilnEnhaLayer != that.hilnEnhaLayer) {
+ return false;
+ }
+ if (hilnEnhaQuantMode != that.hilnEnhaQuantMode) {
+ return false;
+ }
+ if (hilnFrameLength != that.hilnFrameLength) {
+ return false;
+ }
+ if (hilnMaxNumLine != that.hilnMaxNumLine) {
+ return false;
+ }
+ if (hilnQuantMode != that.hilnQuantMode) {
+ return false;
+ }
+ if (hilnSampleRateCode != that.hilnSampleRateCode) {
+ return false;
+ }
+ if (hvxcRateMode != that.hvxcRateMode) {
+ return false;
+ }
+ if (hvxcVarMode != that.hvxcVarMode) {
+ return false;
+ }
+ if (isBaseLayer != that.isBaseLayer) {
+ return false;
+ }
+ if (layerNr != that.layerNr) {
+ return false;
+ }
+ if (layer_length != that.layer_length) {
+ return false;
+ }
+ if (numOfSubFrame != that.numOfSubFrame) {
+ return false;
+ }
+ if (paraExtensionFlag != that.paraExtensionFlag) {
+ return false;
+ }
+ if (paraMode != that.paraMode) {
+ return false;
+ }
+ if (parametricSpecificConfig != that.parametricSpecificConfig) {
+ return false;
+ }
+ if (psPresentFlag != that.psPresentFlag) {
+ return false;
+ }
+ if (sacPayloadEmbedding != that.sacPayloadEmbedding) {
+ return false;
+ }
+ if (samplingFrequency != that.samplingFrequency) {
+ return false;
+ }
+ if (samplingFrequencyIndex != that.samplingFrequencyIndex) {
+ return false;
+ }
+ if (sbrPresentFlag != that.sbrPresentFlag) {
+ return false;
+ }
+ if (syncExtensionType != that.syncExtensionType) {
+ return false;
+ }
+ if (var_ScalableFlag != that.var_ScalableFlag) {
+ return false;
+ }
+ if (!Arrays.equals(configBytes, that.configBytes)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = configBytes != null ? Arrays.hashCode(configBytes) : 0;
+ result = 31 * result + audioObjectType;
+ result = 31 * result + samplingFrequencyIndex;
+ result = 31 * result + samplingFrequency;
+ result = 31 * result + channelConfiguration;
+ result = 31 * result + extensionAudioObjectType;
+ result = 31 * result + sbrPresentFlag;
+ result = 31 * result + psPresentFlag;
+ result = 31 * result + extensionSamplingFrequencyIndex;
+ result = 31 * result + extensionSamplingFrequency;
+ result = 31 * result + extensionChannelConfiguration;
+ result = 31 * result + sacPayloadEmbedding;
+ result = 31 * result + fillBits;
+ result = 31 * result + epConfig;
+ result = 31 * result + directMapping;
+ result = 31 * result + syncExtensionType;
+ result = 31 * result + frameLengthFlag;
+ result = 31 * result + dependsOnCoreCoder;
+ result = 31 * result + coreCoderDelay;
+ result = 31 * result + extensionFlag;
+ result = 31 * result + layerNr;
+ result = 31 * result + numOfSubFrame;
+ result = 31 * result + layer_length;
+ result = 31 * result + aacSectionDataResilienceFlag;
+ result = 31 * result + aacScalefactorDataResilienceFlag;
+ result = 31 * result + aacSpectralDataResilienceFlag;
+ result = 31 * result + extensionFlag3;
+ result = 31 * result + (gaSpecificConfig ? 1 : 0);
+ result = 31 * result + isBaseLayer;
+ result = 31 * result + paraMode;
+ result = 31 * result + paraExtensionFlag;
+ result = 31 * result + hvxcVarMode;
+ result = 31 * result + hvxcRateMode;
+ result = 31 * result + erHvxcExtensionFlag;
+ result = 31 * result + var_ScalableFlag;
+ result = 31 * result + hilnQuantMode;
+ result = 31 * result + hilnMaxNumLine;
+ result = 31 * result + hilnSampleRateCode;
+ result = 31 * result + hilnFrameLength;
+ result = 31 * result + hilnContMode;
+ result = 31 * result + hilnEnhaLayer;
+ result = 31 * result + hilnEnhaQuantMode;
+ result = 31 * result + (parametricSpecificConfig ? 1 : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BaseDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BaseDescriptor.java.svn-base
new file mode 100644
index 0000000..6d94680
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BaseDescriptor.java.svn-base
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/*
+abstract aligned(8) expandable(228-1) class BaseDescriptor : bit(8) tag=0 {
+// empty. To be filled by classes extending this class.
+}
+
+int sizeOfInstance = 0;
+bit(1) nextByte;
+bit(7) sizeOfInstance;
+while(nextByte) {
+bit(1) nextByte;
+bit(7) sizeByte;
+sizeOfInstance = sizeOfInstance<<7 | sizeByte;
+}
+ */
+@Descriptor(tags = 0x00)
+public abstract class BaseDescriptor {
+ int tag;
+ int sizeOfInstance;
+ int sizeBytes;
+
+ public BaseDescriptor() {
+ }
+
+ public int getTag() {
+ return tag;
+ }
+
+ public int getSize() {
+ return sizeOfInstance
+ + 1//1 for the tag
+ + sizeBytes;
+ }
+
+ public int getSizeOfInstance() {
+ return sizeOfInstance;
+ }
+
+ public int getSizeBytes() {
+ return sizeBytes;
+ }
+
+ public final void parse(int tag, ByteBuffer bb) throws IOException {
+ this.tag = tag;
+
+ int i = 0;
+ int tmp = IsoTypeReader.readUInt8(bb);
+ i++;
+ sizeOfInstance = tmp & 0x7f;
+ while (tmp >>> 7 == 1) { //nextbyte indicator bit
+ tmp = IsoTypeReader.readUInt8(bb);
+ i++;
+ //sizeOfInstance = sizeOfInstance<<7 | sizeByte;
+ sizeOfInstance = sizeOfInstance << 7 | tmp & 0x7f;
+ }
+ sizeBytes = i;
+ ByteBuffer detailSource = bb.slice();
+ detailSource.limit(sizeOfInstance);
+ parseDetail(detailSource);
+ assert detailSource.remaining() == 0: this.getClass().getSimpleName() + " has not been fully parsed";
+ bb.position(bb.position() + sizeOfInstance);
+ }
+
+ public abstract void parseDetail(ByteBuffer bb) throws IOException;
+
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BaseDescriptor");
+ sb.append("{tag=").append(tag);
+ sb.append(", sizeOfInstance=").append(sizeOfInstance);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitReaderBuffer.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitReaderBuffer.java.svn-base
new file mode 100644
index 0000000..7221503
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitReaderBuffer.java.svn-base
@@ -0,0 +1,51 @@
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.nio.ByteBuffer;
+
+public class BitReaderBuffer {
+
+ private ByteBuffer buffer;
+ int initialPos;
+ int position;
+
+ public BitReaderBuffer(ByteBuffer buffer) {
+ this.buffer = buffer;
+ initialPos = buffer.position();
+ }
+
+ public int readBits(int i) {
+ byte b = buffer.get(initialPos + position / 8);
+ int v = b < 0 ? b + 256 : b;
+ int left = 8 - position % 8;
+ int rc;
+ if (i <= left) {
+ rc = (v << (position % 8) & 0xFF) >> ((position % 8) + (left - i));
+ position += i;
+ } else {
+ int now = left;
+ int then = i - left;
+ rc = readBits(now);
+ rc = rc << then;
+ rc += readBits(then);
+ }
+ buffer.position(initialPos + (int) Math.ceil((double) position / 8));
+ return rc;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public int byteSync() {
+ int left = 8 - position % 8;
+ if (left == 8) {
+ left = 0;
+ }
+ readBits(left);
+ return left;
+ }
+
+ public int remainingBits() {
+ return buffer.limit() * 8 - position;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitWriterBuffer.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitWriterBuffer.java.svn-base
new file mode 100644
index 0000000..e6ea67f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/BitWriterBuffer.java.svn-base
@@ -0,0 +1,36 @@
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.nio.ByteBuffer;
+
+public class BitWriterBuffer {
+
+ private ByteBuffer buffer;
+ int initialPos;
+ int position = 0;
+
+ public BitWriterBuffer(ByteBuffer buffer) {
+ this.buffer = buffer;
+ this.initialPos = buffer.position();
+ }
+
+ public void writeBits(int i, int numBits) {
+ assert i <= ((1 << numBits)-1): String.format("Trying to write a value bigger (%s) than the number bits (%s) allows. " +
+ "Please mask the value before writing it and make your code is really working as intended.", i, (1<<numBits)-1);
+
+ int left = 8 - position % 8;
+ if (numBits <= left) {
+ int current = (buffer.get(initialPos + position / 8));
+ current = current < 0 ? current + 256 : current;
+ current += i << (left - numBits);
+ buffer.put(initialPos + position / 8, (byte) (current > 127 ? current - 256 : current));
+ position += numBits;
+ } else {
+ int bitsSecondWrite = numBits - left;
+ writeBits(i >> bitsSecondWrite, left);
+ writeBits(i & (1 << bitsSecondWrite) - 1, bitsSecondWrite);
+ }
+ buffer.position(initialPos + position / 8 + ((position % 8 > 0) ? 1 : 0));
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderConfigDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderConfigDescriptor.java.svn-base
new file mode 100644
index 0000000..69d603a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderConfigDescriptor.java.svn-base
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * class DecoderConfigDescriptor extends BaseDescriptor : bit(8)
+ * tag=DecoderConfigDescrTag {
+ * bit(8) objectTypeIndication;
+ * bit(6) streamType;
+ * bit(1) upStream;
+ * const bit(1) reserved=1;
+ * bit(24) bufferSizeDB;
+ * bit(32) maxBitrate;
+ * bit(32) avgBitrate;
+ * DecoderSpecificInfo decSpecificInfo[0 .. 1];
+ * profileLevelIndicationIndexDescriptor profileLevelIndicationIndexDescr
+ * [0..255];
+ * }
+ */
+@Descriptor(tags = {0x04})
+public class DecoderConfigDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(DecoderConfigDescriptor.class.getName());
+
+
+ int objectTypeIndication;
+ int streamType;
+ int upStream;
+ int bufferSizeDB;
+ long maxBitRate;
+ long avgBitRate;
+
+ DecoderSpecificInfo decoderSpecificInfo;
+ AudioSpecificConfig audioSpecificInfo;
+ List<ProfileLevelIndicationDescriptor> profileLevelIndicationDescriptors = new ArrayList<ProfileLevelIndicationDescriptor>();
+ byte[] configDescriptorDeadBytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ objectTypeIndication = IsoTypeReader.readUInt8(bb);
+
+ int data = IsoTypeReader.readUInt8(bb);
+ streamType = data >>> 2;
+ upStream = (data >> 1) & 0x1;
+
+ bufferSizeDB = IsoTypeReader.readUInt24(bb);
+ maxBitRate = IsoTypeReader.readUInt32(bb);
+ avgBitRate = IsoTypeReader.readUInt32(bb);
+
+
+
+ BaseDescriptor descriptor;
+ if (bb.remaining() > 2) { //1byte tag + at least 1byte size
+ final int begin = bb.position();
+ descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
+ final int read = bb.position() - begin;
+ log.finer(descriptor + " - DecoderConfigDescr1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ if (read < size) {
+ //skip
+ configDescriptorDeadBytes = new byte[size - read];
+ bb.get(configDescriptorDeadBytes);
+ }
+ }
+ if (descriptor instanceof DecoderSpecificInfo) {
+ decoderSpecificInfo = (DecoderSpecificInfo) descriptor;
+ }
+ if (descriptor instanceof AudioSpecificConfig) {
+ audioSpecificInfo = (AudioSpecificConfig) descriptor;
+ }
+ }
+
+ while (bb.remaining() > 2) {
+ final long begin = bb.position();
+ descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - DecoderConfigDescr2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor instanceof ProfileLevelIndicationDescriptor) {
+ profileLevelIndicationDescriptors.add((ProfileLevelIndicationDescriptor) descriptor);
+ }
+ }
+ }
+ public int serializedSize() {
+ return 15 + audioSpecificInfo.serializedSize();
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize());
+ IsoTypeWriter.writeUInt8(out, 4);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
+ IsoTypeWriter.writeUInt8(out, objectTypeIndication);
+ int flags = (streamType << 2) | (upStream << 1) | 1;
+ IsoTypeWriter.writeUInt8(out, flags);
+ IsoTypeWriter.writeUInt24(out, bufferSizeDB);
+ IsoTypeWriter.writeUInt32(out, maxBitRate);
+ IsoTypeWriter.writeUInt32(out, avgBitRate);
+ out.put(audioSpecificInfo.serialize().array());
+ return out;
+ }
+
+ public DecoderSpecificInfo getDecoderSpecificInfo() {
+ return decoderSpecificInfo;
+ }
+
+ public AudioSpecificConfig getAudioSpecificInfo() {
+ return audioSpecificInfo;
+ }
+
+ public void setAudioSpecificInfo(AudioSpecificConfig audioSpecificInfo) {
+ this.audioSpecificInfo = audioSpecificInfo;
+ }
+
+ public List<ProfileLevelIndicationDescriptor> getProfileLevelIndicationDescriptors() {
+ return profileLevelIndicationDescriptors;
+ }
+
+ public int getObjectTypeIndication() {
+ return objectTypeIndication;
+ }
+
+ public void setObjectTypeIndication(int objectTypeIndication) {
+ this.objectTypeIndication = objectTypeIndication;
+ }
+
+ public int getStreamType() {
+ return streamType;
+ }
+
+ public void setStreamType(int streamType) {
+ this.streamType = streamType;
+ }
+
+ public int getUpStream() {
+ return upStream;
+ }
+
+ public void setUpStream(int upStream) {
+ this.upStream = upStream;
+ }
+
+ public int getBufferSizeDB() {
+ return bufferSizeDB;
+ }
+
+ public void setBufferSizeDB(int 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;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DecoderConfigDescriptor");
+ sb.append("{objectTypeIndication=").append(objectTypeIndication);
+ sb.append(", streamType=").append(streamType);
+ sb.append(", upStream=").append(upStream);
+ sb.append(", bufferSizeDB=").append(bufferSizeDB);
+ sb.append(", maxBitRate=").append(maxBitRate);
+ sb.append(", avgBitRate=").append(avgBitRate);
+ sb.append(", decoderSpecificInfo=").append(decoderSpecificInfo);
+ sb.append(", audioSpecificInfo=").append(audioSpecificInfo);
+ sb.append(", configDescriptorDeadBytes=").append(Hex.encodeHex(configDescriptorDeadBytes != null ? configDescriptorDeadBytes : new byte[]{}));
+ sb.append(", profileLevelIndicationDescriptors=").append(profileLevelIndicationDescriptors == null ? "null" : Arrays.asList(profileLevelIndicationDescriptors).toString());
+ sb.append('}');
+ return sb.toString();
+ }
+ /*objectTypeIndication values
+ 0x00 Forbidden
+ 0x01 Systems ISO/IEC 14496-1 a
+ 0x02 Systems ISO/IEC 14496-1 b
+ 0x03 Interaction Stream
+ 0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c
+ 0x05 Systems ISO/IEC 14496-1 AFX d
+ 0x06 Font Data Stream
+ 0x07 Synthesized Texture Stream
+ 0x08 Streaming Text Stream
+ 0x09-0x1F reserved for ISO use
+ 0x20 Visual ISO/IEC 14496-2 e
+ 0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+ 0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+ 0x23-0x3F reserved for ISO use
+ 0x40 Audio ISO/IEC 14496-3 g
+ 0x41-0x5F reserved for ISO use
+ 0x60 Visual ISO/IEC 13818-2 Simple Profile
+ 0x61 Visual ISO/IEC 13818-2 Main Profile
+ 0x62 Visual ISO/IEC 13818-2 SNR Profile
+ 0x63 Visual ISO/IEC 13818-2 Spatial Profile
+ 0x64 Visual ISO/IEC 13818-2 High Profile
+ 0x65 Visual ISO/IEC 13818-2 422 Profile
+ 0x66 Audio ISO/IEC 13818-7 Main Profile
+ 0x67 Audio ISO/IEC 13818-7 LowComplexity Profile
+ 0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
+ 0x69 Audio ISO/IEC 13818-3
+ 0x6A Visual ISO/IEC 11172-2
+ 0x6B Audio ISO/IEC 11172-3
+ 0x6C Visual ISO/IEC 10918-1
+ 0x6D reserved for registration authority i
+ 0x6E Visual ISO/IEC 15444-1
+ 0x6F - 0x9F reserved for ISO use
+ 0xA0 - 0xBF reserved for registration authority i
+ 0xC0 - 0xE0 user private
+ 0xE1 reserved for registration authority i
+ 0xE2 - 0xFE user private
+ 0xFF no object type specified h
+ */
+ /* streamType values
+ 0x00 Forbidden
+ 0x01 ObjectDescriptorStream (see 7.2.5)
+ 0x02 ClockReferenceStream (see 7.3.2.5)
+ 0x03 SceneDescriptionStream (see ISO/IEC 14496-11)
+ 0x04 VisualStream
+ 0x05 AudioStream
+ 0x06 MPEG7Stream
+ 0x07 IPMPStream (see 7.2.3.2)
+ 0x08 ObjectContentInfoStream (see 7.2.4.2)
+ 0x09 MPEGJStream
+ 0x0A Interaction Stream
+ 0x0B IPMPToolStream (see [ISO/IEC 14496-13])
+ 0x0C - 0x1F reserved for ISO use
+ 0x20 - 0x3F user private
+ */
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderSpecificInfo.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderSpecificInfo.java.svn-base
new file mode 100644
index 0000000..574943c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/DecoderSpecificInfo.java.svn-base
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * abstract class DecoderSpecificInfo extends BaseDescriptor : bit(8)
+ * tag=DecSpecificInfoTag
+ * {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = 0x05)
+public class DecoderSpecificInfo extends BaseDescriptor {
+ byte[] bytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (sizeOfInstance > 0) {
+ bytes = new byte[sizeOfInstance];
+ bb.get(bytes);
+ }
+ }
+
+ public int serializedSize() {
+ return bytes.length;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.wrap(bytes);
+
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DecoderSpecificInfo");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DecoderSpecificInfo that = (DecoderSpecificInfo) o;
+
+ if (!Arrays.equals(bytes, that.bytes)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return bytes != null ? Arrays.hashCode(bytes) : 0;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/Descriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/Descriptor.java.svn-base
new file mode 100644
index 0000000..11020c7
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/Descriptor.java.svn-base
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mstattma
+ * Date: 06.08.2010
+ * Time: 06:54:58
+ * To change this template use File | Settings | File Templates.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Descriptor {
+ int[] tags();
+
+ int objectTypeIndication() default -1;
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ESDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ESDescriptor.java.svn-base
new file mode 100644
index 0000000..3bb4821
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ESDescriptor.java.svn-base
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+/*
+class ES_Descriptor extends BaseDescriptor : bit(8) tag=ES_DescrTag {
+bit(16) ES_ID;
+bit(1) streamDependenceFlag;
+bit(1) URL_Flag;
+bit(1) OCRstreamFlag;
+bit(5) streamPriority;
+if (streamDependenceFlag)
+bit(16) dependsOn_ES_ID;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+}
+if (OCRstreamFlag)
+bit(16) OCR_ES_Id;
+DecoderConfigDescriptor decConfigDescr;
+if (ODProfileLevelIndication==0x01) //no SL extension.
+{
+SLConfigDescriptor slConfigDescr;
+}
+else // SL extension is possible.
+{
+SLConfigDescriptor slConfigDescr;
+}
+IPI_DescrPointer ipiPtr[0 .. 1];
+IP_IdentificationDataSet ipIDS[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+LanguageDescriptor langDescr[0 .. 255];
+QoS_Descriptor qosDescr[0 .. 1];
+RegistrationDescriptor regDescr[0 .. 1];
+ExtensionDescriptor extDescr[0 .. 255];
+}
+ */
+@Descriptor(tags = {0x03})
+public class ESDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(ESDescriptor.class.getName());
+
+ int esId;
+ int streamDependenceFlag;
+ int URLFlag;
+ int oCRstreamFlag;
+ int streamPriority;
+
+
+ int URLLength = 0;
+ String URLString;
+ int remoteODFlag;
+
+ int dependsOnEsId;
+ int oCREsId;
+
+ DecoderConfigDescriptor decoderConfigDescriptor;
+ SLConfigDescriptor slConfigDescriptor;
+ List<BaseDescriptor> otherDescriptors = new ArrayList<BaseDescriptor>();
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ esId = IsoTypeReader.readUInt16(bb);
+
+ int data = IsoTypeReader.readUInt8(bb);
+ streamDependenceFlag = data >>> 7;
+ URLFlag = (data >>> 6) & 0x1;
+ oCRstreamFlag = (data >>> 5) & 0x1;
+ streamPriority = data & 0x1f;
+
+ if (streamDependenceFlag == 1) {
+ dependsOnEsId = IsoTypeReader.readUInt16(bb);
+ }
+ if (URLFlag == 1) {
+ URLLength = IsoTypeReader.readUInt8(bb);
+ URLString = IsoTypeReader.readString(bb, URLLength);
+ }
+ if (oCRstreamFlag == 1) {
+ oCREsId = IsoTypeReader.readUInt16(bb);
+ }
+
+ int baseSize = 1 /*tag*/ + getSizeBytes() + 2 + 1 + (streamDependenceFlag == 1 ? 2 : 0) + (URLFlag == 1 ? 1 + URLLength : 0) + (oCRstreamFlag == 1 ? 2 : 0);
+
+ int begin = bb.position();
+ if (getSize() > baseSize + 2) {
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ if (descriptor instanceof DecoderConfigDescriptor) {
+ decoderConfigDescriptor = (DecoderConfigDescriptor) descriptor;
+ }
+ }
+
+ begin = bb.position();
+ if (getSize() > baseSize + 2) {
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ if (descriptor instanceof SLConfigDescriptor) {
+ slConfigDescriptor = (SLConfigDescriptor) descriptor;
+ }
+ } else {
+ log.warning("SLConfigDescriptor is missing!");
+ }
+
+ while (getSize() - baseSize > 2) {
+ begin = bb.position();
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor3 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ otherDescriptors.add(descriptor);
+ }
+ }
+ public int serializedSize() {
+ int out = 5;
+ if (streamDependenceFlag > 0) {
+ out += 2;
+ }
+ if (URLFlag > 0) {
+ out += 1 + URLLength;
+ }
+ if (oCRstreamFlag > 0) {
+ out += 2;
+ }
+
+ out += decoderConfigDescriptor.serializedSize();
+ out += slConfigDescriptor.serializedSize();
+
+ // Doesn't handle other descriptors yet
+
+ return out;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize()); // Usually is around 30 bytes, so 200 should be enough...
+ IsoTypeWriter.writeUInt8(out, 3);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2); // Not OK for longer sizes!
+ IsoTypeWriter.writeUInt16(out, esId);
+ int flags = (streamDependenceFlag << 7) | (URLFlag << 6) | (oCRstreamFlag << 5) | (streamPriority & 0x1f);
+ IsoTypeWriter.writeUInt8(out, flags);
+ if (streamDependenceFlag > 0) {
+ IsoTypeWriter.writeUInt16(out, dependsOnEsId);
+ }
+ if (URLFlag > 0) {
+ IsoTypeWriter.writeUInt8(out, URLLength);
+ IsoTypeWriter.writeUtf8String(out, URLString);
+ }
+ if (oCRstreamFlag > 0) {
+ IsoTypeWriter.writeUInt16(out, oCREsId);
+ }
+
+ ByteBuffer dec = decoderConfigDescriptor.serialize();
+ ByteBuffer sl = slConfigDescriptor.serialize();
+ out.put(dec.array());
+ out.put(sl.array());
+
+ // Doesn't handle other descriptors yet
+
+ return out;
+ }
+
+// @Override
+// public int getSize() {
+// return 3 + (streamDependenceFlag == 1 ? 2 : 0) +
+// (URLFlag == 1 ? 1 + 8 * URLLength : 0) +
+// (oCRstreamFlag == 1 ? 2 : 0);
+// }
+
+ public DecoderConfigDescriptor getDecoderConfigDescriptor() {
+ return decoderConfigDescriptor;
+ }
+
+ public SLConfigDescriptor getSlConfigDescriptor() {
+ return slConfigDescriptor;
+ }
+
+ public void setDecoderConfigDescriptor(DecoderConfigDescriptor decoderConfigDescriptor) {
+ this.decoderConfigDescriptor = decoderConfigDescriptor;
+ }
+
+ public void setSlConfigDescriptor(SLConfigDescriptor slConfigDescriptor) {
+ this.slConfigDescriptor = slConfigDescriptor;
+ }
+
+ public List<BaseDescriptor> getOtherDescriptors() {
+ return otherDescriptors;
+ }
+
+ public int getoCREsId() {
+ return oCREsId;
+ }
+
+ public void setoCREsId(int oCREsId) {
+ this.oCREsId = oCREsId;
+ }
+
+ public int getEsId() {
+ return esId;
+ }
+
+ public void setEsId(int esId) {
+ this.esId = esId;
+ }
+
+ public int getStreamDependenceFlag() {
+ return streamDependenceFlag;
+ }
+
+ public void setStreamDependenceFlag(int streamDependenceFlag) {
+ this.streamDependenceFlag = streamDependenceFlag;
+ }
+
+ public int getURLFlag() {
+ return URLFlag;
+ }
+
+ public void setURLFlag(int URLFlag) {
+ this.URLFlag = URLFlag;
+ }
+
+ public int getoCRstreamFlag() {
+ return oCRstreamFlag;
+ }
+
+ public void setoCRstreamFlag(int oCRstreamFlag) {
+ this.oCRstreamFlag = oCRstreamFlag;
+ }
+
+ public int getStreamPriority() {
+ return streamPriority;
+ }
+
+ public void setStreamPriority(int streamPriority) {
+ this.streamPriority = streamPriority;
+ }
+
+ public int getURLLength() {
+ return URLLength;
+ }
+
+ public void setURLLength(int URLLength) {
+ this.URLLength = URLLength;
+ }
+
+ public String getURLString() {
+ return URLString;
+ }
+
+ public void setURLString(String URLString) {
+ this.URLString = URLString;
+ }
+
+ public int getRemoteODFlag() {
+ return remoteODFlag;
+ }
+
+ public void setRemoteODFlag(int remoteODFlag) {
+ this.remoteODFlag = remoteODFlag;
+ }
+
+ public int getDependsOnEsId() {
+ return dependsOnEsId;
+ }
+
+ public void setDependsOnEsId(int dependsOnEsId) {
+ this.dependsOnEsId = dependsOnEsId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ESDescriptor");
+ sb.append("{esId=").append(esId);
+ sb.append(", streamDependenceFlag=").append(streamDependenceFlag);
+ sb.append(", URLFlag=").append(URLFlag);
+ sb.append(", oCRstreamFlag=").append(oCRstreamFlag);
+ sb.append(", streamPriority=").append(streamPriority);
+ sb.append(", URLLength=").append(URLLength);
+ sb.append(", URLString='").append(URLString).append('\'');
+ sb.append(", remoteODFlag=").append(remoteODFlag);
+ sb.append(", dependsOnEsId=").append(dependsOnEsId);
+ sb.append(", oCREsId=").append(oCREsId);
+ sb.append(", decoderConfigDescriptor=").append(decoderConfigDescriptor);
+ sb.append(", slConfigDescriptor=").append(slConfigDescriptor);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ESDescriptor that = (ESDescriptor) o;
+
+ if (URLFlag != that.URLFlag) return false;
+ if (URLLength != that.URLLength) return false;
+ if (dependsOnEsId != that.dependsOnEsId) return false;
+ if (esId != that.esId) return false;
+ if (oCREsId != that.oCREsId) return false;
+ if (oCRstreamFlag != that.oCRstreamFlag) return false;
+ if (remoteODFlag != that.remoteODFlag) return false;
+ if (streamDependenceFlag != that.streamDependenceFlag) return false;
+ if (streamPriority != that.streamPriority) return false;
+ if (URLString != null ? !URLString.equals(that.URLString) : that.URLString != null) return false;
+ if (decoderConfigDescriptor != null ? !decoderConfigDescriptor.equals(that.decoderConfigDescriptor) : that.decoderConfigDescriptor != null)
+ return false;
+ if (otherDescriptors != null ? !otherDescriptors.equals(that.otherDescriptors) : that.otherDescriptors != null)
+ return false;
+ if (slConfigDescriptor != null ? !slConfigDescriptor.equals(that.slConfigDescriptor) : that.slConfigDescriptor != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = esId;
+ result = 31 * result + streamDependenceFlag;
+ result = 31 * result + URLFlag;
+ result = 31 * result + oCRstreamFlag;
+ result = 31 * result + streamPriority;
+ result = 31 * result + URLLength;
+ result = 31 * result + (URLString != null ? URLString.hashCode() : 0);
+ result = 31 * result + remoteODFlag;
+ result = 31 * result + dependsOnEsId;
+ result = 31 * result + oCREsId;
+ result = 31 * result + (decoderConfigDescriptor != null ? decoderConfigDescriptor.hashCode() : 0);
+ result = 31 * result + (slConfigDescriptor != null ? slConfigDescriptor.hashCode() : 0);
+ result = 31 * result + (otherDescriptors != null ? otherDescriptors.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionDescriptor.java.svn-base
new file mode 100644
index 0000000..7933f5a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionDescriptor.java.svn-base
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+/**
+ * abstract class ExtensionDescriptor extends BaseDescriptor
+ * : bit(8) tag = ExtensionProfileLevelDescrTag, ExtDescrTagStartRange ..
+ * ExtDescrTagEndRange {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = {0x13, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253})
+public class ExtensionDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(ExtensionDescriptor.class.getName());
+
+ byte[] bytes;
+
+
+ //todo: add this better to the tags list?
+ //14496-1:2010 p.20:
+ //0x6A-0xBF Reserved for ISO use
+ //0xC0-0xFE User private
+ //
+ //ExtDescrTagStartRange = 0x6A
+ //ExtDescrTagEndRange = 0xFE
+ static int[] allTags() {
+ int[] ints = new int[0xFE - 0x6A];
+
+ for (int i = 0x6A; i < 0xFE; i++) {
+ final int pos = i - 0x6A;
+ log.finest("pos:" + pos);
+ ints[pos] = i;
+ }
+ return ints;
+ }
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (getSize() > 0) {
+ bytes = new byte[sizeOfInstance];
+ bb.get(bytes);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ExtensionDescriptor");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionProfileLevelDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionProfileLevelDescriptor.java.svn-base
new file mode 100644
index 0000000..0cf4915
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ExtensionProfileLevelDescriptor.java.svn-base
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * abstract class ExtensionDescriptor extends BaseDescriptor
+ * : bit(8) tag = ExtensionProfileLevelDescrTag, ExtDescrTagStartRange ..
+ * ExtDescrTagEndRange {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = {0x13})
+public class ExtensionProfileLevelDescriptor extends BaseDescriptor {
+ byte[] bytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (getSize() > 0) {
+ bytes = new byte[getSize()];
+ bb.get(bytes);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ExtensionDescriptor");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/InitialObjectDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/InitialObjectDescriptor.java.svn-base
new file mode 100644
index 0000000..7a1f094
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/InitialObjectDescriptor.java.svn-base
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+class InitialObjectDescriptor extends ObjectDescriptorBase : bit(8)
+tag=InitialObjectDescrTag {
+bit(10) ObjectDescriptorID;
+bit(1) URL_Flag;
+bit(1) includeInlineProfileLevelFlag;
+const bit(4) reserved=0b1111;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+} else {
+bit(8) ODProfileLevelIndication;
+bit(8) sceneProfileLevelIndication;
+bit(8) audioProfileLevelIndication;
+bit(8) visualProfileLevelIndication;
+bit(8) graphicsProfileLevelIndication;
+ES_Descriptor esDescr[1 .. 255];
+OCI_Descriptor ociDescr[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+IPMP_Descriptor ipmpDescr [0 .. 255];
+IPMP_ToolListDescriptor toolListDescr[0 .. 1];
+}
+ExtensionDescriptor extDescr[0 .. 255];
+}
+*/
+//@Descriptor(tags = {0x02, 0x10})
+public class InitialObjectDescriptor extends ObjectDescriptorBase {
+ private int objectDescriptorId;
+ int urlFlag;
+ int includeInlineProfileLevelFlag;
+
+ int urlLength;
+ String urlString;
+
+ int oDProfileLevelIndication;
+ int sceneProfileLevelIndication;
+ int audioProfileLevelIndication;
+ int visualProfileLevelIndication;
+ int graphicsProfileLevelIndication;
+
+ List<ESDescriptor> esDescriptors = new ArrayList<ESDescriptor>();
+
+ List<ExtensionDescriptor> extensionDescriptors = new ArrayList<ExtensionDescriptor>();
+
+ List<BaseDescriptor> unknownDescriptors = new ArrayList<BaseDescriptor>();
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ int data = IsoTypeReader.readUInt16(bb);
+ objectDescriptorId = (data & 0xFFC0) >> 6;
+
+ urlFlag = (data & 0x3F) >> 5;
+ includeInlineProfileLevelFlag = (data & 0x1F) >> 4;
+
+ int sizeLeft = getSize() - 2;
+ if (urlFlag == 1) {
+ urlLength = IsoTypeReader.readUInt8(bb);
+ urlString = IsoTypeReader.readString(bb, urlLength);
+ sizeLeft = sizeLeft - (1 + urlLength);
+ } else {
+ oDProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ sceneProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ audioProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ visualProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ graphicsProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+
+ sizeLeft = sizeLeft - 5;
+
+ if (sizeLeft > 2) {
+ final BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ sizeLeft = sizeLeft - descriptor.getSize();
+ if (descriptor instanceof ESDescriptor) {
+ esDescriptors.add((ESDescriptor) descriptor);
+ } else {
+ unknownDescriptors.add(descriptor);
+ }
+ }
+ }
+
+ if (sizeLeft > 2) {
+ final BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ if (descriptor instanceof ExtensionDescriptor) {
+ extensionDescriptors.add((ExtensionDescriptor) descriptor);
+ } else {
+ unknownDescriptors.add(descriptor);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("InitialObjectDescriptor");
+ sb.append("{objectDescriptorId=").append(objectDescriptorId);
+ sb.append(", urlFlag=").append(urlFlag);
+ sb.append(", includeInlineProfileLevelFlag=").append(includeInlineProfileLevelFlag);
+ sb.append(", urlLength=").append(urlLength);
+ sb.append(", urlString='").append(urlString).append('\'');
+ sb.append(", oDProfileLevelIndication=").append(oDProfileLevelIndication);
+ sb.append(", sceneProfileLevelIndication=").append(sceneProfileLevelIndication);
+ sb.append(", audioProfileLevelIndication=").append(audioProfileLevelIndication);
+ sb.append(", visualProfileLevelIndication=").append(visualProfileLevelIndication);
+ sb.append(", graphicsProfileLevelIndication=").append(graphicsProfileLevelIndication);
+ sb.append(", esDescriptors=").append(esDescriptors);
+ sb.append(", extensionDescriptors=").append(extensionDescriptors);
+ sb.append(", unknownDescriptors=").append(unknownDescriptors);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptor.java_bak.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptor.java_bak.svn-base
new file mode 100644
index 0000000..c5cb586
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptor.java_bak.svn-base
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+class ObjectDescriptor extends ObjectDescriptorBase : bit(8) tag=ObjectDescrTag {
+bit(10) ObjectDescriptorID;
+bit(1) URL_Flag;
+const bit(5) reserved=0b1111.1;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+} else {
+ES_Descriptor esDescr[1 .. 255];
+OCI_Descriptor ociDescr[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+IPMP_Descriptor ipmpDescr [0 .. 255];
+}
+ExtensionDescriptor extDescr[0 .. 255];
+}
+*/
+@Descriptor(tags = {0x01, 0x11})
+public class ObjectDescriptor extends ObjectDescriptorBase {
+ private int objectDescriptorId;
+ int objectDescriptorUrlFlag;
+ int objectDescriptorUrlLength;
+ String objectDescriptorUrlString;
+
+
+ private int streamCount;
+ private int extensionFlag;
+ private List<ESDescriptor> esDescriptors = new ArrayList<ESDescriptor>();
+
+ private int descriptorLength;
+ private List<ExtensionDescriptor> extensionDescriptors = new ArrayList<ExtensionDescriptor>();
+
+ public static ObjectDescriptor createFrom(ByteBuffer in) throws IOException {
+/*
+ tmp = in.readUInt16();
+ esDescriptor.objectDescriptorId = tmp & 0x3f;
+ esDescriptor.objectDescriptorUrlFlag = (tmp >> 5) & 0x1;
+ if (esDescriptor.objectDescriptorUrlFlag == 1) {
+ esDescriptor.objectDescriptorUrlLength = in.readUInt8();
+ esDescriptor.objectDescriptorUrlString = new String(in.read(esDescriptor.objectDescriptorUrlLength));
+ }
+ */
+
+ ObjectDescriptor objectDescriptor = new ObjectDescriptor();
+
+ int data = IsoTypeReader.readUInt16(in);
+
+ objectDescriptor.objectDescriptorId = data & 0xFFC0;
+ objectDescriptor.streamCount = data & 0x3E;
+ objectDescriptor.extensionFlag = data & 0x1;
+
+// for (int i = 0; i < objectDescriptor.streamCount; i++) {
+// objectDescriptor.esDescriptors.add(ESDescriptor.createFrom(in));
+// }
+//
+// if (objectDescriptor.extensionFlag == 1) {
+// objectDescriptor.descriptorLength = in.readUInt8();
+// for (int i = 0; i < objectDescriptor.descriptorLength;) {
+// ExtensionDescriptor extensionDescriptor = ExtensionDescriptor.createFrom(in);
+// objectDescriptor.extensionDescriptors.add(extensionDescriptor);
+// i = i + extensionDescriptor.descriptorDataLength + 1;
+// }
+// }
+
+ return objectDescriptor;
+ }
+
+ @Override
+ public String toString() {
+ return "ObjectDescriptor{" +
+ "objectDescriptorId=" + objectDescriptorId +
+ ", streamCount=" + streamCount +
+ ", extensionFlag=" + extensionFlag +
+ ", esDescriptors=" + esDescriptors +
+ ", descriptorLength=" + descriptorLength +
+ ", extensionDescriptors=" + extensionDescriptors +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorBase.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorBase.java.svn-base
new file mode 100644
index 0000000..69a8684
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorBase.java.svn-base
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+/*
+abstract class ObjectDescriptorBase extends BaseDescriptor : bit(8)
+tag=[ObjectDescrTag..InitialObjectDescrTag] {
+// empty. To be filled by classes extending this class.
+}
+ */
+@Descriptor(tags = 0x00)
+public abstract class ObjectDescriptorBase extends BaseDescriptor {
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorFactory.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorFactory.java.svn-base
new file mode 100644
index 0000000..6afba55
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ObjectDescriptorFactory.java.svn-base
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/* class tag values of 14496-1
+0x00 Forbidden
+0x01 ObjectDescrTag
+0x02 InitialObjectDescrTag
+0x03 ES_DescrTag
+0x04 DecoderConfigDescrTag
+0x05 DecSpecificInfoTag
+0x06 SLConfigDescrTag
+0x07 ContentIdentDescrTag
+0x08 SupplContentIdentDescrTag
+0x09 IPI_DescrPointerTag
+0x0A IPMP_DescrPointerTag
+0x0B IPMP_DescrTag
+0x0C QoS_DescrTag
+0x0D RegistrationDescrTag
+0x0E ES_ID_IncTag
+0x0F ES_ID_RefTag
+0x10 MP4_IOD_Tag
+0x11 MP4_OD_Tag
+0x12 IPL_DescrPointerRefTag
+0x13 ExtensionProfileLevelDescrTag
+0x14 profileLevelIndicationIndexDescrTag
+0x15-0x3F Reserved for ISO use
+0x40 ContentClassificationDescrTag
+0x41 KeyWordDescrTag
+0x42 RatingDescrTag
+0x43 LanguageDescrTag
+0x44 ShortTextualDescrTag
+0x45 ExpandedTextualDescrTag
+0x46 ContentCreatorNameDescrTag
+0x47 ContentCreationDateDescrTag
+0x48 OCICreatorNameDescrTag
+0x49 OCICreationDateDescrTag
+0x4A SmpteCameraPositionDescrTag
+0x4B SegmentDescrTag
+0x4C MediaTimeDescrTag
+0x4D-0x5F Reserved for ISO use (OCI extensions)
+0x60 IPMP_ToolsListDescrTag
+0x61 IPMP_ToolTag
+0x62 M4MuxTimingDescrTag
+0x63 M4MuxCodeTableDescrTag
+0x64 ExtSLConfigDescrTag
+0x65 M4MuxBufferSizeDescrTag
+0x66 M4MuxIdentDescrTag
+0x67 DependencyPointerTag
+0x68 DependencyMarkerTag
+0x69 M4MuxChannelDescrTag
+0x6A-0xBF Reserved for ISO use
+0xC0-0xFE User private
+0xFF Forbidden
+ */
+
+/* objectTypeIndication as of 14496-1
+0x00 Forbidden
+0x01 Systems ISO/IEC 14496-1 a
+0x02 Systems ISO/IEC 14496-1 b
+0x03 Interaction Stream
+0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c
+0x05 Systems ISO/IEC 14496-1 AFX d
+0x06 Font Data Stream
+0x07 Synthesized Texture Stream
+0x08 Streaming Text Stream
+0x09-0x1F reserved for ISO use
+0x20 Visual ISO/IEC 14496-2 e
+0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+0x23-0x3F reserved for ISO use
+0x40 Audio ISO/IEC 14496-3 g
+0x41-0x5F reserved for ISO use
+0x60 Visual ISO/IEC 13818-2 Simple Profile
+0x61 Visual ISO/IEC 13818-2 Main Profile
+0x62 Visual ISO/IEC 13818-2 SNR Profile
+0x63 Visual ISO/IEC 13818-2 Spatial Profile
+0x64 Visual ISO/IEC 13818-2 High Profile
+0x65 Visual ISO/IEC 13818-2 422 Profile
+0x66 Audio ISO/IEC 13818-7 Main Profile
+0x67 Audio ISO/IEC 13818-7 LowComplexity Profile
+0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
+0x69 Audio ISO/IEC 13818-3
+0x6A Visual ISO/IEC 11172-2
+0x6B Audio ISO/IEC 11172-3
+0x6C Visual ISO/IEC 10918-1
+0x6D reserved for registration authority
+0x6E Visual ISO/IEC 15444-1
+0x6F - 0x9F reserved for ISO use
+0xA0 - 0xBF reserved for registration authority i
+0xC0 - 0xE0 user private
+0xE1 reserved for registration authority i
+0xE2 - 0xFE user private
+0xFF no object type specified h
+ */
+public class ObjectDescriptorFactory {
+ protected static Logger log = Logger.getLogger(ObjectDescriptorFactory.class.getName());
+
+ protected static Map<Integer, Map<Integer, Class<? extends BaseDescriptor>>> descriptorRegistry = new HashMap<Integer, Map<Integer, Class<? extends BaseDescriptor>>>();
+
+ static {
+ Set<Class<? extends BaseDescriptor>> annotated = new HashSet<Class<? extends BaseDescriptor>>();
+
+ annotated.add(DecoderSpecificInfo.class);
+ annotated.add(SLConfigDescriptor.class);
+ annotated.add(BaseDescriptor.class);
+ annotated.add(ExtensionDescriptor.class);
+ annotated.add(ObjectDescriptorBase.class);
+ annotated.add(ProfileLevelIndicationDescriptor.class);
+ annotated.add(AudioSpecificConfig.class);
+ annotated.add(ExtensionProfileLevelDescriptor.class);
+ annotated.add(ESDescriptor.class);
+ annotated.add(DecoderConfigDescriptor.class);
+ //annotated.add(ObjectDescriptor.class);
+
+ for (Class<? extends BaseDescriptor> clazz : annotated) {
+ final Descriptor descriptor = clazz.getAnnotation(Descriptor.class);
+ final int[] tags = descriptor.tags();
+ final int objectTypeInd = descriptor.objectTypeIndication();
+
+ Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeInd);
+ if (tagMap == null) {
+ tagMap = new HashMap<Integer, Class<? extends BaseDescriptor>>();
+ }
+ for (int tag : tags) {
+ tagMap.put(tag, clazz);
+ }
+ descriptorRegistry.put(objectTypeInd, tagMap);
+ }
+ }
+
+ public static BaseDescriptor createFrom(int objectTypeIndication, ByteBuffer bb) throws IOException {
+ int tag = IsoTypeReader.readUInt8(bb);
+
+ Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeIndication);
+ if (tagMap == null) {
+ tagMap = descriptorRegistry.get(-1);
+ }
+ Class<? extends BaseDescriptor> aClass = tagMap.get(tag);
+
+// if (tag == 0x00) {
+// log.warning("Found illegal tag 0x00! objectTypeIndication " + Integer.toHexString(objectTypeIndication) +
+// " and tag " + Integer.toHexString(tag) + " using: " + aClass);
+// aClass = BaseDescriptor.class;
+// }
+
+ BaseDescriptor baseDescriptor;
+ if (aClass == null || aClass.isInterface() || Modifier.isAbstract(aClass.getModifiers())) {
+ log.warning("No ObjectDescriptor found for objectTypeIndication " + Integer.toHexString(objectTypeIndication) +
+ " and tag " + Integer.toHexString(tag) + " found: " + aClass);
+ baseDescriptor = new UnknownDescriptor();
+ } else {
+ try {
+ baseDescriptor = aClass.newInstance();
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Couldn't instantiate BaseDescriptor class " + aClass + " for objectTypeIndication " + objectTypeIndication + " and tag " + tag, e);
+ throw new RuntimeException(e);
+ }
+ }
+ baseDescriptor.parse(tag, bb);
+ return baseDescriptor;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ProfileLevelIndicationDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ProfileLevelIndicationDescriptor.java.svn-base
new file mode 100644
index 0000000..625277e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/ProfileLevelIndicationDescriptor.java.svn-base
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * class ProfileLevelIndicationIndexDescriptor () extends BaseDescriptor
+ * : bit(8) ProfileLevelIndicationIndexDescrTag {
+ * bit(8) profileLevelIndicationIndex;
+ * }
+ */
+@Descriptor(tags = 0x14)
+public class ProfileLevelIndicationDescriptor extends BaseDescriptor {
+ int profileLevelIndicationIndex;
+
+ @Override
+ public void parseDetail( ByteBuffer bb) throws IOException {
+ profileLevelIndicationIndex = IsoTypeReader.readUInt8(bb);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ProfileLevelIndicationDescriptor");
+ sb.append("{profileLevelIndicationIndex=").append(Integer.toHexString(profileLevelIndicationIndex));
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ProfileLevelIndicationDescriptor that = (ProfileLevelIndicationDescriptor) o;
+
+ if (profileLevelIndicationIndex != that.profileLevelIndicationIndex) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return profileLevelIndicationIndex;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/SLConfigDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/SLConfigDescriptor.java.svn-base
new file mode 100644
index 0000000..70a58e6
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/SLConfigDescriptor.java.svn-base
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * class SLConfigDescriptor extends BaseDescriptor : bit(8) tag=SLConfigDescrTag {
+ * bit(8) predefined;
+ * if (predefined==0) {
+ * bit(1) useAccessUnitStartFlag;
+ * bit(1) useAccessUnitEndFlag;
+ * bit(1) useRandomAccessPointFlag;
+ * bit(1) hasRandomAccessUnitsOnlyFlag;
+ * bit(1) usePaddingFlag;
+ * bit(1) useTimeStampsFlag;
+ * bit(1) useIdleFlag;
+ * bit(1) durationFlag;
+ * bit(32) timeStampResolution;
+ * bit(32) OCRResolution;
+ * bit(8) timeStampLength; // must be ≤ 64
+ * bit(8) OCRLength; // must be ≤ 64
+ * bit(8) AU_Length; // must be ≤ 32
+ * bit(8) instantBitrateLength;
+ * bit(4) degradationPriorityLength;
+ * bit(5) AU_seqNumLength; // must be ≤ 16
+ * bit(5) packetSeqNumLength; // must be ≤ 16
+ * bit(2) reserved=0b11;
+ * }
+ * if (durationFlag) {
+ * bit(32) timeScale;
+ * bit(16) accessUnitDuration;
+ * bit(16) compositionUnitDuration;
+ * }
+ * if (!useTimeStampsFlag) {
+ * bit(timeStampLength) startDecodingTimeStamp;
+ * bit(timeStampLength) startCompositionTimeStamp;
+ * }
+ * }
+ */
+@Descriptor(tags = {0x06})
+public class SLConfigDescriptor extends BaseDescriptor {
+ int predefined;
+
+ public int getPredefined() {
+ return predefined;
+ }
+
+ public void setPredefined(int predefined) {
+ this.predefined = predefined;
+ }
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ predefined = IsoTypeReader.readUInt8(bb);
+ }
+
+ public int serializedSize() {
+ return 3;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(3);
+ IsoTypeWriter.writeUInt8(out, 6);
+ IsoTypeWriter.writeUInt8(out, 1);
+ IsoTypeWriter.writeUInt8(out, predefined);
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("SLConfigDescriptor");
+ sb.append("{predefined=").append(predefined);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SLConfigDescriptor that = (SLConfigDescriptor) o;
+
+ if (predefined != that.predefined) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return predefined;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/UnknownDescriptor.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/UnknownDescriptor.java.svn-base
new file mode 100644
index 0000000..dd75a0f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/.svn/text-base/UnknownDescriptor.java.svn-base
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+public class UnknownDescriptor extends BaseDescriptor {
+ private ByteBuffer data;
+ private static Logger log = Logger.getLogger(UnknownDescriptor.class.getName());
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ data = (ByteBuffer) bb.slice().limit(this.getSizeOfInstance());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("UnknownDescriptor");
+ sb.append("{tag=").append(tag);
+ sb.append(", sizeOfInstance=").append(sizeOfInstance);
+ sb.append(", data=").append(data);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/AudioSpecificConfig.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/AudioSpecificConfig.java
new file mode 100644
index 0000000..86e319e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/AudioSpecificConfig.java
@@ -0,0 +1,1176 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+
+//
+//GetAudioObjectType()
+//{
+//audioObjectType; 5 uimsbf
+//if (audioObjectType == 31) {
+//audioObjectType = 32 + audioObjectTypeExt; 6 uimsbf
+//}
+//return audioObjectType;
+//}
+//AudioSpecificConfig ()
+//{
+//audioObjectType = GetAudioObjectType();
+//samplingFrequencyIndex; 4 bslbf
+//if ( samplingFrequencyIndex == 0xf ) {
+//samplingFrequency; 24 uimsbf
+//}
+//channelConfiguration; 4 bslbf
+//sbrPresentFlag = -1;
+//psPresentFlag = -1;
+//if ( audioObjectType == 5 ||
+//audioObjectType == 29 ) {
+//extensionAudioObjectType = 5;
+//sbrPresentFlag = 1;
+//if ( audioObjectType == 29 ) {
+//psPresentFlag = 1;
+//}
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf )
+//extensionSamplingFrequency; 24 uimsbf
+//audioObjectType = GetAudioObjectType();
+//if ( audioObjectType == 22 )
+//extensionChannelConfiguration; 4 uimsbf
+//}
+//else {
+//extensionAudioObjectType = 0;
+//}
+//switch (audioObjectType) {
+//case 1:
+//case 2:
+//case 3:
+//case 4:
+//case 6:
+//case 7:
+//case 17:
+//case 19:
+//case 20:
+//case 21:
+//case 22:
+//case 23:
+//GASpecificConfig();
+//break:
+//case 8:
+//CelpSpecificConfig();
+//break;
+//case 9:
+//HvxcSpecificConfig();
+//break:
+//case 12:
+//TTSSpecificConfig();
+//break;
+//case 13:
+//case 14:
+//case 15:
+//case 16:
+//StructuredAudioSpecificConfig();
+//break;
+//case 24:
+//ErrorResilientCelpSpecificConfig();
+//break;
+//case 25:
+//ErrorResilientHvxcSpecificConfig();
+//break;
+//case 26:
+//case 27:
+//ParametricSpecificConfig();
+//break;
+// case 28:
+//SSCSpecificConfig();
+//break;
+//case 30:
+//sacPayloadEmbedding; 1 uimsbf
+//SpatialSpecificConfig();
+//break;
+//case 32:
+//case 33:
+//case 34:
+//MPEG_1_2_SpecificConfig();
+//break;
+//case 35:
+//DSTSpecificConfig();
+//break;
+//case 36:
+//fillBits; 5 bslbf
+//ALSSpecificConfig();
+//break;
+//case 37:
+//case 38:
+//SLSSpecificConfig();
+//break;
+//case 39:
+//ELDSpecificConfig(channelConfiguration);
+//break:
+//case 40:
+//case 41:
+//SymbolicMusicSpecificConfig();
+//break;
+//default:
+///* reserved */
+//}
+//switch (audioObjectType) {
+//case 17:
+//case 19:
+//case 20:
+//case 21:
+//case 22:
+//case 23:
+//case 24:
+//case 25:
+//case 26:
+//case 27:
+//case 39:
+//epConfig; 2 bslbf
+//if ( epConfig == 2 || epConfig == 3 ) {
+//ErrorProtectionSpecificConfig();
+//}
+//if ( epConfig == 3 ) {
+//directMapping; 1 bslbf
+//if ( ! directMapping ) {
+///* tbd */
+//}
+//}
+//}
+//if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) {
+//syncExtensionType; 11 bslbf
+//if (syncExtensionType == 0x2b7) {
+// extensionAudioObjectType = GetAudioObjectType();
+//if ( extensionAudioObjectType == 5 ) {
+//sbrPresentFlag; 1 uimsbf
+//if (sbrPresentFlag == 1) {
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf ) {
+//extensionSamplingFrequency; 24 uimsbf
+//}
+//if ( bits_to_decode() >= 12 ) {
+//syncExtensionType; 11 bslbf
+//if (syncExtesionType == 0x548) {
+//psPresentFlag; 1 uimsbf
+//}
+//}
+//}
+//}
+//if ( extensionAudioObjectType == 22 ) {
+//sbrPresentFlag; 1 uimsbf
+//if (sbrPresentFlag == 1) {
+//extensionSamplingFrequencyIndex; 4 uimsbf
+//if ( extensionSamplingFrequencyIndex == 0xf ) {
+//extensionSamplingFrequency; 24 uimsbf
+//}
+//}
+//extensionChannelConfiguration; 4 uimsbf
+//}
+//}
+//}
+//}
+// }
+//
+// TFCodingType
+//0x0 AAC scaleable
+//0x1 BSAC
+//0x2 TwinVQ
+//0x3 AAC non scaleable (i.e. multichannel)
+//
+// class TFSpecificConfig( uint(4) samplingFrequencyIndex, uint(4) channelConfiguration ) {
+//uint(2) TFCodingType;
+//uint(1) frameLength;
+//uint(1) dependsOnCoreCoder;
+//if (dependsOnCoreCoder == 1){
+//uint(14)coreCoderDelay
+//}
+//if (TFCodingType==BSAC) {
+//uint(11) lslayer_length
+//}
+//uint (1) extensionFlag;
+//if (channelConfiguration == 0 ){
+//program_config_element();
+//}
+//if (extensionFlag==1){
+//<to be defined in mpeg4 phase 2>
+//}
+//}
+//
+//program_config_element()
+//{
+//element_instance_tag 4 uimsbf
+//profile 2 uimsbf
+//sampling_frequency_index 4 uimsbf
+//num_front_channel_elements 4 uimsbf
+//num_side_channel_elements 4 uimsbf
+//num_back_channel_elements 4 uimsbf
+// num_lfe_channel_elements 2 uimsbf
+//num_assoc_data_elements 3 uimsbf
+//num_valid_cc_elements 4 uimsbf
+//mono_mixdown_present 1 uimsbf
+//if ( mono_mixdown_present == 1 )
+//mono_mixdown_element_number 4 uimsbf
+//stereo_mixdown_present 1 uimsbf
+//if ( stereo_mixdown_present == 1 )
+//stereo_mixdown_element_number 4 uimsbf
+//matrix_mixdown_idx_present 1 uimsbf
+//if ( matrix_mixdown_idx_present == 1 ) {
+//matrix_mixdown_idx 2 uimsbf
+//pseudo_surround_enable 1 uimsbf
+//}
+//for ( i = 0; i < num_front_channel_elements; i++) {
+//front_element_is_cpe[i]; 1 bslbf
+//front_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_side_channel_elements; i++) {
+//side_element_is_cpe[i]; 1 bslbf
+//side_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_back_channel_elements; i++) {
+//back_element_is_cpe[i]; 1 bslbf
+//back_element_tag_select[i]; 4 uimsbf
+//}
+//for ( i = 0; i < num_lfe_channel_elements; i++)
+//lfe_element_tag_select[i]; 4 uimsbf
+//for ( i = 0; i < num_assoc_data_elements; i++)
+//assoc_data_element_tag_select[i]; 4 uimsbf
+//for ( i = 0; i < num_valid_cc_elements; i++) {
+//cc_element_is_ind_sw[i]; 1 uimsbf
+//valid_cc_element_tag_select[i]; 4 uimsbf
+//}
+//byte_alignment()
+//comment_field_bytes 8 uimsbf
+//for ( i = 0; i < comment_field_bytes; i++)
+//comment_field_data[i]; 8 uimsbf
+//}
+
+@Descriptor(tags = 0x5, objectTypeIndication = 0x40)
+public class AudioSpecificConfig extends BaseDescriptor {
+ byte[] configBytes;
+
+ public static Map<Integer, Integer> samplingFrequencyIndexMap = new HashMap<Integer, Integer>();
+ public static Map<Integer, String> audioObjectTypeMap = new HashMap<Integer, String>();
+ int audioObjectType;
+ int samplingFrequencyIndex;
+ int samplingFrequency;
+ int channelConfiguration;
+ int extensionAudioObjectType;
+ int sbrPresentFlag;
+ int psPresentFlag;
+ int extensionSamplingFrequencyIndex;
+ int extensionSamplingFrequency;
+ int extensionChannelConfiguration;
+ int sacPayloadEmbedding;
+ int fillBits;
+ int epConfig;
+ int directMapping;
+ int syncExtensionType;
+
+ //GASpecificConfig
+ int frameLengthFlag;
+ int dependsOnCoreCoder;
+ int coreCoderDelay;
+ int extensionFlag;
+ int layerNr;
+ int numOfSubFrame;
+ int layer_length;
+ int aacSectionDataResilienceFlag;
+ int aacScalefactorDataResilienceFlag;
+ int aacSpectralDataResilienceFlag;
+ int extensionFlag3;
+ boolean gaSpecificConfig;
+
+ //ParametricSpecificConfig
+ int isBaseLayer;
+ int paraMode;
+ int paraExtensionFlag;
+ int hvxcVarMode;
+ int hvxcRateMode;
+ int erHvxcExtensionFlag;
+ int var_ScalableFlag;
+ int hilnQuantMode;
+ int hilnMaxNumLine;
+ int hilnSampleRateCode;
+ int hilnFrameLength;
+ int hilnContMode;
+ int hilnEnhaLayer;
+ int hilnEnhaQuantMode;
+ boolean parametricSpecificConfig;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ ByteBuffer configBytes = bb.slice();
+ configBytes.limit(sizeOfInstance);
+ bb.position(bb.position() + sizeOfInstance);
+
+ //copy original bytes to internal array for constructing codec config strings (todo until writing of the config is supported)
+ this.configBytes = new byte[sizeOfInstance];
+ configBytes.get(this.configBytes);
+ configBytes.rewind();
+
+ BitReaderBuffer bitReaderBuffer = new BitReaderBuffer(configBytes);
+ audioObjectType = getAudioObjectType(bitReaderBuffer);
+ samplingFrequencyIndex = bitReaderBuffer.readBits(4);
+
+ if (samplingFrequencyIndex == 0xf) {
+ samplingFrequency = bitReaderBuffer.readBits(24);
+ }
+
+ channelConfiguration = bitReaderBuffer.readBits(4);
+
+ if (audioObjectType == 5 ||
+ audioObjectType == 29) {
+ extensionAudioObjectType = 5;
+ sbrPresentFlag = 1;
+ if (audioObjectType == 29) {
+ psPresentFlag = 1;
+ }
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf)
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ audioObjectType = getAudioObjectType(bitReaderBuffer);
+ if (audioObjectType == 22)
+ extensionChannelConfiguration = bitReaderBuffer.readBits(4);
+ } else {
+ extensionAudioObjectType = 0;
+ }
+
+ switch (audioObjectType) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 6:
+ case 7:
+ case 17:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ parseGaSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
+ //GASpecificConfig();
+ break;
+ case 8:
+ throw new UnsupportedOperationException("can't parse CelpSpecificConfig yet");
+ //CelpSpecificConfig();
+ //break;
+ case 9:
+ throw new UnsupportedOperationException("can't parse HvxcSpecificConfig yet");
+ //HvxcSpecificConfig();
+ //break;
+ case 12:
+ throw new UnsupportedOperationException("can't parse TTSSpecificConfig yet");
+ //TTSSpecificConfig();
+ //break;
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ throw new UnsupportedOperationException("can't parse StructuredAudioSpecificConfig yet");
+ //StructuredAudioSpecificConfig();
+ //break;
+ case 24:
+ throw new UnsupportedOperationException("can't parse ErrorResilientCelpSpecificConfig yet");
+ //ErrorResilientCelpSpecificConfig();
+ //break;
+ case 25:
+ throw new UnsupportedOperationException("can't parse ErrorResilientHvxcSpecificConfig yet");
+ //ErrorResilientHvxcSpecificConfig();
+ //break;
+ case 26:
+ case 27:
+ parseParametricSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
+ //ParametricSpecificConfig();
+ break;
+ case 28:
+ throw new UnsupportedOperationException("can't parse SSCSpecificConfig yet");
+ //SSCSpecificConfig();
+ //break;
+ case 30:
+ sacPayloadEmbedding = bitReaderBuffer.readBits(1);
+ throw new UnsupportedOperationException("can't parse SpatialSpecificConfig yet");
+ //SpatialSpecificConfig();
+ //break;
+ case 32:
+ case 33:
+ case 34:
+ throw new UnsupportedOperationException("can't parse MPEG_1_2_SpecificConfig yet");
+ //MPEG_1_2_SpecificConfig();
+ //break;
+ case 35:
+ throw new UnsupportedOperationException("can't parse DSTSpecificConfig yet");
+ //DSTSpecificConfig();
+ //break;
+ case 36:
+ fillBits = bitReaderBuffer.readBits(5);
+ throw new UnsupportedOperationException("can't parse ALSSpecificConfig yet");
+ //ALSSpecificConfig();
+ //break;
+ case 37:
+ case 38:
+ throw new UnsupportedOperationException("can't parse SLSSpecificConfig yet");
+ //SLSSpecificConfig();
+ //break;
+ case 39:
+ throw new UnsupportedOperationException("can't parse ELDSpecificConfig yet");
+ //ELDSpecificConfig(channelConfiguration);
+ //break;
+ case 40:
+ case 41:
+ throw new UnsupportedOperationException("can't parse SymbolicMusicSpecificConfig yet");
+ //SymbolicMusicSpecificConfig();
+ //break;
+ default:
+ /* reserved */
+ }
+
+ switch (audioObjectType) {
+ case 17:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 39:
+ epConfig = bitReaderBuffer.readBits(2);
+ if (epConfig == 2 || epConfig == 3) {
+ throw new UnsupportedOperationException("can't parse ErrorProtectionSpecificConfig yet");
+ //ErrorProtectionSpecificConfig();
+ }
+ if (epConfig == 3) {
+ directMapping = bitReaderBuffer.readBits(1);
+ if (directMapping == 0) {
+ /* tbd */
+ throw new RuntimeException("not implemented");
+ }
+ }
+ }
+
+ if (extensionAudioObjectType != 5 && bitReaderBuffer.remainingBits() >= 16) {
+ syncExtensionType = bitReaderBuffer.readBits(11);
+ if (syncExtensionType == 0x2b7) {
+ extensionAudioObjectType = getAudioObjectType(bitReaderBuffer);
+ if (extensionAudioObjectType == 5) {
+ sbrPresentFlag = bitReaderBuffer.readBits(1);
+ if (sbrPresentFlag == 1) {
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf) {
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ }
+ if (bitReaderBuffer.remainingBits() >= 12) {
+ syncExtensionType = bitReaderBuffer.readBits(11); //10101001000
+ if (syncExtensionType == 0x548) {
+ psPresentFlag = bitReaderBuffer.readBits(1);
+ }
+ }
+ }
+ }
+ if (extensionAudioObjectType == 22) {
+ sbrPresentFlag = bitReaderBuffer.readBits(1);
+ if (sbrPresentFlag == 1) {
+ extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
+ if (extensionSamplingFrequencyIndex == 0xf) {
+ extensionSamplingFrequency = bitReaderBuffer.readBits(24);
+ }
+ }
+ extensionChannelConfiguration = bitReaderBuffer.readBits(4);
+ }
+ }
+ }
+ }
+
+ private int gaSpecificConfigSize() {
+ return 0;
+ }
+
+ public int serializedSize() {
+ int out = 4;
+ if (audioObjectType == 2) {
+ out += gaSpecificConfigSize();
+ } else {
+ throw new UnsupportedOperationException("can't serialize that yet");
+ }
+ return out;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize());
+ IsoTypeWriter.writeUInt8(out, 5);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
+ BitWriterBuffer bwb = new BitWriterBuffer(out);
+ bwb.writeBits(audioObjectType, 5);
+ bwb.writeBits(samplingFrequencyIndex, 4);
+ if (samplingFrequencyIndex == 0xf) {
+ throw new UnsupportedOperationException("can't serialize that yet");
+ }
+ bwb.writeBits(channelConfiguration, 4);
+
+ // Don't support any extensions, unusual GASpecificConfig other than the default or anything...
+
+ return out;
+ }
+
+ private int getAudioObjectType(BitReaderBuffer in) throws IOException {
+ int audioObjectType = in.readBits(5);
+ if (audioObjectType == 31) {
+ audioObjectType = 32 + in.readBits(6);
+ }
+ return audioObjectType;
+ }
+
+ private void parseGaSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+// GASpecificConfig (samplingFrequencyIndex,
+// channelConfiguration,
+// audioObjectType)
+// {
+ frameLengthFlag = in.readBits(1);
+ dependsOnCoreCoder = in.readBits(1);
+ if (dependsOnCoreCoder == 1) {
+ coreCoderDelay = in.readBits(14);
+ }
+ extensionFlag = in.readBits(1);
+ if (channelConfiguration == 0) {
+ throw new UnsupportedOperationException("can't parse program_config_element yet");
+ //program_config_element ();
+ }
+ if ((audioObjectType == 6) || (audioObjectType == 20)) {
+ layerNr = in.readBits(3);
+ }
+ if (extensionFlag == 1) {
+ if (audioObjectType == 22) {
+ numOfSubFrame = in.readBits(5);
+ layer_length = in.readBits(11);
+ }
+ if (audioObjectType == 17 || audioObjectType == 19 ||
+ audioObjectType == 20 || audioObjectType == 23) {
+ aacSectionDataResilienceFlag = in.readBits(1);
+ aacScalefactorDataResilienceFlag = in.readBits(1);
+ aacSpectralDataResilienceFlag = in.readBits(1);
+ }
+ extensionFlag3 = in.readBits(1);
+ if (extensionFlag3 == 1) {
+ /* tbd in version 3 */
+ }
+ }
+// }
+ gaSpecificConfig = true;
+ }
+
+ private void parseParametricSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ ParametricSpecificConfig() {
+ isBaseLayer; 1 uimsbf
+ if (isBaseLayer) {
+ PARAconfig();
+ } else {
+ HILNenexConfig();
+ }
+ }
+ */
+ isBaseLayer = in.readBits(1);
+ if (isBaseLayer == 1) {
+ parseParaConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ } else {
+ parseHilnEnexConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+ }
+
+ private void parseParaConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ PARAconfig()
+ {
+ PARAmode; 2 uimsbf
+ if (PARAmode != 1) {
+ ErHVXCconfig();
+ }
+ if (PARAmode != 0) {
+ HILNconfig();
+ }
+ PARAextensionFlag; 1 uimsbf
+ if (PARAextensionFlag) {
+ // to be defined in MPEG-4 Phase 3
+ }
+ }
+ */
+ paraMode = in.readBits(2);
+
+ if (paraMode != 1) {
+ parseErHvxcConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+ if (paraMode != 0) {
+ parseHilnConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
+ }
+
+ paraExtensionFlag = in.readBits(1);
+ parametricSpecificConfig = true;
+ }
+
+ private void parseErHvxcConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ ErHVXCconfig()
+ {
+ HVXCvarMode; 1 uimsbf
+ HVXCrateMode; 2 uimsbf
+ extensionFlag; 1 uimsbf
+ if (extensionFlag) {
+ var_ScalableFlag; 1 uimsbf
+ }
+ }
+ */
+ hvxcVarMode = in.readBits(1);
+ hvxcRateMode = in.readBits(2);
+ erHvxcExtensionFlag = in.readBits(1);
+
+ if (erHvxcExtensionFlag == 1) {
+ var_ScalableFlag = in.readBits(1);
+ }
+ }
+
+ private void parseHilnConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ HILNconfig()
+ {
+ HILNquantMode; 1 uimsbf
+ HILNmaxNumLine; 8 uimsbf
+ HILNsampleRateCode; 4 uimsbf
+ HILNframeLength; 12 uimsbf
+ HILNcontMode; 2 uimsbf
+ }
+ */
+ hilnQuantMode = in.readBits(1);
+ hilnMaxNumLine = in.readBits(8);
+ hilnSampleRateCode = in.readBits(4);
+ hilnFrameLength = in.readBits(12);
+ hilnContMode = in.readBits(2);
+ }
+
+ private void parseHilnEnexConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in) throws IOException {
+ /*
+ HILNenexConfig()
+ {
+ HILNenhaLayer; 1 uimsbf
+ if (HILNenhaLayer) {
+ HILNenhaQuantMode; 2 uimsbf
+ }
+ }
+ */
+ hilnEnhaLayer = in.readBits(1);
+ if (hilnEnhaLayer == 1) {
+ hilnEnhaQuantMode = in.readBits(2);
+ }
+ }
+
+ public byte[] getConfigBytes() {
+ return configBytes;
+ }
+
+ public int getAudioObjectType() {
+ return audioObjectType;
+ }
+
+ public int getExtensionAudioObjectType() {
+ return extensionAudioObjectType;
+ }
+
+ public int getSbrPresentFlag() {
+ return sbrPresentFlag;
+ }
+
+ public int getPsPresentFlag() {
+ return psPresentFlag;
+ }
+
+ public void setAudioObjectType(int audioObjectType) {
+ this.audioObjectType = audioObjectType;
+ }
+
+ public void setSamplingFrequencyIndex(int samplingFrequencyIndex) {
+ this.samplingFrequencyIndex = samplingFrequencyIndex;
+ }
+
+ public void setSamplingFrequency(int samplingFrequency) {
+ this.samplingFrequency = samplingFrequency;
+ }
+
+ public void setChannelConfiguration(int channelConfiguration) {
+ this.channelConfiguration = channelConfiguration;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("AudioSpecificConfig");
+ sb.append("{configBytes=").append(Hex.encodeHex(configBytes));
+ sb.append(", audioObjectType=").append(audioObjectType).append(" (").append(audioObjectTypeMap.get(audioObjectType)).append(")");
+ sb.append(", samplingFrequencyIndex=").append(samplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(samplingFrequencyIndex)).append(")");
+ sb.append(", samplingFrequency=").append(samplingFrequency);
+ sb.append(", channelConfiguration=").append(channelConfiguration);
+ if (extensionAudioObjectType > 0) {
+ sb.append(", extensionAudioObjectType=").append(extensionAudioObjectType).append(" (").append(audioObjectTypeMap.get(extensionAudioObjectType)).append(")");
+ sb.append(", sbrPresentFlag=").append(sbrPresentFlag);
+ sb.append(", psPresentFlag=").append(psPresentFlag);
+ sb.append(", extensionSamplingFrequencyIndex=").append(extensionSamplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(extensionSamplingFrequencyIndex)).append(")");
+ sb.append(", extensionSamplingFrequency=").append(extensionSamplingFrequency);
+ sb.append(", extensionChannelConfiguration=").append(extensionChannelConfiguration);
+ }
+// sb.append(", sacPayloadEmbedding=").append(sacPayloadEmbedding);
+// sb.append(", fillBits=").append(fillBits);
+// sb.append(", epConfig=").append(epConfig);
+// sb.append(", directMapping=").append(directMapping);
+ sb.append(", syncExtensionType=").append(syncExtensionType);
+ if (gaSpecificConfig) {
+ sb.append(", frameLengthFlag=").append(frameLengthFlag);
+ sb.append(", dependsOnCoreCoder=").append(dependsOnCoreCoder);
+ sb.append(", coreCoderDelay=").append(coreCoderDelay);
+ sb.append(", extensionFlag=").append(extensionFlag);
+ sb.append(", layerNr=").append(layerNr);
+ sb.append(", numOfSubFrame=").append(numOfSubFrame);
+ sb.append(", layer_length=").append(layer_length);
+ sb.append(", aacSectionDataResilienceFlag=").append(aacSectionDataResilienceFlag);
+ sb.append(", aacScalefactorDataResilienceFlag=").append(aacScalefactorDataResilienceFlag);
+ sb.append(", aacSpectralDataResilienceFlag=").append(aacSpectralDataResilienceFlag);
+ sb.append(", extensionFlag3=").append(extensionFlag3);
+ }
+ if (parametricSpecificConfig) {
+ sb.append(", isBaseLayer=").append(isBaseLayer);
+ sb.append(", paraMode=").append(paraMode);
+ sb.append(", paraExtensionFlag=").append(paraExtensionFlag);
+ sb.append(", hvxcVarMode=").append(hvxcVarMode);
+ sb.append(", hvxcRateMode=").append(hvxcRateMode);
+ sb.append(", erHvxcExtensionFlag=").append(erHvxcExtensionFlag);
+ sb.append(", var_ScalableFlag=").append(var_ScalableFlag);
+ sb.append(", hilnQuantMode=").append(hilnQuantMode);
+ sb.append(", hilnMaxNumLine=").append(hilnMaxNumLine);
+ sb.append(", hilnSampleRateCode=").append(hilnSampleRateCode);
+ sb.append(", hilnFrameLength=").append(hilnFrameLength);
+ sb.append(", hilnContMode=").append(hilnContMode);
+ sb.append(", hilnEnhaLayer=").append(hilnEnhaLayer);
+ sb.append(", hilnEnhaQuantMode=").append(hilnEnhaQuantMode);
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ static {
+ // sampling_frequency_index sampling frequeny
+//0x0 96000
+//0x1 88200
+//0x2 64000
+//0x3 48000
+//0x4 44100
+//0x5 32000
+//0x6 24000
+//0x7 22050
+//0x8 16000
+//0x9 12000
+//0xa 11025
+//0xb 8000
+//0xc reserved
+//0xd reserved
+//0xe reserved
+//0xf reserved
+ samplingFrequencyIndexMap.put(0x0, 96000);
+ samplingFrequencyIndexMap.put(0x1, 88200);
+ samplingFrequencyIndexMap.put(0x2, 64000);
+ samplingFrequencyIndexMap.put(0x3, 48000);
+ samplingFrequencyIndexMap.put(0x4, 44100);
+ samplingFrequencyIndexMap.put(0x5, 32000);
+ samplingFrequencyIndexMap.put(0x6, 24000);
+ samplingFrequencyIndexMap.put(0x7, 22050);
+ samplingFrequencyIndexMap.put(0x8, 16000);
+ samplingFrequencyIndexMap.put(0x9, 12000);
+ samplingFrequencyIndexMap.put(0xa, 11025);
+ samplingFrequencyIndexMap.put(0xb, 8000);
+
+ /* audioObjectType IDs
+ 0 Null
+ 1 AAC main X X
+ 2 AAC LC X X X X X X X
+ 3 AAC SSR X X
+ 4 AAC LTP X X X X
+ 5 SBR X X
+ 6 AAC Scalable X X X X
+ 7 TwinVQ X X X
+ 8 CELP X X X X X X
+ 9 HVXC X X X X X
+ 10 (reserved)
+ 11 (reserved)
+ 12 TTSI X X X X X X
+ 13 Main synthetic X X
+ 14 Wavetable synthesis X* X*
+ 15 General MIDI X* X*
+ 16 Algorithmic Synthesis and Audio FX X* X*
+ 17 ER AAC LC X X X
+ 18 (reserved)
+ 19 ER AAC LTP X X
+ 20 ER AAC Scalable X X X
+ 21 ER TwinVQ X X
+ 22 ER BSAC X X
+ 23 ER AAC LD X X X X
+ 24 ER CELP X X X
+ 25 ER HVXC X X
+ 26 ER HILN X
+ 27 ER Parametric X
+ 28 SSC
+ 29 PS X
+ 30 MPEG Surround
+ 31 (escape)
+ 32 Layer-1
+ 33 Layer-2
+ 34 Layer-3
+ 35 DST
+ 36 ALS
+ 37 SLS
+ 38 SLS non-core
+ 39 ER AAC ELD
+ 40 SMR Simple
+ 41 SMR Main
+ */
+ audioObjectTypeMap.put(1, "AAC main");
+ audioObjectTypeMap.put(2, "AAC LC");
+ audioObjectTypeMap.put(3, "AAC SSR");
+ audioObjectTypeMap.put(4, "AAC LTP");
+ audioObjectTypeMap.put(5, "SBR");
+ audioObjectTypeMap.put(6, "AAC Scalable");
+ audioObjectTypeMap.put(7, "TwinVQ");
+ audioObjectTypeMap.put(8, "CELP");
+ audioObjectTypeMap.put(9, "HVXC");
+ audioObjectTypeMap.put(10, "(reserved)");
+ audioObjectTypeMap.put(11, "(reserved)");
+ audioObjectTypeMap.put(12, "TTSI");
+ audioObjectTypeMap.put(13, "Main synthetic");
+ audioObjectTypeMap.put(14, "Wavetable synthesis");
+ audioObjectTypeMap.put(15, "General MIDI");
+ audioObjectTypeMap.put(16, "Algorithmic Synthesis and Audio FX");
+ audioObjectTypeMap.put(17, "ER AAC LC");
+ audioObjectTypeMap.put(18, "(reserved)");
+ audioObjectTypeMap.put(19, "ER AAC LTP");
+ audioObjectTypeMap.put(20, "ER AAC Scalable");
+ audioObjectTypeMap.put(21, "ER TwinVQ");
+ audioObjectTypeMap.put(22, "ER BSAC");
+ audioObjectTypeMap.put(23, "ER AAC LD");
+ audioObjectTypeMap.put(24, "ER CELP");
+ audioObjectTypeMap.put(25, "ER HVXC");
+ audioObjectTypeMap.put(26, "ER HILN");
+ audioObjectTypeMap.put(27, "ER Parametric");
+ audioObjectTypeMap.put(28, "SSC");
+ audioObjectTypeMap.put(29, "PS");
+ audioObjectTypeMap.put(30, "MPEG Surround");
+ audioObjectTypeMap.put(31, "(escape)");
+ audioObjectTypeMap.put(32, "Layer-1");
+ audioObjectTypeMap.put(33, "Layer-2");
+ audioObjectTypeMap.put(34, "Layer-3");
+ audioObjectTypeMap.put(35, "DST");
+ audioObjectTypeMap.put(36, "ALS");
+ audioObjectTypeMap.put(37, "SLS");
+ audioObjectTypeMap.put(38, "SLS non-core");
+ audioObjectTypeMap.put(39, "ER AAC ELD");
+ audioObjectTypeMap.put(40, "SMR Simple");
+ audioObjectTypeMap.put(41, "SMR Main");
+
+ /* profileLevelIds
+ 0x00 Reserved for ISO use -
+ 0x01 Main Audio Profile L1
+ 0x02 Main Audio Profile L2
+ 0x03 Main Audio Profile L3
+ 0x04 Main Audio Profile L4
+ 0x05 Scalable Audio Profile L1
+ 0x06 Scalable Audio Profile L2
+ 0x07 Scalable Audio Profile L3
+ 0x08 Scalable Audio Profile L4
+ 0x09 Speech Audio Profile L1
+ 0x0A Speech Audio Profile L2
+ 0x0B Synthetic Audio Profile L1
+ 0x0C Synthetic Audio Profile L2
+ 0x0D Synthetic Audio Profile L3
+ 0x0E High Quality Audio Profile L1
+ 0x0F High Quality Audio Profile L2
+ 0x10 High Quality Audio Profile L3
+ 0x11 High Quality Audio Profile L4
+ 0x12 High Quality Audio Profile L5
+ 0x13 High Quality Audio Profile L6
+ 0x14 High Quality Audio Profile L7
+ 0x15 High Quality Audio Profile L8
+ 0x16 Low Delay Audio Profile L1
+ 0x17 Low Delay Audio Profile L2
+ 0x18 Low Delay Audio Profile L3
+ 0x19 Low Delay Audio Profile L4
+ 0x1A Low Delay Audio Profile L5
+ 0x1B Low Delay Audio Profile L6
+ 0x1C Low Delay Audio Profile L7
+ 0x1D Low Delay Audio Profile L8
+ 0x1E Natural Audio Profile L1
+ 0x1F Natural Audio Profile L2
+ 0x20 Natural Audio Profile L3
+ 0x21 Natural Audio Profile L4
+ 0x22 Mobile Audio Internetworking Profile L1
+ 0x23 Mobile Audio Internetworking Profile L2
+ 0x24 Mobile Audio Internetworking Profile L3
+ 0x25 Mobile Audio Internetworking Profile L4
+ 0x26 Mobile Audio Internetworking Profile L5
+ 0x27 Mobile Audio Internetworking Profile L6
+ 0x28 AAC Profile L1
+ 0x29 AAC Profile L2
+ 0x2A AAC Profile L4
+ 0x2B AAC Profile L5
+ 0x2C High Efficiency AAC Profile L2
+ 0x2D High Efficiency AAC Profile L3
+ 0x2E High Efficiency AAC Profile L4
+ 0x2F High Efficiency AAC Profile L5
+ 0x30 High Efficiency AAC v2 Profile L2
+ 0x31 High Efficiency AAC v2 Profile L3
+ 0x32 High Efficiency AAC v2 Profile L4
+ 0x33 High Efficiency AAC v2 Profile L5
+ 0x34 Low Delay AAC Profile L1
+ 0x35 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L1
+ 0x36 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L2
+ 0x37 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L3
+ 0x38 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L4
+ 0c39 Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L5
+ 0x3A Baseline MPEG Surround Profile (see ISO/IEC
+ 23003-1)
+ L6
+ 0x3B - 0x7F reserved for ISO use -
+ 0x80 - 0xFD user private -
+ 0xFE no audio profile specified -
+ 0xFF no audio capability required -
+
+ */
+ }
+
+
+ public int getSamplingFrequency() {
+ return samplingFrequencyIndex == 0xf ? samplingFrequency : samplingFrequencyIndexMap.get(samplingFrequencyIndex);
+ }
+
+ public int getChannelConfiguration() {
+ return channelConfiguration;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ AudioSpecificConfig that = (AudioSpecificConfig) o;
+
+ if (aacScalefactorDataResilienceFlag != that.aacScalefactorDataResilienceFlag) {
+ return false;
+ }
+ if (aacSectionDataResilienceFlag != that.aacSectionDataResilienceFlag) {
+ return false;
+ }
+ if (aacSpectralDataResilienceFlag != that.aacSpectralDataResilienceFlag) {
+ return false;
+ }
+ if (audioObjectType != that.audioObjectType) {
+ return false;
+ }
+ if (channelConfiguration != that.channelConfiguration) {
+ return false;
+ }
+ if (coreCoderDelay != that.coreCoderDelay) {
+ return false;
+ }
+ if (dependsOnCoreCoder != that.dependsOnCoreCoder) {
+ return false;
+ }
+ if (directMapping != that.directMapping) {
+ return false;
+ }
+ if (epConfig != that.epConfig) {
+ return false;
+ }
+ if (erHvxcExtensionFlag != that.erHvxcExtensionFlag) {
+ return false;
+ }
+ if (extensionAudioObjectType != that.extensionAudioObjectType) {
+ return false;
+ }
+ if (extensionChannelConfiguration != that.extensionChannelConfiguration) {
+ return false;
+ }
+ if (extensionFlag != that.extensionFlag) {
+ return false;
+ }
+ if (extensionFlag3 != that.extensionFlag3) {
+ return false;
+ }
+ if (extensionSamplingFrequency != that.extensionSamplingFrequency) {
+ return false;
+ }
+ if (extensionSamplingFrequencyIndex != that.extensionSamplingFrequencyIndex) {
+ return false;
+ }
+ if (fillBits != that.fillBits) {
+ return false;
+ }
+ if (frameLengthFlag != that.frameLengthFlag) {
+ return false;
+ }
+ if (gaSpecificConfig != that.gaSpecificConfig) {
+ return false;
+ }
+ if (hilnContMode != that.hilnContMode) {
+ return false;
+ }
+ if (hilnEnhaLayer != that.hilnEnhaLayer) {
+ return false;
+ }
+ if (hilnEnhaQuantMode != that.hilnEnhaQuantMode) {
+ return false;
+ }
+ if (hilnFrameLength != that.hilnFrameLength) {
+ return false;
+ }
+ if (hilnMaxNumLine != that.hilnMaxNumLine) {
+ return false;
+ }
+ if (hilnQuantMode != that.hilnQuantMode) {
+ return false;
+ }
+ if (hilnSampleRateCode != that.hilnSampleRateCode) {
+ return false;
+ }
+ if (hvxcRateMode != that.hvxcRateMode) {
+ return false;
+ }
+ if (hvxcVarMode != that.hvxcVarMode) {
+ return false;
+ }
+ if (isBaseLayer != that.isBaseLayer) {
+ return false;
+ }
+ if (layerNr != that.layerNr) {
+ return false;
+ }
+ if (layer_length != that.layer_length) {
+ return false;
+ }
+ if (numOfSubFrame != that.numOfSubFrame) {
+ return false;
+ }
+ if (paraExtensionFlag != that.paraExtensionFlag) {
+ return false;
+ }
+ if (paraMode != that.paraMode) {
+ return false;
+ }
+ if (parametricSpecificConfig != that.parametricSpecificConfig) {
+ return false;
+ }
+ if (psPresentFlag != that.psPresentFlag) {
+ return false;
+ }
+ if (sacPayloadEmbedding != that.sacPayloadEmbedding) {
+ return false;
+ }
+ if (samplingFrequency != that.samplingFrequency) {
+ return false;
+ }
+ if (samplingFrequencyIndex != that.samplingFrequencyIndex) {
+ return false;
+ }
+ if (sbrPresentFlag != that.sbrPresentFlag) {
+ return false;
+ }
+ if (syncExtensionType != that.syncExtensionType) {
+ return false;
+ }
+ if (var_ScalableFlag != that.var_ScalableFlag) {
+ return false;
+ }
+ if (!Arrays.equals(configBytes, that.configBytes)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = configBytes != null ? Arrays.hashCode(configBytes) : 0;
+ result = 31 * result + audioObjectType;
+ result = 31 * result + samplingFrequencyIndex;
+ result = 31 * result + samplingFrequency;
+ result = 31 * result + channelConfiguration;
+ result = 31 * result + extensionAudioObjectType;
+ result = 31 * result + sbrPresentFlag;
+ result = 31 * result + psPresentFlag;
+ result = 31 * result + extensionSamplingFrequencyIndex;
+ result = 31 * result + extensionSamplingFrequency;
+ result = 31 * result + extensionChannelConfiguration;
+ result = 31 * result + sacPayloadEmbedding;
+ result = 31 * result + fillBits;
+ result = 31 * result + epConfig;
+ result = 31 * result + directMapping;
+ result = 31 * result + syncExtensionType;
+ result = 31 * result + frameLengthFlag;
+ result = 31 * result + dependsOnCoreCoder;
+ result = 31 * result + coreCoderDelay;
+ result = 31 * result + extensionFlag;
+ result = 31 * result + layerNr;
+ result = 31 * result + numOfSubFrame;
+ result = 31 * result + layer_length;
+ result = 31 * result + aacSectionDataResilienceFlag;
+ result = 31 * result + aacScalefactorDataResilienceFlag;
+ result = 31 * result + aacSpectralDataResilienceFlag;
+ result = 31 * result + extensionFlag3;
+ result = 31 * result + (gaSpecificConfig ? 1 : 0);
+ result = 31 * result + isBaseLayer;
+ result = 31 * result + paraMode;
+ result = 31 * result + paraExtensionFlag;
+ result = 31 * result + hvxcVarMode;
+ result = 31 * result + hvxcRateMode;
+ result = 31 * result + erHvxcExtensionFlag;
+ result = 31 * result + var_ScalableFlag;
+ result = 31 * result + hilnQuantMode;
+ result = 31 * result + hilnMaxNumLine;
+ result = 31 * result + hilnSampleRateCode;
+ result = 31 * result + hilnFrameLength;
+ result = 31 * result + hilnContMode;
+ result = 31 * result + hilnEnhaLayer;
+ result = 31 * result + hilnEnhaQuantMode;
+ result = 31 * result + (parametricSpecificConfig ? 1 : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BaseDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BaseDescriptor.java
new file mode 100644
index 0000000..6d94680
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BaseDescriptor.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/*
+abstract aligned(8) expandable(228-1) class BaseDescriptor : bit(8) tag=0 {
+// empty. To be filled by classes extending this class.
+}
+
+int sizeOfInstance = 0;
+bit(1) nextByte;
+bit(7) sizeOfInstance;
+while(nextByte) {
+bit(1) nextByte;
+bit(7) sizeByte;
+sizeOfInstance = sizeOfInstance<<7 | sizeByte;
+}
+ */
+@Descriptor(tags = 0x00)
+public abstract class BaseDescriptor {
+ int tag;
+ int sizeOfInstance;
+ int sizeBytes;
+
+ public BaseDescriptor() {
+ }
+
+ public int getTag() {
+ return tag;
+ }
+
+ public int getSize() {
+ return sizeOfInstance
+ + 1//1 for the tag
+ + sizeBytes;
+ }
+
+ public int getSizeOfInstance() {
+ return sizeOfInstance;
+ }
+
+ public int getSizeBytes() {
+ return sizeBytes;
+ }
+
+ public final void parse(int tag, ByteBuffer bb) throws IOException {
+ this.tag = tag;
+
+ int i = 0;
+ int tmp = IsoTypeReader.readUInt8(bb);
+ i++;
+ sizeOfInstance = tmp & 0x7f;
+ while (tmp >>> 7 == 1) { //nextbyte indicator bit
+ tmp = IsoTypeReader.readUInt8(bb);
+ i++;
+ //sizeOfInstance = sizeOfInstance<<7 | sizeByte;
+ sizeOfInstance = sizeOfInstance << 7 | tmp & 0x7f;
+ }
+ sizeBytes = i;
+ ByteBuffer detailSource = bb.slice();
+ detailSource.limit(sizeOfInstance);
+ parseDetail(detailSource);
+ assert detailSource.remaining() == 0: this.getClass().getSimpleName() + " has not been fully parsed";
+ bb.position(bb.position() + sizeOfInstance);
+ }
+
+ public abstract void parseDetail(ByteBuffer bb) throws IOException;
+
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("BaseDescriptor");
+ sb.append("{tag=").append(tag);
+ sb.append(", sizeOfInstance=").append(sizeOfInstance);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitReaderBuffer.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitReaderBuffer.java
new file mode 100644
index 0000000..7221503
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitReaderBuffer.java
@@ -0,0 +1,51 @@
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.nio.ByteBuffer;
+
+public class BitReaderBuffer {
+
+ private ByteBuffer buffer;
+ int initialPos;
+ int position;
+
+ public BitReaderBuffer(ByteBuffer buffer) {
+ this.buffer = buffer;
+ initialPos = buffer.position();
+ }
+
+ public int readBits(int i) {
+ byte b = buffer.get(initialPos + position / 8);
+ int v = b < 0 ? b + 256 : b;
+ int left = 8 - position % 8;
+ int rc;
+ if (i <= left) {
+ rc = (v << (position % 8) & 0xFF) >> ((position % 8) + (left - i));
+ position += i;
+ } else {
+ int now = left;
+ int then = i - left;
+ rc = readBits(now);
+ rc = rc << then;
+ rc += readBits(then);
+ }
+ buffer.position(initialPos + (int) Math.ceil((double) position / 8));
+ return rc;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public int byteSync() {
+ int left = 8 - position % 8;
+ if (left == 8) {
+ left = 0;
+ }
+ readBits(left);
+ return left;
+ }
+
+ public int remainingBits() {
+ return buffer.limit() * 8 - position;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitWriterBuffer.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitWriterBuffer.java
new file mode 100644
index 0000000..e6ea67f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/BitWriterBuffer.java
@@ -0,0 +1,36 @@
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.nio.ByteBuffer;
+
+public class BitWriterBuffer {
+
+ private ByteBuffer buffer;
+ int initialPos;
+ int position = 0;
+
+ public BitWriterBuffer(ByteBuffer buffer) {
+ this.buffer = buffer;
+ this.initialPos = buffer.position();
+ }
+
+ public void writeBits(int i, int numBits) {
+ assert i <= ((1 << numBits)-1): String.format("Trying to write a value bigger (%s) than the number bits (%s) allows. " +
+ "Please mask the value before writing it and make your code is really working as intended.", i, (1<<numBits)-1);
+
+ int left = 8 - position % 8;
+ if (numBits <= left) {
+ int current = (buffer.get(initialPos + position / 8));
+ current = current < 0 ? current + 256 : current;
+ current += i << (left - numBits);
+ buffer.put(initialPos + position / 8, (byte) (current > 127 ? current - 256 : current));
+ position += numBits;
+ } else {
+ int bitsSecondWrite = numBits - left;
+ writeBits(i >> bitsSecondWrite, left);
+ writeBits(i & (1 << bitsSecondWrite) - 1, bitsSecondWrite);
+ }
+ buffer.position(initialPos + position / 8 + ((position % 8 > 0) ? 1 : 0));
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderConfigDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderConfigDescriptor.java
new file mode 100644
index 0000000..69d603a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderConfigDescriptor.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * class DecoderConfigDescriptor extends BaseDescriptor : bit(8)
+ * tag=DecoderConfigDescrTag {
+ * bit(8) objectTypeIndication;
+ * bit(6) streamType;
+ * bit(1) upStream;
+ * const bit(1) reserved=1;
+ * bit(24) bufferSizeDB;
+ * bit(32) maxBitrate;
+ * bit(32) avgBitrate;
+ * DecoderSpecificInfo decSpecificInfo[0 .. 1];
+ * profileLevelIndicationIndexDescriptor profileLevelIndicationIndexDescr
+ * [0..255];
+ * }
+ */
+@Descriptor(tags = {0x04})
+public class DecoderConfigDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(DecoderConfigDescriptor.class.getName());
+
+
+ int objectTypeIndication;
+ int streamType;
+ int upStream;
+ int bufferSizeDB;
+ long maxBitRate;
+ long avgBitRate;
+
+ DecoderSpecificInfo decoderSpecificInfo;
+ AudioSpecificConfig audioSpecificInfo;
+ List<ProfileLevelIndicationDescriptor> profileLevelIndicationDescriptors = new ArrayList<ProfileLevelIndicationDescriptor>();
+ byte[] configDescriptorDeadBytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ objectTypeIndication = IsoTypeReader.readUInt8(bb);
+
+ int data = IsoTypeReader.readUInt8(bb);
+ streamType = data >>> 2;
+ upStream = (data >> 1) & 0x1;
+
+ bufferSizeDB = IsoTypeReader.readUInt24(bb);
+ maxBitRate = IsoTypeReader.readUInt32(bb);
+ avgBitRate = IsoTypeReader.readUInt32(bb);
+
+
+
+ BaseDescriptor descriptor;
+ if (bb.remaining() > 2) { //1byte tag + at least 1byte size
+ final int begin = bb.position();
+ descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
+ final int read = bb.position() - begin;
+ log.finer(descriptor + " - DecoderConfigDescr1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ if (read < size) {
+ //skip
+ configDescriptorDeadBytes = new byte[size - read];
+ bb.get(configDescriptorDeadBytes);
+ }
+ }
+ if (descriptor instanceof DecoderSpecificInfo) {
+ decoderSpecificInfo = (DecoderSpecificInfo) descriptor;
+ }
+ if (descriptor instanceof AudioSpecificConfig) {
+ audioSpecificInfo = (AudioSpecificConfig) descriptor;
+ }
+ }
+
+ while (bb.remaining() > 2) {
+ final long begin = bb.position();
+ descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - DecoderConfigDescr2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor instanceof ProfileLevelIndicationDescriptor) {
+ profileLevelIndicationDescriptors.add((ProfileLevelIndicationDescriptor) descriptor);
+ }
+ }
+ }
+ public int serializedSize() {
+ return 15 + audioSpecificInfo.serializedSize();
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize());
+ IsoTypeWriter.writeUInt8(out, 4);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
+ IsoTypeWriter.writeUInt8(out, objectTypeIndication);
+ int flags = (streamType << 2) | (upStream << 1) | 1;
+ IsoTypeWriter.writeUInt8(out, flags);
+ IsoTypeWriter.writeUInt24(out, bufferSizeDB);
+ IsoTypeWriter.writeUInt32(out, maxBitRate);
+ IsoTypeWriter.writeUInt32(out, avgBitRate);
+ out.put(audioSpecificInfo.serialize().array());
+ return out;
+ }
+
+ public DecoderSpecificInfo getDecoderSpecificInfo() {
+ return decoderSpecificInfo;
+ }
+
+ public AudioSpecificConfig getAudioSpecificInfo() {
+ return audioSpecificInfo;
+ }
+
+ public void setAudioSpecificInfo(AudioSpecificConfig audioSpecificInfo) {
+ this.audioSpecificInfo = audioSpecificInfo;
+ }
+
+ public List<ProfileLevelIndicationDescriptor> getProfileLevelIndicationDescriptors() {
+ return profileLevelIndicationDescriptors;
+ }
+
+ public int getObjectTypeIndication() {
+ return objectTypeIndication;
+ }
+
+ public void setObjectTypeIndication(int objectTypeIndication) {
+ this.objectTypeIndication = objectTypeIndication;
+ }
+
+ public int getStreamType() {
+ return streamType;
+ }
+
+ public void setStreamType(int streamType) {
+ this.streamType = streamType;
+ }
+
+ public int getUpStream() {
+ return upStream;
+ }
+
+ public void setUpStream(int upStream) {
+ this.upStream = upStream;
+ }
+
+ public int getBufferSizeDB() {
+ return bufferSizeDB;
+ }
+
+ public void setBufferSizeDB(int 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;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DecoderConfigDescriptor");
+ sb.append("{objectTypeIndication=").append(objectTypeIndication);
+ sb.append(", streamType=").append(streamType);
+ sb.append(", upStream=").append(upStream);
+ sb.append(", bufferSizeDB=").append(bufferSizeDB);
+ sb.append(", maxBitRate=").append(maxBitRate);
+ sb.append(", avgBitRate=").append(avgBitRate);
+ sb.append(", decoderSpecificInfo=").append(decoderSpecificInfo);
+ sb.append(", audioSpecificInfo=").append(audioSpecificInfo);
+ sb.append(", configDescriptorDeadBytes=").append(Hex.encodeHex(configDescriptorDeadBytes != null ? configDescriptorDeadBytes : new byte[]{}));
+ sb.append(", profileLevelIndicationDescriptors=").append(profileLevelIndicationDescriptors == null ? "null" : Arrays.asList(profileLevelIndicationDescriptors).toString());
+ sb.append('}');
+ return sb.toString();
+ }
+ /*objectTypeIndication values
+ 0x00 Forbidden
+ 0x01 Systems ISO/IEC 14496-1 a
+ 0x02 Systems ISO/IEC 14496-1 b
+ 0x03 Interaction Stream
+ 0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c
+ 0x05 Systems ISO/IEC 14496-1 AFX d
+ 0x06 Font Data Stream
+ 0x07 Synthesized Texture Stream
+ 0x08 Streaming Text Stream
+ 0x09-0x1F reserved for ISO use
+ 0x20 Visual ISO/IEC 14496-2 e
+ 0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+ 0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+ 0x23-0x3F reserved for ISO use
+ 0x40 Audio ISO/IEC 14496-3 g
+ 0x41-0x5F reserved for ISO use
+ 0x60 Visual ISO/IEC 13818-2 Simple Profile
+ 0x61 Visual ISO/IEC 13818-2 Main Profile
+ 0x62 Visual ISO/IEC 13818-2 SNR Profile
+ 0x63 Visual ISO/IEC 13818-2 Spatial Profile
+ 0x64 Visual ISO/IEC 13818-2 High Profile
+ 0x65 Visual ISO/IEC 13818-2 422 Profile
+ 0x66 Audio ISO/IEC 13818-7 Main Profile
+ 0x67 Audio ISO/IEC 13818-7 LowComplexity Profile
+ 0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
+ 0x69 Audio ISO/IEC 13818-3
+ 0x6A Visual ISO/IEC 11172-2
+ 0x6B Audio ISO/IEC 11172-3
+ 0x6C Visual ISO/IEC 10918-1
+ 0x6D reserved for registration authority i
+ 0x6E Visual ISO/IEC 15444-1
+ 0x6F - 0x9F reserved for ISO use
+ 0xA0 - 0xBF reserved for registration authority i
+ 0xC0 - 0xE0 user private
+ 0xE1 reserved for registration authority i
+ 0xE2 - 0xFE user private
+ 0xFF no object type specified h
+ */
+ /* streamType values
+ 0x00 Forbidden
+ 0x01 ObjectDescriptorStream (see 7.2.5)
+ 0x02 ClockReferenceStream (see 7.3.2.5)
+ 0x03 SceneDescriptionStream (see ISO/IEC 14496-11)
+ 0x04 VisualStream
+ 0x05 AudioStream
+ 0x06 MPEG7Stream
+ 0x07 IPMPStream (see 7.2.3.2)
+ 0x08 ObjectContentInfoStream (see 7.2.4.2)
+ 0x09 MPEGJStream
+ 0x0A Interaction Stream
+ 0x0B IPMPToolStream (see [ISO/IEC 14496-13])
+ 0x0C - 0x1F reserved for ISO use
+ 0x20 - 0x3F user private
+ */
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderSpecificInfo.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderSpecificInfo.java
new file mode 100644
index 0000000..574943c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/DecoderSpecificInfo.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * abstract class DecoderSpecificInfo extends BaseDescriptor : bit(8)
+ * tag=DecSpecificInfoTag
+ * {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = 0x05)
+public class DecoderSpecificInfo extends BaseDescriptor {
+ byte[] bytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (sizeOfInstance > 0) {
+ bytes = new byte[sizeOfInstance];
+ bb.get(bytes);
+ }
+ }
+
+ public int serializedSize() {
+ return bytes.length;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.wrap(bytes);
+
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DecoderSpecificInfo");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DecoderSpecificInfo that = (DecoderSpecificInfo) o;
+
+ if (!Arrays.equals(bytes, that.bytes)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return bytes != null ? Arrays.hashCode(bytes) : 0;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/Descriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/Descriptor.java
new file mode 100644
index 0000000..11020c7
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/Descriptor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mstattma
+ * Date: 06.08.2010
+ * Time: 06:54:58
+ * To change this template use File | Settings | File Templates.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Descriptor {
+ int[] tags();
+
+ int objectTypeIndication() default -1;
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ESDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ESDescriptor.java
new file mode 100644
index 0000000..3bb4821
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ESDescriptor.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+/*
+class ES_Descriptor extends BaseDescriptor : bit(8) tag=ES_DescrTag {
+bit(16) ES_ID;
+bit(1) streamDependenceFlag;
+bit(1) URL_Flag;
+bit(1) OCRstreamFlag;
+bit(5) streamPriority;
+if (streamDependenceFlag)
+bit(16) dependsOn_ES_ID;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+}
+if (OCRstreamFlag)
+bit(16) OCR_ES_Id;
+DecoderConfigDescriptor decConfigDescr;
+if (ODProfileLevelIndication==0x01) //no SL extension.
+{
+SLConfigDescriptor slConfigDescr;
+}
+else // SL extension is possible.
+{
+SLConfigDescriptor slConfigDescr;
+}
+IPI_DescrPointer ipiPtr[0 .. 1];
+IP_IdentificationDataSet ipIDS[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+LanguageDescriptor langDescr[0 .. 255];
+QoS_Descriptor qosDescr[0 .. 1];
+RegistrationDescriptor regDescr[0 .. 1];
+ExtensionDescriptor extDescr[0 .. 255];
+}
+ */
+@Descriptor(tags = {0x03})
+public class ESDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(ESDescriptor.class.getName());
+
+ int esId;
+ int streamDependenceFlag;
+ int URLFlag;
+ int oCRstreamFlag;
+ int streamPriority;
+
+
+ int URLLength = 0;
+ String URLString;
+ int remoteODFlag;
+
+ int dependsOnEsId;
+ int oCREsId;
+
+ DecoderConfigDescriptor decoderConfigDescriptor;
+ SLConfigDescriptor slConfigDescriptor;
+ List<BaseDescriptor> otherDescriptors = new ArrayList<BaseDescriptor>();
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ esId = IsoTypeReader.readUInt16(bb);
+
+ int data = IsoTypeReader.readUInt8(bb);
+ streamDependenceFlag = data >>> 7;
+ URLFlag = (data >>> 6) & 0x1;
+ oCRstreamFlag = (data >>> 5) & 0x1;
+ streamPriority = data & 0x1f;
+
+ if (streamDependenceFlag == 1) {
+ dependsOnEsId = IsoTypeReader.readUInt16(bb);
+ }
+ if (URLFlag == 1) {
+ URLLength = IsoTypeReader.readUInt8(bb);
+ URLString = IsoTypeReader.readString(bb, URLLength);
+ }
+ if (oCRstreamFlag == 1) {
+ oCREsId = IsoTypeReader.readUInt16(bb);
+ }
+
+ int baseSize = 1 /*tag*/ + getSizeBytes() + 2 + 1 + (streamDependenceFlag == 1 ? 2 : 0) + (URLFlag == 1 ? 1 + URLLength : 0) + (oCRstreamFlag == 1 ? 2 : 0);
+
+ int begin = bb.position();
+ if (getSize() > baseSize + 2) {
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ if (descriptor instanceof DecoderConfigDescriptor) {
+ decoderConfigDescriptor = (DecoderConfigDescriptor) descriptor;
+ }
+ }
+
+ begin = bb.position();
+ if (getSize() > baseSize + 2) {
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ if (descriptor instanceof SLConfigDescriptor) {
+ slConfigDescriptor = (SLConfigDescriptor) descriptor;
+ }
+ } else {
+ log.warning("SLConfigDescriptor is missing!");
+ }
+
+ while (getSize() - baseSize > 2) {
+ begin = bb.position();
+ BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ final long read = bb.position() - begin;
+ log.finer(descriptor + " - ESDescriptor3 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
+ if (descriptor != null) {
+ final int size = descriptor.getSize();
+ bb.position(begin + size);
+ baseSize += size;
+ } else {
+ baseSize += read;
+ }
+ otherDescriptors.add(descriptor);
+ }
+ }
+ public int serializedSize() {
+ int out = 5;
+ if (streamDependenceFlag > 0) {
+ out += 2;
+ }
+ if (URLFlag > 0) {
+ out += 1 + URLLength;
+ }
+ if (oCRstreamFlag > 0) {
+ out += 2;
+ }
+
+ out += decoderConfigDescriptor.serializedSize();
+ out += slConfigDescriptor.serializedSize();
+
+ // Doesn't handle other descriptors yet
+
+ return out;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(serializedSize()); // Usually is around 30 bytes, so 200 should be enough...
+ IsoTypeWriter.writeUInt8(out, 3);
+ IsoTypeWriter.writeUInt8(out, serializedSize() - 2); // Not OK for longer sizes!
+ IsoTypeWriter.writeUInt16(out, esId);
+ int flags = (streamDependenceFlag << 7) | (URLFlag << 6) | (oCRstreamFlag << 5) | (streamPriority & 0x1f);
+ IsoTypeWriter.writeUInt8(out, flags);
+ if (streamDependenceFlag > 0) {
+ IsoTypeWriter.writeUInt16(out, dependsOnEsId);
+ }
+ if (URLFlag > 0) {
+ IsoTypeWriter.writeUInt8(out, URLLength);
+ IsoTypeWriter.writeUtf8String(out, URLString);
+ }
+ if (oCRstreamFlag > 0) {
+ IsoTypeWriter.writeUInt16(out, oCREsId);
+ }
+
+ ByteBuffer dec = decoderConfigDescriptor.serialize();
+ ByteBuffer sl = slConfigDescriptor.serialize();
+ out.put(dec.array());
+ out.put(sl.array());
+
+ // Doesn't handle other descriptors yet
+
+ return out;
+ }
+
+// @Override
+// public int getSize() {
+// return 3 + (streamDependenceFlag == 1 ? 2 : 0) +
+// (URLFlag == 1 ? 1 + 8 * URLLength : 0) +
+// (oCRstreamFlag == 1 ? 2 : 0);
+// }
+
+ public DecoderConfigDescriptor getDecoderConfigDescriptor() {
+ return decoderConfigDescriptor;
+ }
+
+ public SLConfigDescriptor getSlConfigDescriptor() {
+ return slConfigDescriptor;
+ }
+
+ public void setDecoderConfigDescriptor(DecoderConfigDescriptor decoderConfigDescriptor) {
+ this.decoderConfigDescriptor = decoderConfigDescriptor;
+ }
+
+ public void setSlConfigDescriptor(SLConfigDescriptor slConfigDescriptor) {
+ this.slConfigDescriptor = slConfigDescriptor;
+ }
+
+ public List<BaseDescriptor> getOtherDescriptors() {
+ return otherDescriptors;
+ }
+
+ public int getoCREsId() {
+ return oCREsId;
+ }
+
+ public void setoCREsId(int oCREsId) {
+ this.oCREsId = oCREsId;
+ }
+
+ public int getEsId() {
+ return esId;
+ }
+
+ public void setEsId(int esId) {
+ this.esId = esId;
+ }
+
+ public int getStreamDependenceFlag() {
+ return streamDependenceFlag;
+ }
+
+ public void setStreamDependenceFlag(int streamDependenceFlag) {
+ this.streamDependenceFlag = streamDependenceFlag;
+ }
+
+ public int getURLFlag() {
+ return URLFlag;
+ }
+
+ public void setURLFlag(int URLFlag) {
+ this.URLFlag = URLFlag;
+ }
+
+ public int getoCRstreamFlag() {
+ return oCRstreamFlag;
+ }
+
+ public void setoCRstreamFlag(int oCRstreamFlag) {
+ this.oCRstreamFlag = oCRstreamFlag;
+ }
+
+ public int getStreamPriority() {
+ return streamPriority;
+ }
+
+ public void setStreamPriority(int streamPriority) {
+ this.streamPriority = streamPriority;
+ }
+
+ public int getURLLength() {
+ return URLLength;
+ }
+
+ public void setURLLength(int URLLength) {
+ this.URLLength = URLLength;
+ }
+
+ public String getURLString() {
+ return URLString;
+ }
+
+ public void setURLString(String URLString) {
+ this.URLString = URLString;
+ }
+
+ public int getRemoteODFlag() {
+ return remoteODFlag;
+ }
+
+ public void setRemoteODFlag(int remoteODFlag) {
+ this.remoteODFlag = remoteODFlag;
+ }
+
+ public int getDependsOnEsId() {
+ return dependsOnEsId;
+ }
+
+ public void setDependsOnEsId(int dependsOnEsId) {
+ this.dependsOnEsId = dependsOnEsId;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ESDescriptor");
+ sb.append("{esId=").append(esId);
+ sb.append(", streamDependenceFlag=").append(streamDependenceFlag);
+ sb.append(", URLFlag=").append(URLFlag);
+ sb.append(", oCRstreamFlag=").append(oCRstreamFlag);
+ sb.append(", streamPriority=").append(streamPriority);
+ sb.append(", URLLength=").append(URLLength);
+ sb.append(", URLString='").append(URLString).append('\'');
+ sb.append(", remoteODFlag=").append(remoteODFlag);
+ sb.append(", dependsOnEsId=").append(dependsOnEsId);
+ sb.append(", oCREsId=").append(oCREsId);
+ sb.append(", decoderConfigDescriptor=").append(decoderConfigDescriptor);
+ sb.append(", slConfigDescriptor=").append(slConfigDescriptor);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ESDescriptor that = (ESDescriptor) o;
+
+ if (URLFlag != that.URLFlag) return false;
+ if (URLLength != that.URLLength) return false;
+ if (dependsOnEsId != that.dependsOnEsId) return false;
+ if (esId != that.esId) return false;
+ if (oCREsId != that.oCREsId) return false;
+ if (oCRstreamFlag != that.oCRstreamFlag) return false;
+ if (remoteODFlag != that.remoteODFlag) return false;
+ if (streamDependenceFlag != that.streamDependenceFlag) return false;
+ if (streamPriority != that.streamPriority) return false;
+ if (URLString != null ? !URLString.equals(that.URLString) : that.URLString != null) return false;
+ if (decoderConfigDescriptor != null ? !decoderConfigDescriptor.equals(that.decoderConfigDescriptor) : that.decoderConfigDescriptor != null)
+ return false;
+ if (otherDescriptors != null ? !otherDescriptors.equals(that.otherDescriptors) : that.otherDescriptors != null)
+ return false;
+ if (slConfigDescriptor != null ? !slConfigDescriptor.equals(that.slConfigDescriptor) : that.slConfigDescriptor != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = esId;
+ result = 31 * result + streamDependenceFlag;
+ result = 31 * result + URLFlag;
+ result = 31 * result + oCRstreamFlag;
+ result = 31 * result + streamPriority;
+ result = 31 * result + URLLength;
+ result = 31 * result + (URLString != null ? URLString.hashCode() : 0);
+ result = 31 * result + remoteODFlag;
+ result = 31 * result + dependsOnEsId;
+ result = 31 * result + oCREsId;
+ result = 31 * result + (decoderConfigDescriptor != null ? decoderConfigDescriptor.hashCode() : 0);
+ result = 31 * result + (slConfigDescriptor != null ? slConfigDescriptor.hashCode() : 0);
+ result = 31 * result + (otherDescriptors != null ? otherDescriptors.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionDescriptor.java
new file mode 100644
index 0000000..7933f5a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionDescriptor.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+/**
+ * abstract class ExtensionDescriptor extends BaseDescriptor
+ * : bit(8) tag = ExtensionProfileLevelDescrTag, ExtDescrTagStartRange ..
+ * ExtDescrTagEndRange {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = {0x13, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253})
+public class ExtensionDescriptor extends BaseDescriptor {
+ private static Logger log = Logger.getLogger(ExtensionDescriptor.class.getName());
+
+ byte[] bytes;
+
+
+ //todo: add this better to the tags list?
+ //14496-1:2010 p.20:
+ //0x6A-0xBF Reserved for ISO use
+ //0xC0-0xFE User private
+ //
+ //ExtDescrTagStartRange = 0x6A
+ //ExtDescrTagEndRange = 0xFE
+ static int[] allTags() {
+ int[] ints = new int[0xFE - 0x6A];
+
+ for (int i = 0x6A; i < 0xFE; i++) {
+ final int pos = i - 0x6A;
+ log.finest("pos:" + pos);
+ ints[pos] = i;
+ }
+ return ints;
+ }
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (getSize() > 0) {
+ bytes = new byte[sizeOfInstance];
+ bb.get(bytes);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ExtensionDescriptor");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionProfileLevelDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionProfileLevelDescriptor.java
new file mode 100644
index 0000000..0cf4915
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ExtensionProfileLevelDescriptor.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.Hex;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * abstract class ExtensionDescriptor extends BaseDescriptor
+ * : bit(8) tag = ExtensionProfileLevelDescrTag, ExtDescrTagStartRange ..
+ * ExtDescrTagEndRange {
+ * // empty. To be filled by classes extending this class.
+ * }
+ */
+@Descriptor(tags = {0x13})
+public class ExtensionProfileLevelDescriptor extends BaseDescriptor {
+ byte[] bytes;
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ if (getSize() > 0) {
+ bytes = new byte[getSize()];
+ bb.get(bytes);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ExtensionDescriptor");
+ sb.append("{bytes=").append(bytes == null ? "null" : Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/InitialObjectDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/InitialObjectDescriptor.java
new file mode 100644
index 0000000..7a1f094
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/InitialObjectDescriptor.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+class InitialObjectDescriptor extends ObjectDescriptorBase : bit(8)
+tag=InitialObjectDescrTag {
+bit(10) ObjectDescriptorID;
+bit(1) URL_Flag;
+bit(1) includeInlineProfileLevelFlag;
+const bit(4) reserved=0b1111;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+} else {
+bit(8) ODProfileLevelIndication;
+bit(8) sceneProfileLevelIndication;
+bit(8) audioProfileLevelIndication;
+bit(8) visualProfileLevelIndication;
+bit(8) graphicsProfileLevelIndication;
+ES_Descriptor esDescr[1 .. 255];
+OCI_Descriptor ociDescr[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+IPMP_Descriptor ipmpDescr [0 .. 255];
+IPMP_ToolListDescriptor toolListDescr[0 .. 1];
+}
+ExtensionDescriptor extDescr[0 .. 255];
+}
+*/
+//@Descriptor(tags = {0x02, 0x10})
+public class InitialObjectDescriptor extends ObjectDescriptorBase {
+ private int objectDescriptorId;
+ int urlFlag;
+ int includeInlineProfileLevelFlag;
+
+ int urlLength;
+ String urlString;
+
+ int oDProfileLevelIndication;
+ int sceneProfileLevelIndication;
+ int audioProfileLevelIndication;
+ int visualProfileLevelIndication;
+ int graphicsProfileLevelIndication;
+
+ List<ESDescriptor> esDescriptors = new ArrayList<ESDescriptor>();
+
+ List<ExtensionDescriptor> extensionDescriptors = new ArrayList<ExtensionDescriptor>();
+
+ List<BaseDescriptor> unknownDescriptors = new ArrayList<BaseDescriptor>();
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ int data = IsoTypeReader.readUInt16(bb);
+ objectDescriptorId = (data & 0xFFC0) >> 6;
+
+ urlFlag = (data & 0x3F) >> 5;
+ includeInlineProfileLevelFlag = (data & 0x1F) >> 4;
+
+ int sizeLeft = getSize() - 2;
+ if (urlFlag == 1) {
+ urlLength = IsoTypeReader.readUInt8(bb);
+ urlString = IsoTypeReader.readString(bb, urlLength);
+ sizeLeft = sizeLeft - (1 + urlLength);
+ } else {
+ oDProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ sceneProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ audioProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ visualProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+ graphicsProfileLevelIndication = IsoTypeReader.readUInt8(bb);
+
+ sizeLeft = sizeLeft - 5;
+
+ if (sizeLeft > 2) {
+ final BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ sizeLeft = sizeLeft - descriptor.getSize();
+ if (descriptor instanceof ESDescriptor) {
+ esDescriptors.add((ESDescriptor) descriptor);
+ } else {
+ unknownDescriptors.add(descriptor);
+ }
+ }
+ }
+
+ if (sizeLeft > 2) {
+ final BaseDescriptor descriptor = ObjectDescriptorFactory.createFrom(-1, bb);
+ if (descriptor instanceof ExtensionDescriptor) {
+ extensionDescriptors.add((ExtensionDescriptor) descriptor);
+ } else {
+ unknownDescriptors.add(descriptor);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("InitialObjectDescriptor");
+ sb.append("{objectDescriptorId=").append(objectDescriptorId);
+ sb.append(", urlFlag=").append(urlFlag);
+ sb.append(", includeInlineProfileLevelFlag=").append(includeInlineProfileLevelFlag);
+ sb.append(", urlLength=").append(urlLength);
+ sb.append(", urlString='").append(urlString).append('\'');
+ sb.append(", oDProfileLevelIndication=").append(oDProfileLevelIndication);
+ sb.append(", sceneProfileLevelIndication=").append(sceneProfileLevelIndication);
+ sb.append(", audioProfileLevelIndication=").append(audioProfileLevelIndication);
+ sb.append(", visualProfileLevelIndication=").append(visualProfileLevelIndication);
+ sb.append(", graphicsProfileLevelIndication=").append(graphicsProfileLevelIndication);
+ sb.append(", esDescriptors=").append(esDescriptors);
+ sb.append(", extensionDescriptors=").append(extensionDescriptors);
+ sb.append(", unknownDescriptors=").append(unknownDescriptors);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptor.java_bak b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptor.java_bak
new file mode 100644
index 0000000..c5cb586
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptor.java_bak
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+class ObjectDescriptor extends ObjectDescriptorBase : bit(8) tag=ObjectDescrTag {
+bit(10) ObjectDescriptorID;
+bit(1) URL_Flag;
+const bit(5) reserved=0b1111.1;
+if (URL_Flag) {
+bit(8) URLlength;
+bit(8) URLstring[URLlength];
+} else {
+ES_Descriptor esDescr[1 .. 255];
+OCI_Descriptor ociDescr[0 .. 255];
+IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
+IPMP_Descriptor ipmpDescr [0 .. 255];
+}
+ExtensionDescriptor extDescr[0 .. 255];
+}
+*/
+@Descriptor(tags = {0x01, 0x11})
+public class ObjectDescriptor extends ObjectDescriptorBase {
+ private int objectDescriptorId;
+ int objectDescriptorUrlFlag;
+ int objectDescriptorUrlLength;
+ String objectDescriptorUrlString;
+
+
+ private int streamCount;
+ private int extensionFlag;
+ private List<ESDescriptor> esDescriptors = new ArrayList<ESDescriptor>();
+
+ private int descriptorLength;
+ private List<ExtensionDescriptor> extensionDescriptors = new ArrayList<ExtensionDescriptor>();
+
+ public static ObjectDescriptor createFrom(ByteBuffer in) throws IOException {
+/*
+ tmp = in.readUInt16();
+ esDescriptor.objectDescriptorId = tmp & 0x3f;
+ esDescriptor.objectDescriptorUrlFlag = (tmp >> 5) & 0x1;
+ if (esDescriptor.objectDescriptorUrlFlag == 1) {
+ esDescriptor.objectDescriptorUrlLength = in.readUInt8();
+ esDescriptor.objectDescriptorUrlString = new String(in.read(esDescriptor.objectDescriptorUrlLength));
+ }
+ */
+
+ ObjectDescriptor objectDescriptor = new ObjectDescriptor();
+
+ int data = IsoTypeReader.readUInt16(in);
+
+ objectDescriptor.objectDescriptorId = data & 0xFFC0;
+ objectDescriptor.streamCount = data & 0x3E;
+ objectDescriptor.extensionFlag = data & 0x1;
+
+// for (int i = 0; i < objectDescriptor.streamCount; i++) {
+// objectDescriptor.esDescriptors.add(ESDescriptor.createFrom(in));
+// }
+//
+// if (objectDescriptor.extensionFlag == 1) {
+// objectDescriptor.descriptorLength = in.readUInt8();
+// for (int i = 0; i < objectDescriptor.descriptorLength;) {
+// ExtensionDescriptor extensionDescriptor = ExtensionDescriptor.createFrom(in);
+// objectDescriptor.extensionDescriptors.add(extensionDescriptor);
+// i = i + extensionDescriptor.descriptorDataLength + 1;
+// }
+// }
+
+ return objectDescriptor;
+ }
+
+ @Override
+ public String toString() {
+ return "ObjectDescriptor{" +
+ "objectDescriptorId=" + objectDescriptorId +
+ ", streamCount=" + streamCount +
+ ", extensionFlag=" + extensionFlag +
+ ", esDescriptors=" + esDescriptors +
+ ", descriptorLength=" + descriptorLength +
+ ", extensionDescriptors=" + extensionDescriptors +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorBase.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorBase.java
new file mode 100644
index 0000000..69a8684
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorBase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+/*
+abstract class ObjectDescriptorBase extends BaseDescriptor : bit(8)
+tag=[ObjectDescrTag..InitialObjectDescrTag] {
+// empty. To be filled by classes extending this class.
+}
+ */
+@Descriptor(tags = 0x00)
+public abstract class ObjectDescriptorBase extends BaseDescriptor {
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorFactory.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorFactory.java
new file mode 100644
index 0000000..6afba55
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ObjectDescriptorFactory.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/* class tag values of 14496-1
+0x00 Forbidden
+0x01 ObjectDescrTag
+0x02 InitialObjectDescrTag
+0x03 ES_DescrTag
+0x04 DecoderConfigDescrTag
+0x05 DecSpecificInfoTag
+0x06 SLConfigDescrTag
+0x07 ContentIdentDescrTag
+0x08 SupplContentIdentDescrTag
+0x09 IPI_DescrPointerTag
+0x0A IPMP_DescrPointerTag
+0x0B IPMP_DescrTag
+0x0C QoS_DescrTag
+0x0D RegistrationDescrTag
+0x0E ES_ID_IncTag
+0x0F ES_ID_RefTag
+0x10 MP4_IOD_Tag
+0x11 MP4_OD_Tag
+0x12 IPL_DescrPointerRefTag
+0x13 ExtensionProfileLevelDescrTag
+0x14 profileLevelIndicationIndexDescrTag
+0x15-0x3F Reserved for ISO use
+0x40 ContentClassificationDescrTag
+0x41 KeyWordDescrTag
+0x42 RatingDescrTag
+0x43 LanguageDescrTag
+0x44 ShortTextualDescrTag
+0x45 ExpandedTextualDescrTag
+0x46 ContentCreatorNameDescrTag
+0x47 ContentCreationDateDescrTag
+0x48 OCICreatorNameDescrTag
+0x49 OCICreationDateDescrTag
+0x4A SmpteCameraPositionDescrTag
+0x4B SegmentDescrTag
+0x4C MediaTimeDescrTag
+0x4D-0x5F Reserved for ISO use (OCI extensions)
+0x60 IPMP_ToolsListDescrTag
+0x61 IPMP_ToolTag
+0x62 M4MuxTimingDescrTag
+0x63 M4MuxCodeTableDescrTag
+0x64 ExtSLConfigDescrTag
+0x65 M4MuxBufferSizeDescrTag
+0x66 M4MuxIdentDescrTag
+0x67 DependencyPointerTag
+0x68 DependencyMarkerTag
+0x69 M4MuxChannelDescrTag
+0x6A-0xBF Reserved for ISO use
+0xC0-0xFE User private
+0xFF Forbidden
+ */
+
+/* objectTypeIndication as of 14496-1
+0x00 Forbidden
+0x01 Systems ISO/IEC 14496-1 a
+0x02 Systems ISO/IEC 14496-1 b
+0x03 Interaction Stream
+0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c
+0x05 Systems ISO/IEC 14496-1 AFX d
+0x06 Font Data Stream
+0x07 Synthesized Texture Stream
+0x08 Streaming Text Stream
+0x09-0x1F reserved for ISO use
+0x20 Visual ISO/IEC 14496-2 e
+0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
+0x23-0x3F reserved for ISO use
+0x40 Audio ISO/IEC 14496-3 g
+0x41-0x5F reserved for ISO use
+0x60 Visual ISO/IEC 13818-2 Simple Profile
+0x61 Visual ISO/IEC 13818-2 Main Profile
+0x62 Visual ISO/IEC 13818-2 SNR Profile
+0x63 Visual ISO/IEC 13818-2 Spatial Profile
+0x64 Visual ISO/IEC 13818-2 High Profile
+0x65 Visual ISO/IEC 13818-2 422 Profile
+0x66 Audio ISO/IEC 13818-7 Main Profile
+0x67 Audio ISO/IEC 13818-7 LowComplexity Profile
+0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
+0x69 Audio ISO/IEC 13818-3
+0x6A Visual ISO/IEC 11172-2
+0x6B Audio ISO/IEC 11172-3
+0x6C Visual ISO/IEC 10918-1
+0x6D reserved for registration authority
+0x6E Visual ISO/IEC 15444-1
+0x6F - 0x9F reserved for ISO use
+0xA0 - 0xBF reserved for registration authority i
+0xC0 - 0xE0 user private
+0xE1 reserved for registration authority i
+0xE2 - 0xFE user private
+0xFF no object type specified h
+ */
+public class ObjectDescriptorFactory {
+ protected static Logger log = Logger.getLogger(ObjectDescriptorFactory.class.getName());
+
+ protected static Map<Integer, Map<Integer, Class<? extends BaseDescriptor>>> descriptorRegistry = new HashMap<Integer, Map<Integer, Class<? extends BaseDescriptor>>>();
+
+ static {
+ Set<Class<? extends BaseDescriptor>> annotated = new HashSet<Class<? extends BaseDescriptor>>();
+
+ annotated.add(DecoderSpecificInfo.class);
+ annotated.add(SLConfigDescriptor.class);
+ annotated.add(BaseDescriptor.class);
+ annotated.add(ExtensionDescriptor.class);
+ annotated.add(ObjectDescriptorBase.class);
+ annotated.add(ProfileLevelIndicationDescriptor.class);
+ annotated.add(AudioSpecificConfig.class);
+ annotated.add(ExtensionProfileLevelDescriptor.class);
+ annotated.add(ESDescriptor.class);
+ annotated.add(DecoderConfigDescriptor.class);
+ //annotated.add(ObjectDescriptor.class);
+
+ for (Class<? extends BaseDescriptor> clazz : annotated) {
+ final Descriptor descriptor = clazz.getAnnotation(Descriptor.class);
+ final int[] tags = descriptor.tags();
+ final int objectTypeInd = descriptor.objectTypeIndication();
+
+ Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeInd);
+ if (tagMap == null) {
+ tagMap = new HashMap<Integer, Class<? extends BaseDescriptor>>();
+ }
+ for (int tag : tags) {
+ tagMap.put(tag, clazz);
+ }
+ descriptorRegistry.put(objectTypeInd, tagMap);
+ }
+ }
+
+ public static BaseDescriptor createFrom(int objectTypeIndication, ByteBuffer bb) throws IOException {
+ int tag = IsoTypeReader.readUInt8(bb);
+
+ Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeIndication);
+ if (tagMap == null) {
+ tagMap = descriptorRegistry.get(-1);
+ }
+ Class<? extends BaseDescriptor> aClass = tagMap.get(tag);
+
+// if (tag == 0x00) {
+// log.warning("Found illegal tag 0x00! objectTypeIndication " + Integer.toHexString(objectTypeIndication) +
+// " and tag " + Integer.toHexString(tag) + " using: " + aClass);
+// aClass = BaseDescriptor.class;
+// }
+
+ BaseDescriptor baseDescriptor;
+ if (aClass == null || aClass.isInterface() || Modifier.isAbstract(aClass.getModifiers())) {
+ log.warning("No ObjectDescriptor found for objectTypeIndication " + Integer.toHexString(objectTypeIndication) +
+ " and tag " + Integer.toHexString(tag) + " found: " + aClass);
+ baseDescriptor = new UnknownDescriptor();
+ } else {
+ try {
+ baseDescriptor = aClass.newInstance();
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "Couldn't instantiate BaseDescriptor class " + aClass + " for objectTypeIndication " + objectTypeIndication + " and tag " + tag, e);
+ throw new RuntimeException(e);
+ }
+ }
+ baseDescriptor.parse(tag, bb);
+ return baseDescriptor;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ProfileLevelIndicationDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ProfileLevelIndicationDescriptor.java
new file mode 100644
index 0000000..625277e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/ProfileLevelIndicationDescriptor.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * class ProfileLevelIndicationIndexDescriptor () extends BaseDescriptor
+ * : bit(8) ProfileLevelIndicationIndexDescrTag {
+ * bit(8) profileLevelIndicationIndex;
+ * }
+ */
+@Descriptor(tags = 0x14)
+public class ProfileLevelIndicationDescriptor extends BaseDescriptor {
+ int profileLevelIndicationIndex;
+
+ @Override
+ public void parseDetail( ByteBuffer bb) throws IOException {
+ profileLevelIndicationIndex = IsoTypeReader.readUInt8(bb);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ProfileLevelIndicationDescriptor");
+ sb.append("{profileLevelIndicationIndex=").append(Integer.toHexString(profileLevelIndicationIndex));
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ProfileLevelIndicationDescriptor that = (ProfileLevelIndicationDescriptor) o;
+
+ if (profileLevelIndicationIndex != that.profileLevelIndicationIndex) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return profileLevelIndicationIndex;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/SLConfigDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/SLConfigDescriptor.java
new file mode 100644
index 0000000..70a58e6
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/SLConfigDescriptor.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * class SLConfigDescriptor extends BaseDescriptor : bit(8) tag=SLConfigDescrTag {
+ * bit(8) predefined;
+ * if (predefined==0) {
+ * bit(1) useAccessUnitStartFlag;
+ * bit(1) useAccessUnitEndFlag;
+ * bit(1) useRandomAccessPointFlag;
+ * bit(1) hasRandomAccessUnitsOnlyFlag;
+ * bit(1) usePaddingFlag;
+ * bit(1) useTimeStampsFlag;
+ * bit(1) useIdleFlag;
+ * bit(1) durationFlag;
+ * bit(32) timeStampResolution;
+ * bit(32) OCRResolution;
+ * bit(8) timeStampLength; // must be ≤ 64
+ * bit(8) OCRLength; // must be ≤ 64
+ * bit(8) AU_Length; // must be ≤ 32
+ * bit(8) instantBitrateLength;
+ * bit(4) degradationPriorityLength;
+ * bit(5) AU_seqNumLength; // must be ≤ 16
+ * bit(5) packetSeqNumLength; // must be ≤ 16
+ * bit(2) reserved=0b11;
+ * }
+ * if (durationFlag) {
+ * bit(32) timeScale;
+ * bit(16) accessUnitDuration;
+ * bit(16) compositionUnitDuration;
+ * }
+ * if (!useTimeStampsFlag) {
+ * bit(timeStampLength) startDecodingTimeStamp;
+ * bit(timeStampLength) startCompositionTimeStamp;
+ * }
+ * }
+ */
+@Descriptor(tags = {0x06})
+public class SLConfigDescriptor extends BaseDescriptor {
+ int predefined;
+
+ public int getPredefined() {
+ return predefined;
+ }
+
+ public void setPredefined(int predefined) {
+ this.predefined = predefined;
+ }
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ predefined = IsoTypeReader.readUInt8(bb);
+ }
+
+ public int serializedSize() {
+ return 3;
+ }
+
+ public ByteBuffer serialize() {
+ ByteBuffer out = ByteBuffer.allocate(3);
+ IsoTypeWriter.writeUInt8(out, 6);
+ IsoTypeWriter.writeUInt8(out, 1);
+ IsoTypeWriter.writeUInt8(out, predefined);
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("SLConfigDescriptor");
+ sb.append("{predefined=").append(predefined);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SLConfigDescriptor that = (SLConfigDescriptor) o;
+
+ if (predefined != that.predefined) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return predefined;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/UnknownDescriptor.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/UnknownDescriptor.java
new file mode 100644
index 0000000..dd75a0f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/objectdescriptors/UnknownDescriptor.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+public class UnknownDescriptor extends BaseDescriptor {
+ private ByteBuffer data;
+ private static Logger log = Logger.getLogger(UnknownDescriptor.class.getName());
+
+ @Override
+ public void parseDetail(ByteBuffer bb) throws IOException {
+ data = (ByteBuffer) bb.slice().limit(this.getSizeOfInstance());
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("UnknownDescriptor");
+ sb.append("{tag=").append(tag);
+ sb.append(", sizeOfInstance=").append(sizeOfInstance);
+ sb.append(", data=").append(data);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/all-wcprops
new file mode 100644
index 0000000..7ac0085
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/all-wcprops
@@ -0,0 +1,59 @@
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping
+END
+RateShareEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RateShareEntry.java
+END
+UnknownEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 115
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/UnknownEntry.java
+END
+VisualRandomAccessEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/VisualRandomAccessEntry.java
+END
+RollRecoveryEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RollRecoveryEntry.java
+END
+SampleToGroupBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 119
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleToGroupBox.java
+END
+CencSampleEncryptionInformationGroupEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 144
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/CencSampleEncryptionInformationGroupEntry.java
+END
+SampleGroupDescriptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 128
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleGroupDescriptionBox.java
+END
+TemporalLevelEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/svn/!svn/ver/770/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/TemporalLevelEntry.java
+END
+GroupEntry.java
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/svn/!svn/ver/726/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/GroupEntry.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/entries
new file mode 100644
index 0000000..05c761e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/entries
@@ -0,0 +1,334 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+RateShareEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+800d0a2f813152ba00d293052be8b937
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8043
+
+UnknownEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+92c8a49a5fb8f163a1a38714e8776de1
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2046
+
+VisualRandomAccessEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+544b84d4026c3b8926ba2a44b11ebfcb
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3781
+
+RollRecoveryEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+9233a1017082e95aff5d23c84d635589
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2417
+
+SampleToGroupBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+5eca2acada7e010970a7037166d46bc1
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5685
+
+CencSampleEncryptionInformationGroupEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+fc1a2ad8992cd88b104626d531df492b
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3641
+
+SampleGroupDescriptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+07cd2c76b48eea326d9865d4ba5320e3
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7107
+
+TemporalLevelEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+4657c50c8e3abaf12747fc9413eb83a0
+2012-08-31T05:20:57.236953Z
+770
+michael.stattmann@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3101
+
+GroupEntry.java
+file
+
+
+
+
+2012-09-14T17:27:51.127228Z
+a699e1a559c1de4043b594f65d462a82
+2012-07-31T09:37:53.699964Z
+726
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+877
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/CencSampleEncryptionInformationGroupEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/CencSampleEncryptionInformationGroupEntry.java.svn-base
new file mode 100644
index 0000000..b54f4d9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/CencSampleEncryptionInformationGroupEntry.java.svn-base
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * Each sample in a protected track shall be associated with an IsEncrypted flag, IV_Size, and KID.
+ * This can be accomplished by (a) relying on the default values in the TrackEncryptionBox
+ * (see 8.2), or (b) specifying the parameters by sample group, or (c) using a combination of these two techniques.
+ * <p/>
+ * When specifying the parameters by sample group, the SampleToGroupBox in the sample table or track
+ * fragment specifies which samples use which sample group description from the SampleGroupDescriptionBox.
+ */
+public class CencSampleEncryptionInformationGroupEntry extends GroupEntry {
+ public static final String TYPE = "seig";
+
+ private int isEncrypted;
+ private byte ivSize;
+ private byte[] kid = new byte[16];
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ isEncrypted = IsoTypeReader.readUInt24(byteBuffer);
+ ivSize = (byte) IsoTypeReader.readUInt8(byteBuffer);
+ kid = new byte[16];
+ byteBuffer.get(kid);
+
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer byteBuffer = ByteBuffer.allocate(20);
+ IsoTypeWriter.writeUInt24(byteBuffer, isEncrypted);
+ IsoTypeWriter.writeUInt8(byteBuffer, ivSize);
+ byteBuffer.put(kid);
+ byteBuffer.rewind();
+ return byteBuffer;
+ }
+
+ public int getEncrypted() {
+ return isEncrypted;
+ }
+
+ public void setEncrypted(int encrypted) {
+ isEncrypted = encrypted;
+ }
+
+ public byte getIvSize() {
+ return ivSize;
+ }
+
+ public void setIvSize(byte ivSize) {
+ this.ivSize = ivSize;
+ }
+
+ public byte[] getKid() {
+ return kid;
+ }
+
+ public void setKid(byte[] kid) {
+ assert kid.length == 16;
+ this.kid = kid;
+ }
+
+ @Override
+ public String toString() {
+ return "CencSampleEncryptionInformationGroupEntry{" +
+ "isEncrypted=" + isEncrypted +
+ ", ivSize=" + ivSize +
+ ", kid=" + Hex.encodeHex(kid) +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ CencSampleEncryptionInformationGroupEntry that = (CencSampleEncryptionInformationGroupEntry) o;
+
+ if (isEncrypted != that.isEncrypted) {
+ return false;
+ }
+ if (ivSize != that.ivSize) {
+ return false;
+ }
+ if (!Arrays.equals(kid, that.kid)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = isEncrypted;
+ result = 31 * result + (int) ivSize;
+ result = 31 * result + (kid != null ? Arrays.hashCode(kid) : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/GroupEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/GroupEntry.java.svn-base
new file mode 100644
index 0000000..0d78d25
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/GroupEntry.java.svn-base
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+public abstract class GroupEntry {
+ public abstract void parse(ByteBuffer byteBuffer);
+ public abstract ByteBuffer get();
+
+ public int size() {
+ return get().limit();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RateShareEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RateShareEntry.java.svn-base
new file mode 100644
index 0000000..ae5d380
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RateShareEntry.java.svn-base
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * Each sample of a track may be associated to (zero or) one of a number of sample group descriptions, each of
+ * which defines a record of rate-share information. Typically the same rate-share information applies to many
+ * consecutive samples and it may therefore be enough to define two or three sample group descriptions that
+ * can be used at different time intervals.
+ * <p/>
+ * The grouping type 'rash' (short for rate share) is defined as the grouping criterion for rate share information.
+ * Zero or one sample-to-group box ('sbgp') for the grouping type 'rash' can be contained in the sample
+ * table box ('stbl') of a track. It shall reside in a hint track, if a hint track is used, otherwise in a media track.
+ * <p/>
+ * Target rate share may be specified for several operation points that are defined in terms of the total available
+ * bitrate, i.e., the bitrate that should be shared. If only one operation point is defined, the target rate share
+ * applies to all available bitrates. If several operation points are defined, then each operation point specifies a
+ * target rate share. Target rate share values specified for the first and the last operation points also specify the
+ * target rate share values at lower and higher available bitrates, respectively. The target rate share between two
+ * operation points is specified to be in the range between the target rate shares of those operation points. One
+ * possibility is to estimate with linear interpolation.
+ */
+public class RateShareEntry extends GroupEntry {
+ public static final String TYPE = "rash";
+
+ private short operationPointCut;
+ private short targetRateShare;
+ private List<Entry> entries = new LinkedList<Entry>();
+ private int maximumBitrate;
+ private int minimumBitrate;
+ private short discardPriority;
+
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ operationPointCut = byteBuffer.getShort();
+ if (operationPointCut == 1) {
+ targetRateShare = byteBuffer.getShort();
+ } else {
+ int entriesLeft = operationPointCut;
+ while (entriesLeft-- > 0) {
+ entries.add(new Entry(l2i(IsoTypeReader.readUInt32(byteBuffer)), byteBuffer.getShort()));
+ }
+ }
+ maximumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
+ minimumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
+ discardPriority = (short) IsoTypeReader.readUInt8(byteBuffer);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer buf = ByteBuffer.allocate(operationPointCut == 1?13:(operationPointCut * 6 + 11 ));
+ buf.putShort(operationPointCut);
+ if (operationPointCut == 1) {
+ buf.putShort(targetRateShare );
+ } else {
+ for (Entry entry : entries) {
+ buf.putInt(entry.getAvailableBitrate());
+ buf.putShort(entry.getTargetRateShare());
+ }
+ }
+ buf.putInt(maximumBitrate);
+ buf.putInt(minimumBitrate);
+ IsoTypeWriter.writeUInt8(buf, discardPriority);
+ buf.rewind();
+ return buf;
+ }
+
+ public static class Entry {
+ public Entry(int availableBitrate, short targetRateShare) {
+ this.availableBitrate = availableBitrate;
+ this.targetRateShare = targetRateShare;
+ }
+
+ int availableBitrate;
+ short targetRateShare;
+
+ @Override
+ public String toString() {
+ return "{" +
+ "availableBitrate=" + availableBitrate +
+ ", targetRateShare=" + targetRateShare +
+ '}';
+ }
+
+ public int getAvailableBitrate() {
+ return availableBitrate;
+ }
+
+ public void setAvailableBitrate(int availableBitrate) {
+ this.availableBitrate = availableBitrate;
+ }
+
+ public short getTargetRateShare() {
+ return targetRateShare;
+ }
+
+ public void setTargetRateShare(short targetRateShare) {
+ this.targetRateShare = targetRateShare;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (availableBitrate != entry.availableBitrate) {
+ return false;
+ }
+ if (targetRateShare != entry.targetRateShare) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = availableBitrate;
+ result = 31 * result + (int) targetRateShare;
+ return result;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ RateShareEntry that = (RateShareEntry) o;
+
+ if (discardPriority != that.discardPriority) {
+ return false;
+ }
+ if (maximumBitrate != that.maximumBitrate) {
+ return false;
+ }
+ if (minimumBitrate != that.minimumBitrate) {
+ return false;
+ }
+ if (operationPointCut != that.operationPointCut) {
+ return false;
+ }
+ if (targetRateShare != that.targetRateShare) {
+ return false;
+ }
+ if (entries != null ? !entries.equals(that.entries) : that.entries != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) operationPointCut;
+ result = 31 * result + (int) targetRateShare;
+ result = 31 * result + (entries != null ? entries.hashCode() : 0);
+ result = 31 * result + maximumBitrate;
+ result = 31 * result + minimumBitrate;
+ result = 31 * result + (int) discardPriority;
+ return result;
+ }
+
+ public short getOperationPointCut() {
+ return operationPointCut;
+ }
+
+ public void setOperationPointCut(short operationPointCut) {
+ this.operationPointCut = operationPointCut;
+ }
+
+ public short getTargetRateShare() {
+ return targetRateShare;
+ }
+
+ public void setTargetRateShare(short targetRateShare) {
+ this.targetRateShare = targetRateShare;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public int getMaximumBitrate() {
+ return maximumBitrate;
+ }
+
+ public void setMaximumBitrate(int maximumBitrate) {
+ this.maximumBitrate = maximumBitrate;
+ }
+
+ public int getMinimumBitrate() {
+ return minimumBitrate;
+ }
+
+ public void setMinimumBitrate(int minimumBitrate) {
+ this.minimumBitrate = minimumBitrate;
+ }
+
+ public short getDiscardPriority() {
+ return discardPriority;
+ }
+
+ public void setDiscardPriority(short discardPriority) {
+ this.discardPriority = discardPriority;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RollRecoveryEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RollRecoveryEntry.java.svn-base
new file mode 100644
index 0000000..bd5b89e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/RollRecoveryEntry.java.svn-base
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+/**
+ * roll_distance is a signed integer that gives the number of samples that must be decoded in order for
+ * a sample to be decoded correctly. A positive value indicates the number of samples after the sample
+ * that is a group member that must be decoded such that at the last of these recovery is complete, i.e.
+ * the last sample is correct. A negative value indicates the number of samples before the sample that is
+ * a group member that must be decoded in order for recovery to be complete at the marked sample.
+ * The value zero must not be used; the sync sample table documents random access points for which
+ * no recovery roll is needed.
+ */
+public class RollRecoveryEntry extends GroupEntry {
+ public static final String TYPE = "roll";
+ private short rollDistance;
+
+ public short getRollDistance() {
+ return rollDistance;
+ }
+
+ public void setRollDistance(short rollDistance) {
+ this.rollDistance = rollDistance;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ rollDistance = byteBuffer.getShort();
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(2);
+ content.putShort(rollDistance);
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ RollRecoveryEntry entry = (RollRecoveryEntry) o;
+
+ if (rollDistance != entry.rollDistance) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) rollDistance;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleGroupDescriptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleGroupDescriptionBox.java.svn-base
new file mode 100644
index 0000000..df4a96f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleGroupDescriptionBox.java.svn-base
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+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;
+
+/**
+ * This description table gives information about the characteristics of sample groups. The descriptive
+ * information is any other information needed to define or characterize the sample group.
+ * <p/>
+ * There may be multiple instances of this box if there is more than one sample grouping for the samples in a
+ * track. Each instance of the SampleGroupDescription box has a type code that distinguishes different
+ * sample groupings. Within a track, there shall be at most one instance of this box with a particular grouping
+ * type. The associated SampleToGroup shall indicate the same value for the grouping type.
+ * <p/>
+ * The information is stored in the sample group description box after the entry-count. An abstract entry type is
+ * defined and sample groupings shall define derived types to represent the description of each sample group.
+ * For video tracks, an abstract VisualSampleGroupEntry is used with similar types for audio and hint tracks.
+ */
+public class SampleGroupDescriptionBox extends AbstractFullBox {
+ public static final String TYPE = "sgpd";
+
+ private String groupingType;
+ private int defaultLength;
+ private List<GroupEntry> groupEntries = new LinkedList<GroupEntry>();
+ private int descriptionLength;
+
+ public SampleGroupDescriptionBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 8;
+ if (getVersion() == 1) {
+ size += 4;
+ }
+ size += 4; // entryCount
+ for (GroupEntry groupEntry : groupEntries) {
+ if (getVersion() == 1 && defaultLength == 0) {
+ size += 4;
+ }
+ size += groupEntry.size();
+ }
+ return size;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(groupingType.getBytes());
+ if (this.getVersion() == 1) {
+ IsoTypeWriter.writeUInt32(byteBuffer, defaultLength);
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, this.groupEntries.size());
+ for (GroupEntry entry : groupEntries) {
+ if (this.getVersion() == 1 && defaultLength == 0) {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.get().limit());
+ }
+ byteBuffer.put(entry.get());
+ }
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ if (this.getVersion() != 1) {
+ throw new RuntimeException("SampleGroupDescriptionBox are only supported in version 1");
+ }
+ groupingType = IsoTypeReader.read4cc(content);
+ if (this.getVersion() == 1) {
+ defaultLength = l2i(IsoTypeReader.readUInt32(content));
+ }
+ long entryCount = IsoTypeReader.readUInt32(content);
+ while (entryCount-- > 0) {
+ int length = defaultLength;
+ if (this.getVersion() == 1) {
+ if (defaultLength == 0) {
+ descriptionLength = l2i(IsoTypeReader.readUInt32(content));
+ length = descriptionLength;
+ }
+ } else {
+ throw new RuntimeException("This should be implemented");
+ }
+ int finalPos = content.position() + length;
+ ByteBuffer parseMe = content.slice();
+ parseMe.limit(length);
+ groupEntries.add(parseGroupEntry(parseMe, groupingType));
+ content.position(finalPos);
+ }
+
+ }
+
+ private GroupEntry parseGroupEntry(ByteBuffer content, String groupingType) {
+ GroupEntry groupEntry;
+ if (RollRecoveryEntry.TYPE.equals(groupingType)) {
+ groupEntry = new RollRecoveryEntry();
+ } else if (RateShareEntry.TYPE.equals(groupingType)) {
+ groupEntry = new RateShareEntry();
+ } else if (CencSampleEncryptionInformationGroupEntry.TYPE.equals(groupingType)) {
+ groupEntry = new CencSampleEncryptionInformationGroupEntry();
+ } else if (VisualRandomAccessEntry.TYPE.equals(groupingType)) {
+ groupEntry = new VisualRandomAccessEntry();
+ } else if (TemporalLevelEntry.TYPE.equals(groupingType)) {
+ groupEntry = new TemporalLevelEntry();
+ } else {
+ groupEntry = new UnknownEntry();
+ }
+ groupEntry.parse(content);
+ return groupEntry;
+ }
+
+
+ public String getGroupingType() {
+ return groupingType;
+ }
+
+ public void setGroupingType(String groupingType) {
+ this.groupingType = groupingType;
+ }
+
+ public int getDefaultLength() {
+ return defaultLength;
+ }
+
+ public void setDefaultLength(int defaultLength) {
+ this.defaultLength = defaultLength;
+ }
+
+ public List<GroupEntry> getGroupEntries() {
+ return groupEntries;
+ }
+
+ public void setGroupEntries(List<GroupEntry> groupEntries) {
+ this.groupEntries = groupEntries;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SampleGroupDescriptionBox that = (SampleGroupDescriptionBox) o;
+
+ if (defaultLength != that.defaultLength) {
+ return false;
+ }
+ if (groupEntries != null ? !groupEntries.equals(that.groupEntries) : that.groupEntries != null) {
+ return false;
+ }
+ if (groupingType != null ? !groupingType.equals(that.groupingType) : that.groupingType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupingType != null ? groupingType.hashCode() : 0;
+ result = 31 * result + defaultLength;
+ result = 31 * result + (groupEntries != null ? groupEntries.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "SampleGroupDescriptionBox{" +
+ "groupingType='" + groupingType + '\'' +
+ ", defaultLength=" + defaultLength +
+ ", groupEntries=" + groupEntries +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleToGroupBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleToGroupBox.java.svn-base
new file mode 100644
index 0000000..0fa059e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/SampleToGroupBox.java.svn-base
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+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;
+
+/**
+ * This table can be used to find the group that a sample belongs to and the associated description of that
+ * sample group. The table is compactly coded with each entry giving the index of the first sample of a run of
+ * samples with the same sample group descriptor. The sample group description ID is an index that refers to a
+ * SampleGroupDescription box, which contains entries describing the characteristics of each sample group.
+ * <p/>
+ * There may be multiple instances of this box if there is more than one sample grouping for the samples in a
+ * track. Each instance of the SampleToGroup box has a type code that distinguishes different sample
+ * groupings. Within a track, there shall be at most one instance of this box with a particular grouping type. The
+ * associated SampleGroupDescription shall indicate the same value for the grouping type.
+ * <p/>
+ * Version 1 of this box should only be used if a grouping type parameter is needed.
+ */
+public class SampleToGroupBox extends AbstractFullBox {
+ public static final String TYPE = "sbgp";
+
+
+ private String groupingType;
+ private String groupingTypeParameter;
+
+ List<Entry> entries = new LinkedList<Entry>();
+
+ public SampleToGroupBox() {
+ super(TYPE);
+
+ }
+
+ @Override
+ protected long getContentSize() {
+ return this.getVersion() == 1 ? entries.size() * 8 + 16 : entries.size() * 8 + 12;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(groupingType.getBytes());
+ if (this.getVersion() == 1) {
+ byteBuffer.put(groupingTypeParameter.getBytes());
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleCount());
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getGroupDescriptionIndex());
+ }
+
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ groupingType = IsoTypeReader.read4cc(content);
+ if (this.getVersion() == 1) {
+ groupingTypeParameter = IsoTypeReader.read4cc(content);
+ }
+ long entryCount = IsoTypeReader.readUInt32(content);
+ while (entryCount-- > 0) {
+ entries.add(new Entry(l2i(IsoTypeReader.readUInt32(content)), l2i(IsoTypeReader.readUInt32(content))));
+ }
+ }
+
+ public static class Entry {
+ private long sampleCount;
+ private int groupDescriptionIndex;
+
+ public Entry(long sampleCount, int groupDescriptionIndex) {
+ this.sampleCount = sampleCount;
+ this.groupDescriptionIndex = groupDescriptionIndex;
+ }
+
+ public long getSampleCount() {
+ return sampleCount;
+ }
+
+ public void setSampleCount(long sampleCount) {
+ this.sampleCount = sampleCount;
+ }
+
+ public int getGroupDescriptionIndex() {
+ return groupDescriptionIndex;
+ }
+
+ public void setGroupDescriptionIndex(int groupDescriptionIndex) {
+ this.groupDescriptionIndex = groupDescriptionIndex;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "sampleCount=" + sampleCount +
+ ", groupDescriptionIndex=" + groupDescriptionIndex +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (groupDescriptionIndex != entry.groupDescriptionIndex) {
+ return false;
+ }
+ if (sampleCount != entry.sampleCount) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (sampleCount ^ (sampleCount >>> 32));
+ result = 31 * result + groupDescriptionIndex;
+ return result;
+ }
+ }
+
+ public String getGroupingType() {
+ return groupingType;
+ }
+
+ public void setGroupingType(String groupingType) {
+ this.groupingType = groupingType;
+ }
+
+ public String getGroupingTypeParameter() {
+ return groupingTypeParameter;
+ }
+
+ public void setGroupingTypeParameter(String groupingTypeParameter) {
+ this.groupingTypeParameter = groupingTypeParameter;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/TemporalLevelEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/TemporalLevelEntry.java.svn-base
new file mode 100644
index 0000000..798fd9c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/TemporalLevelEntry.java.svn-base
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The Temporal Level sample grouping ('tele') provides a codec-independent sample grouping that can be used to group samples (access units) in a track (and potential track fragments) according to temporal level, where samples of one temporal level have no coding dependencies on samples of higher temporal levels. The temporal level equals the sample group description index (taking values 1, 2, 3, etc). The bitstream containing only the access units from the first temporal level to a higher temporal level remains conforming to the coding standard.
+ *
+ * A grouping according to temporal level facilitates easy extraction of temporal subsequences, for instance using the Subsegment Indexing box in 0.
+ *
+ */
+public class TemporalLevelEntry extends GroupEntry {
+ public static final String TYPE = "tele";
+ private boolean levelIndependentlyDecodable;
+ private short reserved;
+
+ public boolean isLevelIndependentlyDecodable() {
+ return levelIndependentlyDecodable;
+ }
+
+ public void setLevelIndependentlyDecodable(boolean levelIndependentlyDecodable) {
+ this.levelIndependentlyDecodable = levelIndependentlyDecodable;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ final byte b = byteBuffer.get();
+ levelIndependentlyDecodable = ((b & 0x80) == 0x80);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(1);
+ content.put((byte) (levelIndependentlyDecodable ? 0x80 : 0x00));
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ TemporalLevelEntry that = (TemporalLevelEntry) o;
+
+ if (levelIndependentlyDecodable != that.levelIndependentlyDecodable) return false;
+ if (reserved != that.reserved) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (levelIndependentlyDecodable ? 1 : 0);
+ result = 31 * result + (int) reserved;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TemporalLevelEntry");
+ sb.append("{levelIndependentlyDecodable=").append(levelIndependentlyDecodable);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/UnknownEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/UnknownEntry.java.svn-base
new file mode 100644
index 0000000..9efcbea
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/UnknownEntry.java.svn-base
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.Hex;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public class UnknownEntry extends GroupEntry {
+ private ByteBuffer content;
+
+ public UnknownEntry() {
+ }
+
+ public ByteBuffer getContent() {
+ return content;
+ }
+
+ public void setContent(ByteBuffer content) {
+ this.content = (ByteBuffer) content.duplicate().rewind();
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ this.content = (ByteBuffer) byteBuffer.duplicate().rewind();
+ }
+
+ @Override
+ public ByteBuffer get() {
+ return content.duplicate();
+ }
+
+ @Override
+ public String toString() {
+ ByteBuffer bb = content.duplicate();
+ bb.rewind();
+ byte[] b = new byte[bb.limit()];
+ bb.get(b);
+ return "UnknownEntry{" +
+ "content=" + Hex.encodeHex(b) +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ UnknownEntry that = (UnknownEntry) o;
+
+ if (content != null ? !content.equals(that.content) : that.content != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return content != null ? content.hashCode() : 0;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/VisualRandomAccessEntry.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/VisualRandomAccessEntry.java.svn-base
new file mode 100644
index 0000000..ed5d199
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/.svn/text-base/VisualRandomAccessEntry.java.svn-base
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.nio.ByteBuffer;
+
+/**
+ * For some coding systems a sync sample is specified to be a random access point after which all samples in decoding order can be correctly decoded. However, it may be possible to encode an “open” random access point, after which all samples in output order can be correctly decoded, but some samples following the random access point in decoding order and preceding the random access point in output order need not be correctly decodable. For example, an intra picture starting an open group of pictures can be followed in decoding order by (bi-)predicted pictures that however precede the intra picture in output order; though they possibly cannot be correctly decoded if the decoding starts from the intra picture, they are not needed.
+ *
+ * Such “open” random-access samples can be marked by being a member of this group. Samples marked by this group must be random access points, and may also be sync points (i.e. it is not required that samples marked by the sync sample table be excluded).
+ *
+ */
+public class VisualRandomAccessEntry extends GroupEntry {
+ public static final String TYPE = "rap ";
+ private boolean numLeadingSamplesKnown;
+ private short numLeadingSamples;
+
+ public boolean isNumLeadingSamplesKnown() {
+ return numLeadingSamplesKnown;
+ }
+
+ public void setNumLeadingSamplesKnown(boolean numLeadingSamplesKnown) {
+ this.numLeadingSamplesKnown = numLeadingSamplesKnown;
+ }
+
+ public short getNumLeadingSamples() {
+ return numLeadingSamples;
+ }
+
+ public void setNumLeadingSamples(short numLeadingSamples) {
+ this.numLeadingSamples = numLeadingSamples;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ final byte b = byteBuffer.get();
+ numLeadingSamplesKnown = ((b & 0x80) == 0x80);
+ numLeadingSamples = (short) (b & 0x7f);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(1);
+ content.put((byte) ((numLeadingSamplesKnown? 0x80 : 0x00)| (numLeadingSamples & 0x7f)));
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ VisualRandomAccessEntry that = (VisualRandomAccessEntry) o;
+
+ if (numLeadingSamples != that.numLeadingSamples) return false;
+ if (numLeadingSamplesKnown != that.numLeadingSamplesKnown) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (numLeadingSamplesKnown ? 1 : 0);
+ result = 31 * result + (int) numLeadingSamples;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("VisualRandomAccessEntry");
+ sb.append("{numLeadingSamplesKnown=").append(numLeadingSamplesKnown);
+ sb.append(", numLeadingSamples=").append(numLeadingSamples);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/CencSampleEncryptionInformationGroupEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/CencSampleEncryptionInformationGroupEntry.java
new file mode 100644
index 0000000..b54f4d9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/CencSampleEncryptionInformationGroupEntry.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.Hex;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * Each sample in a protected track shall be associated with an IsEncrypted flag, IV_Size, and KID.
+ * This can be accomplished by (a) relying on the default values in the TrackEncryptionBox
+ * (see 8.2), or (b) specifying the parameters by sample group, or (c) using a combination of these two techniques.
+ * <p/>
+ * When specifying the parameters by sample group, the SampleToGroupBox in the sample table or track
+ * fragment specifies which samples use which sample group description from the SampleGroupDescriptionBox.
+ */
+public class CencSampleEncryptionInformationGroupEntry extends GroupEntry {
+ public static final String TYPE = "seig";
+
+ private int isEncrypted;
+ private byte ivSize;
+ private byte[] kid = new byte[16];
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ isEncrypted = IsoTypeReader.readUInt24(byteBuffer);
+ ivSize = (byte) IsoTypeReader.readUInt8(byteBuffer);
+ kid = new byte[16];
+ byteBuffer.get(kid);
+
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer byteBuffer = ByteBuffer.allocate(20);
+ IsoTypeWriter.writeUInt24(byteBuffer, isEncrypted);
+ IsoTypeWriter.writeUInt8(byteBuffer, ivSize);
+ byteBuffer.put(kid);
+ byteBuffer.rewind();
+ return byteBuffer;
+ }
+
+ public int getEncrypted() {
+ return isEncrypted;
+ }
+
+ public void setEncrypted(int encrypted) {
+ isEncrypted = encrypted;
+ }
+
+ public byte getIvSize() {
+ return ivSize;
+ }
+
+ public void setIvSize(byte ivSize) {
+ this.ivSize = ivSize;
+ }
+
+ public byte[] getKid() {
+ return kid;
+ }
+
+ public void setKid(byte[] kid) {
+ assert kid.length == 16;
+ this.kid = kid;
+ }
+
+ @Override
+ public String toString() {
+ return "CencSampleEncryptionInformationGroupEntry{" +
+ "isEncrypted=" + isEncrypted +
+ ", ivSize=" + ivSize +
+ ", kid=" + Hex.encodeHex(kid) +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ CencSampleEncryptionInformationGroupEntry that = (CencSampleEncryptionInformationGroupEntry) o;
+
+ if (isEncrypted != that.isEncrypted) {
+ return false;
+ }
+ if (ivSize != that.ivSize) {
+ return false;
+ }
+ if (!Arrays.equals(kid, that.kid)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = isEncrypted;
+ result = 31 * result + (int) ivSize;
+ result = 31 * result + (kid != null ? Arrays.hashCode(kid) : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/GroupEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/GroupEntry.java
new file mode 100644
index 0000000..0d78d25
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/GroupEntry.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+public abstract class GroupEntry {
+ public abstract void parse(ByteBuffer byteBuffer);
+ public abstract ByteBuffer get();
+
+ public int size() {
+ return get().limit();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RateShareEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RateShareEntry.java
new file mode 100644
index 0000000..ae5d380
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RateShareEntry.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * Each sample of a track may be associated to (zero or) one of a number of sample group descriptions, each of
+ * which defines a record of rate-share information. Typically the same rate-share information applies to many
+ * consecutive samples and it may therefore be enough to define two or three sample group descriptions that
+ * can be used at different time intervals.
+ * <p/>
+ * The grouping type 'rash' (short for rate share) is defined as the grouping criterion for rate share information.
+ * Zero or one sample-to-group box ('sbgp') for the grouping type 'rash' can be contained in the sample
+ * table box ('stbl') of a track. It shall reside in a hint track, if a hint track is used, otherwise in a media track.
+ * <p/>
+ * Target rate share may be specified for several operation points that are defined in terms of the total available
+ * bitrate, i.e., the bitrate that should be shared. If only one operation point is defined, the target rate share
+ * applies to all available bitrates. If several operation points are defined, then each operation point specifies a
+ * target rate share. Target rate share values specified for the first and the last operation points also specify the
+ * target rate share values at lower and higher available bitrates, respectively. The target rate share between two
+ * operation points is specified to be in the range between the target rate shares of those operation points. One
+ * possibility is to estimate with linear interpolation.
+ */
+public class RateShareEntry extends GroupEntry {
+ public static final String TYPE = "rash";
+
+ private short operationPointCut;
+ private short targetRateShare;
+ private List<Entry> entries = new LinkedList<Entry>();
+ private int maximumBitrate;
+ private int minimumBitrate;
+ private short discardPriority;
+
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ operationPointCut = byteBuffer.getShort();
+ if (operationPointCut == 1) {
+ targetRateShare = byteBuffer.getShort();
+ } else {
+ int entriesLeft = operationPointCut;
+ while (entriesLeft-- > 0) {
+ entries.add(new Entry(l2i(IsoTypeReader.readUInt32(byteBuffer)), byteBuffer.getShort()));
+ }
+ }
+ maximumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
+ minimumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
+ discardPriority = (short) IsoTypeReader.readUInt8(byteBuffer);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer buf = ByteBuffer.allocate(operationPointCut == 1?13:(operationPointCut * 6 + 11 ));
+ buf.putShort(operationPointCut);
+ if (operationPointCut == 1) {
+ buf.putShort(targetRateShare );
+ } else {
+ for (Entry entry : entries) {
+ buf.putInt(entry.getAvailableBitrate());
+ buf.putShort(entry.getTargetRateShare());
+ }
+ }
+ buf.putInt(maximumBitrate);
+ buf.putInt(minimumBitrate);
+ IsoTypeWriter.writeUInt8(buf, discardPriority);
+ buf.rewind();
+ return buf;
+ }
+
+ public static class Entry {
+ public Entry(int availableBitrate, short targetRateShare) {
+ this.availableBitrate = availableBitrate;
+ this.targetRateShare = targetRateShare;
+ }
+
+ int availableBitrate;
+ short targetRateShare;
+
+ @Override
+ public String toString() {
+ return "{" +
+ "availableBitrate=" + availableBitrate +
+ ", targetRateShare=" + targetRateShare +
+ '}';
+ }
+
+ public int getAvailableBitrate() {
+ return availableBitrate;
+ }
+
+ public void setAvailableBitrate(int availableBitrate) {
+ this.availableBitrate = availableBitrate;
+ }
+
+ public short getTargetRateShare() {
+ return targetRateShare;
+ }
+
+ public void setTargetRateShare(short targetRateShare) {
+ this.targetRateShare = targetRateShare;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (availableBitrate != entry.availableBitrate) {
+ return false;
+ }
+ if (targetRateShare != entry.targetRateShare) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = availableBitrate;
+ result = 31 * result + (int) targetRateShare;
+ return result;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ RateShareEntry that = (RateShareEntry) o;
+
+ if (discardPriority != that.discardPriority) {
+ return false;
+ }
+ if (maximumBitrate != that.maximumBitrate) {
+ return false;
+ }
+ if (minimumBitrate != that.minimumBitrate) {
+ return false;
+ }
+ if (operationPointCut != that.operationPointCut) {
+ return false;
+ }
+ if (targetRateShare != that.targetRateShare) {
+ return false;
+ }
+ if (entries != null ? !entries.equals(that.entries) : that.entries != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) operationPointCut;
+ result = 31 * result + (int) targetRateShare;
+ result = 31 * result + (entries != null ? entries.hashCode() : 0);
+ result = 31 * result + maximumBitrate;
+ result = 31 * result + minimumBitrate;
+ result = 31 * result + (int) discardPriority;
+ return result;
+ }
+
+ public short getOperationPointCut() {
+ return operationPointCut;
+ }
+
+ public void setOperationPointCut(short operationPointCut) {
+ this.operationPointCut = operationPointCut;
+ }
+
+ public short getTargetRateShare() {
+ return targetRateShare;
+ }
+
+ public void setTargetRateShare(short targetRateShare) {
+ this.targetRateShare = targetRateShare;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public int getMaximumBitrate() {
+ return maximumBitrate;
+ }
+
+ public void setMaximumBitrate(int maximumBitrate) {
+ this.maximumBitrate = maximumBitrate;
+ }
+
+ public int getMinimumBitrate() {
+ return minimumBitrate;
+ }
+
+ public void setMinimumBitrate(int minimumBitrate) {
+ this.minimumBitrate = minimumBitrate;
+ }
+
+ public short getDiscardPriority() {
+ return discardPriority;
+ }
+
+ public void setDiscardPriority(short discardPriority) {
+ this.discardPriority = discardPriority;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RollRecoveryEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RollRecoveryEntry.java
new file mode 100644
index 0000000..bd5b89e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/RollRecoveryEntry.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+/**
+ * roll_distance is a signed integer that gives the number of samples that must be decoded in order for
+ * a sample to be decoded correctly. A positive value indicates the number of samples after the sample
+ * that is a group member that must be decoded such that at the last of these recovery is complete, i.e.
+ * the last sample is correct. A negative value indicates the number of samples before the sample that is
+ * a group member that must be decoded in order for recovery to be complete at the marked sample.
+ * The value zero must not be used; the sync sample table documents random access points for which
+ * no recovery roll is needed.
+ */
+public class RollRecoveryEntry extends GroupEntry {
+ public static final String TYPE = "roll";
+ private short rollDistance;
+
+ public short getRollDistance() {
+ return rollDistance;
+ }
+
+ public void setRollDistance(short rollDistance) {
+ this.rollDistance = rollDistance;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ rollDistance = byteBuffer.getShort();
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(2);
+ content.putShort(rollDistance);
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ RollRecoveryEntry entry = (RollRecoveryEntry) o;
+
+ if (rollDistance != entry.rollDistance) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) rollDistance;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleGroupDescriptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleGroupDescriptionBox.java
new file mode 100644
index 0000000..df4a96f
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleGroupDescriptionBox.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+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;
+
+/**
+ * This description table gives information about the characteristics of sample groups. The descriptive
+ * information is any other information needed to define or characterize the sample group.
+ * <p/>
+ * There may be multiple instances of this box if there is more than one sample grouping for the samples in a
+ * track. Each instance of the SampleGroupDescription box has a type code that distinguishes different
+ * sample groupings. Within a track, there shall be at most one instance of this box with a particular grouping
+ * type. The associated SampleToGroup shall indicate the same value for the grouping type.
+ * <p/>
+ * The information is stored in the sample group description box after the entry-count. An abstract entry type is
+ * defined and sample groupings shall define derived types to represent the description of each sample group.
+ * For video tracks, an abstract VisualSampleGroupEntry is used with similar types for audio and hint tracks.
+ */
+public class SampleGroupDescriptionBox extends AbstractFullBox {
+ public static final String TYPE = "sgpd";
+
+ private String groupingType;
+ private int defaultLength;
+ private List<GroupEntry> groupEntries = new LinkedList<GroupEntry>();
+ private int descriptionLength;
+
+ public SampleGroupDescriptionBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 8;
+ if (getVersion() == 1) {
+ size += 4;
+ }
+ size += 4; // entryCount
+ for (GroupEntry groupEntry : groupEntries) {
+ if (getVersion() == 1 && defaultLength == 0) {
+ size += 4;
+ }
+ size += groupEntry.size();
+ }
+ return size;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(groupingType.getBytes());
+ if (this.getVersion() == 1) {
+ IsoTypeWriter.writeUInt32(byteBuffer, defaultLength);
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, this.groupEntries.size());
+ for (GroupEntry entry : groupEntries) {
+ if (this.getVersion() == 1 && defaultLength == 0) {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.get().limit());
+ }
+ byteBuffer.put(entry.get());
+ }
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ if (this.getVersion() != 1) {
+ throw new RuntimeException("SampleGroupDescriptionBox are only supported in version 1");
+ }
+ groupingType = IsoTypeReader.read4cc(content);
+ if (this.getVersion() == 1) {
+ defaultLength = l2i(IsoTypeReader.readUInt32(content));
+ }
+ long entryCount = IsoTypeReader.readUInt32(content);
+ while (entryCount-- > 0) {
+ int length = defaultLength;
+ if (this.getVersion() == 1) {
+ if (defaultLength == 0) {
+ descriptionLength = l2i(IsoTypeReader.readUInt32(content));
+ length = descriptionLength;
+ }
+ } else {
+ throw new RuntimeException("This should be implemented");
+ }
+ int finalPos = content.position() + length;
+ ByteBuffer parseMe = content.slice();
+ parseMe.limit(length);
+ groupEntries.add(parseGroupEntry(parseMe, groupingType));
+ content.position(finalPos);
+ }
+
+ }
+
+ private GroupEntry parseGroupEntry(ByteBuffer content, String groupingType) {
+ GroupEntry groupEntry;
+ if (RollRecoveryEntry.TYPE.equals(groupingType)) {
+ groupEntry = new RollRecoveryEntry();
+ } else if (RateShareEntry.TYPE.equals(groupingType)) {
+ groupEntry = new RateShareEntry();
+ } else if (CencSampleEncryptionInformationGroupEntry.TYPE.equals(groupingType)) {
+ groupEntry = new CencSampleEncryptionInformationGroupEntry();
+ } else if (VisualRandomAccessEntry.TYPE.equals(groupingType)) {
+ groupEntry = new VisualRandomAccessEntry();
+ } else if (TemporalLevelEntry.TYPE.equals(groupingType)) {
+ groupEntry = new TemporalLevelEntry();
+ } else {
+ groupEntry = new UnknownEntry();
+ }
+ groupEntry.parse(content);
+ return groupEntry;
+ }
+
+
+ public String getGroupingType() {
+ return groupingType;
+ }
+
+ public void setGroupingType(String groupingType) {
+ this.groupingType = groupingType;
+ }
+
+ public int getDefaultLength() {
+ return defaultLength;
+ }
+
+ public void setDefaultLength(int defaultLength) {
+ this.defaultLength = defaultLength;
+ }
+
+ public List<GroupEntry> getGroupEntries() {
+ return groupEntries;
+ }
+
+ public void setGroupEntries(List<GroupEntry> groupEntries) {
+ this.groupEntries = groupEntries;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SampleGroupDescriptionBox that = (SampleGroupDescriptionBox) o;
+
+ if (defaultLength != that.defaultLength) {
+ return false;
+ }
+ if (groupEntries != null ? !groupEntries.equals(that.groupEntries) : that.groupEntries != null) {
+ return false;
+ }
+ if (groupingType != null ? !groupingType.equals(that.groupingType) : that.groupingType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupingType != null ? groupingType.hashCode() : 0;
+ result = 31 * result + defaultLength;
+ result = 31 * result + (groupEntries != null ? groupEntries.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "SampleGroupDescriptionBox{" +
+ "groupingType='" + groupingType + '\'' +
+ ", defaultLength=" + defaultLength +
+ ", groupEntries=" + groupEntries +
+ '}';
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleToGroupBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleToGroupBox.java
new file mode 100644
index 0000000..0fa059e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/SampleToGroupBox.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+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;
+
+/**
+ * This table can be used to find the group that a sample belongs to and the associated description of that
+ * sample group. The table is compactly coded with each entry giving the index of the first sample of a run of
+ * samples with the same sample group descriptor. The sample group description ID is an index that refers to a
+ * SampleGroupDescription box, which contains entries describing the characteristics of each sample group.
+ * <p/>
+ * There may be multiple instances of this box if there is more than one sample grouping for the samples in a
+ * track. Each instance of the SampleToGroup box has a type code that distinguishes different sample
+ * groupings. Within a track, there shall be at most one instance of this box with a particular grouping type. The
+ * associated SampleGroupDescription shall indicate the same value for the grouping type.
+ * <p/>
+ * Version 1 of this box should only be used if a grouping type parameter is needed.
+ */
+public class SampleToGroupBox extends AbstractFullBox {
+ public static final String TYPE = "sbgp";
+
+
+ private String groupingType;
+ private String groupingTypeParameter;
+
+ List<Entry> entries = new LinkedList<Entry>();
+
+ public SampleToGroupBox() {
+ super(TYPE);
+
+ }
+
+ @Override
+ protected long getContentSize() {
+ return this.getVersion() == 1 ? entries.size() * 8 + 16 : entries.size() * 8 + 12;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(groupingType.getBytes());
+ if (this.getVersion() == 1) {
+ byteBuffer.put(groupingTypeParameter.getBytes());
+ }
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleCount());
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getGroupDescriptionIndex());
+ }
+
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ groupingType = IsoTypeReader.read4cc(content);
+ if (this.getVersion() == 1) {
+ groupingTypeParameter = IsoTypeReader.read4cc(content);
+ }
+ long entryCount = IsoTypeReader.readUInt32(content);
+ while (entryCount-- > 0) {
+ entries.add(new Entry(l2i(IsoTypeReader.readUInt32(content)), l2i(IsoTypeReader.readUInt32(content))));
+ }
+ }
+
+ public static class Entry {
+ private long sampleCount;
+ private int groupDescriptionIndex;
+
+ public Entry(long sampleCount, int groupDescriptionIndex) {
+ this.sampleCount = sampleCount;
+ this.groupDescriptionIndex = groupDescriptionIndex;
+ }
+
+ public long getSampleCount() {
+ return sampleCount;
+ }
+
+ public void setSampleCount(long sampleCount) {
+ this.sampleCount = sampleCount;
+ }
+
+ public int getGroupDescriptionIndex() {
+ return groupDescriptionIndex;
+ }
+
+ public void setGroupDescriptionIndex(int groupDescriptionIndex) {
+ this.groupDescriptionIndex = groupDescriptionIndex;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "sampleCount=" + sampleCount +
+ ", groupDescriptionIndex=" + groupDescriptionIndex +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Entry entry = (Entry) o;
+
+ if (groupDescriptionIndex != entry.groupDescriptionIndex) {
+ return false;
+ }
+ if (sampleCount != entry.sampleCount) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (sampleCount ^ (sampleCount >>> 32));
+ result = 31 * result + groupDescriptionIndex;
+ return result;
+ }
+ }
+
+ public String getGroupingType() {
+ return groupingType;
+ }
+
+ public void setGroupingType(String groupingType) {
+ this.groupingType = groupingType;
+ }
+
+ public String getGroupingTypeParameter() {
+ return groupingTypeParameter;
+ }
+
+ public void setGroupingTypeParameter(String groupingTypeParameter) {
+ this.groupingTypeParameter = groupingTypeParameter;
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/TemporalLevelEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/TemporalLevelEntry.java
new file mode 100644
index 0000000..798fd9c
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/TemporalLevelEntry.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The Temporal Level sample grouping ('tele') provides a codec-independent sample grouping that can be used to group samples (access units) in a track (and potential track fragments) according to temporal level, where samples of one temporal level have no coding dependencies on samples of higher temporal levels. The temporal level equals the sample group description index (taking values 1, 2, 3, etc). The bitstream containing only the access units from the first temporal level to a higher temporal level remains conforming to the coding standard.
+ *
+ * A grouping according to temporal level facilitates easy extraction of temporal subsequences, for instance using the Subsegment Indexing box in 0.
+ *
+ */
+public class TemporalLevelEntry extends GroupEntry {
+ public static final String TYPE = "tele";
+ private boolean levelIndependentlyDecodable;
+ private short reserved;
+
+ public boolean isLevelIndependentlyDecodable() {
+ return levelIndependentlyDecodable;
+ }
+
+ public void setLevelIndependentlyDecodable(boolean levelIndependentlyDecodable) {
+ this.levelIndependentlyDecodable = levelIndependentlyDecodable;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ final byte b = byteBuffer.get();
+ levelIndependentlyDecodable = ((b & 0x80) == 0x80);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(1);
+ content.put((byte) (levelIndependentlyDecodable ? 0x80 : 0x00));
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ TemporalLevelEntry that = (TemporalLevelEntry) o;
+
+ if (levelIndependentlyDecodable != that.levelIndependentlyDecodable) return false;
+ if (reserved != that.reserved) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (levelIndependentlyDecodable ? 1 : 0);
+ result = 31 * result + (int) reserved;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TemporalLevelEntry");
+ sb.append("{levelIndependentlyDecodable=").append(levelIndependentlyDecodable);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/UnknownEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/UnknownEntry.java
new file mode 100644
index 0000000..9efcbea
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/UnknownEntry.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.Hex;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public class UnknownEntry extends GroupEntry {
+ private ByteBuffer content;
+
+ public UnknownEntry() {
+ }
+
+ public ByteBuffer getContent() {
+ return content;
+ }
+
+ public void setContent(ByteBuffer content) {
+ this.content = (ByteBuffer) content.duplicate().rewind();
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ this.content = (ByteBuffer) byteBuffer.duplicate().rewind();
+ }
+
+ @Override
+ public ByteBuffer get() {
+ return content.duplicate();
+ }
+
+ @Override
+ public String toString() {
+ ByteBuffer bb = content.duplicate();
+ bb.rewind();
+ byte[] b = new byte[bb.limit()];
+ bb.get(b);
+ return "UnknownEntry{" +
+ "content=" + Hex.encodeHex(b) +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ UnknownEntry that = (UnknownEntry) o;
+
+ if (content != null ? !content.equals(that.content) : that.content != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return content != null ? content.hashCode() : 0;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/VisualRandomAccessEntry.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/VisualRandomAccessEntry.java
new file mode 100644
index 0000000..ed5d199
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/mp4/samplegrouping/VisualRandomAccessEntry.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
+
+import com.coremedia.iso.IsoTypeReader;
+
+import java.nio.ByteBuffer;
+
+/**
+ * For some coding systems a sync sample is specified to be a random access point after which all samples in decoding order can be correctly decoded. However, it may be possible to encode an “open” random access point, after which all samples in output order can be correctly decoded, but some samples following the random access point in decoding order and preceding the random access point in output order need not be correctly decodable. For example, an intra picture starting an open group of pictures can be followed in decoding order by (bi-)predicted pictures that however precede the intra picture in output order; though they possibly cannot be correctly decoded if the decoding starts from the intra picture, they are not needed.
+ *
+ * Such “open” random-access samples can be marked by being a member of this group. Samples marked by this group must be random access points, and may also be sync points (i.e. it is not required that samples marked by the sync sample table be excluded).
+ *
+ */
+public class VisualRandomAccessEntry extends GroupEntry {
+ public static final String TYPE = "rap ";
+ private boolean numLeadingSamplesKnown;
+ private short numLeadingSamples;
+
+ public boolean isNumLeadingSamplesKnown() {
+ return numLeadingSamplesKnown;
+ }
+
+ public void setNumLeadingSamplesKnown(boolean numLeadingSamplesKnown) {
+ this.numLeadingSamplesKnown = numLeadingSamplesKnown;
+ }
+
+ public short getNumLeadingSamples() {
+ return numLeadingSamples;
+ }
+
+ public void setNumLeadingSamples(short numLeadingSamples) {
+ this.numLeadingSamples = numLeadingSamples;
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ final byte b = byteBuffer.get();
+ numLeadingSamplesKnown = ((b & 0x80) == 0x80);
+ numLeadingSamples = (short) (b & 0x7f);
+ }
+
+ @Override
+ public ByteBuffer get() {
+ ByteBuffer content = ByteBuffer.allocate(1);
+ content.put((byte) ((numLeadingSamplesKnown? 0x80 : 0x00)| (numLeadingSamples & 0x7f)));
+ content.rewind();
+ return content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ VisualRandomAccessEntry that = (VisualRandomAccessEntry) o;
+
+ if (numLeadingSamples != that.numLeadingSamples) return false;
+ if (numLeadingSamplesKnown != that.numLeadingSamplesKnown) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (numLeadingSamplesKnown ? 1 : 0);
+ result = 31 * result + (int) numLeadingSamples;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("VisualRandomAccessEntry");
+ sb.append("{numLeadingSamplesKnown=").append(numLeadingSamplesKnown);
+ sb.append(", numLeadingSamples=").append(numLeadingSamples);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/all-wcprops
new file mode 100644
index 0000000..73d7e4e
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/all-wcprops
@@ -0,0 +1,47 @@
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/!svn/ver/616/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff
+END
+PlayReadyHeader.java
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/svn/!svn/ver/525/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PlayReadyHeader.java
+END
+ProtectionSpecificHeader.java
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/svn/!svn/ver/527/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/ProtectionSpecificHeader.java
+END
+UuidBasedProtectionSystemSpecificHeaderBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 131
+/svn/!svn/ver/616/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/UuidBasedProtectionSystemSpecificHeaderBox.java
+END
+PiffSampleEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffSampleEncryptionBox.java
+END
+TfrfBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfrfBox.java
+END
+PiffTrackEncryptionBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/svn/!svn/ver/377/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffTrackEncryptionBox.java
+END
+TfxdBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfxdBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/entries
new file mode 100644
index 0000000..f869342
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/entries
@@ -0,0 +1,266 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-05-17T09:04:15.805545Z
+616
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+PlayReadyHeader.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+414299d2fe72802bfdba588cd197cc8d
+2012-04-25T19:24:04.485529Z
+525
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8099
+
+ProtectionSpecificHeader.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+206bcc330dd14e88a9b36dbdab4b5676
+2012-04-25T23:16:14.370289Z
+527
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2339
+
+UuidBasedProtectionSystemSpecificHeaderBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+bee6a83aa218637d445d55bb317bf1f0
+2012-05-17T09:04:15.805545Z
+616
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3419
+
+PiffSampleEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+e8e29f48bf61c02cd75f62b654664a1d
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1187
+
+TfrfBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+87a71e91a262d3294bb9b1e4959b0b99
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4379
+
+PiffTrackEncryptionBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.797223Z
+f412ae4506ee42fea327a2b274c0602d
+2012-03-05T23:28:24.666173Z
+377
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+854
+
+TfxdBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.807223Z
+d98ba32db0ee574c4130985dee95179a
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2998
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffSampleEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffSampleEncryptionBox.java.svn-base
new file mode 100644
index 0000000..da3512d
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffSampleEncryptionBox.java.svn-base
@@ -0,0 +1,45 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.googlecode.mp4parser.boxes.AbstractSampleEncryptionBox;
+
+/**
+ * <pre>
+ * aligned(8) class SampleEncryptionBox extends FullBox(‘uuid’, extended_type= 0xA2394F52-5A9B-4f14-A244-6C427C648DF4, version=0, flags=0)
+ * {
+ * if (flags & 0x000001)
+ * {
+ * unsigned int(24) AlgorithmID;
+ * unsigned int(8) IV_size;
+ * unsigned int(8)[16] KID;
+ * }
+ * unsigned int (32) sample_count;
+ * {
+ * unsigned int(IV_size) InitializationVector;
+ * if (flags & 0x000002)
+ * {
+ * unsigned int(16) NumberOfEntries;
+ * {
+ * unsigned int(16) BytesOfClearData;
+ * unsigned int(32) BytesOfEncryptedData;
+ * } [ NumberOfEntries]
+ * }
+ * }[ sample_count ]
+ * }
+ * </pre>
+ */
+public class PiffSampleEncryptionBox extends AbstractSampleEncryptionBox {
+
+ /**
+ * Creates a AbstractSampleEncryptionBox for non-h264 tracks.
+ */
+ public PiffSampleEncryptionBox() {
+ super("uuid");
+
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0xA2, 0x39, 0x4F, 0x52, 0x5A, (byte) 0x9B, 0x4f, 0x14, (byte) 0xA2, 0x44, 0x6C, 0x42, 0x7C, 0x64, (byte) 0x8D, (byte) 0xF4};
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffTrackEncryptionBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffTrackEncryptionBox.java.svn-base
new file mode 100644
index 0000000..f92c0f3
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PiffTrackEncryptionBox.java.svn-base
@@ -0,0 +1,34 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.googlecode.mp4parser.boxes.AbstractTrackEncryptionBox;
+
+/**
+ * aligned(8) class TrackEncryptionBox extends FullBox(‘uuid’,
+ * extended_type=0x8974dbce-7be7-4c51-84f9-7148f9882554, version=0,
+ * flags=0)
+ * {
+ * unsigned int(24) default_AlgorithmID;
+ * unsigned int(8) default_IV_size;
+ * unsigned int(8)[16] default_KID;
+ * }
+ */
+public class PiffTrackEncryptionBox extends AbstractTrackEncryptionBox {
+
+
+ public PiffTrackEncryptionBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0x89, 0x74, (byte) 0xdb, (byte) 0xce, 0x7b, (byte) 0xe7, 0x4c, 0x51,
+ (byte) 0x84, (byte) 0xf9, 0x71, 0x48, (byte) 0xf9, (byte) 0x88, 0x25, 0x54};
+ }
+
+ @Override
+ public int getFlags() {
+ return 0;
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PlayReadyHeader.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PlayReadyHeader.java.svn-base
new file mode 100644
index 0000000..74246d0
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/PlayReadyHeader.java.svn-base
@@ -0,0 +1,253 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.util.Path;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.7. ASF GUIDs
+ * <p/>
+ * <p/>
+ * ASF_Protection_System_Identifier_Object
+ * 9A04F079-9840-4286-AB92E65BE0885F95
+ * <p/>
+ * ASF_Content_Protection_System_Microsoft_PlayReady
+ * F4637010-03C3-42CD-B932B48ADF3A6A54
+ * <p/>
+ * ASF_StreamType_PlayReady_Encrypted_Command_Media
+ * 8683973A-6639-463A-ABD764F1CE3EEAE0
+ * <p/>
+ * <p/>
+ * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.5. Data Objects > 2.5.1. Payload Extension for AES in Counter Mode
+ * <p/>
+ * The sample Id is used as the IV in CTR mode. Block offset, starting at 0 and incremented by 1 after every 16 bytes, from the beginning of the sample is used as the Counter.
+ * <p/>
+ * The sample ID for each sample (media object) is stored as an ASF payload extension system with the ID of ASF_Payload_Extension_Encryption_SampleID = {6698B84E-0AFA-4330-AEB2-1C0A98D7A44D}. The payload extension can be stored as a fixed size extension of 8 bytes.
+ * <p/>
+ * The sample ID is always stored in big-endian byte order.
+ */
+public class PlayReadyHeader extends ProtectionSpecificHeader {
+ private long length;
+ private List<PlayReadyRecord> records;
+
+ public PlayReadyHeader() {
+
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ /*
+ Length DWORD 32
+
+ PlayReady Record Count WORD 16
+
+ PlayReady Records See Text Varies
+
+ */
+
+ length = IsoTypeReader.readUInt32BE(byteBuffer);
+ int recordCount = IsoTypeReader.readUInt16BE(byteBuffer);
+
+ records = PlayReadyRecord.createFor(byteBuffer, recordCount);
+ }
+
+ @Override
+ public ByteBuffer getData() {
+
+ int size = 4 + 2;
+ for (PlayReadyRecord record : records) {
+ size += 2 + 2;
+ size += record.getValue().rewind().limit();
+ }
+ ByteBuffer byteBuffer = ByteBuffer.allocate(size);
+
+ IsoTypeWriter.writeUInt32BE(byteBuffer, size);
+ IsoTypeWriter.writeUInt16BE(byteBuffer, records.size());
+ for (PlayReadyRecord record : records) {
+ IsoTypeWriter.writeUInt16BE(byteBuffer, record.type);
+ IsoTypeWriter.writeUInt16BE(byteBuffer, record.getValue().limit());
+ ByteBuffer tmp4debug = record.getValue();
+ byteBuffer.put(tmp4debug);
+ }
+
+ return byteBuffer;
+ }
+
+ public void setRecords(List<PlayReadyRecord> records) {
+ this.records = records;
+ }
+
+ public List<PlayReadyRecord> getRecords() {
+ return Collections.unmodifiableList(records);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("PlayReadyHeader");
+ sb.append("{length=").append(length);
+ sb.append(", recordCount=").append(records.size());
+ sb.append(", records=").append(records);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static abstract class PlayReadyRecord {
+ int type;
+
+
+ public PlayReadyRecord(int type) {
+ this.type = type;
+ }
+
+ public static List<PlayReadyRecord> createFor(ByteBuffer byteBuffer, int recordCount) {
+ List<PlayReadyRecord> records = new ArrayList<PlayReadyRecord>(recordCount);
+
+ for (int i = 0; i < recordCount; i++) {
+ PlayReadyRecord record;
+ int type = IsoTypeReader.readUInt16BE(byteBuffer);
+ int length = IsoTypeReader.readUInt16BE(byteBuffer);
+ switch (type) {
+ case 0x1:
+ record = new RMHeader();
+ break;
+ case 0x2:
+ record = new DefaulPlayReadyRecord(0x02);
+ break;
+ case 0x3:
+ record = new EmeddedLicenseStore();
+ break;
+ default:
+ record = new DefaulPlayReadyRecord(type);
+ }
+ record.parse((ByteBuffer) byteBuffer.slice().limit(length));
+ byteBuffer.position(byteBuffer.position() + length);
+ records.add(record);
+ }
+
+ return records;
+ }
+
+ public abstract void parse(ByteBuffer bytes);
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("PlayReadyRecord");
+ sb.append("{type=").append(type);
+ sb.append(", length=").append(getValue().limit());
+// sb.append(", value=").append(Hex.encodeHex(getValue())).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public abstract ByteBuffer getValue();
+
+ public static class RMHeader extends PlayReadyRecord {
+ String header;
+
+ public RMHeader() {
+ super(0x01);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ try {
+ byte[] str = new byte[bytes.slice().limit()];
+ bytes.get(str);
+ header = new String(str, "UTF-16LE");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ byte[] headerBytes;
+ try {
+ headerBytes = header.getBytes("UTF-16LE");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ return ByteBuffer.wrap(headerBytes);
+ }
+
+ public void setHeader(String header) {
+ this.header = header;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("RMHeader");
+ sb.append("{length=").append(getValue().limit());
+ sb.append(", header='").append(header).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ public static class EmeddedLicenseStore extends PlayReadyRecord {
+ ByteBuffer value;
+
+ public EmeddedLicenseStore() {
+ super(0x03);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ this.value = bytes.duplicate();
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("EmeddedLicenseStore");
+ sb.append("{length=").append(getValue().limit());
+ //sb.append(", value='").append(Hex.encodeHex(getValue())).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ public static class DefaulPlayReadyRecord extends PlayReadyRecord {
+ ByteBuffer value;
+
+ public DefaulPlayReadyRecord(int type) {
+ super(type);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ this.value = bytes.duplicate();
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ return value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/ProtectionSpecificHeader.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/ProtectionSpecificHeader.java.svn-base
new file mode 100644
index 0000000..0d2f344
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/ProtectionSpecificHeader.java.svn-base
@@ -0,0 +1,79 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+
+import com.coremedia.iso.Hex;
+
+import java.lang.Class;
+import java.lang.IllegalAccessException;
+import java.lang.InstantiationException;
+import java.lang.Object;
+import java.lang.Override;
+import java.lang.RuntimeException;
+import java.lang.String;
+import java.lang.StringBuilder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+
+public class ProtectionSpecificHeader {
+ protected static Map<UUID, Class<? extends ProtectionSpecificHeader>> uuidRegistry = new HashMap<UUID, Class<? extends ProtectionSpecificHeader>>();
+ ByteBuffer data;
+
+ static {
+ uuidRegistry.put(UUID.fromString("9A04F079-9840-4286-AB92-E65BE0885F95"), PlayReadyHeader.class);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ProtectionSpecificHeader) {
+ if (this.getClass().equals(obj.getClass())) {
+ return data.equals(((ProtectionSpecificHeader) obj).data);
+ }
+ }
+ return false;
+ }
+
+ public static ProtectionSpecificHeader createFor(UUID systemId, ByteBuffer bufferWrapper) {
+ final Class<? extends ProtectionSpecificHeader> aClass = uuidRegistry.get(systemId);
+
+ ProtectionSpecificHeader protectionSpecificHeader = new ProtectionSpecificHeader();
+ if (aClass != null) {
+ try {
+ protectionSpecificHeader = aClass.newInstance();
+
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ protectionSpecificHeader.parse(bufferWrapper);
+ return protectionSpecificHeader;
+
+ }
+
+ public void parse(ByteBuffer buffer) {
+ data = buffer;
+
+ }
+
+ public ByteBuffer getData() {
+ return data;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ProtectionSpecificHeader");
+ sb.append("{data=");
+ ByteBuffer data = getData().duplicate();
+ data.rewind();
+ byte[] bytes = new byte[data.limit()];
+ data.get(bytes);
+ sb.append(Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfrfBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfrfBox.java.svn-base
new file mode 100644
index 0000000..1e862e9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfrfBox.java.svn-base
@@ -0,0 +1,129 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+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;
+
+/**
+ * The syntax of the fields defined in this section, specified in ABNF [RFC5234], is as follows:
+ * TfrfBox = TfrfBoxLength TfrfBoxType [TfrfBoxLongLength] TfrfBoxUUID TfrfBoxFields
+ * TfrfBoxChildren
+ * TfrfBoxType = "u" "u" "i" "d"
+ * TfrfBoxLength = BoxLength
+ * TfrfBoxLongLength = LongBoxLength
+ * TfrfBoxUUID = %xD4 %x80 %x7E %xF2 %xCA %x39 %x46 %x95
+ * %x8E %x54 %x26 %xCB %x9E %x46 %xA7 %x9F
+ * TfrfBoxFields = TfrfBoxVersion
+ * TfrfBoxFlags
+ * FragmentCount
+ * (1* TfrfBoxDataFields32) / (1* TfrfBoxDataFields64)
+ * TfrfBoxVersion = %x00 / %x01
+ * TfrfBoxFlags = 24*24 RESERVED_BIT
+ * FragmentCount = UINT8
+ * TfrfBoxDataFields32 = FragmentAbsoluteTime32
+ * FragmentDuration32
+ * TfrfBoxDataFields64 = FragmentAbsoluteTime64
+ * FragmentDuration64
+ * FragmentAbsoluteTime64 = UNSIGNED_INT32
+ * FragmentDuration64 = UNSIGNED_INT32
+ * FragmentAbsoluteTime64 = UNSIGNED_INT64
+ * FragmentDuration64 = UNSIGNED_INT64
+ * TfrfBoxChildren = *( VendorExtensionUUIDBox )
+ */
+public class TfrfBox extends AbstractFullBox {
+ public List<Entry> entries = new ArrayList<Entry>();
+
+ public TfrfBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0xd4, (byte) 0x80, (byte) 0x7e, (byte) 0xf2, (byte) 0xca, (byte) 0x39, (byte) 0x46,
+ (byte) 0x95, (byte) 0x8e, (byte) 0x54, 0x26, (byte) 0xcb, (byte) 0x9e, (byte) 0x46, (byte) 0xa7, (byte) 0x9f};
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 5 + entries.size() * (getVersion() == 0x01 ? 16 : 8);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt8(byteBuffer, entries.size());
+
+ for (Entry entry : entries) {
+ if (getVersion() == 0x01) {
+ IsoTypeWriter.writeUInt64(byteBuffer, entry.fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, entry.fragmentAbsoluteDuration);
+ } else {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.fragmentAbsoluteDuration);
+ }
+ }
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ int fragmentCount = IsoTypeReader.readUInt8(content);
+
+ for (int i = 0; i < fragmentCount; i++) {
+ Entry entry = new Entry();
+ if (getVersion() == 0x01) {
+ entry.fragmentAbsoluteTime = IsoTypeReader.readUInt64(content);
+ entry.fragmentAbsoluteDuration = IsoTypeReader.readUInt64(content);
+ } else {
+ entry.fragmentAbsoluteTime = IsoTypeReader.readUInt32(content);
+ entry.fragmentAbsoluteDuration = IsoTypeReader.readUInt32(content);
+ }
+ entries.add(entry);
+ }
+ }
+
+
+ public long getFragmentCount() {
+ return entries.size();
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TfrfBox");
+ sb.append("{entries=").append(entries);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public class Entry {
+ long fragmentAbsoluteTime;
+ long fragmentAbsoluteDuration;
+
+ public long getFragmentAbsoluteTime() {
+ return fragmentAbsoluteTime;
+ }
+
+ public long getFragmentAbsoluteDuration() {
+ return fragmentAbsoluteDuration;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Entry");
+ sb.append("{fragmentAbsoluteTime=").append(fragmentAbsoluteTime);
+ sb.append(", fragmentAbsoluteDuration=").append(fragmentAbsoluteDuration);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfxdBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfxdBox.java.svn-base
new file mode 100644
index 0000000..52e8e87
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/TfxdBox.java.svn-base
@@ -0,0 +1,85 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The syntax of the fields defined in this section, specified in ABNF [RFC5234], is as follows:
+ * TfxdBox = TfxdBoxLength TfxdBoxType [TfxdBoxLongLength] TfxdBoxUUID TfxdBoxFields
+ * TfxdBoxChildren
+ * TfxdBoxType = "u" "u" "i" "d"
+ * TfxdBoxLength = BoxLength
+ * TfxdBoxLongLength = LongBoxLength
+ * TfxdBoxUUID = %x6D %x1D %x9B %x05 %x42 %xD5 %x44 %xE6
+ * %x80 %xE2 %x14 %x1D %xAF %xF7 %x57 %xB2
+ * TfxdBoxFields = TfxdBoxVersion
+ * TfxdBoxFlags
+ * TfxdBoxDataFields32 / TfxdBoxDataFields64
+ * TfxdBoxVersion = %x00 / %x01
+ * TfxdBoxFlags = 24*24 RESERVED_BIT
+ * TfxdBoxDataFields32 = FragmentAbsoluteTime32
+ * FragmentDuration32
+ * TfxdBoxDataFields64 = FragmentAbsoluteTime64
+ * FragmentDuration64
+ * FragmentAbsoluteTime64 = UNSIGNED_INT32
+ * FragmentDuration64 = UNSIGNED_INT32
+ * FragmentAbsoluteTime64 = UNSIGNED_INT64
+ * FragmentDuration64 = UNSIGNED_INT64
+ * TfxdBoxChildren = *( VendorExtensionUUIDBox )
+ */
+//@ExtendedUserType(uuid = "6d1d9b05-42d5-44e6-80e2-141daff757b2")
+public class TfxdBox extends AbstractFullBox {
+ public long fragmentAbsoluteTime;
+ public long fragmentAbsoluteDuration;
+
+ public TfxdBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0x6d, (byte) 0x1d, (byte) 0x9b, (byte) 0x05, (byte) 0x42, (byte) 0xd5, (byte) 0x44,
+ (byte) 0xe6, (byte) 0x80, (byte) 0xe2, 0x14, (byte) 0x1d, (byte) 0xaf, (byte) 0xf7, (byte) 0x57, (byte) 0xb2};
+ }
+
+ @Override
+ protected long getContentSize() {
+ return getVersion() == 0x01 ? 20 : 12;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+
+ if (getVersion() == 0x01) {
+ fragmentAbsoluteTime = IsoTypeReader.readUInt64(content);
+ fragmentAbsoluteDuration = IsoTypeReader.readUInt64(content);
+ } else {
+ fragmentAbsoluteTime = IsoTypeReader.readUInt32(content);
+ fragmentAbsoluteDuration = IsoTypeReader.readUInt32(content);
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ if (getVersion() == 0x01) {
+ IsoTypeWriter.writeUInt64(byteBuffer, fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, fragmentAbsoluteDuration);
+ } else {
+ IsoTypeWriter.writeUInt32(byteBuffer, fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, fragmentAbsoluteDuration);
+ }
+ }
+
+ public long getFragmentAbsoluteTime() {
+ return fragmentAbsoluteTime;
+ }
+
+ public long getFragmentAbsoluteDuration() {
+ return fragmentAbsoluteDuration;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/UuidBasedProtectionSystemSpecificHeaderBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/UuidBasedProtectionSystemSpecificHeaderBox.java.svn-base
new file mode 100644
index 0000000..b147398
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/.svn/text-base/UuidBasedProtectionSystemSpecificHeaderBox.java.svn-base
@@ -0,0 +1,106 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.util.Path;
+import com.googlecode.mp4parser.util.UUIDConverter;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.Override;import java.lang.String;import java.lang.StringBuilder;import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * aligned(8) class UuidBasedProtectionSystemSpecificHeaderBox extends FullBox(‘uuid’,
+ * extended_type=0xd08a4f18-10f3-4a82-b6c8-32d8aba183d3,
+ * version=0, flags=0)
+ * {
+ * unsigned int(8)[16] SystemID;
+ * unsigned int(32) DataSize;
+ * unsigned int(8)[DataSize] Data;
+ * }
+ */
+public class UuidBasedProtectionSystemSpecificHeaderBox extends AbstractFullBox {
+ public static byte[] USER_TYPE = new byte[]{(byte) 0xd0, (byte) 0x8a, 0x4f, 0x18, 0x10, (byte) 0xf3, 0x4a, (byte) 0x82,
+ (byte) 0xb6, (byte) 0xc8, 0x32, (byte) 0xd8, (byte) 0xab, (byte) 0xa1, (byte) 0x83, (byte) 0xd3};
+
+ UUID systemId;
+
+ ProtectionSpecificHeader protectionSpecificHeader;
+
+ public UuidBasedProtectionSystemSpecificHeaderBox() {
+ super("uuid", USER_TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24 + protectionSpecificHeader.getData().limit();
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return USER_TYPE;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt64(byteBuffer, systemId.getMostSignificantBits());
+ IsoTypeWriter.writeUInt64(byteBuffer, systemId.getLeastSignificantBits());
+ ByteBuffer data = protectionSpecificHeader.getData();
+ data.rewind();
+ IsoTypeWriter.writeUInt32(byteBuffer, data.limit());
+ byteBuffer.put(data);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ byte[] systemIdBytes = new byte[16];
+ content.get(systemIdBytes);
+ systemId = UUIDConverter.convert(systemIdBytes);
+ int dataSize = l2i(IsoTypeReader.readUInt32(content));
+ protectionSpecificHeader = ProtectionSpecificHeader.createFor(systemId, content);
+ }
+
+ public UUID getSystemId() {
+ return systemId;
+ }
+
+ public void setSystemId(UUID systemId) {
+ this.systemId = systemId;
+ }
+
+ public String getSystemIdString() {
+ return systemId.toString();
+ }
+
+ public ProtectionSpecificHeader getProtectionSpecificHeader() {
+ return protectionSpecificHeader;
+ }
+
+ public String getProtectionSpecificHeaderString() {
+ return protectionSpecificHeader.toString();
+ }
+
+ public void setProtectionSpecificHeader(ProtectionSpecificHeader protectionSpecificHeader) {
+ this.protectionSpecificHeader = protectionSpecificHeader;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("UuidBasedProtectionSystemSpecificHeaderBox");
+ sb.append("{systemId=").append(systemId.toString());
+ sb.append(", dataSize=").append(protectionSpecificHeader.getData().limit());
+ sb.append('}');
+ return sb.toString();
+ }
+
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffSampleEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffSampleEncryptionBox.java
new file mode 100644
index 0000000..da3512d
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffSampleEncryptionBox.java
@@ -0,0 +1,45 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.googlecode.mp4parser.boxes.AbstractSampleEncryptionBox;
+
+/**
+ * <pre>
+ * aligned(8) class SampleEncryptionBox extends FullBox(‘uuid’, extended_type= 0xA2394F52-5A9B-4f14-A244-6C427C648DF4, version=0, flags=0)
+ * {
+ * if (flags & 0x000001)
+ * {
+ * unsigned int(24) AlgorithmID;
+ * unsigned int(8) IV_size;
+ * unsigned int(8)[16] KID;
+ * }
+ * unsigned int (32) sample_count;
+ * {
+ * unsigned int(IV_size) InitializationVector;
+ * if (flags & 0x000002)
+ * {
+ * unsigned int(16) NumberOfEntries;
+ * {
+ * unsigned int(16) BytesOfClearData;
+ * unsigned int(32) BytesOfEncryptedData;
+ * } [ NumberOfEntries]
+ * }
+ * }[ sample_count ]
+ * }
+ * </pre>
+ */
+public class PiffSampleEncryptionBox extends AbstractSampleEncryptionBox {
+
+ /**
+ * Creates a AbstractSampleEncryptionBox for non-h264 tracks.
+ */
+ public PiffSampleEncryptionBox() {
+ super("uuid");
+
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0xA2, 0x39, 0x4F, 0x52, 0x5A, (byte) 0x9B, 0x4f, 0x14, (byte) 0xA2, 0x44, 0x6C, 0x42, 0x7C, 0x64, (byte) 0x8D, (byte) 0xF4};
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffTrackEncryptionBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffTrackEncryptionBox.java
new file mode 100644
index 0000000..f92c0f3
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PiffTrackEncryptionBox.java
@@ -0,0 +1,34 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.googlecode.mp4parser.boxes.AbstractTrackEncryptionBox;
+
+/**
+ * aligned(8) class TrackEncryptionBox extends FullBox(‘uuid’,
+ * extended_type=0x8974dbce-7be7-4c51-84f9-7148f9882554, version=0,
+ * flags=0)
+ * {
+ * unsigned int(24) default_AlgorithmID;
+ * unsigned int(8) default_IV_size;
+ * unsigned int(8)[16] default_KID;
+ * }
+ */
+public class PiffTrackEncryptionBox extends AbstractTrackEncryptionBox {
+
+
+ public PiffTrackEncryptionBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0x89, 0x74, (byte) 0xdb, (byte) 0xce, 0x7b, (byte) 0xe7, 0x4c, 0x51,
+ (byte) 0x84, (byte) 0xf9, 0x71, 0x48, (byte) 0xf9, (byte) 0x88, 0x25, 0x54};
+ }
+
+ @Override
+ public int getFlags() {
+ return 0;
+ }
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PlayReadyHeader.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PlayReadyHeader.java
new file mode 100644
index 0000000..74246d0
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/PlayReadyHeader.java
@@ -0,0 +1,253 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.util.Path;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.7. ASF GUIDs
+ * <p/>
+ * <p/>
+ * ASF_Protection_System_Identifier_Object
+ * 9A04F079-9840-4286-AB92E65BE0885F95
+ * <p/>
+ * ASF_Content_Protection_System_Microsoft_PlayReady
+ * F4637010-03C3-42CD-B932B48ADF3A6A54
+ * <p/>
+ * ASF_StreamType_PlayReady_Encrypted_Command_Media
+ * 8683973A-6639-463A-ABD764F1CE3EEAE0
+ * <p/>
+ * <p/>
+ * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.5. Data Objects > 2.5.1. Payload Extension for AES in Counter Mode
+ * <p/>
+ * The sample Id is used as the IV in CTR mode. Block offset, starting at 0 and incremented by 1 after every 16 bytes, from the beginning of the sample is used as the Counter.
+ * <p/>
+ * The sample ID for each sample (media object) is stored as an ASF payload extension system with the ID of ASF_Payload_Extension_Encryption_SampleID = {6698B84E-0AFA-4330-AEB2-1C0A98D7A44D}. The payload extension can be stored as a fixed size extension of 8 bytes.
+ * <p/>
+ * The sample ID is always stored in big-endian byte order.
+ */
+public class PlayReadyHeader extends ProtectionSpecificHeader {
+ private long length;
+ private List<PlayReadyRecord> records;
+
+ public PlayReadyHeader() {
+
+ }
+
+ @Override
+ public void parse(ByteBuffer byteBuffer) {
+ /*
+ Length DWORD 32
+
+ PlayReady Record Count WORD 16
+
+ PlayReady Records See Text Varies
+
+ */
+
+ length = IsoTypeReader.readUInt32BE(byteBuffer);
+ int recordCount = IsoTypeReader.readUInt16BE(byteBuffer);
+
+ records = PlayReadyRecord.createFor(byteBuffer, recordCount);
+ }
+
+ @Override
+ public ByteBuffer getData() {
+
+ int size = 4 + 2;
+ for (PlayReadyRecord record : records) {
+ size += 2 + 2;
+ size += record.getValue().rewind().limit();
+ }
+ ByteBuffer byteBuffer = ByteBuffer.allocate(size);
+
+ IsoTypeWriter.writeUInt32BE(byteBuffer, size);
+ IsoTypeWriter.writeUInt16BE(byteBuffer, records.size());
+ for (PlayReadyRecord record : records) {
+ IsoTypeWriter.writeUInt16BE(byteBuffer, record.type);
+ IsoTypeWriter.writeUInt16BE(byteBuffer, record.getValue().limit());
+ ByteBuffer tmp4debug = record.getValue();
+ byteBuffer.put(tmp4debug);
+ }
+
+ return byteBuffer;
+ }
+
+ public void setRecords(List<PlayReadyRecord> records) {
+ this.records = records;
+ }
+
+ public List<PlayReadyRecord> getRecords() {
+ return Collections.unmodifiableList(records);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("PlayReadyHeader");
+ sb.append("{length=").append(length);
+ sb.append(", recordCount=").append(records.size());
+ sb.append(", records=").append(records);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static abstract class PlayReadyRecord {
+ int type;
+
+
+ public PlayReadyRecord(int type) {
+ this.type = type;
+ }
+
+ public static List<PlayReadyRecord> createFor(ByteBuffer byteBuffer, int recordCount) {
+ List<PlayReadyRecord> records = new ArrayList<PlayReadyRecord>(recordCount);
+
+ for (int i = 0; i < recordCount; i++) {
+ PlayReadyRecord record;
+ int type = IsoTypeReader.readUInt16BE(byteBuffer);
+ int length = IsoTypeReader.readUInt16BE(byteBuffer);
+ switch (type) {
+ case 0x1:
+ record = new RMHeader();
+ break;
+ case 0x2:
+ record = new DefaulPlayReadyRecord(0x02);
+ break;
+ case 0x3:
+ record = new EmeddedLicenseStore();
+ break;
+ default:
+ record = new DefaulPlayReadyRecord(type);
+ }
+ record.parse((ByteBuffer) byteBuffer.slice().limit(length));
+ byteBuffer.position(byteBuffer.position() + length);
+ records.add(record);
+ }
+
+ return records;
+ }
+
+ public abstract void parse(ByteBuffer bytes);
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("PlayReadyRecord");
+ sb.append("{type=").append(type);
+ sb.append(", length=").append(getValue().limit());
+// sb.append(", value=").append(Hex.encodeHex(getValue())).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public abstract ByteBuffer getValue();
+
+ public static class RMHeader extends PlayReadyRecord {
+ String header;
+
+ public RMHeader() {
+ super(0x01);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ try {
+ byte[] str = new byte[bytes.slice().limit()];
+ bytes.get(str);
+ header = new String(str, "UTF-16LE");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ byte[] headerBytes;
+ try {
+ headerBytes = header.getBytes("UTF-16LE");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ return ByteBuffer.wrap(headerBytes);
+ }
+
+ public void setHeader(String header) {
+ this.header = header;
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("RMHeader");
+ sb.append("{length=").append(getValue().limit());
+ sb.append(", header='").append(header).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ public static class EmeddedLicenseStore extends PlayReadyRecord {
+ ByteBuffer value;
+
+ public EmeddedLicenseStore() {
+ super(0x03);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ this.value = bytes.duplicate();
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("EmeddedLicenseStore");
+ sb.append("{length=").append(getValue().limit());
+ //sb.append(", value='").append(Hex.encodeHex(getValue())).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ public static class DefaulPlayReadyRecord extends PlayReadyRecord {
+ ByteBuffer value;
+
+ public DefaulPlayReadyRecord(int type) {
+ super(type);
+ }
+
+ @Override
+ public void parse(ByteBuffer bytes) {
+ this.value = bytes.duplicate();
+ }
+
+ @Override
+ public ByteBuffer getValue() {
+ return value;
+ }
+
+ }
+
+ }
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/ProtectionSpecificHeader.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/ProtectionSpecificHeader.java
new file mode 100644
index 0000000..0d2f344
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/ProtectionSpecificHeader.java
@@ -0,0 +1,79 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+
+import com.coremedia.iso.Hex;
+
+import java.lang.Class;
+import java.lang.IllegalAccessException;
+import java.lang.InstantiationException;
+import java.lang.Object;
+import java.lang.Override;
+import java.lang.RuntimeException;
+import java.lang.String;
+import java.lang.StringBuilder;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+
+public class ProtectionSpecificHeader {
+ protected static Map<UUID, Class<? extends ProtectionSpecificHeader>> uuidRegistry = new HashMap<UUID, Class<? extends ProtectionSpecificHeader>>();
+ ByteBuffer data;
+
+ static {
+ uuidRegistry.put(UUID.fromString("9A04F079-9840-4286-AB92-E65BE0885F95"), PlayReadyHeader.class);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ProtectionSpecificHeader) {
+ if (this.getClass().equals(obj.getClass())) {
+ return data.equals(((ProtectionSpecificHeader) obj).data);
+ }
+ }
+ return false;
+ }
+
+ public static ProtectionSpecificHeader createFor(UUID systemId, ByteBuffer bufferWrapper) {
+ final Class<? extends ProtectionSpecificHeader> aClass = uuidRegistry.get(systemId);
+
+ ProtectionSpecificHeader protectionSpecificHeader = new ProtectionSpecificHeader();
+ if (aClass != null) {
+ try {
+ protectionSpecificHeader = aClass.newInstance();
+
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ protectionSpecificHeader.parse(bufferWrapper);
+ return protectionSpecificHeader;
+
+ }
+
+ public void parse(ByteBuffer buffer) {
+ data = buffer;
+
+ }
+
+ public ByteBuffer getData() {
+ return data;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ProtectionSpecificHeader");
+ sb.append("{data=");
+ ByteBuffer data = getData().duplicate();
+ data.rewind();
+ byte[] bytes = new byte[data.limit()];
+ data.get(bytes);
+ sb.append(Hex.encodeHex(bytes));
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfrfBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfrfBox.java
new file mode 100644
index 0000000..1e862e9
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfrfBox.java
@@ -0,0 +1,129 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+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;
+
+/**
+ * The syntax of the fields defined in this section, specified in ABNF [RFC5234], is as follows:
+ * TfrfBox = TfrfBoxLength TfrfBoxType [TfrfBoxLongLength] TfrfBoxUUID TfrfBoxFields
+ * TfrfBoxChildren
+ * TfrfBoxType = "u" "u" "i" "d"
+ * TfrfBoxLength = BoxLength
+ * TfrfBoxLongLength = LongBoxLength
+ * TfrfBoxUUID = %xD4 %x80 %x7E %xF2 %xCA %x39 %x46 %x95
+ * %x8E %x54 %x26 %xCB %x9E %x46 %xA7 %x9F
+ * TfrfBoxFields = TfrfBoxVersion
+ * TfrfBoxFlags
+ * FragmentCount
+ * (1* TfrfBoxDataFields32) / (1* TfrfBoxDataFields64)
+ * TfrfBoxVersion = %x00 / %x01
+ * TfrfBoxFlags = 24*24 RESERVED_BIT
+ * FragmentCount = UINT8
+ * TfrfBoxDataFields32 = FragmentAbsoluteTime32
+ * FragmentDuration32
+ * TfrfBoxDataFields64 = FragmentAbsoluteTime64
+ * FragmentDuration64
+ * FragmentAbsoluteTime64 = UNSIGNED_INT32
+ * FragmentDuration64 = UNSIGNED_INT32
+ * FragmentAbsoluteTime64 = UNSIGNED_INT64
+ * FragmentDuration64 = UNSIGNED_INT64
+ * TfrfBoxChildren = *( VendorExtensionUUIDBox )
+ */
+public class TfrfBox extends AbstractFullBox {
+ public List<Entry> entries = new ArrayList<Entry>();
+
+ public TfrfBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0xd4, (byte) 0x80, (byte) 0x7e, (byte) 0xf2, (byte) 0xca, (byte) 0x39, (byte) 0x46,
+ (byte) 0x95, (byte) 0x8e, (byte) 0x54, 0x26, (byte) 0xcb, (byte) 0x9e, (byte) 0x46, (byte) 0xa7, (byte) 0x9f};
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 5 + entries.size() * (getVersion() == 0x01 ? 16 : 8);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt8(byteBuffer, entries.size());
+
+ for (Entry entry : entries) {
+ if (getVersion() == 0x01) {
+ IsoTypeWriter.writeUInt64(byteBuffer, entry.fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, entry.fragmentAbsoluteDuration);
+ } else {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.fragmentAbsoluteDuration);
+ }
+ }
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ int fragmentCount = IsoTypeReader.readUInt8(content);
+
+ for (int i = 0; i < fragmentCount; i++) {
+ Entry entry = new Entry();
+ if (getVersion() == 0x01) {
+ entry.fragmentAbsoluteTime = IsoTypeReader.readUInt64(content);
+ entry.fragmentAbsoluteDuration = IsoTypeReader.readUInt64(content);
+ } else {
+ entry.fragmentAbsoluteTime = IsoTypeReader.readUInt32(content);
+ entry.fragmentAbsoluteDuration = IsoTypeReader.readUInt32(content);
+ }
+ entries.add(entry);
+ }
+ }
+
+
+ public long getFragmentCount() {
+ return entries.size();
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TfrfBox");
+ sb.append("{entries=").append(entries);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public class Entry {
+ long fragmentAbsoluteTime;
+ long fragmentAbsoluteDuration;
+
+ public long getFragmentAbsoluteTime() {
+ return fragmentAbsoluteTime;
+ }
+
+ public long getFragmentAbsoluteDuration() {
+ return fragmentAbsoluteDuration;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Entry");
+ sb.append("{fragmentAbsoluteTime=").append(fragmentAbsoluteTime);
+ sb.append(", fragmentAbsoluteDuration=").append(fragmentAbsoluteDuration);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfxdBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfxdBox.java
new file mode 100644
index 0000000..52e8e87
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/TfxdBox.java
@@ -0,0 +1,85 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The syntax of the fields defined in this section, specified in ABNF [RFC5234], is as follows:
+ * TfxdBox = TfxdBoxLength TfxdBoxType [TfxdBoxLongLength] TfxdBoxUUID TfxdBoxFields
+ * TfxdBoxChildren
+ * TfxdBoxType = "u" "u" "i" "d"
+ * TfxdBoxLength = BoxLength
+ * TfxdBoxLongLength = LongBoxLength
+ * TfxdBoxUUID = %x6D %x1D %x9B %x05 %x42 %xD5 %x44 %xE6
+ * %x80 %xE2 %x14 %x1D %xAF %xF7 %x57 %xB2
+ * TfxdBoxFields = TfxdBoxVersion
+ * TfxdBoxFlags
+ * TfxdBoxDataFields32 / TfxdBoxDataFields64
+ * TfxdBoxVersion = %x00 / %x01
+ * TfxdBoxFlags = 24*24 RESERVED_BIT
+ * TfxdBoxDataFields32 = FragmentAbsoluteTime32
+ * FragmentDuration32
+ * TfxdBoxDataFields64 = FragmentAbsoluteTime64
+ * FragmentDuration64
+ * FragmentAbsoluteTime64 = UNSIGNED_INT32
+ * FragmentDuration64 = UNSIGNED_INT32
+ * FragmentAbsoluteTime64 = UNSIGNED_INT64
+ * FragmentDuration64 = UNSIGNED_INT64
+ * TfxdBoxChildren = *( VendorExtensionUUIDBox )
+ */
+//@ExtendedUserType(uuid = "6d1d9b05-42d5-44e6-80e2-141daff757b2")
+public class TfxdBox extends AbstractFullBox {
+ public long fragmentAbsoluteTime;
+ public long fragmentAbsoluteDuration;
+
+ public TfxdBox() {
+ super("uuid");
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return new byte[]{(byte) 0x6d, (byte) 0x1d, (byte) 0x9b, (byte) 0x05, (byte) 0x42, (byte) 0xd5, (byte) 0x44,
+ (byte) 0xe6, (byte) 0x80, (byte) 0xe2, 0x14, (byte) 0x1d, (byte) 0xaf, (byte) 0xf7, (byte) 0x57, (byte) 0xb2};
+ }
+
+ @Override
+ protected long getContentSize() {
+ return getVersion() == 0x01 ? 20 : 12;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+
+ if (getVersion() == 0x01) {
+ fragmentAbsoluteTime = IsoTypeReader.readUInt64(content);
+ fragmentAbsoluteDuration = IsoTypeReader.readUInt64(content);
+ } else {
+ fragmentAbsoluteTime = IsoTypeReader.readUInt32(content);
+ fragmentAbsoluteDuration = IsoTypeReader.readUInt32(content);
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ if (getVersion() == 0x01) {
+ IsoTypeWriter.writeUInt64(byteBuffer, fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, fragmentAbsoluteDuration);
+ } else {
+ IsoTypeWriter.writeUInt32(byteBuffer, fragmentAbsoluteTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, fragmentAbsoluteDuration);
+ }
+ }
+
+ public long getFragmentAbsoluteTime() {
+ return fragmentAbsoluteTime;
+ }
+
+ public long getFragmentAbsoluteDuration() {
+ return fragmentAbsoluteDuration;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/UuidBasedProtectionSystemSpecificHeaderBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/UuidBasedProtectionSystemSpecificHeaderBox.java
new file mode 100644
index 0000000..b147398
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/piff/UuidBasedProtectionSystemSpecificHeaderBox.java
@@ -0,0 +1,106 @@
+package com.googlecode.mp4parser.boxes.piff;
+
+import com.coremedia.iso.IsoFile;
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.util.Path;
+import com.googlecode.mp4parser.util.UUIDConverter;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.Override;import java.lang.String;import java.lang.StringBuilder;import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * aligned(8) class UuidBasedProtectionSystemSpecificHeaderBox extends FullBox(‘uuid’,
+ * extended_type=0xd08a4f18-10f3-4a82-b6c8-32d8aba183d3,
+ * version=0, flags=0)
+ * {
+ * unsigned int(8)[16] SystemID;
+ * unsigned int(32) DataSize;
+ * unsigned int(8)[DataSize] Data;
+ * }
+ */
+public class UuidBasedProtectionSystemSpecificHeaderBox extends AbstractFullBox {
+ public static byte[] USER_TYPE = new byte[]{(byte) 0xd0, (byte) 0x8a, 0x4f, 0x18, 0x10, (byte) 0xf3, 0x4a, (byte) 0x82,
+ (byte) 0xb6, (byte) 0xc8, 0x32, (byte) 0xd8, (byte) 0xab, (byte) 0xa1, (byte) 0x83, (byte) 0xd3};
+
+ UUID systemId;
+
+ ProtectionSpecificHeader protectionSpecificHeader;
+
+ public UuidBasedProtectionSystemSpecificHeaderBox() {
+ super("uuid", USER_TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 24 + protectionSpecificHeader.getData().limit();
+ }
+
+ @Override
+ public byte[] getUserType() {
+ return USER_TYPE;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt64(byteBuffer, systemId.getMostSignificantBits());
+ IsoTypeWriter.writeUInt64(byteBuffer, systemId.getLeastSignificantBits());
+ ByteBuffer data = protectionSpecificHeader.getData();
+ data.rewind();
+ IsoTypeWriter.writeUInt32(byteBuffer, data.limit());
+ byteBuffer.put(data);
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ byte[] systemIdBytes = new byte[16];
+ content.get(systemIdBytes);
+ systemId = UUIDConverter.convert(systemIdBytes);
+ int dataSize = l2i(IsoTypeReader.readUInt32(content));
+ protectionSpecificHeader = ProtectionSpecificHeader.createFor(systemId, content);
+ }
+
+ public UUID getSystemId() {
+ return systemId;
+ }
+
+ public void setSystemId(UUID systemId) {
+ this.systemId = systemId;
+ }
+
+ public String getSystemIdString() {
+ return systemId.toString();
+ }
+
+ public ProtectionSpecificHeader getProtectionSpecificHeader() {
+ return protectionSpecificHeader;
+ }
+
+ public String getProtectionSpecificHeaderString() {
+ return protectionSpecificHeader.toString();
+ }
+
+ public void setProtectionSpecificHeader(ProtectionSpecificHeader protectionSpecificHeader) {
+ this.protectionSpecificHeader = protectionSpecificHeader;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("UuidBasedProtectionSystemSpecificHeaderBox");
+ sb.append("{systemId=").append(systemId.toString());
+ sb.append(", dataSize=").append(protectionSpecificHeader.getData().limit());
+ sb.append('}');
+ return sb.toString();
+ }
+
+
+
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/all-wcprops
new file mode 100644
index 0000000..1f9ed7a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/svn/!svn/ver/683/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244
+END
+SegmentIndexBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/svn/!svn/ver/683/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/SegmentIndexBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/entries
new file mode 100644
index 0000000..954a06a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-06-23T08:51:59.024275Z
+683
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+SegmentIndexBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.567220Z
+1d0e3a16184ab4820e3c6dc9ebdcea87
+2012-06-23T08:51:59.024275Z
+683
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8722
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/text-base/SegmentIndexBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/text-base/SegmentIndexBox.java.svn-base
new file mode 100644
index 0000000..638a87b
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/.svn/text-base/SegmentIndexBox.java.svn-base
@@ -0,0 +1,283 @@
+package com.googlecode.mp4parser.boxes.threegpp26244;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <pre>
+ * aligned(8) class SegmentIndexBox extends FullBox(‘sidx’, version, 0) {
+ * unsigned int(32) reference_ID;
+ * unsigned int(32) timescale;
+ * if (version==0)
+ * {
+ * unsigned int(32) earliest_presentation_time;
+ * unsigned int(32) first_offset;
+ * }
+ * else
+ * {
+ * unsigned int(64) earliest_presentation_time;
+ * unsigned int(64) first_offset;
+ * }
+ * unsigned int(16) reserved = 0;
+ * unsigned int(16) reference_count;
+ * for(i=1; i <= reference_count; i++)
+ * {
+ * bit (1) reference_type;
+ * unsigned int(31) referenced_size;
+ * unsigned int(32) subsegment_duration;
+ * bit(1) starts_with_SAP;
+ * unsigned int(3) SAP_type;
+ * unsigned int(28) SAP_delta_time;
+ * }
+ * }
+ * </pre>
+ */
+public class SegmentIndexBox extends AbstractFullBox {
+ public static final String TYPE = "sidx";
+ List<Entry> entries = new ArrayList<Entry>();
+
+ long referenceId;
+ long timeScale;
+ long earliestPresentationTime;
+ long firstOffset;
+ int reserved;
+
+
+ public SegmentIndexBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 4;
+ size += 4;
+ size += 4;
+ size += getVersion() == 0 ? 8 : 16;
+ size += 2; // reserved
+ size += 2; // reference count
+
+ size += entries.size() * 12;
+
+ return size;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, referenceId);
+ IsoTypeWriter.writeUInt32(byteBuffer, timeScale);
+ if (getVersion() == 0) {
+ IsoTypeWriter.writeUInt32(byteBuffer, earliestPresentationTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, firstOffset);
+ } else {
+ IsoTypeWriter.writeUInt64(byteBuffer, earliestPresentationTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, firstOffset);
+ }
+ IsoTypeWriter.writeUInt16(byteBuffer, reserved);
+ IsoTypeWriter.writeUInt16(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ BitWriterBuffer b = new BitWriterBuffer(byteBuffer);
+ b.writeBits(entry.getReferenceType(), 1);
+ b.writeBits(entry.getReferencedSize(), 31);
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getSubsegmentDuration());
+ b = new BitWriterBuffer(byteBuffer);
+ b.writeBits(entry.getStartsWithSap(), 1);
+ b.writeBits(entry.getSapType(), 3);
+ b.writeBits(entry.getSapDeltaTime(), 28);
+ }
+
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ referenceId = IsoTypeReader.readUInt32(content);
+ timeScale = IsoTypeReader.readUInt32(content);
+ if (getVersion() == 0) {
+ earliestPresentationTime = IsoTypeReader.readUInt32(content);
+ firstOffset = IsoTypeReader.readUInt32(content);
+ } else {
+ earliestPresentationTime = IsoTypeReader.readUInt64(content);
+ firstOffset = IsoTypeReader.readUInt64(content);
+ }
+ reserved = IsoTypeReader.readUInt16(content);
+ int numEntries = IsoTypeReader.readUInt16(content);
+ for (int i = 0; i < numEntries; i++) {
+ BitReaderBuffer b = new BitReaderBuffer(content);
+ Entry e = new Entry();
+ e.setReferenceType((byte) b.readBits(1));
+ e.setReferencedSize(b.readBits(31));
+ e.setSubsegmentDuration(IsoTypeReader.readUInt32(content));
+ b = new BitReaderBuffer(content);
+ e.setStartsWithSap((byte) b.readBits(1));
+ e.setSapType((byte) b.readBits(3));
+ e.setSapDeltaTime(b.readBits(28));
+ entries.add(e);
+ }
+ }
+
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public long getReferenceId() {
+ return referenceId;
+ }
+
+ public void setReferenceId(long referenceId) {
+ this.referenceId = referenceId;
+ }
+
+ public long getTimeScale() {
+ return timeScale;
+ }
+
+ public void setTimeScale(long timeScale) {
+ this.timeScale = timeScale;
+ }
+
+ public long getEarliestPresentationTime() {
+ return earliestPresentationTime;
+ }
+
+ public void setEarliestPresentationTime(long earliestPresentationTime) {
+ this.earliestPresentationTime = earliestPresentationTime;
+ }
+
+ public long getFirstOffset() {
+ return firstOffset;
+ }
+
+ public void setFirstOffset(long firstOffset) {
+ this.firstOffset = firstOffset;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public static class Entry {
+ byte referenceType;
+ int referencedSize;
+ long subsegmentDuration;
+ byte startsWithSap;
+ byte sapType;
+ int sapDeltaTime;
+
+ public Entry() {
+ }
+
+ public Entry(byte referenceType, int referencedSize, long subsegmentDuration, byte startsWithSap, byte sapType, int sapDeltaTime) {
+ this.referenceType = referenceType;
+ this.referencedSize = referencedSize;
+ this.subsegmentDuration = subsegmentDuration;
+ this.startsWithSap = startsWithSap;
+ this.sapType = sapType;
+ this.sapDeltaTime = sapDeltaTime;
+ }
+
+ public byte getReferenceType() {
+ return referenceType;
+ }
+
+ public void setReferenceType(byte referenceType) {
+ this.referenceType = referenceType;
+ }
+
+ public int getReferencedSize() {
+ return referencedSize;
+ }
+
+ public void setReferencedSize(int referencedSize) {
+ this.referencedSize = referencedSize;
+ }
+
+ public long getSubsegmentDuration() {
+ return subsegmentDuration;
+ }
+
+ public void setSubsegmentDuration(long subsegmentDuration) {
+ this.subsegmentDuration = subsegmentDuration;
+ }
+
+ public byte getStartsWithSap() {
+ return startsWithSap;
+ }
+
+ public void setStartsWithSap(byte startsWithSap) {
+ this.startsWithSap = startsWithSap;
+ }
+
+ public byte getSapType() {
+ return sapType;
+ }
+
+ public void setSapType(byte sapType) {
+ this.sapType = sapType;
+ }
+
+ public int getSapDeltaTime() {
+ return sapDeltaTime;
+ }
+
+ public void setSapDeltaTime(int sapDeltaTime) {
+ this.sapDeltaTime = sapDeltaTime;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "referenceType=" + referenceType +
+ ", referencedSize=" + referencedSize +
+ ", subsegmentDuration=" + subsegmentDuration +
+ ", startsWithSap=" + startsWithSap +
+ ", sapType=" + sapType +
+ ", sapDeltaTime=" + sapDeltaTime +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Entry entry = (Entry) o;
+
+ if (referenceType != entry.referenceType) return false;
+ if (referencedSize != entry.referencedSize) return false;
+ if (sapDeltaTime != entry.sapDeltaTime) return false;
+ if (sapType != entry.sapType) return false;
+ if (startsWithSap != entry.startsWithSap) return false;
+ if (subsegmentDuration != entry.subsegmentDuration) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) referenceType;
+ result = 31 * result + referencedSize;
+ result = 31 * result + (int) (subsegmentDuration ^ (subsegmentDuration >>> 32));
+ result = 31 * result + (int) startsWithSap;
+ result = 31 * result + (int) sapType;
+ result = 31 * result + sapDeltaTime;
+ return result;
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/SegmentIndexBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/SegmentIndexBox.java
new file mode 100644
index 0000000..638a87b
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26244/SegmentIndexBox.java
@@ -0,0 +1,283 @@
+package com.googlecode.mp4parser.boxes.threegpp26244;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
+import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <pre>
+ * aligned(8) class SegmentIndexBox extends FullBox(‘sidx’, version, 0) {
+ * unsigned int(32) reference_ID;
+ * unsigned int(32) timescale;
+ * if (version==0)
+ * {
+ * unsigned int(32) earliest_presentation_time;
+ * unsigned int(32) first_offset;
+ * }
+ * else
+ * {
+ * unsigned int(64) earliest_presentation_time;
+ * unsigned int(64) first_offset;
+ * }
+ * unsigned int(16) reserved = 0;
+ * unsigned int(16) reference_count;
+ * for(i=1; i <= reference_count; i++)
+ * {
+ * bit (1) reference_type;
+ * unsigned int(31) referenced_size;
+ * unsigned int(32) subsegment_duration;
+ * bit(1) starts_with_SAP;
+ * unsigned int(3) SAP_type;
+ * unsigned int(28) SAP_delta_time;
+ * }
+ * }
+ * </pre>
+ */
+public class SegmentIndexBox extends AbstractFullBox {
+ public static final String TYPE = "sidx";
+ List<Entry> entries = new ArrayList<Entry>();
+
+ long referenceId;
+ long timeScale;
+ long earliestPresentationTime;
+ long firstOffset;
+ int reserved;
+
+
+ public SegmentIndexBox() {
+ super(TYPE);
+ }
+
+ @Override
+ protected long getContentSize() {
+ long size = 4;
+ size += 4;
+ size += 4;
+ size += getVersion() == 0 ? 8 : 16;
+ size += 2; // reserved
+ size += 2; // reference count
+
+ size += entries.size() * 12;
+
+ return size;
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, referenceId);
+ IsoTypeWriter.writeUInt32(byteBuffer, timeScale);
+ if (getVersion() == 0) {
+ IsoTypeWriter.writeUInt32(byteBuffer, earliestPresentationTime);
+ IsoTypeWriter.writeUInt32(byteBuffer, firstOffset);
+ } else {
+ IsoTypeWriter.writeUInt64(byteBuffer, earliestPresentationTime);
+ IsoTypeWriter.writeUInt64(byteBuffer, firstOffset);
+ }
+ IsoTypeWriter.writeUInt16(byteBuffer, reserved);
+ IsoTypeWriter.writeUInt16(byteBuffer, entries.size());
+ for (Entry entry : entries) {
+ BitWriterBuffer b = new BitWriterBuffer(byteBuffer);
+ b.writeBits(entry.getReferenceType(), 1);
+ b.writeBits(entry.getReferencedSize(), 31);
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getSubsegmentDuration());
+ b = new BitWriterBuffer(byteBuffer);
+ b.writeBits(entry.getStartsWithSap(), 1);
+ b.writeBits(entry.getSapType(), 3);
+ b.writeBits(entry.getSapDeltaTime(), 28);
+ }
+
+ }
+
+ @Override
+ protected void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ referenceId = IsoTypeReader.readUInt32(content);
+ timeScale = IsoTypeReader.readUInt32(content);
+ if (getVersion() == 0) {
+ earliestPresentationTime = IsoTypeReader.readUInt32(content);
+ firstOffset = IsoTypeReader.readUInt32(content);
+ } else {
+ earliestPresentationTime = IsoTypeReader.readUInt64(content);
+ firstOffset = IsoTypeReader.readUInt64(content);
+ }
+ reserved = IsoTypeReader.readUInt16(content);
+ int numEntries = IsoTypeReader.readUInt16(content);
+ for (int i = 0; i < numEntries; i++) {
+ BitReaderBuffer b = new BitReaderBuffer(content);
+ Entry e = new Entry();
+ e.setReferenceType((byte) b.readBits(1));
+ e.setReferencedSize(b.readBits(31));
+ e.setSubsegmentDuration(IsoTypeReader.readUInt32(content));
+ b = new BitReaderBuffer(content);
+ e.setStartsWithSap((byte) b.readBits(1));
+ e.setSapType((byte) b.readBits(3));
+ e.setSapDeltaTime(b.readBits(28));
+ entries.add(e);
+ }
+ }
+
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ public long getReferenceId() {
+ return referenceId;
+ }
+
+ public void setReferenceId(long referenceId) {
+ this.referenceId = referenceId;
+ }
+
+ public long getTimeScale() {
+ return timeScale;
+ }
+
+ public void setTimeScale(long timeScale) {
+ this.timeScale = timeScale;
+ }
+
+ public long getEarliestPresentationTime() {
+ return earliestPresentationTime;
+ }
+
+ public void setEarliestPresentationTime(long earliestPresentationTime) {
+ this.earliestPresentationTime = earliestPresentationTime;
+ }
+
+ public long getFirstOffset() {
+ return firstOffset;
+ }
+
+ public void setFirstOffset(long firstOffset) {
+ this.firstOffset = firstOffset;
+ }
+
+ public int getReserved() {
+ return reserved;
+ }
+
+ public void setReserved(int reserved) {
+ this.reserved = reserved;
+ }
+
+ public static class Entry {
+ byte referenceType;
+ int referencedSize;
+ long subsegmentDuration;
+ byte startsWithSap;
+ byte sapType;
+ int sapDeltaTime;
+
+ public Entry() {
+ }
+
+ public Entry(byte referenceType, int referencedSize, long subsegmentDuration, byte startsWithSap, byte sapType, int sapDeltaTime) {
+ this.referenceType = referenceType;
+ this.referencedSize = referencedSize;
+ this.subsegmentDuration = subsegmentDuration;
+ this.startsWithSap = startsWithSap;
+ this.sapType = sapType;
+ this.sapDeltaTime = sapDeltaTime;
+ }
+
+ public byte getReferenceType() {
+ return referenceType;
+ }
+
+ public void setReferenceType(byte referenceType) {
+ this.referenceType = referenceType;
+ }
+
+ public int getReferencedSize() {
+ return referencedSize;
+ }
+
+ public void setReferencedSize(int referencedSize) {
+ this.referencedSize = referencedSize;
+ }
+
+ public long getSubsegmentDuration() {
+ return subsegmentDuration;
+ }
+
+ public void setSubsegmentDuration(long subsegmentDuration) {
+ this.subsegmentDuration = subsegmentDuration;
+ }
+
+ public byte getStartsWithSap() {
+ return startsWithSap;
+ }
+
+ public void setStartsWithSap(byte startsWithSap) {
+ this.startsWithSap = startsWithSap;
+ }
+
+ public byte getSapType() {
+ return sapType;
+ }
+
+ public void setSapType(byte sapType) {
+ this.sapType = sapType;
+ }
+
+ public int getSapDeltaTime() {
+ return sapDeltaTime;
+ }
+
+ public void setSapDeltaTime(int sapDeltaTime) {
+ this.sapDeltaTime = sapDeltaTime;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "referenceType=" + referenceType +
+ ", referencedSize=" + referencedSize +
+ ", subsegmentDuration=" + subsegmentDuration +
+ ", startsWithSap=" + startsWithSap +
+ ", sapType=" + sapType +
+ ", sapDeltaTime=" + sapDeltaTime +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Entry entry = (Entry) o;
+
+ if (referenceType != entry.referenceType) return false;
+ if (referencedSize != entry.referencedSize) return false;
+ if (sapDeltaTime != entry.sapDeltaTime) return false;
+ if (sapType != entry.sapType) return false;
+ if (startsWithSap != entry.startsWithSap) return false;
+ if (subsegmentDuration != entry.subsegmentDuration) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) referenceType;
+ result = 31 * result + referencedSize;
+ result = 31 * result + (int) (subsegmentDuration ^ (subsegmentDuration >>> 32));
+ result = 31 * result + (int) startsWithSap;
+ result = 31 * result + (int) sapType;
+ result = 31 * result + sapDeltaTime;
+ return result;
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/all-wcprops
new file mode 100644
index 0000000..92aa246
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245
+END
+FontTableBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/FontTableBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/entries
new file mode 100644
index 0000000..a126e77
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+FontTableBox.java
+file
+
+
+
+
+2012-09-14T17:27:50.567220Z
+edbb8c6ba22fb01c3b13ce20e34513b8
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2444
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/text-base/FontTableBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/text-base/FontTableBox.java.svn-base
new file mode 100644
index 0000000..2e3f640
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/.svn/text-base/FontTableBox.java.svn-base
@@ -0,0 +1,95 @@
+package com.googlecode.mp4parser.boxes.threegpp26245;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractBox;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class FontTableBox extends AbstractBox {
+ List<FontRecord> entries = new LinkedList<FontRecord>();
+
+ public FontTableBox() {
+ super("ftab");
+ }
+
+ @Override
+ protected long getContentSize() {
+ int size = 2;
+ for (FontRecord fontRecord : entries) {
+ size += fontRecord.getSize();
+ }
+ return size;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ int numberOfRecords = IsoTypeReader.readUInt16(content);
+ for (int i = 0; i < numberOfRecords; i++) {
+ FontRecord fr = new FontRecord();
+ fr.parse(content);
+ entries.add(fr);
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ IsoTypeWriter.writeUInt16(byteBuffer, entries.size());
+ for (FontRecord record : entries) {
+ record.getContent(byteBuffer);
+ }
+ }
+
+ public List<FontRecord> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<FontRecord> entries) {
+ this.entries = entries;
+ }
+
+ public static class FontRecord {
+ int fontId;
+ String fontname;
+
+ public FontRecord() {
+ }
+
+ public FontRecord(int fontId, String fontname) {
+ this.fontId = fontId;
+ this.fontname = fontname;
+ }
+
+ public void parse(ByteBuffer bb) {
+ fontId = IsoTypeReader.readUInt16(bb);
+ int length = IsoTypeReader.readUInt8(bb);
+ fontname = IsoTypeReader.readString(bb, length);
+ }
+
+ public void getContent(ByteBuffer bb) {
+ IsoTypeWriter.writeUInt16(bb, fontId);
+ IsoTypeWriter.writeUInt8(bb, fontname.length());
+ bb.put(Utf8.convert(fontname));
+ }
+
+ public int getSize() {
+ return Utf8.utf8StringLengthInBytes(fontname) + 3;
+ }
+
+ @Override
+ public String toString() {
+ return "FontRecord{" +
+ "fontId=" + fontId +
+ ", fontname='" + fontname + '\'' +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/FontTableBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/FontTableBox.java
new file mode 100644
index 0000000..2e3f640
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/threegpp26245/FontTableBox.java
@@ -0,0 +1,95 @@
+package com.googlecode.mp4parser.boxes.threegpp26245;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractBox;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public class FontTableBox extends AbstractBox {
+ List<FontRecord> entries = new LinkedList<FontRecord>();
+
+ public FontTableBox() {
+ super("ftab");
+ }
+
+ @Override
+ protected long getContentSize() {
+ int size = 2;
+ for (FontRecord fontRecord : entries) {
+ size += fontRecord.getSize();
+ }
+ return size;
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ int numberOfRecords = IsoTypeReader.readUInt16(content);
+ for (int i = 0; i < numberOfRecords; i++) {
+ FontRecord fr = new FontRecord();
+ fr.parse(content);
+ entries.add(fr);
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ IsoTypeWriter.writeUInt16(byteBuffer, entries.size());
+ for (FontRecord record : entries) {
+ record.getContent(byteBuffer);
+ }
+ }
+
+ public List<FontRecord> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<FontRecord> entries) {
+ this.entries = entries;
+ }
+
+ public static class FontRecord {
+ int fontId;
+ String fontname;
+
+ public FontRecord() {
+ }
+
+ public FontRecord(int fontId, String fontname) {
+ this.fontId = fontId;
+ this.fontname = fontname;
+ }
+
+ public void parse(ByteBuffer bb) {
+ fontId = IsoTypeReader.readUInt16(bb);
+ int length = IsoTypeReader.readUInt8(bb);
+ fontname = IsoTypeReader.readString(bb, length);
+ }
+
+ public void getContent(ByteBuffer bb) {
+ IsoTypeWriter.writeUInt16(bb, fontId);
+ IsoTypeWriter.writeUInt8(bb, fontname.length());
+ bb.put(Utf8.convert(fontname));
+ }
+
+ public int getSize() {
+ return Utf8.utf8StringLengthInBytes(fontname) + 3;
+ }
+
+ @Override
+ public String toString() {
+ return "FontRecord{" +
+ "fontId=" + fontId +
+ ", fontname='" + fontname + '\'' +
+ '}';
+ }
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/all-wcprops b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/all-wcprops
new file mode 100644
index 0000000..4e87a87
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet
+END
+BaseLocationBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/svn/!svn/ver/507/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/BaseLocationBox.java
+END
+AssetInformationBox.java
+K 25
+svn:wc:ra_dav:version-url
+V 115
+/svn/!svn/ver/505/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/AssetInformationBox.java
+END
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/entries b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/entries
new file mode 100644
index 0000000..c7166b8
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+778
+http://mp4parser.googlecode.com/svn/trunk/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet
+http://mp4parser.googlecode.com/svn
+
+
+
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7decde4b-c250-0410-a0da-51896bc88be6
+
+BaseLocationBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+40378a4f505496f720804c1f201fc542
+2012-04-21T22:05:38.425329Z
+507
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3319
+
+AssetInformationBox.java
+file
+
+
+
+
+2012-09-14T17:27:51.307230Z
+a43de0d08b7416e7a9034f0840cc2eeb
+2012-04-21T21:18:31.685061Z
+505
+Sebastian.Annies@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2063
+
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/AssetInformationBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/AssetInformationBox.java.svn-base
new file mode 100644
index 0000000..a2a9e8a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/AssetInformationBox.java.svn-base
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.ultraviolet;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * AssetInformationBox as defined Common File Format Spec.
+ */
+public class AssetInformationBox extends AbstractFullBox {
+ String apid = "";
+ String profileVersion = "0000";
+
+ public AssetInformationBox() {
+ super("ainf");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return Utf8.utf8StringLengthInBytes(apid) + 9;
+ }
+
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(profileVersion), 0, 4);
+ byteBuffer.put(Utf8.convert(apid));
+ byteBuffer.put((byte) 0);
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ profileVersion = IsoTypeReader.readString(content, 4);
+ apid = IsoTypeReader.readString(content);
+ content = null;
+ }
+
+ public String getApid() {
+ return apid;
+ }
+
+ public void setApid(String apid) {
+ this.apid = apid;
+ }
+
+ public String getProfileVersion() {
+ return profileVersion;
+ }
+
+ public void setProfileVersion(String profileVersion) {
+ assert profileVersion != null && profileVersion.length() == 4;
+ this.profileVersion = profileVersion;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/BaseLocationBox.java.svn-base b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/BaseLocationBox.java.svn-base
new file mode 100644
index 0000000..1c63293
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/.svn/text-base/BaseLocationBox.java.svn-base
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.ultraviolet;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public class BaseLocationBox extends AbstractFullBox {
+ String baseLocation = "";
+ String purchaseLocation = "";
+
+ public BaseLocationBox() {
+ super("bloc");
+ }
+
+ public BaseLocationBox(String baseLocation, String purchaseLocation) {
+ super("bloc");
+ this.baseLocation = baseLocation;
+ this.purchaseLocation = purchaseLocation;
+ }
+
+ public String getBaseLocation() {
+ return baseLocation;
+ }
+
+ public void setBaseLocation(String baseLocation) {
+ this.baseLocation = baseLocation;
+ }
+
+ public String getPurchaseLocation() {
+ return purchaseLocation;
+ }
+
+ public void setPurchaseLocation(String purchaseLocation) {
+ this.purchaseLocation = purchaseLocation;
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 1028;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ baseLocation = IsoTypeReader.readString(content);
+ content.get(new byte[256 - Utf8.utf8StringLengthInBytes(baseLocation) - 1]);
+ purchaseLocation = IsoTypeReader.readString(content);
+ content.get(new byte[256 - Utf8.utf8StringLengthInBytes(purchaseLocation) - 1]);
+ content.get(new byte[512]);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(baseLocation));
+ byteBuffer.put(new byte[256 - Utf8.utf8StringLengthInBytes(baseLocation)]); // string plus term zero
+ byteBuffer.put(Utf8.convert(purchaseLocation));
+ byteBuffer.put(new byte[256 - Utf8.utf8StringLengthInBytes(purchaseLocation)]); // string plus term zero
+ byteBuffer.put(new byte[512]);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BaseLocationBox that = (BaseLocationBox) o;
+
+ if (baseLocation != null ? !baseLocation.equals(that.baseLocation) : that.baseLocation != null) return false;
+ if (purchaseLocation != null ? !purchaseLocation.equals(that.purchaseLocation) : that.purchaseLocation != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = baseLocation != null ? baseLocation.hashCode() : 0;
+ result = 31 * result + (purchaseLocation != null ? purchaseLocation.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/AssetInformationBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/AssetInformationBox.java
new file mode 100644
index 0000000..a2a9e8a
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/AssetInformationBox.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.ultraviolet;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ * AssetInformationBox as defined Common File Format Spec.
+ */
+public class AssetInformationBox extends AbstractFullBox {
+ String apid = "";
+ String profileVersion = "0000";
+
+ public AssetInformationBox() {
+ super("ainf");
+ }
+
+ @Override
+ protected long getContentSize() {
+ return Utf8.utf8StringLengthInBytes(apid) + 9;
+ }
+
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(profileVersion), 0, 4);
+ byteBuffer.put(Utf8.convert(apid));
+ byteBuffer.put((byte) 0);
+ }
+
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ profileVersion = IsoTypeReader.readString(content, 4);
+ apid = IsoTypeReader.readString(content);
+ content = null;
+ }
+
+ public String getApid() {
+ return apid;
+ }
+
+ public void setApid(String apid) {
+ this.apid = apid;
+ }
+
+ public String getProfileVersion() {
+ return profileVersion;
+ }
+
+ public void setProfileVersion(String profileVersion) {
+ assert profileVersion != null && profileVersion.length() == 4;
+ this.profileVersion = profileVersion;
+ }
+}
diff --git a/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/BaseLocationBox.java b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/BaseLocationBox.java
new file mode 100644
index 0000000..1c63293
--- /dev/null
+++ b/isoparser/src/main/java/com/googlecode/mp4parser/boxes/ultraviolet/BaseLocationBox.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2011 castLabs, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.googlecode.mp4parser.boxes.ultraviolet;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.Utf8;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ */
+public class BaseLocationBox extends AbstractFullBox {
+ String baseLocation = "";
+ String purchaseLocation = "";
+
+ public BaseLocationBox() {
+ super("bloc");
+ }
+
+ public BaseLocationBox(String baseLocation, String purchaseLocation) {
+ super("bloc");
+ this.baseLocation = baseLocation;
+ this.purchaseLocation = purchaseLocation;
+ }
+
+ public String getBaseLocation() {
+ return baseLocation;
+ }
+
+ public void setBaseLocation(String baseLocation) {
+ this.baseLocation = baseLocation;
+ }
+
+ public String getPurchaseLocation() {
+ return purchaseLocation;
+ }
+
+ public void setPurchaseLocation(String purchaseLocation) {
+ this.purchaseLocation = purchaseLocation;
+ }
+
+ @Override
+ protected long getContentSize() {
+ return 1028;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ baseLocation = IsoTypeReader.readString(content);
+ content.get(new byte[256 - Utf8.utf8StringLengthInBytes(baseLocation) - 1]);
+ purchaseLocation = IsoTypeReader.readString(content);
+ content.get(new byte[256 - Utf8.utf8StringLengthInBytes(purchaseLocation) - 1]);
+ content.get(new byte[512]);
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ byteBuffer.put(Utf8.convert(baseLocation));
+ byteBuffer.put(new byte[256 - Utf8.utf8StringLengthInBytes(baseLocation)]); // string plus term zero
+ byteBuffer.put(Utf8.convert(purchaseLocation));
+ byteBuffer.put(new byte[256 - Utf8.utf8StringLengthInBytes(purchaseLocation)]); // string plus term zero
+ byteBuffer.put(new byte[512]);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BaseLocationBox that = (BaseLocationBox) o;
+
+ if (baseLocation != null ? !baseLocation.equals(that.baseLocation) : that.baseLocation != null) return false;
+ if (purchaseLocation != null ? !purchaseLocation.equals(that.purchaseLocation) : that.purchaseLocation != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = baseLocation != null ? baseLocation.hashCode() : 0;
+ result = 31 * result + (purchaseLocation != null ? purchaseLocation.hashCode() : 0);
+ return result;
+ }
+}