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.sampleentry; 18 19 import com.coremedia.iso.IsoTypeReader; 20 import com.coremedia.iso.IsoTypeWriter; 21 import com.coremedia.iso.Utf8; 22 import com.coremedia.iso.boxes.Box; 23 import com.coremedia.iso.boxes.ContainerBox; 24 25 import java.nio.ByteBuffer; 26 27 /** 28 * Contains information common to all visual tracks. 29 * <code> 30 * <pre> 31 * class VisualSampleEntry(codingname) extends SampleEntry (codingname){ 32 * unsigned int(16) pre_defined = 0; 33 * const unsigned int(16) reserved = 0; 34 * unsigned int(32)[3] pre_defined = 0; 35 * unsigned int(16) width; 36 * unsigned int(16) height; 37 * template unsigned int(32) horizresolution = 0x00480000; // 72 dpi 38 * template unsigned int(32) vertresolution = 0x00480000; // 72 dpi 39 * const unsigned int(32) reserved = 0; 40 * template unsigned int(16) frame_count = 1; 41 * string[32] compressorname; 42 * template unsigned int(16) depth = 0x0018; 43 * int(16) pre_defined = -1; 44 * }<br> 45 * </pre> 46 * </code> 47 * <p/> 48 * Format-specific informationis appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. 49 */ 50 public class VisualSampleEntry extends SampleEntry implements ContainerBox { 51 public static final String TYPE1 = "mp4v"; 52 public static final String TYPE2 = "s263"; 53 public static final String TYPE3 = "avc1"; 54 55 56 /** 57 * Identifier for an encrypted video track. 58 * 59 * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox 60 */ 61 public static final String TYPE_ENCRYPTED = "encv"; 62 63 64 private int width; 65 private int height; 66 private double horizresolution = 72; 67 private double vertresolution = 72; 68 private int frameCount = 1; 69 private String compressorname; 70 private int depth = 24; 71 72 private long[] predefined = new long[3]; 73 VisualSampleEntry(String type)74 public VisualSampleEntry(String type) { 75 super(type); 76 } 77 getWidth()78 public int getWidth() { 79 return width; 80 } 81 getHeight()82 public int getHeight() { 83 return height; 84 } 85 getHorizresolution()86 public double getHorizresolution() { 87 return horizresolution; 88 } 89 getVertresolution()90 public double getVertresolution() { 91 return vertresolution; 92 } 93 getFrameCount()94 public int getFrameCount() { 95 return frameCount; 96 } 97 getCompressorname()98 public String getCompressorname() { 99 return compressorname; 100 } 101 getDepth()102 public int getDepth() { 103 return depth; 104 } 105 setCompressorname(String compressorname)106 public void setCompressorname(String compressorname) { 107 this.compressorname = compressorname; 108 } 109 setWidth(int width)110 public void setWidth(int width) { 111 this.width = width; 112 } 113 setHeight(int height)114 public void setHeight(int height) { 115 this.height = height; 116 } 117 setHorizresolution(double horizresolution)118 public void setHorizresolution(double horizresolution) { 119 this.horizresolution = horizresolution; 120 } 121 setVertresolution(double vertresolution)122 public void setVertresolution(double vertresolution) { 123 this.vertresolution = vertresolution; 124 } 125 setFrameCount(int frameCount)126 public void setFrameCount(int frameCount) { 127 this.frameCount = frameCount; 128 } 129 setDepth(int depth)130 public void setDepth(int depth) { 131 this.depth = depth; 132 } 133 134 @Override _parseDetails(ByteBuffer content)135 public void _parseDetails(ByteBuffer content) { 136 _parseReservedAndDataReferenceIndex(content); 137 long tmp = IsoTypeReader.readUInt16(content); 138 assert 0 == tmp : "reserved byte not 0"; 139 tmp = IsoTypeReader.readUInt16(content); 140 assert 0 == tmp : "reserved byte not 0"; 141 predefined[0] = IsoTypeReader.readUInt32(content); // should be zero 142 predefined[1] = IsoTypeReader.readUInt32(content); // should be zero 143 predefined[2] = IsoTypeReader.readUInt32(content); // should be zero 144 width = IsoTypeReader.readUInt16(content); 145 height = IsoTypeReader.readUInt16(content); 146 horizresolution = IsoTypeReader.readFixedPoint1616(content); 147 vertresolution = IsoTypeReader.readFixedPoint1616(content); 148 tmp = IsoTypeReader.readUInt32(content); 149 assert 0 == tmp : "reserved byte not 0"; 150 frameCount = IsoTypeReader.readUInt16(content); 151 int compressornameDisplayAbleData = IsoTypeReader.readUInt8(content); 152 if (compressornameDisplayAbleData > 31) { 153 System.out.println("invalid compressor name displayable data: " + compressornameDisplayAbleData); 154 compressornameDisplayAbleData = 31; 155 } 156 byte[] bytes = new byte[compressornameDisplayAbleData]; 157 content.get(bytes); 158 compressorname = Utf8.convert(bytes); 159 if (compressornameDisplayAbleData < 31) { 160 byte[] zeros = new byte[31 - compressornameDisplayAbleData]; 161 content.get(zeros); 162 //assert Arrays.equals(zeros, new byte[zeros.length]) : "The compressor name length was not filled up with zeros"; 163 } 164 depth = IsoTypeReader.readUInt16(content); 165 tmp = IsoTypeReader.readUInt16(content); 166 assert 0xFFFF == tmp; 167 168 _parseChildBoxes(content); 169 170 } 171 172 getContentSize()173 protected long getContentSize() { 174 long contentSize = 78; 175 for (Box boxe : boxes) { 176 contentSize += boxe.getSize(); 177 } 178 return contentSize; 179 } 180 181 @Override getContent(ByteBuffer byteBuffer)182 protected void getContent(ByteBuffer byteBuffer) { 183 _writeReservedAndDataReferenceIndex(byteBuffer); 184 IsoTypeWriter.writeUInt16(byteBuffer, 0); 185 IsoTypeWriter.writeUInt16(byteBuffer, 0); 186 IsoTypeWriter.writeUInt32(byteBuffer, predefined[0]); 187 IsoTypeWriter.writeUInt32(byteBuffer, predefined[1]); 188 IsoTypeWriter.writeUInt32(byteBuffer, predefined[2]); 189 190 IsoTypeWriter.writeUInt16(byteBuffer, getWidth()); 191 IsoTypeWriter.writeUInt16(byteBuffer, getHeight()); 192 193 IsoTypeWriter.writeFixedPont1616(byteBuffer, getHorizresolution()); 194 IsoTypeWriter.writeFixedPont1616(byteBuffer, getVertresolution()); 195 196 197 IsoTypeWriter.writeUInt32(byteBuffer, 0); 198 IsoTypeWriter.writeUInt16(byteBuffer, getFrameCount()); 199 IsoTypeWriter.writeUInt8(byteBuffer, Utf8.utf8StringLengthInBytes(getCompressorname())); 200 byteBuffer.put(Utf8.convert(getCompressorname())); 201 int a = Utf8.utf8StringLengthInBytes(getCompressorname()); 202 while (a < 31) { 203 a++; 204 byteBuffer.put((byte) 0); 205 } 206 IsoTypeWriter.writeUInt16(byteBuffer, getDepth()); 207 IsoTypeWriter.writeUInt16(byteBuffer, 0xFFFF); 208 209 _writeChildBoxes(byteBuffer); 210 211 } 212 213 } 214