package org.jcodec.containers.mps;
import org.jcodec.common.IntIntMap;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.tools.MainUtils;
import org.jcodec.common.tools.MainUtils.Cmd;
import org.jcodec.containers.mps.psi.PATSection;
import org.jcodec.containers.mps.psi.PSISection;
import java.io.File;
import java.io.IOException;
import java.lang.System;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Replaces pid of a stream with a different value
*
* @author Stan Vitvitskyy
*
*/
public class MTSReplacePid extends MTSUtils.TSReader {
private Set<Integer> pmtPids;
private IntIntMap replaceSpec;
public MTSReplacePid(IntIntMap replaceSpec) {
super(true);
this.pmtPids = new HashSet<Integer>();
this.replaceSpec = replaceSpec;
}
@Override
public boolean onPkt(int guid, boolean payloadStart, ByteBuffer tsBuf, long filePos, boolean sectionSyntax,
ByteBuffer fullPkt) {
if (sectionSyntax) {
replaceRefs(replaceSpec, guid, tsBuf, pmtPids);
} else {
System.out.print("TS ");
ByteBuffer buf = fullPkt.duplicate();
short tsFlags = buf.getShort(buf.position() + 1);
buf.putShort(buf.position() + 1, (short) (replacePid(replaceSpec, tsFlags & 0x1fff) | (tsFlags & ~0x1fff)));
}
return true;
}
private static IntIntMap parseReplaceSpec(String spec) {
IntIntMap map = new IntIntMap();
for (String pidPair : spec.split(",")) {
String[] pidPairParsed = pidPair.split(":");
map.put(Integer.parseInt(pidPairParsed[0]), Integer.parseInt(pidPairParsed[1]));
}
return map;
}
private void replaceRefs(IntIntMap replaceSpec, int guid, ByteBuffer buf, Set<Integer> pmtPids) {
if (guid == 0) {
PATSection pat = PATSection.parsePAT(buf);
for (int pids : pat.getPrograms().values()) {
pmtPids.add(pids);
}
} else if (pmtPids.contains(guid)) {
System.out.println(MainUtils.bold("PMT"));
PSISection.parsePSI(buf);
buf.getShort();
NIOUtils.skip(buf, buf.getShort() & 0xfff);
while (buf.remaining() > 4) {
byte streamType = buf.get();
MTSStreamType fromTag = MTSStreamType.fromTag(streamType);
System.out.print((fromTag == null ? "UNKNOWN" : fromTag) + "(" + String.format("0x%02x", streamType)
+ "):\t");
int wn = buf.getShort() & 0xffff;
int wasPid = wn & 0x1fff;
int elementaryPid = replacePid(replaceSpec, wasPid);
buf.putShort(buf.position() - 2, (short) ((elementaryPid & 0x1fff) | (wn & ~0x1fff)));
NIOUtils.skip(buf, buf.getShort() & 0xfff);
}
}
}
private int replacePid(IntIntMap replaceSpec, int pid) {
int newPid = pid;
if (replaceSpec.contains(pid)) {
newPid = replaceSpec.get(pid);
}
System.out.println("[" + pid + "->" + newPid + "]");
return newPid;
}
public static void main1(String[] args) throws IOException {
Cmd cmd = MainUtils.parseArguments(args);
if (cmd.args.length < 2) {
MainUtils.printHelpNoFlags("pid_from:pid_to,[pid_from:pid_to...]", "file");
return;
}
IntIntMap replaceSpec = parseReplaceSpec(cmd.getArg(0));
SeekableByteChannel ch = null;
try {
ch = NIOUtils.rwChannel(new File(cmd.getArg(1)));
new MTSReplacePid(replaceSpec).readTsFile(ch);
} finally {
NIOUtils.closeQuietly(ch);
}
}
}