package org.jcodec.containers.mp4.boxes;
import org.jcodec.common.JCodecUtil2;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.io.StringReader;
import org.jcodec.common.logging.Logger;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* An MP4 file structure (atom)
*
* @author The JCodec project
*
*/
public class Header {
private static final long MAX_UNSIGNED_INT = 0x100000000L;
private String fourcc;
private long size;
private boolean lng;
public Header(String fourcc) {
this.fourcc = fourcc;
}
public static Header createHeader(String fourcc, long size) {
Header header = new Header(fourcc);
header.size = size;
return header;
}
public static Header newHeader(String fourcc, long size, boolean lng) {
Header header = new Header(fourcc);
header.size = size;
header.lng = lng;
return header;
}
public static Header read(ByteBuffer input) {
long size = 0;
while (input.remaining() >= 4 && (size = (((long) input.getInt()) & 0xffffffffL)) == 0)
;
if (input.remaining() < 4 || size < 8 && size != 1) {
Logger.error("Broken atom of size " + size);
return null;
}
String fourcc = NIOUtils.readString(input, 4);
boolean lng = false;
if (size == 1) {
if (input.remaining() >= 8) {
lng = true;
size = input.getLong();
} else {
Logger.error("Broken atom of size " + size);
return null;
}
}
return newHeader(fourcc, size, lng);
}
public void skip(InputStream di) throws IOException {
StringReader.sureSkip(di, size - headerSize());
}
public long headerSize() {
return lng || (size > MAX_UNSIGNED_INT) ? 16 : 8;
}
public byte[] readContents(InputStream di) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < size - headerSize(); i++) {
baos.write(di.read());
}
return baos.toByteArray();
}
public String getFourcc() {
return fourcc;
}
public long getBodySize() {
return size - headerSize();
}
public void setBodySize(int length) {
size = length + headerSize();
}
public void write(ByteBuffer out) {
if (size > MAX_UNSIGNED_INT)
out.putInt(1);
else
out.putInt((int) size);
out.put(JCodecUtil2.asciiString(fourcc));
if (size > MAX_UNSIGNED_INT) {
out.putLong(size);
}
}
public void writeChannel(SeekableByteChannel output) throws IOException {
ByteBuffer bb = ByteBuffer.allocate(16);
write(bb);
bb.flip();
output.write(bb);
}
public long getSize() {
return size;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fourcc == null) ? 0 : fourcc.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Header other = (Header) obj;
if (fourcc == null) {
if (other.fourcc != null)
return false;
} else if (!fourcc.equals(other.fourcc))
return false;
return true;
}
}