/* * Copyright 2012 Sebastian Annies, Hamburg * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.coremedia.iso; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; public final class IsoTypeReader { public static long readUInt32BE(ByteBuffer bb) { long ch1 = readUInt8(bb); long ch2 = readUInt8(bb); long ch3 = readUInt8(bb); long ch4 = readUInt8(bb); return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); } public static long readUInt32(ByteBuffer bb) { long i = bb.getInt(); if (i < 0) { i += 1l<<32; } return i; } public static int readUInt24(ByteBuffer bb) { int result = 0; result += readUInt16(bb) << 8; result += byte2int(bb.get()); return result; } public static int readUInt16(ByteBuffer bb) { int result = 0; result += byte2int(bb.get()) << 8; result += byte2int(bb.get()); return result; } public static int readUInt16BE(ByteBuffer bb) { int result = 0; result += byte2int(bb.get()); result += byte2int(bb.get()) << 8; return result; } public static int readUInt8(ByteBuffer bb) { return byte2int(bb.get()); } public static int byte2int(byte b) { return b < 0 ? b + 256 : b; } /** * Reads a zero terminated UTF-8 string. * * @param byteBuffer the data source * @return the string readByte * @throws Error in case of an error in the underlying stream */ public static String readString(ByteBuffer byteBuffer) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int read; while ((read = byteBuffer.get()) != 0) { out.write(read); } return Utf8.convert(out.toByteArray()); } public static String readString(ByteBuffer byteBuffer, int length) { byte[] buffer = new byte[length]; byteBuffer.get(buffer); return Utf8.convert(buffer); } public static long readUInt64(ByteBuffer byteBuffer) { long result = 0; // thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed result += readUInt32(byteBuffer) << 32; if (result < 0) { throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt"); } result += readUInt32(byteBuffer); return result; } public static double readFixedPoint1616(ByteBuffer bb) { byte[] bytes = new byte[4]; bb.get(bytes); int result = 0; result |= ((bytes[0] << 24) & 0xFF000000); result |= ((bytes[1] << 16) & 0xFF0000); result |= ((bytes[2] << 8) & 0xFF00); result |= ((bytes[3]) & 0xFF); return ((double) result) / 65536; } public static float readFixedPoint88(ByteBuffer bb) { byte[] bytes = new byte[2]; bb.get(bytes); short result = 0; result |= ((bytes[0] << 8) & 0xFF00); result |= ((bytes[1]) & 0xFF); return ((float) result) / 256; } public static String readIso639(ByteBuffer bb) { int bits = readUInt16(bb); StringBuilder result = new StringBuilder(); for (int i = 0; i < 3; i++) { int c = (bits >> (2 - i) * 5) & 0x1f; result.append((char) (c + 0x60)); } return result.toString(); } public static String read4cc(ByteBuffer bb) { byte[] b = new byte[4]; bb.get(b); return IsoFile.bytesToFourCC(b); } }