1/* 2 * Copyright 2011 castLabs, Berlin 3 * 4 * Licensed under the Apache License, Version 2.0 (the License); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an AS IS BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.googlecode.mp4parser.boxes.mp4.objectdescriptors; 18 19import com.coremedia.iso.IsoTypeReader; 20 21import java.io.IOException; 22import java.lang.reflect.Modifier; 23import java.nio.ByteBuffer; 24import java.util.HashMap; 25import java.util.HashSet; 26import java.util.Map; 27import java.util.Set; 28import java.util.logging.Level; 29import java.util.logging.Logger; 30 31/* class tag values of 14496-1 320x00 Forbidden 330x01 ObjectDescrTag 340x02 InitialObjectDescrTag 350x03 ES_DescrTag 360x04 DecoderConfigDescrTag 370x05 DecSpecificInfoTag 380x06 SLConfigDescrTag 390x07 ContentIdentDescrTag 400x08 SupplContentIdentDescrTag 410x09 IPI_DescrPointerTag 420x0A IPMP_DescrPointerTag 430x0B IPMP_DescrTag 440x0C QoS_DescrTag 450x0D RegistrationDescrTag 460x0E ES_ID_IncTag 470x0F ES_ID_RefTag 480x10 MP4_IOD_Tag 490x11 MP4_OD_Tag 500x12 IPL_DescrPointerRefTag 510x13 ExtensionProfileLevelDescrTag 520x14 profileLevelIndicationIndexDescrTag 530x15-0x3F Reserved for ISO use 540x40 ContentClassificationDescrTag 550x41 KeyWordDescrTag 560x42 RatingDescrTag 570x43 LanguageDescrTag 580x44 ShortTextualDescrTag 590x45 ExpandedTextualDescrTag 600x46 ContentCreatorNameDescrTag 610x47 ContentCreationDateDescrTag 620x48 OCICreatorNameDescrTag 630x49 OCICreationDateDescrTag 640x4A SmpteCameraPositionDescrTag 650x4B SegmentDescrTag 660x4C MediaTimeDescrTag 670x4D-0x5F Reserved for ISO use (OCI extensions) 680x60 IPMP_ToolsListDescrTag 690x61 IPMP_ToolTag 700x62 M4MuxTimingDescrTag 710x63 M4MuxCodeTableDescrTag 720x64 ExtSLConfigDescrTag 730x65 M4MuxBufferSizeDescrTag 740x66 M4MuxIdentDescrTag 750x67 DependencyPointerTag 760x68 DependencyMarkerTag 770x69 M4MuxChannelDescrTag 780x6A-0xBF Reserved for ISO use 790xC0-0xFE User private 800xFF Forbidden 81 */ 82 83/* objectTypeIndication as of 14496-1 840x00 Forbidden 850x01 Systems ISO/IEC 14496-1 a 860x02 Systems ISO/IEC 14496-1 b 870x03 Interaction Stream 880x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c 890x05 Systems ISO/IEC 14496-1 AFX d 900x06 Font Data Stream 910x07 Synthesized Texture Stream 920x08 Streaming Text Stream 930x09-0x1F reserved for ISO use 940x20 Visual ISO/IEC 14496-2 e 950x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f 960x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f 970x23-0x3F reserved for ISO use 980x40 Audio ISO/IEC 14496-3 g 990x41-0x5F reserved for ISO use 1000x60 Visual ISO/IEC 13818-2 Simple Profile 1010x61 Visual ISO/IEC 13818-2 Main Profile 1020x62 Visual ISO/IEC 13818-2 SNR Profile 1030x63 Visual ISO/IEC 13818-2 Spatial Profile 1040x64 Visual ISO/IEC 13818-2 High Profile 1050x65 Visual ISO/IEC 13818-2 422 Profile 1060x66 Audio ISO/IEC 13818-7 Main Profile 1070x67 Audio ISO/IEC 13818-7 LowComplexity Profile 1080x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile 1090x69 Audio ISO/IEC 13818-3 1100x6A Visual ISO/IEC 11172-2 1110x6B Audio ISO/IEC 11172-3 1120x6C Visual ISO/IEC 10918-1 1130x6D reserved for registration authority 1140x6E Visual ISO/IEC 15444-1 1150x6F - 0x9F reserved for ISO use 1160xA0 - 0xBF reserved for registration authority i 1170xC0 - 0xE0 user private 1180xE1 reserved for registration authority i 1190xE2 - 0xFE user private 1200xFF no object type specified h 121 */ 122public class ObjectDescriptorFactory { 123 protected static Logger log = Logger.getLogger(ObjectDescriptorFactory.class.getName()); 124 125 protected static Map<Integer, Map<Integer, Class<? extends BaseDescriptor>>> descriptorRegistry = new HashMap<Integer, Map<Integer, Class<? extends BaseDescriptor>>>(); 126 127 static { 128 Set<Class<? extends BaseDescriptor>> annotated = new HashSet<Class<? extends BaseDescriptor>>(); 129 130 annotated.add(DecoderSpecificInfo.class); 131 annotated.add(SLConfigDescriptor.class); 132 annotated.add(BaseDescriptor.class); 133 annotated.add(ExtensionDescriptor.class); 134 annotated.add(ObjectDescriptorBase.class); 135 annotated.add(ProfileLevelIndicationDescriptor.class); 136 annotated.add(AudioSpecificConfig.class); 137 annotated.add(ExtensionProfileLevelDescriptor.class); 138 annotated.add(ESDescriptor.class); 139 annotated.add(DecoderConfigDescriptor.class); 140 //annotated.add(ObjectDescriptor.class); 141 142 for (Class<? extends BaseDescriptor> clazz : annotated) { 143 final Descriptor descriptor = clazz.getAnnotation(Descriptor.class); 144 final int[] tags = descriptor.tags(); 145 final int objectTypeInd = descriptor.objectTypeIndication(); 146 147 Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeInd); 148 if (tagMap == null) { 149 tagMap = new HashMap<Integer, Class<? extends BaseDescriptor>>(); 150 } 151 for (int tag : tags) { 152 tagMap.put(tag, clazz); 153 } 154 descriptorRegistry.put(objectTypeInd, tagMap); 155 } 156 } 157 158 public static BaseDescriptor createFrom(int objectTypeIndication, ByteBuffer bb) throws IOException { 159 int tag = IsoTypeReader.readUInt8(bb); 160 161 Map<Integer, Class<? extends BaseDescriptor>> tagMap = descriptorRegistry.get(objectTypeIndication); 162 if (tagMap == null) { 163 tagMap = descriptorRegistry.get(-1); 164 } 165 Class<? extends BaseDescriptor> aClass = tagMap.get(tag); 166 167// if (tag == 0x00) { 168// log.warning("Found illegal tag 0x00! objectTypeIndication " + Integer.toHexString(objectTypeIndication) + 169// " and tag " + Integer.toHexString(tag) + " using: " + aClass); 170// aClass = BaseDescriptor.class; 171// } 172 173 BaseDescriptor baseDescriptor; 174 if (aClass == null || aClass.isInterface() || Modifier.isAbstract(aClass.getModifiers())) { 175 log.warning("No ObjectDescriptor found for objectTypeIndication " + Integer.toHexString(objectTypeIndication) + 176 " and tag " + Integer.toHexString(tag) + " found: " + aClass); 177 baseDescriptor = new UnknownDescriptor(); 178 } else { 179 try { 180 baseDescriptor = aClass.newInstance(); 181 } catch (Exception e) { 182 log.log(Level.SEVERE, "Couldn't instantiate BaseDescriptor class " + aClass + " for objectTypeIndication " + objectTypeIndication + " and tag " + tag, e); 183 throw new RuntimeException(e); 184 } 185 } 186 baseDescriptor.parse(tag, bb); 187 return baseDescriptor; 188 } 189} 190