문제

나는 실행하여 Java에서 비디오 응용 프로그램을 작성하고 있습니다. ffmpeg 출력을 표준 출력으로 캡처합니다. 나는 Java 대신 Apache Commons-Exec을 사용하기로 결정했습니다. Runtime, 더 좋아 보이기 때문에. 그러나 모든 출력을 포착하는 데 어려움이 있습니다.

파이프를 사용하는 것이 진행되는 길이라고 생각했습니다. 왜냐하면 그것은 프로세스 간 통신의 표준 방법이기 때문입니다. 그러나 내 설정을 사용합니다 PipedInputStream 그리고 PipedOutputStream 잘못되었습니다. 그것은 효과가있는 것 같지만 하천의 첫 1042 바이트에 대해서만 호기심이 호기심이 있습니다. PipedInputStream.PIPE_SIZE.

파이프 사용에 대한 연애는 없지만 데이터의 속도와 양 (512x384 해상도의 1m 20s 비디오 690) 때문에 디스크 I/O (가능한 경우)를 사용하지 않기를 원합니다.M 파이프 데이터).

파이프에서 나오는 다량의 데이터를 처리하기위한 최상의 솔루션에 대한 생각? 두 클래스에 대한 내 코드는 다음과 같습니다. (예, sleep 나쁘다. 그것에 대한 생각? wait() 그리고 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();
        }
    }
}
도움이 되었습니까?

해결책

문제는 yuv4mpegpipeparser 클래스의 실행 방법에 있습니다. 두 개의 연속 루프가 있습니다. 스트림에 현재 사용할 수있는 데이터가없는 경우 두 번째 루프는 즉시 종료됩니다 (예 : 지금까지 모든 입력은 Parser에 의해 처리되었으며 FFMPEG 또는 스트림 펌프는 새로운 데이터를 제공하기에 충분히 빠르지 않았습니다 -> usaval () == 0 -> 루프가 종료됩니다 -> 펌프 스레드 마감).

이 두 루프와 수면을 제거하고 처리 할 수있는 데이터가 있는지 확인하는 대신 간단한 차단 read ()를 수행하십시오. 파서 코드가 별도의 스레드에서 시작 되었기 때문에 Wait ()/notify () 또는 sleep ()가 필요하지 않을 수도 있습니다.

다음과 같은 run () 메소드 코드를 다시 작성할 수 있습니다.

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 ...
     }
 }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top