Frage

Ich schreibe eine Videoanwendung in Java durch Ausführung ffmpeg und die Ausgabe an die Standardausgabe erfassen. Ich habe mich entschlossen, Apache Commons-exec anstelle von Java zu verwenden Runtime, weil es besser erscheint. Es fällt mir jedoch schwer, die gesamte Ausgabe zu erfassen.

Ich dachte, die Verwendung von Rohren wäre der richtige Weg, da es sich um eine Standardmethode für die Kommunikation zwischen den Prozess handelt. Mein Setup verwendet jedoch PipedInputStream und PipedOutputStream ist falsch. Es scheint zu funktionieren, aber nur für die ersten 1042 Bytes des Stroms, die seltsamerweise der Wert von ist PipedInputStream.PIPE_SIZE.

Ich habe keine Liebesbeziehung bei der Verwendung von Pfeifen, aber ich möchte aufgrund der Geschwindigkeit und des Datenvolumens (ein 1M 20S -Video bei 512x384 Auflösung 690 (1M 20S) verwenden (wenn möglich), aber wenn möglich) (wenn möglich).M von Rohrdaten).

Gedanken zur besten Lösung, um große Datenmengen aus einer Rohr zu verarbeiten? Mein Code für meine beiden Klassen ist unten. (Jawohl, sleep ist schlecht. Gedanken dazu? wait() und notifyAll() ?)

WriteFrames.java

public class WriteFrames {
    public static void main(String[] args) {
        String commandName = "ffmpeg";
        CommandLine commandLine = new CommandLine(commandName);
        File filename = new File(args[0]);
        String[] options = new String[] { 
                "-i",
                filename.getAbsolutePath(),
                "-an",
                "-f",
                "yuv4mpegpipe",
                "-"};

        for (String s : options) {
            commandLine.addArgument(s);
        }



        PipedOutputStream output = new PipedOutputStream();
        PumpStreamHandler streamHandler = new PumpStreamHandler(output, System.err);
        DefaultExecutor executor = new DefaultExecutor();

        try {
            DataInputStream is = new DataInputStream(new PipedInputStream(output));
            YUV4MPEGPipeParser p = new YUV4MPEGPipeParser(is);
            p.start();

            executor.setStreamHandler(streamHandler);
            executor.execute(commandLine);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

YUV4MPEGPipeParser.java

public class YUV4MPEGPipeParser extends Thread {

    private InputStream is;
    int width, height;

    public YUV4MPEGPipeParser(InputStream is) {
        this.is = is;
    }

    public void run() {
        try {
            while (is.available() == 0) {
                Thread.sleep(100);
            }

            while (is.available() != 0) {
                // do stuff.... like write out YUV frames
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
War es hilfreich?

Lösung

Das Problem liegt in der Laufmethode der YUV4MPEGPIPIPARSER -Klasse. Es gibt zwei aufeinanderfolgende Schleifen. Die zweite Schleife endet sofort, wenn derzeit keine Daten im Stream verfügbar sind (z. B. alle bisherigen Eingaben wurden von Parser verarbeitet, und FFMPEG oder Stream -Pumpe waren nicht schnell genug, um einige neue Daten dafür zu bedienen -> verfügbar () == 0 -> Schleife wird terminiert -> Pumpengewindeflächen).

Befreien Sie sich einfach diese beiden Loops und schlafen Sie und führen Sie einfach ein einfaches Blocking Read () durch, anstatt zu überprüfen, ob Daten zur Verarbeitung verfügbar sind. Es ist wahrscheinlich auch keine Notwendigkeit für Warten ()/Notify () oder sogar Schlaf () erforderlich, da der Parser -Code auf einem separaten Thread gestartet wird.

Sie können den Code von run () wie folgt umschreiben:

public class YUV4MPEGPipeParser extends Thread {

    ...

    // optimal size of buffer for reading from pipe stream :-)
    private static final int BUFSIZE = PipedInputStream.PIPE_SIZE; 

    public void run() {
        try {
            byte buffer[] = new byte[BUFSIZE];
            int len = 0;
            while ((len = is.read(buffer, 0, BUFSIZE) != -1) {
                // we have valid data available 
                // in first 'len' bytes of 'buffer' array.

                // do stuff.... like write out YUV frames
            }
         } catch ...
     }
 }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top