/* * 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; } }