package org.jcodec.containers.mkv;
import static org.jcodec.common.io.IOUtils.readFileToByteArray;
import static org.jcodec.containers.mkv.MKVType.Block;
import static org.jcodec.containers.mkv.MKVType.BlockGroup;
import static org.jcodec.containers.mkv.MKVType.Cluster;
import static org.jcodec.containers.mkv.MKVType.Segment;
import static org.jcodec.containers.mkv.MKVType.SimpleBlock;
import static org.jcodec.containers.mkv.MKVType.Timecode;
import static org.jcodec.containers.mkv.MKVType.TrackEntry;
import static org.jcodec.containers.mkv.MKVType.TrackNumber;
import static org.jcodec.containers.mkv.MKVType.Tracks;
import static org.jcodec.containers.mkv.MKVType.findAllTree;
import static org.jcodec.containers.mkv.MKVType.findFirst;
import org.jcodec.codecs.vpx.VP8Decoder;
import org.jcodec.common.io.FileChannelWrapper;
import org.jcodec.common.io.IOUtils;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.containers.mkv.boxes.EbmlBase;
import org.jcodec.containers.mkv.boxes.EbmlMaster;
import org.jcodec.containers.mkv.boxes.EbmlUint;
import org.jcodec.containers.mkv.boxes.MkvBlock;
import org.jcodec.containers.mkv.util.EbmlUtil;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.System;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;
public class BlockOrderingTest {
@Test
public void testFixedLacing() throws IOException {
File file = new File("src/test/resources/mkv/fixed_lacing_simple_block.ebml");
byte[] rawFrame = IOUtils.readFileToByteArray(file);
MkvBlock be = new MkvBlock(SimpleBlock.id);
be.offset = 0x00;
be.dataLen = 0xC05;
be.dataOffset = 0x03;
FileInputStream fileInputStream = new FileInputStream(file);
ByteBuffer source = ByteBuffer.allocate(fileInputStream.available());
try {
FileChannel channel = fileInputStream.getChannel();
channel.position(be.dataOffset);
channel.read(source);
source.flip();
} finally {
IOUtils.closeQuietly(fileInputStream);
}
be.read(source);
be.readFrames(source);
Assert.assertEquals(rawFrame.length, be.size());
byte[] data = be.getData().array();
System.out.println(EbmlUtil.toHexString(data));
Assert.assertArrayEquals(rawFrame, data);
}
@Test
public void testEbmlLacing() throws IOException {
File file = new File("src/test/resources/mkv/ebml_lacing_block.ebml");
ByteBuffer rawFrame = NIOUtils.fetchFromFile(file);
MkvBlock be = new MkvBlock(Block.id);
be.offset = 0x00;
be.dataLen = 0xF22;
be.dataOffset = 0x03;
FileInputStream fileInputStream = new FileInputStream(file);
ByteBuffer source = ByteBuffer.allocate(fileInputStream.available());
try {
FileChannel channel = fileInputStream.getChannel();
channel.position(be.dataOffset);
channel.read(source);
source.flip();
} finally {
IOUtils.closeQuietly(fileInputStream);
}
be.read(source);
be.readFrames(source);
Assert.assertEquals(rawFrame.capacity(), be.size());
Assert.assertArrayEquals(rawFrame.array(), be.getData().array());
}
@Test
public void testName() throws Exception {
System.out.println(VP8Decoder.printHexByte((byte)-98));
System.out.println(VP8Decoder.printHexByte((byte)-95));
}
@Test
public void testXiphLacing() throws IOException {
File file = new File("src/test/resources/mkv/xiph_lacing_block.ebml");
byte[] rawFrame = readFileToByteArray(file);
MkvBlock be = new MkvBlock(Block.id);
be.offset = 0x00;
be.dataLen = 0x353;
be.dataOffset = 0x03;
FileInputStream fileInputStream = new FileInputStream(file);
ByteBuffer source = ByteBuffer.allocate(fileInputStream.available());
try {
FileChannel channel = fileInputStream.getChannel();
channel.position(be.dataOffset);
channel.read(source);
source.flip();
} finally {
IOUtils.closeQuietly(fileInputStream);
}
be.read(source);
be.readFrames(source);
Assert.assertEquals(rawFrame.length, be.size());
Assert.assertArrayEquals(rawFrame, be.getData().array());
}
@Test
public void testNoLacing() throws IOException {
File file = new File("src/test/resources/mkv/no_lacing_simple_block.ebml");
byte[] rawFrame = readFileToByteArray(file);
MkvBlock be = new MkvBlock(SimpleBlock.id);
be.offset = 0x00;
be.dataLen = 0x304;
be.dataOffset = 0x03;
FileInputStream fileInputStream = new FileInputStream(file);
ByteBuffer source = ByteBuffer.allocate(fileInputStream.available());
try {
FileChannel channel = fileInputStream.getChannel();
channel.position(be.dataOffset);
channel.read(source);
source.flip();
} finally {
IOUtils.closeQuietly(fileInputStream);
}
be.read(source);
be.readFrames(source);
Assert.assertEquals(be.dataLen, be.getDataSize());
Assert.assertEquals(rawFrame.length, be.size());
Assert.assertArrayEquals(rawFrame, be.getData().array());
}
public void test() throws IOException {
MKVTestSuite suite = MKVTestSuite.read();
if (!suite.isSuitePresent())
Assert.fail("MKV test suite is missing, please download from http://www.matroska.org/downloads/test_w1.html, and save to the path recorded in src/test/resources/mkv/suite.properties");
System.out.println("Scanning file: " + suite.test1.getAbsolutePath());
FileInputStream inputStream = new FileInputStream(suite.test1);
try {
MKVParser reader = new MKVParser(new FileChannelWrapper(inputStream.getChannel()));
List<EbmlMaster> t = reader.parse();
printTracks(t);
printTimecodes(t);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
private void printTracks(List<EbmlMaster> tree) {
MKVType[] path = { Segment, Tracks, TrackEntry, TrackNumber };
for (EbmlUint nr : findAllTree(tree, EbmlUint.class, path))
System.out.println("Track nr:" + nr.getUint());
}
private void printTimecodes(List<EbmlMaster> tree) {
MKVType[] path2 = { Segment, Cluster };
EbmlMaster[] clusters = findAllTree(tree, EbmlMaster.class, path2);
for (EbmlMaster c : clusters) {
MKVType[] path = { Cluster, Timecode };
long ctc = ((EbmlUint) findFirst(c, path)).getUint();
long bks = 0;
for (EbmlBase e : c.children) {
if (e instanceof MkvBlock) {
MkvBlock block = (MkvBlock) e;
int btc = block.timecode;
block.absoluteTimecode = btc+ctc;
System.out.println(" Block timecode: " + btc + " absoluete timecode: " + (btc + ctc) + " track: " + block.trackNumber + " offset: " + e.offset +" lacing "+block.lacing);
bks++;
} else if (BlockGroup.equals(e.type)) {
MKVType[] path1 = { BlockGroup, Block };
MkvBlock be = (MkvBlock) findFirst(e, path1);
be.absoluteTimecode = be.timecode + ctc;
System.out.println(" Block Group timecode: " + be.timecode + " absoluete timecode: " + (be.timecode + ctc) + " track: " + be.trackNumber + " offset: " +be.offset+" lacing "+be.lacing);
bks++;
}
}
System.out.println(" Cluster timecode: " + ctc + " offset: " + c.offset + " bks: " + bks);
}
}
}