1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/* 2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright 2012 Sebastian Annies, Hamburg 3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the License); 5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * you may not use this file except in compliance with the License. 6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * You may obtain a copy of the License at 7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * http://www.apache.org/licenses/LICENSE-2.0 9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software 11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * distributed under the License is distributed on an AS IS BASIS, 12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * See the License for the specific language governing permissions and 14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * limitations under the License. 15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.coremedia.iso; 17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.ByteArrayOutputStream; 19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer; 20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic final class IsoTypeReader { 22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static long readUInt32BE(ByteBuffer bb) { 25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long ch1 = readUInt8(bb); 26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long ch2 = readUInt8(bb); 27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long ch3 = readUInt8(bb); 28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long ch4 = readUInt8(bb); 29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); 30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static long readUInt32(ByteBuffer bb) { 35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long i = bb.getInt(); 36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (i < 0) { 37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu i += 1l<<32; 38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return i; 40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static int readUInt24(ByteBuffer bb) { 43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int result = 0; 44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += readUInt16(bb) << 8; 45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += byte2int(bb.get()); 46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return result; 47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static int readUInt16(ByteBuffer bb) { 51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int result = 0; 52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += byte2int(bb.get()) << 8; 53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += byte2int(bb.get()); 54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return result; 55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static int readUInt16BE(ByteBuffer bb) { 58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int result = 0; 59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += byte2int(bb.get()); 60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += byte2int(bb.get()) << 8; 61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return result; 62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static int readUInt8(ByteBuffer bb) { 65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return byte2int(bb.get()); 66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static int byte2int(byte b) { 69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return b < 0 ? b + 256 : b; 70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu /** 74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Reads a zero terminated UTF-8 string. 75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param byteBuffer the data source 77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @return the string readByte 78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @throws Error in case of an error in the underlying stream 79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static String readString(ByteBuffer byteBuffer) { 81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ByteArrayOutputStream out = new ByteArrayOutputStream(); 83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int read; 84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu while ((read = byteBuffer.get()) != 0) { 85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu out.write(read); 86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return Utf8.convert(out.toByteArray()); 88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static String readString(ByteBuffer byteBuffer, int length) { 91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu byte[] buffer = new byte[length]; 92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu byteBuffer.get(buffer); 93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return Utf8.convert(buffer); 94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static long readUInt64(ByteBuffer byteBuffer) { 98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long result = 0; 99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu // thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed 100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += readUInt32(byteBuffer) << 32; 101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (result < 0) { 102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt"); 103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result += readUInt32(byteBuffer); 105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return result; 107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static double readFixedPoint1616(ByteBuffer bb) { 110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu byte[] bytes = new byte[4]; 111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu bb.get(bytes); 112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int result = 0; 114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[0] << 24) & 0xFF000000); 115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[1] << 16) & 0xFF0000); 116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[2] << 8) & 0xFF00); 117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[3]) & 0xFF); 118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return ((double) result) / 65536; 119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static float readFixedPoint88(ByteBuffer bb) { 123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu byte[] bytes = new byte[2]; 124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu bb.get(bytes); 125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu short result = 0; 126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[0] << 8) & 0xFF00); 127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result |= ((bytes[1]) & 0xFF); 128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return ((float) result) / 256; 129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static String readIso639(ByteBuffer bb) { 132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int bits = readUInt16(bb); 133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu StringBuilder result = new StringBuilder(); 134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = 0; i < 3; i++) { 135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int c = (bits >> (2 - i) * 5) & 0x1f; 136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu result.append((char) (c + 0x60)); 137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return result.toString(); 139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static String read4cc(ByteBuffer bb) { 142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu byte[] b = new byte[4]; 143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu bb.get(b); 144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return IsoFile.bytesToFourCC(b); 145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu} 148