package jpcsp.test; import static jpcsp.format.psmf.PsmfAudioDemuxVirtualFile.PACK_START_CODE; import static jpcsp.format.psmf.PsmfAudioDemuxVirtualFile.PADDING_STREAM; import static jpcsp.format.psmf.PsmfAudioDemuxVirtualFile.PRIVATE_STREAM_1; import static jpcsp.format.psmf.PsmfAudioDemuxVirtualFile.PRIVATE_STREAM_2; import static jpcsp.format.psmf.PsmfAudioDemuxVirtualFile.SYSTEM_HEADER_START_CODE; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import jpcsp.HLE.modules.sceMpeg; public class ExtractRawVideoFromPSMF { private static byte buffer[] = new byte[sceMpeg.MPEG_AVC_ES_SIZE]; private static int read8(InputStream in) throws IOException { return in.read() & 0xFF; } private static int read16(InputStream in) throws IOException { return (read8(in) << 8) | read8(in); } private static int read32(InputStream in) throws IOException { return (read8(in) << 24) | (read8(in) << 16) | (read8(in) << 8) | read8(in); } private static void skip(InputStream in, int n) throws IOException { in.skip(n); } private static int skipPesHeader(InputStream in, int startCode) throws IOException { int pesLength = 0; int c = read8(in); pesLength++; while (c == 0xFF) { c = read8(in); pesLength++; } if ((c & 0xC0) == 0x40) { skip(in, 1); c = read8(in); pesLength += 2; } if ((c & 0xE0) == 0x20) { skip(in, 4); pesLength += 4; if ((c & 0x10) != 0) { skip(in, 5); pesLength += 5; } } else if ((c & 0xC0) == 0x80) { skip(in, 1); int headerLength = read8(in); pesLength += 2; skip(in, headerLength); pesLength += headerLength; } if (startCode == 0x1BD) { // PRIVATE_STREAM_1 int channel = read8(in); pesLength++; if (channel >= 0x80 && channel <= 0xCF) { skip(in, 3); pesLength += 3; if (channel >= 0xB0 && channel <= 0xBF) { skip(in, 1); pesLength++; } } else { skip(in, 3); pesLength += 3; } } return pesLength; } private static void write(OutputStream out, InputStream in, int n) throws IOException { if (n > 0) { in.read(buffer, 0, n); out.write(buffer, 0, n); } } public static void main(String[] args) { try { FileInputStream in = new FileInputStream(args[0]); FileOutputStream out = new FileOutputStream(args[0] + ".raw"); while (true) { int startCode = read32(in); if (startCode == -1) { break; } int codeLength; switch (startCode) { case PACK_START_CODE: skip(in, 10); break; case SYSTEM_HEADER_START_CODE: skip(in, 14); break; case PADDING_STREAM: case PRIVATE_STREAM_2: case PRIVATE_STREAM_1: // Audio stream codeLength = read16(in); skip(in, codeLength); break; case 0x1E0: case 0x1E1: case 0x1E2: case 0x1E3: // Video streams case 0x1E4: case 0x1E5: case 0x1E6: case 0x1E7: case 0x1E8: case 0x1E9: case 0x1EA: case 0x1EB: case 0x1EC: case 0x1ED: case 0x1EE: case 0x1EF: codeLength = read16(in); codeLength -= skipPesHeader(in, startCode); write(out, in, codeLength); break; } } out.close(); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }