PipedInputStream / PipedOutputStream、ImageIO 和 ffmpeg

3

I have the following code in Scala:

      val pos = new PipedOutputStream()
      val pis = new PipedInputStream(pos)

      Future {
        LOG.trace("Start rendering")
        generateFrames(videoRenderParams.length) {
          img ⇒ ImageIO.write(img, "PNG", pos)
        }
        pos.flush()
        IOUtils.closeQuietly(pos)
        LOG.trace("Finished rendering")
      } onComplete {
        case Success(_) ⇒ 
          LOG.trace("Complete successfully")
        case Failure(err) ⇒
          LOG.error("Can't render stuff", err)
          IOUtils.closeQuietly(pis)
          IOUtils.closeQuietly(pos)
      }

      val prc = (ffmpegCli #< pis).!(logger)

未来只是将生成的图像依次写入 OutputStream 。现在, ffmpeg 进程从 stdin 读取输入图像,并将其转换为MP4文件。

这很有效,但出于某些原因,有时我会遇到以下堆栈跟踪:

I/O error Pipe closed for process: <input stream>
java.io.IOException: Pipe closed
    at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:260)
    at java.io.PipedInputStream.receive(PipedInputStream.java:226)
    at java.io.PipedOutputStream.write(PipedOutputStream.java:149)
    at scala.sys.process.BasicIO$.loop$1(BasicIO.scala:236)
    at scala.sys.process.BasicIO$.transferFullyImpl(BasicIO.scala:242)
    at scala.sys.process.BasicIO$.transferFully(BasicIO.scala:223)
    at scala.sys.process.ProcessImpl$PipeThread.runloop(ProcessImpl.scala:159)
    at scala.sys.process.ProcessImpl$PipeSource.run(ProcessImpl.scala:179)

同时,我从另一个流中获得以下错误:

javax.imageio.IIOException: I/O error writing PNG file!
    at com.sun.imageio.plugins.png.PNGImageWriter.write(PNGImageWriter.java:1168)
    at javax.imageio.ImageWriter.write(ImageWriter.java:615)
    at javax.imageio.ImageIO.doWrite(ImageIO.java:1612)
    at javax.imageio.ImageIO.write(ImageIO.java:1578)
    at 

似乎流在某个地方中断了,因此ffmpeg无法读取数据,ImageIO无法写入数据。更有趣的是,这个问题只在某些Linux服务器(Amazon)上出现。它在其他Linux盒子上运行得很好。因此,我想知道有人能否指出这个错误可能的原因。
到目前为止,我尝试过以下方法:
  • 使用Oracle JDK 8和OpenJDK
  • 使用不同版本的FFMPEG
目前为止没有任何作用。

你正在使用哪个 ExecutionContext 来运行 Future - isomarcte
ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(threads)) - jdevelop
1个回答

4

这个问题有些可预测,同时也有些奇怪。当时有十个并行的ffmpeg进程用来处理输入,而输入是数百张FullHD图片,这显然需要大量计算能力,因此内核随机关闭ffmpeg进程,导致Java封装器同时报告输入和输出管道损坏。

因此,/var/log/messages包含了很多像下面这样的日志:

Out of memory: Kill process 25778 (java) score 159 or sacrifice child
Killed process 25931 (ffmpeg) total-vm:2337040kB, anon-rss:966340kB, file-rss:104kB

减少并发的ffmpeg进程数解决了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接