package org.jcodec.codecs.mpeg12; import org.jcodec.common.io.IOUtils; import org.jcodec.common.model.RationalLarge; import org.jcodec.common.tools.MainUtils; import org.jcodec.common.tools.MainUtils.Cmd; import java.io.File; import java.io.IOException; import java.lang.System; import java.util.Arrays; import java.util.HashMap; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * A utility for manipulation MPEG TS timestamps * * @author The JCodec project * */ public class TimestampUtil { private static final String STREAM_ALL = "all"; private static final String STREAM_AUDIO = "audio"; private static final String STRAM_VIDEO = "video"; private static final String FLAG_STREAM = "stream"; private static final String COMMAND_SHIFT = "shift"; private static final String COMMAND_SCALE = "scale"; private static final String COMMAND_ROUND = "round"; public static void main1(String[] args) throws IOException { Cmd cmd = MainUtils.parseArguments(args); if (cmd.args.length < 3) { System.out.println("A utility to tweak MPEG TS timestamps."); HashMap<String, String> map = new HashMap<String, String>(); map.put(FLAG_STREAM, "A stream to shift, i.e. '" + STRAM_VIDEO + "' or '" + STREAM_AUDIO + "' or '" + STREAM_ALL + "' [default]"); MainUtils.printHelp(map, Arrays.asList("command", "arg", "in name", "?out file")); System.out.println("Where command is:\n" + "\t" + COMMAND_SHIFT + "\tShift timestamps of selected stream by arg." + "\n" + "\t" + COMMAND_SCALE + "\tScale timestams of selected stream by arg [num:den]." + "\n" + "\t" + COMMAND_ROUND + "\tRound timestamps of selected stream to multiples of arg."); return; } File src = new File(cmd.getArg(2)); if (cmd.argsLength() > 3) { File dst = new File(cmd.getArg(3)); IOUtils.copyFile(src, dst); src = dst; } String command = cmd.getArg(0); String stream = cmd.getStringFlagD(FLAG_STREAM, STREAM_ALL); if (COMMAND_SHIFT.equalsIgnoreCase(command)) { final long shift = Long.parseLong(cmd.getArg(1)); new BaseCommand(stream) { protected long withTimestamp(long pts, boolean isPts) { return Math.max(pts + shift, 0); } }.fix(src); } else if (COMMAND_SCALE.equalsIgnoreCase(command)) { final RationalLarge scale = RationalLarge.parse(cmd.getArg(1)); new BaseCommand(stream) { protected long withTimestamp(long pts, boolean isPts) { return scale.multiplyS(pts); } }.fix(src); } else if (COMMAND_ROUND.equalsIgnoreCase(command)) { final int precision = Integer.parseInt(cmd.getArg(1)); new BaseCommand(stream) { protected long withTimestamp(long pts, boolean isPts) { return Math.round((double) pts / precision) * precision; } }.fix(src); } } private static abstract class BaseCommand extends FixTimestamp { private String streamSelector; public BaseCommand(String stream) { this.streamSelector = stream; } protected long doWithTimestamp(int streamId, long pts, boolean isPts) { if (STREAM_ALL.equals(streamSelector) || STRAM_VIDEO.equals(streamSelector) && isVideo(streamId) || STREAM_AUDIO.equals(streamSelector) && isAudio(streamId)) { return withTimestamp(pts, isPts); } else { return pts; } } protected abstract long withTimestamp(long pts, boolean isPts); } }