package org.jcodec.codecs.h264.conformance; import org.jcodec.codecs.h264.H264Decoder; import org.jcodec.codecs.h264.BufferH264ES; import org.jcodec.common.io.IOUtils; import org.jcodec.common.io.NIOUtils; import org.jcodec.common.model.ColorSpace; import org.jcodec.common.model.Packet; import org.jcodec.common.model.Picture8Bit; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.StringBuilder; import java.lang.System; import java.nio.ByteBuffer; /** * A tool to test jcodec for conformance * * @author The JCodec project * */ public class ConformanceTestTool { public static void main1(String[] args) throws IOException { (new ConformanceTestTool()).doIt(args); } private void doIt(String[] args) throws IOException { if (args.length < 2) { System.out.println("Syntax: conformace <directory> <report.html>"); return; } File dir = new File(args[0]); StringBuilder sb = new StringBuilder(); sb.append("<table>"); int i = 0; File[] files = dir.listFiles(); for (File file : files) { if (file.isDirectory()) { processOneDir(file, sb, i); i++; } } sb.append("</table>"); System.out.println("TESTING DONE"); NIOUtils.writeTo(ByteBuffer.wrap(sb.toString().getBytes()), new File(args[1])); } private void processOneDir(File file, StringBuilder sb, int i) throws IOException { File[] listFiles = file.listFiles(); File coded = null, decoded = null; // Check the candidate for (File file2 : listFiles) { if (file2.isDirectory()) return; String name = file2.getName(); if (name.endsWith(".264") || name.endsWith(".h264")) { coded = file2; } else if (name.endsWith(".yuv") || name.endsWith(".raw")) { decoded = file2; } } if (coded == null || decoded == null) { System.out.println("No suitable files found for directory: " + file.getName()); return; } sb.append("<tr><td>" + (i + 1) + "</td><td><a href=\"http://storage.jcodec.org/h264/baseline/" + file.getName() + ".zip\">" + file.getName() + ".zip</a></td><td>"); System.out.print("-- " + file.getName()); doOneTest(coded, decoded, sb); sb.append("</td><td> </td></tr>"); } private void doOneTest(File coded, File decoded, StringBuilder sb) { try { RawReader rawReader = null; int oldWidth = 0, oldHeight = 0; InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(coded)); BufferH264ES demuxer = new BufferH264ES(NIOUtils.mapFile(coded)); H264Decoder decoder = new H264Decoder(); Picture8Bit buf = Picture8Bit.create(1920, 1088, ColorSpace.YUV420); Picture8Bit pic; int i = 0; while ((pic = decoder.decodeFrame8Bit(reorder(demuxer.nextFrame()), buf.getData())) != null) { if (rawReader == null || oldWidth != pic.getWidth() || oldHeight != pic.getHeight()) { rawReader = new RawReader(decoded, pic.getWidth(), pic.getHeight()); oldWidth = pic.getWidth(); oldHeight = pic.getHeight(); } Picture8Bit ref = rawReader.readNextFrame8Bit(); if (!compare(ref, pic)) { System.err.println(" - FAILED (" + i + ")"); sb.append("FAILED"); return; } i++; } Picture8Bit ref = rawReader.readNextFrame8Bit(); if (ref != null) { System.err.println(" - FAILED"); sb.append("FAILED"); } else { System.out.println(" - PASSED"); sb.append("<span class=\"passed\">PASSED</span>"); } } finally { IOUtils.closeQuietly(is); } } catch (Throwable t) { System.err.println(" - FAILED"); sb.append("FAILED"); t.printStackTrace(); } } private ByteBuffer reorder(Packet nextFrame) { throw new RuntimeException("Display order reordering!!!"); } private static boolean compare(Picture8Bit expected, Picture8Bit actual) { int size = expected.getWidth() * expected.getHeight(); byte[] expY = expected.getPlaneData(0); byte[] actY = actual.getPlaneData(0); for (int i = 0; i < size; i++) { if (expY[i] != actY[i]) return false; } byte[] expCb = expected.getPlaneData(1); byte[] actCb = actual.getPlaneData(1); for (int i = 0; i < (size >> 2); i++) { if (expCb[i] != actCb[i]) return false; } byte[] expCr = expected.getPlaneData(2); byte[] actCr = actual.getPlaneData(2); for (int i = 0; i < (size >> 2); i++) { if (expCr[i] != actCr[i]) return false; } return true; } }