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