org.jcodec.samples.splitter.H264SplitterMain.java Source code

Java tutorial

Introduction

Here is the source code for org.jcodec.samples.splitter.H264SplitterMain.java

Source

package org.jcodec.samples.splitter;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
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 org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

/**
 * This class is part of JCodec ( www.jcodec.org ) This software is distributed
 * under FreeBSD License
 * 
 * Splits H264 bitstream into slices having n IDR sequences each
 * 
 * @author The JCodec project
 * 
 */
public class H264SplitterMain extends H264SplitterBase {

    private String fnPattern;

    private String slicePath;
    private String[] exec;
    private boolean verbose;
    private int maxIdr;

    public static void main(String[] args) throws Exception {
        CommandLineParser parser = new PosixParser();

        Options options = new Options();
        options.addOption(OptionBuilder.withLongOpt("num-idr")
                .withDescription("Maximum number of IDR sequences to be written into one slice. Default is 1.")
                .hasArg().withArgName("number").create("n"));
        options.addOption(OptionBuilder.withLongOpt("pattern")
                .withDescription("File name pattern for output slices."
                        + " Use '{index}' as a placeholder for slice index." + " Default is 'output{index}.264'.")
                .hasArg().withArgName("pattern").create("p"));
        options.addOption("v", "verbose", false, "Generate verbose output.");
        options.addOption(OptionBuilder.withLongOpt("exec")
                .withDescription("A command to execute after a new slice is created."
                        + " A full path to the new slice file is" + " passed as a first parameter to the command."
                        + " This should be a full path to executable module." + " Use shell to execute a script.")
                .hasArg().withArgName("command").create("e"));

        options.addOption("h", "help", false, "Print this message.");

        try {
            CommandLine line = parser.parse(options, args);

            String[] files = line.getArgs();
            if (line.hasOption("help") || files.length == 0) {
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp("split264", options);
                System.exit(0);
            }

            String filePattern = "output{index}.264";
            if (line.hasOption("p")) {
                filePattern = line.getOptionValue("p");
            }

            File file = new File(produceFilePath(filePattern, 0));
            if (!file.isAbsolute()) {
                String fileName = files[0];
                filePattern = new File(new File(fileName).getParentFile(), filePattern).getAbsolutePath();
            }

            int numIDR = 1;
            if (line.hasOption("n")) {
                numIDR = Integer.parseInt(line.getOptionValue("n"));
            }

            String execute = null;
            if (line.hasOption("e")) {
                execute = line.getOptionValue("e");
            }

            boolean verbose = false;
            if (line.hasOption("v")) {
                verbose = true;
            }

            new H264SplitterMain().doTheJob(filePattern, numIDR, execute, verbose, files[0]);
        } catch (ParseException exp) {
            System.out.println("Unexpected exception:" + exp.getMessage());
        }
    }

    private void doTheJob(String filePattern, int numIDR, String execute, boolean verbose2, String fileName)
            throws Exception {
        fnPattern = filePattern;
        maxIdr = numIDR;
        if (execute != null) {
            exec = execute.split("\\s");
        }
        verbose = verbose2;
        InputStream io = null;
        try {
            String inFileName = fileName;
            if ("-".equals(inFileName)) {
                io = new BufferedInputStream(System.in);
            } else {
                io = new BufferedInputStream(new FileInputStream(inFileName));
            }

            split(io);
        } finally {
            io.close();
        }
    }

    @Override
    protected void startNewSlice() throws FileNotFoundException, IOException {
        slicePath = produceFilePath(fnPattern, getSliceCount());
        String slicePathTmp = slicePath + ".tmp";

        setOutputStream(new BufferedOutputStream(new FileOutputStream(slicePathTmp)));
    }

    @Override
    protected void finishCurrentSlice() {
        try {
            OutputStream os = getOutputStream();
            if (os != null) {
                os.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (slicePath != null) {
            String slicePathTmp = slicePath + ".tmp";
            File file = new File(slicePathTmp);
            file.renameTo(new File(slicePath));

            executeCommand(slicePath);
        }
    }

    private void executeCommand(String slicePath) {
        if (exec == null)
            return;

        try {
            String[] newArr = new String[exec.length + 1];
            System.arraycopy(exec, 0, newArr, 0, exec.length);
            newArr[exec.length] = slicePath;
            ProcessWrapper pw = new ProcessWrapper(newArr, null);
            int exit = pw.execute();

            if (verbose)
                System.out.println(new String(pw.getOut()));

            byte[] err = pw.getErr();
            if (err.length > 0) {
                System.err.println(new String(err));
            }

            if (exit != 0) {
                System.err.println("Command '" + join(newArr) + "' exited with code: " + exit);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String join(String[] arr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            if (i < arr.length - 1) {
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    private static String produceFilePath(String pattern, int sliceCount) {
        return pattern.replace("{index}", String.valueOf(sliceCount));
    }

    @Override
    protected int getMaxIdr() {
        return maxIdr;
    }
}