Add MPS/MPEG-PS demuxer (H.264 video + ATRAC3+ audio packets)
- Parse PS packets, PES headers and PTS/DTS timestamps - 'mps' CLI command samples packets from a stream - Validated on Batman Begins 00001.MPS (Annex-B H.264 + 2-channel ATRAC3+)
This commit is contained in:
@@ -3,6 +3,7 @@ package dev.quoije.umd.cli;
|
||||
|
||||
import dev.quoije.umd.iso.UmdIsoFile;
|
||||
import dev.quoije.umd.iso.UmdIsoReader;
|
||||
import dev.quoije.umd.mps.MpsDemuxer;
|
||||
import dev.quoije.umd.playlist.Playlist;
|
||||
import dev.quoije.umd.sfo.Sfo;
|
||||
|
||||
@@ -14,7 +15,7 @@ import java.util.Map;
|
||||
/** Command-line front-end for the UMD player library. */
|
||||
public final class Main {
|
||||
|
||||
private static final String USAGE = "usage: umdplayer dump <image.iso>";
|
||||
private static final String USAGE = "usage: umdplayer dump <image.iso>\n umdplayer mps <image.iso> <streamName>";
|
||||
|
||||
private Main() {
|
||||
}
|
||||
@@ -29,6 +30,7 @@ public final class Main {
|
||||
try {
|
||||
exitCode = switch (args[0]) {
|
||||
case "dump" -> dump(requireArg(args, 1));
|
||||
case "mps" -> mps(requireArg(args, 1), requireArg(args, 2));
|
||||
case "help", "--help", "-h" -> {
|
||||
System.out.println(USAGE);
|
||||
yield 0;
|
||||
@@ -151,6 +153,47 @@ public final class Main {
|
||||
return String.format("%02d:%02d:%02d.%02d", hours, minutes, secs, hundredth);
|
||||
}
|
||||
|
||||
private static int mps(String imagePath, String streamName) throws IOException {
|
||||
try (UmdIsoReader iso = new UmdIsoReader(Path.of(imagePath))) {
|
||||
try (MpsDemuxer demuxer = MpsDemuxer.open(iso, streamName)) {
|
||||
int count = 0;
|
||||
int videoPackets = 0;
|
||||
int audioPackets = 0;
|
||||
while (count < 40) {
|
||||
MpsDemuxer.Packet packet = demuxer.nextPacket();
|
||||
if (packet == null) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
String type = packet.isVideo()
|
||||
? "video"
|
||||
: packet.isAudio() ? "audio(ch=" + packet.channel() + ")" : "other";
|
||||
System.out.printf("%d: stream=0x%02X %s pts=%d len=%d%n",
|
||||
count, packet.streamId(), type, packet.pts(), packet.payload().length);
|
||||
if (packet.isVideo()) {
|
||||
videoPackets++;
|
||||
if (videoPackets == 1) {
|
||||
System.out.println(" first video payload: " + hexPrefix(packet.payload(), 16));
|
||||
}
|
||||
} else if (packet.isAudio()) {
|
||||
audioPackets++;
|
||||
}
|
||||
}
|
||||
System.out.printf("Sampled %d packets (%d video, %d audio)%n",
|
||||
count, videoPackets, audioPackets);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static String hexPrefix(byte[] data, int max) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < Math.min(data.length, max); i++) {
|
||||
sb.append(String.format("%02X ", data[i] & 0xFF));
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
private static byte[] readFile(UmdIsoReader iso, String path) throws IOException {
|
||||
if (!iso.hasFile(path)) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user