/* * Copyright (C) 2011 in-somnia * * This file is part of JAAD. * * JAAD is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * JAAD is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.jaad.mp4.boxes; import java.io.IOException; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import net.sourceforge.jaad.mp4.MP4InputStream; import net.sourceforge.jaad.mp4.boxes.impl.*; import net.sourceforge.jaad.mp4.boxes.impl.fd.*; import net.sourceforge.jaad.mp4.boxes.impl.meta.*; import net.sourceforge.jaad.mp4.boxes.impl.oma.*; import net.sourceforge.jaad.mp4.boxes.impl.sampleentries.*; import net.sourceforge.jaad.mp4.boxes.impl.sampleentries.codec.*; import net.sourceforge.jaad.mp4.boxes.impl.ESDBox; import net.sourceforge.jaad.mp4.boxes.impl.drm.FairPlayDataBox; public class BoxFactory implements BoxTypes { private static final Logger LOGGER = Logger.getLogger("MP4 Boxes"); static { for(Handler h : LOGGER.getHandlers()) { LOGGER.removeHandler(h); } LOGGER.setLevel(Level.WARNING); final ConsoleHandler h = new ConsoleHandler(); h.setLevel(Level.ALL); LOGGER.addHandler(h); } private static final Map<Long, Class<? extends BoxImpl>> BOX_CLASSES = new HashMap<Long, Class<? extends BoxImpl>>(); private static final Map<Long, Class<? extends BoxImpl>[]> BOX_MULTIPLE_CLASSES = new HashMap<Long, Class<? extends BoxImpl>[]>(); private static final Map<Long, String[]> PARAMETER = new HashMap<Long, String[]>(); static { //classes BOX_CLASSES.put(ADDITIONAL_METADATA_CONTAINER_BOX, BoxImpl.class); BOX_CLASSES.put(APPLE_LOSSLESS_BOX, AppleLosslessBox.class); BOX_CLASSES.put(BINARY_XML_BOX, BinaryXMLBox.class); BOX_CLASSES.put(BIT_RATE_BOX, BitRateBox.class); BOX_CLASSES.put(CHAPTER_BOX, ChapterBox.class); BOX_CLASSES.put(CHUNK_OFFSET_BOX, ChunkOffsetBox.class); BOX_CLASSES.put(CHUNK_LARGE_OFFSET_BOX, ChunkOffsetBox.class); BOX_CLASSES.put(CLEAN_APERTURE_BOX, CleanApertureBox.class); BOX_CLASSES.put(COMPACT_SAMPLE_SIZE_BOX, SampleSizeBox.class); BOX_CLASSES.put(COMPOSITION_TIME_TO_SAMPLE_BOX, CompositionTimeToSampleBox.class); BOX_CLASSES.put(COPYRIGHT_BOX, CopyrightBox.class); BOX_CLASSES.put(DATA_ENTRY_URN_BOX, DataEntryUrnBox.class); BOX_CLASSES.put(DATA_ENTRY_URL_BOX, DataEntryUrlBox.class); BOX_CLASSES.put(DATA_INFORMATION_BOX, BoxImpl.class); BOX_CLASSES.put(DATA_REFERENCE_BOX, DataReferenceBox.class); BOX_CLASSES.put(DECODING_TIME_TO_SAMPLE_BOX, DecodingTimeToSampleBox.class); BOX_CLASSES.put(DEGRADATION_PRIORITY_BOX, DegradationPriorityBox.class); BOX_CLASSES.put(EDIT_BOX, BoxImpl.class); BOX_CLASSES.put(EDIT_LIST_BOX, EditListBox.class); BOX_CLASSES.put(FD_ITEM_INFORMATION_BOX, FDItemInformationBox.class); BOX_CLASSES.put(FD_SESSION_GROUP_BOX, FDSessionGroupBox.class); BOX_CLASSES.put(FEC_RESERVOIR_BOX, FECReservoirBox.class); BOX_CLASSES.put(FILE_PARTITION_BOX, FilePartitionBox.class); BOX_CLASSES.put(FILE_TYPE_BOX, FileTypeBox.class); BOX_CLASSES.put(FREE_SPACE_BOX, FreeSpaceBox.class); BOX_CLASSES.put(GROUP_ID_TO_NAME_BOX, GroupIDToNameBox.class); BOX_CLASSES.put(HANDLER_BOX, HandlerBox.class); BOX_CLASSES.put(HINT_MEDIA_HEADER_BOX, HintMediaHeaderBox.class); BOX_CLASSES.put(IPMP_CONTROL_BOX, IPMPControlBox.class); BOX_CLASSES.put(IPMP_INFO_BOX, IPMPInfoBox.class); BOX_CLASSES.put(ITEM_INFORMATION_BOX, ItemInformationBox.class); BOX_CLASSES.put(ITEM_INFORMATION_ENTRY, ItemInformationEntry.class); BOX_CLASSES.put(ITEM_LOCATION_BOX, ItemLocationBox.class); BOX_CLASSES.put(ITEM_PROTECTION_BOX, ItemProtectionBox.class); BOX_CLASSES.put(MEDIA_BOX, BoxImpl.class); BOX_CLASSES.put(MEDIA_DATA_BOX, MediaDataBox.class); BOX_CLASSES.put(MEDIA_HEADER_BOX, MediaHeaderBox.class); BOX_CLASSES.put(MEDIA_INFORMATION_BOX, BoxImpl.class); BOX_CLASSES.put(META_BOX, MetaBox.class); BOX_CLASSES.put(META_BOX_RELATION_BOX, MetaBoxRelationBox.class); BOX_CLASSES.put(MOVIE_BOX, BoxImpl.class); BOX_CLASSES.put(MOVIE_EXTENDS_BOX, BoxImpl.class); BOX_CLASSES.put(MOVIE_EXTENDS_HEADER_BOX, MovieExtendsHeaderBox.class); BOX_CLASSES.put(MOVIE_FRAGMENT_BOX, BoxImpl.class); BOX_CLASSES.put(MOVIE_FRAGMENT_HEADER_BOX, MovieFragmentHeaderBox.class); BOX_CLASSES.put(MOVIE_FRAGMENT_RANDOM_ACCESS_BOX, BoxImpl.class); BOX_CLASSES.put(MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_BOX, MovieFragmentRandomAccessOffsetBox.class); BOX_CLASSES.put(MOVIE_HEADER_BOX, MovieHeaderBox.class); BOX_CLASSES.put(NERO_METADATA_TAGS_BOX, NeroMetadataTagsBox.class); BOX_CLASSES.put(NULL_MEDIA_HEADER_BOX, FullBox.class); BOX_CLASSES.put(ORIGINAL_FORMAT_BOX, OriginalFormatBox.class); BOX_CLASSES.put(PADDING_BIT_BOX, PaddingBitBox.class); BOX_CLASSES.put(PARTITION_ENTRY, BoxImpl.class); BOX_CLASSES.put(PIXEL_ASPECT_RATIO_BOX, PixelAspectRatioBox.class); BOX_CLASSES.put(PRIMARY_ITEM_BOX, PrimaryItemBox.class); BOX_CLASSES.put(PROGRESSIVE_DOWNLOAD_INFORMATION_BOX, ProgressiveDownloadInformationBox.class); BOX_CLASSES.put(PROTECTION_SCHEME_INFORMATION_BOX, BoxImpl.class); BOX_CLASSES.put(SAMPLE_DEPENDENCY_TYPE_BOX, SampleDependencyTypeBox.class); BOX_CLASSES.put(SAMPLE_DESCRIPTION_BOX, SampleDescriptionBox.class); BOX_CLASSES.put(SAMPLE_GROUP_DESCRIPTION_BOX, SampleGroupDescriptionBox.class); BOX_CLASSES.put(SAMPLE_SCALE_BOX, SampleScaleBox.class); BOX_CLASSES.put(SAMPLE_SIZE_BOX, SampleSizeBox.class); BOX_CLASSES.put(SAMPLE_TABLE_BOX, BoxImpl.class); BOX_CLASSES.put(SAMPLE_TO_CHUNK_BOX, SampleToChunkBox.class); BOX_CLASSES.put(SAMPLE_TO_GROUP_BOX, SampleToGroupBox.class); BOX_CLASSES.put(SCHEME_TYPE_BOX, SchemeTypeBox.class); BOX_CLASSES.put(SCHEME_INFORMATION_BOX, BoxImpl.class); BOX_CLASSES.put(SHADOW_SYNC_SAMPLE_BOX, ShadowSyncSampleBox.class); BOX_CLASSES.put(SKIP_BOX, FreeSpaceBox.class); BOX_CLASSES.put(SOUND_MEDIA_HEADER_BOX, SoundMediaHeaderBox.class); BOX_CLASSES.put(SUB_SAMPLE_INFORMATION_BOX, SubSampleInformationBox.class); BOX_CLASSES.put(SYNC_SAMPLE_BOX, SyncSampleBox.class); BOX_CLASSES.put(TRACK_BOX, BoxImpl.class); BOX_CLASSES.put(TRACK_EXTENDS_BOX, TrackExtendsBox.class); BOX_CLASSES.put(TRACK_FRAGMENT_BOX, BoxImpl.class); BOX_CLASSES.put(TRACK_FRAGMENT_HEADER_BOX, TrackFragmentHeaderBox.class); BOX_CLASSES.put(TRACK_FRAGMENT_RANDOM_ACCESS_BOX, TrackFragmentRandomAccessBox.class); BOX_CLASSES.put(TRACK_FRAGMENT_RUN_BOX, TrackFragmentRunBox.class); BOX_CLASSES.put(TRACK_HEADER_BOX, TrackHeaderBox.class); BOX_CLASSES.put(TRACK_REFERENCE_BOX, TrackReferenceBox.class); BOX_CLASSES.put(TRACK_SELECTION_BOX, TrackSelectionBox.class); BOX_CLASSES.put(USER_DATA_BOX, BoxImpl.class); BOX_CLASSES.put(VIDEO_MEDIA_HEADER_BOX, VideoMediaHeaderBox.class); BOX_CLASSES.put(WIDE_BOX, FreeSpaceBox.class); BOX_CLASSES.put(XML_BOX, XMLBox.class); BOX_CLASSES.put(OBJECT_DESCRIPTOR_BOX, ObjectDescriptorBox.class); BOX_CLASSES.put(SAMPLE_DEPENDENCY_BOX, SampleDependencyBox.class); BOX_CLASSES.put(ID3_TAG_BOX, ID3TagBox.class); BOX_CLASSES.put(ITUNES_META_LIST_BOX, BoxImpl.class); BOX_CLASSES.put(CUSTOM_ITUNES_METADATA_BOX, BoxImpl.class); BOX_CLASSES.put(ITUNES_METADATA_BOX, ITunesMetadataBox.class); BOX_CLASSES.put(ITUNES_METADATA_NAME_BOX, ITunesMetadataNameBox.class); BOX_CLASSES.put(ITUNES_METADATA_MEAN_BOX, ITunesMetadataMeanBox.class); BOX_CLASSES.put(ALBUM_ARTIST_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(ALBUM_ARTIST_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(ALBUM_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(ALBUM_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(ARTIST_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(ARTIST_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(CATEGORY_BOX, BoxImpl.class); BOX_CLASSES.put(COMMENTS_BOX, BoxImpl.class); BOX_CLASSES.put(COMPILATION_PART_BOX, BoxImpl.class); BOX_CLASSES.put(COMPOSER_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(COMPOSER_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(COVER_BOX, BoxImpl.class); BOX_CLASSES.put(CUSTOM_GENRE_BOX, BoxImpl.class); BOX_CLASSES.put(DESCRIPTION_BOX, BoxImpl.class); BOX_CLASSES.put(DISK_NUMBER_BOX, BoxImpl.class); BOX_CLASSES.put(ENCODER_NAME_BOX, EncoderBox.class); BOX_CLASSES.put(ENCODER_TOOL_BOX, EncoderBox.class); BOX_CLASSES.put(EPISODE_GLOBAL_UNIQUE_ID_BOX, BoxImpl.class); BOX_CLASSES.put(GAPLESS_PLAYBACK_BOX, BoxImpl.class); BOX_CLASSES.put(GENRE_BOX, GenreBox.class); BOX_CLASSES.put(GROUPING_BOX, BoxImpl.class); BOX_CLASSES.put(HD_VIDEO_BOX, BoxImpl.class); BOX_CLASSES.put(ITUNES_PURCHASE_ACCOUNT_BOX, BoxImpl.class); BOX_CLASSES.put(ITUNES_ACCOUNT_TYPE_BOX, BoxImpl.class); BOX_CLASSES.put(ITUNES_CATALOGUE_ID_BOX, BoxImpl.class); BOX_CLASSES.put(ITUNES_COUNTRY_CODE_BOX, BoxImpl.class); BOX_CLASSES.put(KEYWORD_BOX, BoxImpl.class); BOX_CLASSES.put(LONG_DESCRIPTION_BOX, BoxImpl.class); BOX_CLASSES.put(LYRICS_BOX, BoxImpl.class); BOX_CLASSES.put(META_TYPE_BOX, BoxImpl.class); BOX_CLASSES.put(PODCAST_BOX, BoxImpl.class); BOX_CLASSES.put(PODCAST_URL_BOX, BoxImpl.class); BOX_CLASSES.put(PURCHASE_DATE_BOX, BoxImpl.class); BOX_CLASSES.put(RATING_BOX, RatingBox.class); BOX_CLASSES.put(RELEASE_DATE_BOX, BoxImpl.class); BOX_CLASSES.put(REQUIREMENT_BOX, RequirementBox.class); BOX_CLASSES.put(TEMPO_BOX, BoxImpl.class); BOX_CLASSES.put(TRACK_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(TRACK_NUMBER_BOX, BoxImpl.class); BOX_CLASSES.put(TRACK_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(TV_EPISODE_BOX, BoxImpl.class); BOX_CLASSES.put(TV_EPISODE_NUMBER_BOX, BoxImpl.class); BOX_CLASSES.put(TV_NETWORK_NAME_BOX, BoxImpl.class); BOX_CLASSES.put(TV_SEASON_BOX, BoxImpl.class); BOX_CLASSES.put(TV_SHOW_BOX, BoxImpl.class); BOX_CLASSES.put(TV_SHOW_SORT_BOX, BoxImpl.class); BOX_CLASSES.put(THREE_GPP_ALBUM_BOX, ThreeGPPAlbumBox.class); BOX_CLASSES.put(THREE_GPP_AUTHOR_BOX, ThreeGPPMetadataBox.class); BOX_CLASSES.put(THREE_GPP_CLASSIFICATION_BOX, ThreeGPPMetadataBox.class); BOX_CLASSES.put(THREE_GPP_DESCRIPTION_BOX, ThreeGPPMetadataBox.class); BOX_CLASSES.put(THREE_GPP_KEYWORDS_BOX, ThreeGPPKeywordsBox.class); BOX_CLASSES.put(THREE_GPP_LOCATION_INFORMATION_BOX, ThreeGPPLocationBox.class); BOX_CLASSES.put(THREE_GPP_PERFORMER_BOX, ThreeGPPMetadataBox.class); BOX_CLASSES.put(THREE_GPP_RECORDING_YEAR_BOX, ThreeGPPRecordingYearBox.class); BOX_CLASSES.put(THREE_GPP_TITLE_BOX, ThreeGPPMetadataBox.class); BOX_CLASSES.put(GOOGLE_HOST_HEADER_BOX, BoxImpl.class); BOX_CLASSES.put(GOOGLE_PING_MESSAGE_BOX, BoxImpl.class); BOX_CLASSES.put(GOOGLE_PING_URL_BOX, BoxImpl.class); BOX_CLASSES.put(GOOGLE_SOURCE_DATA_BOX, BoxImpl.class); BOX_CLASSES.put(GOOGLE_START_TIME_BOX, BoxImpl.class); BOX_CLASSES.put(GOOGLE_TRACK_DURATION_BOX, BoxImpl.class); BOX_CLASSES.put(MP4V_SAMPLE_ENTRY, VideoSampleEntry.class); BOX_CLASSES.put(H263_SAMPLE_ENTRY, VideoSampleEntry.class); BOX_CLASSES.put(ENCRYPTED_VIDEO_SAMPLE_ENTRY, VideoSampleEntry.class); BOX_CLASSES.put(AVC_SAMPLE_ENTRY, VideoSampleEntry.class); BOX_CLASSES.put(MP4A_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(AC3_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(EAC3_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(DRMS_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(AMR_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(AMR_WB_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(EVRC_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(QCELP_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(SMV_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(ENCRYPTED_AUDIO_SAMPLE_ENTRY, AudioSampleEntry.class); BOX_CLASSES.put(MPEG_SAMPLE_ENTRY, MPEGSampleEntry.class); BOX_CLASSES.put(TEXT_METADATA_SAMPLE_ENTRY, TextMetadataSampleEntry.class); BOX_CLASSES.put(XML_METADATA_SAMPLE_ENTRY, XMLMetadataSampleEntry.class); BOX_CLASSES.put(RTP_HINT_SAMPLE_ENTRY, RTPHintSampleEntry.class); BOX_CLASSES.put(FD_HINT_SAMPLE_ENTRY, FDHintSampleEntry.class); BOX_CLASSES.put(ESD_BOX, ESDBox.class); BOX_CLASSES.put(H263_SPECIFIC_BOX, H263SpecificBox.class); BOX_CLASSES.put(AVC_SPECIFIC_BOX, AVCSpecificBox.class); BOX_CLASSES.put(AC3_SPECIFIC_BOX, AC3SpecificBox.class); BOX_CLASSES.put(EAC3_SPECIFIC_BOX, EAC3SpecificBox.class); BOX_CLASSES.put(AMR_SPECIFIC_BOX, AMRSpecificBox.class); BOX_CLASSES.put(EVRC_SPECIFIC_BOX, EVRCSpecificBox.class); BOX_CLASSES.put(QCELP_SPECIFIC_BOX, QCELPSpecificBox.class); BOX_CLASSES.put(SMV_SPECIFIC_BOX, SMVSpecificBox.class); BOX_CLASSES.put(OMA_ACCESS_UNIT_FORMAT_BOX, OMAAccessUnitFormatBox.class); BOX_CLASSES.put(OMA_COMMON_HEADERS_BOX, OMACommonHeadersBox.class); BOX_CLASSES.put(OMA_CONTENT_ID_BOX, OMAContentIDBox.class); BOX_CLASSES.put(OMA_CONTENT_OBJECT_BOX, OMAContentObjectBox.class); BOX_CLASSES.put(OMA_COVER_URI_BOX, OMAURLBox.class); BOX_CLASSES.put(OMA_DISCRETE_MEDIA_HEADERS_BOX, OMADiscreteMediaHeadersBox.class); BOX_CLASSES.put(OMA_DRM_CONTAINER_BOX, FullBox.class); BOX_CLASSES.put(OMA_ICON_URI_BOX, OMAURLBox.class); BOX_CLASSES.put(OMA_INFO_URL_BOX, OMAURLBox.class); BOX_CLASSES.put(OMA_LYRICS_URI_BOX, OMAURLBox.class); BOX_CLASSES.put(OMA_MUTABLE_DRM_INFORMATION_BOX, BoxImpl.class); BOX_CLASSES.put(OMA_KEY_MANAGEMENT_BOX, FullBox.class); BOX_CLASSES.put(OMA_RIGHTS_OBJECT_BOX, OMARightsObjectBox.class); BOX_CLASSES.put(OMA_TRANSACTION_TRACKING_BOX, OMATransactionTrackingBox.class); BOX_CLASSES.put(FAIRPLAY_USER_ID_BOX, FairPlayDataBox.class); BOX_CLASSES.put(FAIRPLAY_USER_NAME_BOX, FairPlayDataBox.class); BOX_CLASSES.put(FAIRPLAY_USER_KEY_BOX, FairPlayDataBox.class); BOX_CLASSES.put(FAIRPLAY_IV_BOX, FairPlayDataBox.class); BOX_CLASSES.put(FAIRPLAY_PRIVATE_KEY_BOX, FairPlayDataBox.class); //parameter PARAMETER.put(ADDITIONAL_METADATA_CONTAINER_BOX, new String[]{"Additional Metadata Container Box"}); PARAMETER.put(DATA_INFORMATION_BOX, new String[]{"Data Information Box"}); PARAMETER.put(EDIT_BOX, new String[]{"Edit Box"}); PARAMETER.put(MEDIA_BOX, new String[]{"Media Box"}); PARAMETER.put(MEDIA_INFORMATION_BOX, new String[]{"Media Information Box"}); PARAMETER.put(MOVIE_BOX, new String[]{"Movie Box"}); PARAMETER.put(MOVIE_EXTENDS_BOX, new String[]{"Movie Extends Box"}); PARAMETER.put(MOVIE_FRAGMENT_BOX, new String[]{"Movie Fragment Box"}); PARAMETER.put(MOVIE_FRAGMENT_RANDOM_ACCESS_BOX, new String[]{"Movie Fragment Random Access Box"}); PARAMETER.put(NULL_MEDIA_HEADER_BOX, new String[]{"Null Media Header Box"}); PARAMETER.put(PARTITION_ENTRY, new String[]{"Partition Entry"}); PARAMETER.put(PROTECTION_SCHEME_INFORMATION_BOX, new String[]{"Protection Scheme Information Box"}); PARAMETER.put(SAMPLE_TABLE_BOX, new String[]{"Sample Table Box"}); PARAMETER.put(SCHEME_INFORMATION_BOX, new String[]{"Scheme Information Box"}); PARAMETER.put(TRACK_BOX, new String[]{"Track Box"}); PARAMETER.put(TRACK_FRAGMENT_BOX, new String[]{"Track Fragment Box"}); PARAMETER.put(USER_DATA_BOX, new String[]{"User Data Box"}); PARAMETER.put(ITUNES_META_LIST_BOX, new String[]{"iTunes Meta List Box"}); PARAMETER.put(CUSTOM_ITUNES_METADATA_BOX, new String[]{"Custom iTunes Metadata Box"}); PARAMETER.put(ALBUM_ARTIST_NAME_BOX, new String[]{"Album Artist Name Box"}); PARAMETER.put(ALBUM_ARTIST_SORT_BOX, new String[]{"Album Artist Sort Box"}); PARAMETER.put(ALBUM_NAME_BOX, new String[]{"Album Name Box"}); PARAMETER.put(ALBUM_SORT_BOX, new String[]{"Album Sort Box"}); PARAMETER.put(ARTIST_NAME_BOX, new String[]{"Artist Name Box"}); PARAMETER.put(ARTIST_SORT_BOX, new String[]{"Artist Sort Box"}); PARAMETER.put(CATEGORY_BOX, new String[]{"Category Box"}); PARAMETER.put(COMMENTS_BOX, new String[]{"Comments Box"}); PARAMETER.put(COMPILATION_PART_BOX, new String[]{"Compilation Part Box"}); PARAMETER.put(COMPOSER_NAME_BOX, new String[]{"Composer Name Box"}); PARAMETER.put(COMPOSER_SORT_BOX, new String[]{"Composer Sort Box"}); PARAMETER.put(COVER_BOX, new String[]{"Cover Box"}); PARAMETER.put(CUSTOM_GENRE_BOX, new String[]{"Custom Genre Box"}); PARAMETER.put(DESCRIPTION_BOX, new String[]{"Description Cover Box"}); PARAMETER.put(DISK_NUMBER_BOX, new String[]{"Disk Number Box"}); PARAMETER.put(EPISODE_GLOBAL_UNIQUE_ID_BOX, new String[]{"Episode Global Unique ID Box"}); PARAMETER.put(GAPLESS_PLAYBACK_BOX, new String[]{"Gapless Playback Box"}); PARAMETER.put(GROUPING_BOX, new String[]{"Grouping Box"}); PARAMETER.put(HD_VIDEO_BOX, new String[]{"HD Video Box"}); PARAMETER.put(ITUNES_PURCHASE_ACCOUNT_BOX, new String[]{"iTunes Purchase Account Box"}); PARAMETER.put(ITUNES_ACCOUNT_TYPE_BOX, new String[]{"iTunes Account Type Box"}); PARAMETER.put(ITUNES_CATALOGUE_ID_BOX, new String[]{"iTunes Catalogue ID Box"}); PARAMETER.put(ITUNES_COUNTRY_CODE_BOX, new String[]{"iTunes Country Code Box"}); PARAMETER.put(KEYWORD_BOX, new String[]{"Keyword Box"}); PARAMETER.put(LONG_DESCRIPTION_BOX, new String[]{"Long Description Box"}); PARAMETER.put(LYRICS_BOX, new String[]{"Lyrics Box"}); PARAMETER.put(META_TYPE_BOX, new String[]{"Meta Type Box"}); PARAMETER.put(PODCAST_BOX, new String[]{"Podcast Box"}); PARAMETER.put(PODCAST_URL_BOX, new String[]{"Podcast URL Box"}); PARAMETER.put(PURCHASE_DATE_BOX, new String[]{"Purchase Date Box"}); PARAMETER.put(RELEASE_DATE_BOX, new String[]{"Release Date Box"}); PARAMETER.put(TEMPO_BOX, new String[]{"Tempo Box"}); PARAMETER.put(TRACK_NAME_BOX, new String[]{"Track Name Box"}); PARAMETER.put(TRACK_NUMBER_BOX, new String[]{"Track Number Box"}); PARAMETER.put(TRACK_SORT_BOX, new String[]{"Track Sort Box"}); PARAMETER.put(TV_EPISODE_BOX, new String[]{"TV Episode Box"}); PARAMETER.put(TV_EPISODE_NUMBER_BOX, new String[]{"TV Episode Number Box"}); PARAMETER.put(TV_NETWORK_NAME_BOX, new String[]{"TV Network Name Box"}); PARAMETER.put(TV_SEASON_BOX, new String[]{"TV Season Box"}); PARAMETER.put(TV_SHOW_BOX, new String[]{"TV Show Box"}); PARAMETER.put(TV_SHOW_SORT_BOX, new String[]{"TV Show Sort Box"}); PARAMETER.put(THREE_GPP_AUTHOR_BOX, new String[]{"3GPP Author Box"}); PARAMETER.put(THREE_GPP_CLASSIFICATION_BOX, new String[]{"3GPP Classification Box"}); PARAMETER.put(THREE_GPP_DESCRIPTION_BOX, new String[]{"3GPP Description Box"}); PARAMETER.put(THREE_GPP_PERFORMER_BOX, new String[]{"3GPP Performer Box"}); PARAMETER.put(THREE_GPP_TITLE_BOX, new String[]{"3GPP Title Box"}); PARAMETER.put(GOOGLE_HOST_HEADER_BOX, new String[]{"Google Host Header Box"}); PARAMETER.put(GOOGLE_PING_MESSAGE_BOX, new String[]{"Google Ping Message Box"}); PARAMETER.put(GOOGLE_PING_URL_BOX, new String[]{"Google Ping URL Box"}); PARAMETER.put(GOOGLE_SOURCE_DATA_BOX, new String[]{"Google Source Data Box"}); PARAMETER.put(GOOGLE_START_TIME_BOX, new String[]{"Google Start Time Box"}); PARAMETER.put(GOOGLE_TRACK_DURATION_BOX, new String[]{"Google Track Duration Box"}); PARAMETER.put(MP4V_SAMPLE_ENTRY, new String[]{"MPEG-4 Video Sample Entry"}); PARAMETER.put(H263_SAMPLE_ENTRY, new String[]{"H263 Video Sample Entry"}); PARAMETER.put(ENCRYPTED_VIDEO_SAMPLE_ENTRY, new String[]{"Encrypted Video Sample Entry"}); PARAMETER.put(AVC_SAMPLE_ENTRY, new String[]{"AVC Video Sample Entry"}); PARAMETER.put(MP4A_SAMPLE_ENTRY, new String[]{"MPEG- 4Audio Sample Entry"}); PARAMETER.put(AC3_SAMPLE_ENTRY, new String[]{"AC-3 Audio Sample Entry"}); PARAMETER.put(EAC3_SAMPLE_ENTRY, new String[]{"Extended AC-3 Audio Sample Entry"}); PARAMETER.put(DRMS_SAMPLE_ENTRY, new String[]{"DRMS Audio Sample Entry"}); PARAMETER.put(AMR_SAMPLE_ENTRY, new String[]{"AMR Audio Sample Entry"}); PARAMETER.put(AMR_WB_SAMPLE_ENTRY, new String[]{"AMR-Wideband Audio Sample Entry"}); PARAMETER.put(EVRC_SAMPLE_ENTRY, new String[]{"EVC Audio Sample Entry"}); PARAMETER.put(QCELP_SAMPLE_ENTRY, new String[]{"QCELP Audio Sample Entry"}); PARAMETER.put(SMV_SAMPLE_ENTRY, new String[]{"SMV Audio Sample Entry"}); PARAMETER.put(ENCRYPTED_AUDIO_SAMPLE_ENTRY, new String[]{"Encrypted Audio Sample Entry"}); PARAMETER.put(OMA_COVER_URI_BOX, new String[]{"OMA DRM Cover URI Box"}); PARAMETER.put(OMA_DRM_CONTAINER_BOX, new String[]{"OMA DRM Container Box"}); PARAMETER.put(OMA_ICON_URI_BOX, new String[]{"OMA DRM Icon URI Box"}); PARAMETER.put(OMA_INFO_URL_BOX, new String[]{"OMA DRM Info URL Box"}); PARAMETER.put(OMA_LYRICS_URI_BOX, new String[]{"OMA DRM Lyrics URI Box"}); PARAMETER.put(OMA_MUTABLE_DRM_INFORMATION_BOX, new String[]{"OMA DRM Mutable DRM Information Box"}); } public static Box parseBox(Box parent, MP4InputStream in) throws IOException { final long offset = in.getOffset(); long size = in.readBytes(4); long type = in.readBytes(4); if(size==1) size = in.readBytes(8); if(type==EXTENDED_TYPE) in.skipBytes(16); //error protection if(parent!=null) { final long parentLeft = (parent.getOffset()+parent.getSize())-offset; if(size>parentLeft) throw new IOException("error while decoding box '"+typeToString(type)+"' at offset "+offset+": box too large for parent"); } Logger.getLogger("MP4 Boxes").finest(typeToString(type)); final BoxImpl box = forType(type, in.getOffset()); box.setParams(parent, size, type, offset); box.decode(in); //if box doesn't contain data it only contains children final Class<?> cl = box.getClass(); if(cl==BoxImpl.class||cl==FullBox.class) box.readChildren(in); //check bytes left final long left = (box.getOffset()+box.getSize())-in.getOffset(); if(left>0 &&!(box instanceof MediaDataBox) &&!(box instanceof UnknownBox) &&!(box instanceof FreeSpaceBox)) LOGGER.log(Level.INFO, "bytes left after reading box {0}: left: {1}, offset: {2}", new Object[]{typeToString(type), left, in.getOffset()}); else if(left<0) LOGGER.log(Level.SEVERE, "box {0} overread: {1} bytes, offset: {2}", new Object[]{typeToString(type), -left, in.getOffset()}); //if mdat found and no random access, don't skip if(box.getType()!=MEDIA_DATA_BOX||in.hasRandomAccess()) in.skipBytes(left); return box; } //TODO: remove usages public static Box parseBox(MP4InputStream in, Class<? extends BoxImpl> boxClass) throws IOException { final long offset = in.getOffset(); long size = in.readBytes(4); long type = in.readBytes(4); if(size==1) size = in.readBytes(8); if(type==EXTENDED_TYPE) in.skipBytes(16); BoxImpl box = null; try { box = boxClass.newInstance(); } catch(InstantiationException e) { } catch(IllegalAccessException e) { } if(box!=null) { box.setParams(null, size, type, offset); box.decode(in); final long left = (box.getOffset()+box.getSize())-in.getOffset(); in.skipBytes(left); } return box; } private static BoxImpl forType(long type, long offset) { BoxImpl box = null; final Long l = Long.valueOf(type); if(BOX_CLASSES.containsKey(l)) { Class<? extends BoxImpl> cl = BOX_CLASSES.get(l); if(PARAMETER.containsKey(l)) { final String[] s = PARAMETER.get(l); try { Constructor<? extends BoxImpl> con = cl.getConstructor(String.class); box = con.newInstance(s[0]); } catch(Exception e) { LOGGER.log(Level.SEVERE, "BoxFactory: could not call constructor for "+typeToString(type), e); box = new UnknownBox(); } } else { try { box = cl.newInstance(); } catch(Exception e) { LOGGER.log(Level.SEVERE, "BoxFactory: could not instantiate box "+typeToString(type), e); } } } if(box==null) { LOGGER.log(Level.INFO, "BoxFactory: unknown box type: {0}; position: {1}", new Object[]{typeToString(type), offset}); box = new UnknownBox(); } return box; } public static String typeToString(long l) { byte[] b = new byte[4]; b[0] = (byte) ((l>>24)&0xFF); b[1] = (byte) ((l>>16)&0xFF); b[2] = (byte) ((l>>8)&0xFF); b[3] = (byte) (l&0xFF); return new String(b); } }