package org.jcodec.codecs.mpeg12;
import org.jcodec.common.Assert;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.containers.mps.MTSUtils;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.System;
import java.nio.ByteBuffer;
import java.util.zip.CRC32;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class HLSFixPMT {
public void fix(File file) throws IOException {
RandomAccessFile ra = null;
try {
ra = new RandomAccessFile(file, "rw");
byte[] tsPkt = new byte[188];
while (ra.read(tsPkt) == 188) {
Assert.assertEquals(0x47, tsPkt[0] & 0xff);
int guidFlags = ((tsPkt[1] & 0xff) << 8) | (tsPkt[2] & 0xff);
int guid = (int) guidFlags & 0x1fff;
int payloadStart = (guidFlags >> 14) & 0x1;
int b0 = tsPkt[3] & 0xff;
int counter = b0 & 0xf;
int payloadOff = 0;
if ((b0 & 0x20) != 0) {
payloadOff = (tsPkt[4 + payloadOff] & 0xff) + 1;
}
if (payloadStart == 1) {
payloadOff += (tsPkt[4 + payloadOff] & 0xff) + 1;
}
if (guid == 0) {
if (payloadStart == 0)
throw new RuntimeException("PAT spans multiple TS packets, not supported!!!!!!");
ByteBuffer bb = ByteBuffer.wrap(tsPkt, 4 + payloadOff, 184 - payloadOff);
fixPAT(bb);
ra.seek(ra.getFilePointer() - 188);
ra.write(tsPkt);
}
}
} finally {
if (ra != null)
ra.close();
}
}
public static void fixPAT(ByteBuffer data) {
ByteBuffer table = data.duplicate();
MTSUtils.parseSection(data);
ByteBuffer newPmt = data.duplicate();
while (data.remaining() > 4) {
short num = data.getShort();
short pid = data.getShort();
if (num != 0) {
newPmt.putShort(num);
newPmt.putShort(pid);
}
}
if (newPmt.position() != data.position()) {
// rewrite Section len
ByteBuffer section = table.duplicate();
section.get();
int sectionLen = newPmt.position() - table.position() + 1;
section.putShort((short) ((sectionLen & 0xfff) | 0xB000));
// Redo crc32
CRC32 crc32 = new CRC32();
table.limit(newPmt.position());
crc32.update(NIOUtils.toArray(table));
newPmt.putInt((int) crc32.getValue());
// fill with 0xff
while (newPmt.hasRemaining())
newPmt.put((byte) 0xff);
}
}
public static void main1(String[] args) throws IOException {
if (args.length < 1)
exit("Please specify package location");
File hlsPkg = new File(args[0]);
if (!hlsPkg.isDirectory())
exit("Not an HLS package, expected a folder");
File[] listFiles = hlsPkg.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".ts");
}
});
HLSFixPMT fix = new HLSFixPMT();
for (int i = 0; i < listFiles.length; i++) {
File file = listFiles[i];
System.err.println("Processing: " + file.getName());
fix.fix(file);
}
}
private static void exit(String message) {
System.err.println("Syntax: hls_fixpmt <hls package location>");
System.err.println(message);
System.exit(-1);
}
}