1 /* 2 * Copyright 2008 CoreMedia AG, Hamburg 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 17 package com.coremedia.iso.boxes; 18 19 20 import com.coremedia.iso.IsoFile; 21 import com.coremedia.iso.IsoTypeReader; 22 import com.coremedia.iso.IsoTypeWriter; 23 import com.coremedia.iso.Utf8; 24 import com.googlecode.mp4parser.AbstractFullBox; 25 26 import java.nio.ByteBuffer; 27 import java.util.Collections; 28 import java.util.HashMap; 29 import java.util.Map; 30 31 /** 32 * This box within a Media Box declares the process by which the media-data in the track is presented, 33 * and thus, the nature of the media in a track. 34 * This Box when present in a Meta Box, declares the structure or format of the 'meta' box contents. 35 * See ISO/IEC 14496-12 for details. 36 * 37 * @see MetaBox 38 * @see MediaBox 39 */ 40 public class HandlerBox extends AbstractFullBox { 41 public static final String TYPE = "hdlr"; 42 public static final Map<String, String> readableTypes; 43 44 static { 45 HashMap<String, String> hm = new HashMap<String, String>(); 46 hm.put("odsm", "ObjectDescriptorStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 47 hm.put("crsm", "ClockReferenceStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 48 hm.put("sdsm", "SceneDescriptionStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 49 hm.put("m7sm", "MPEG7Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 50 hm.put("ocsm", "ObjectContentInfoStream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 51 hm.put("ipsm", "IPMP Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 52 hm.put("mjsm", "MPEG-J Stream - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 53 hm.put("mdir", "Apple Meta Data iTunes Reader"); 54 hm.put("mp7b", "MPEG-7 binary XML"); 55 hm.put("mp7t", "MPEG-7 XML"); 56 hm.put("vide", "Video Track"); 57 hm.put("soun", "Sound Track"); 58 hm.put("hint", "Hint Track"); 59 hm.put("appl", "Apple specific"); 60 hm.put("meta", "Timed Metadata track - defined in ISO/IEC JTC1/SC29/WG11 - CODING OF MOVING PICTURES AND AUDIO"); 61 62 readableTypes = Collections.unmodifiableMap(hm); 63 64 } 65 66 private String handlerType; 67 private String name = null; 68 private long a, b, c; 69 private boolean zeroTerm = true; 70 71 private long shouldBeZeroButAppleWritesHereSomeValue; 72 73 public HandlerBox() { 74 super(TYPE); 75 } 76 77 public String getHandlerType() { 78 return handlerType; 79 } 80 81 /** 82 * You are required to add a '\0' string termination by yourself. 83 * 84 * @param name the new human readable name 85 */ 86 public void setName(String name) { 87 this.name = name; 88 } 89 90 public void setHandlerType(String handlerType) { 91 this.handlerType = handlerType; 92 } 93 94 public String getName() { 95 return name; 96 } 97 98 public String getHumanReadableTrackType() { 99 return readableTypes.get(handlerType) != null ? readableTypes.get(handlerType) : "Unknown Handler Type"; 100 } 101 102 protected long getContentSize() { 103 if (zeroTerm) { 104 return 25 + Utf8.utf8StringLengthInBytes(name); 105 } else { 106 return 24 + Utf8.utf8StringLengthInBytes(name); 107 } 108 109 } 110 111 @Override 112 public void _parseDetails(ByteBuffer content) { 113 parseVersionAndFlags(content); 114 shouldBeZeroButAppleWritesHereSomeValue = IsoTypeReader.readUInt32(content); 115 handlerType = IsoTypeReader.read4cc(content); 116 a = IsoTypeReader.readUInt32(content); 117 b = IsoTypeReader.readUInt32(content); 118 c = IsoTypeReader.readUInt32(content); 119 if (content.remaining() > 0) { 120 name = IsoTypeReader.readString(content, content.remaining()); 121 if (name.endsWith("\0")) { 122 name = name.substring(0, name.length() - 1); 123 zeroTerm = true; 124 } else { 125 zeroTerm = false; 126 } 127 } else { 128 zeroTerm = false; //No string at all, not even zero term char 129 } 130 } 131 132 @Override 133 protected void getContent(ByteBuffer byteBuffer) { 134 writeVersionAndFlags(byteBuffer); 135 IsoTypeWriter.writeUInt32(byteBuffer, shouldBeZeroButAppleWritesHereSomeValue); 136 byteBuffer.put(IsoFile.fourCCtoBytes(handlerType)); 137 IsoTypeWriter.writeUInt32(byteBuffer, a); 138 IsoTypeWriter.writeUInt32(byteBuffer, b); 139 IsoTypeWriter.writeUInt32(byteBuffer, c); 140 if (name != null) { 141 byteBuffer.put(Utf8.convert(name)); 142 } 143 if (zeroTerm) { 144 byteBuffer.put((byte) 0); 145 } 146 } 147 148 public String toString() { 149 return "HandlerBox[handlerType=" + getHandlerType() + ";name=" + getName() + "]"; 150 } 151 } 152