Bri*_*ian 5 java pipe apache-commons video-streaming
我正在用Java编写视频应用程序,执行ffmpeg并将其输出捕获到标准输出.我决定使用Apache Commons-Exec而不是Java Runtime,因为它似乎更好.但是,我很难捕获所有输出.
我认为使用管道是可行的方法,因为它是进程间通信的标准方式.但是,我的设置使用PipedInputStream和PipedOutputStream错误.它似乎工作,但只适用于流的前1042个字节,奇怪的是恰好是值的PipedInputStream.PIPE_SIZE.
我对使用管道并不感兴趣,但我想避免使用磁盘I/O(如果可能),因为数据的速度和数量(512x384分辨率的1m 20s视频产生690 M个管道数据).
关于处理来自管道的大量数据的最佳解决方案的想法?我的两个课程的代码如下.(是的,sleep很糟糕.对此的想法? wait()和notifyAll()?)
WriteFrames.javapublic 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
YUV4MPEGPipeParser.javapublic 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题出在 YUV4MPEGPipeParser 类的 run 方法中。有两个连续的循环。如果流上当前没有可用数据(例如,到目前为止所有输入均由解析器处理,并且 ffmpeg 或流泵不够快,无法为其提供一些新数据 -> available() == 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 ...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5240 次 |
| 最近记录: |