2017-07-19 6 views
0

JavaCVを使用してフレーム単位でビデオフレームをフィルタリングするコードがあります。コードはJavaCVを使用した同時ビデオフレーム処理

try (FFmpegFrameGrabber grabber = createGrabber()) { 
    grabber.start(); 
    try (FFmpegFrameRecorder recorder = createRecorder(grabber)) { 
     recorder.start(); 
     Frame frame; 
     while ((frame = grabber.grab()) != null) { 
      Frame editedFrame = filterFrame(frame); //This takes a long time. 
      recorder.setTimestamp(grabber.getTimestamp()); 
      recorder.record(editedFrame); 
     } 
    } 
} 

以下の行Frame editedFrame = filterFrame(frame);は非常に長い時間がかかるされているためのように、それは全体のプロセスは非常に速くできるようにマルチスレッドを利用することができますか?私はExecutorServiceまたはLinkedBlockingQueueのようなものを使って、一度に複数のフレームを処理し、タイムスタンプに従ってフレームを記録することを考えていました。

+0

フィルタフレームメソッド(これまで示していない)はマルチスレッドを利用してより高速に実行できますか? – auburg

+0

はい、できます。フレームの同期について考える必要があります。おそらく、https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.htmlのようなfilterFrameで作業を分割できます。 –

+0

@ VladislavKysliyは、4スレッドのようなエグゼキュータサービスを持つことが可能で、フィルタリングは4フレームごとに実行され、フレームは取得された順序と同じ順序で記録されますか? –

答えて

0

それはpattern producerです:

プロデューサークラスが長いタスク(filterFrame)を実行するためにされています

import java.util.concurrent.Callable; 

public class Producer implements Callable<Frame> { 

    private final Frame frame; 

    public Producer(Frame frame) { 
     this.frame = frame; 
    } 

    @Override 
    public Frame call() throws Exception { 
     return filterFrame(frame); 
    } 
} 

Consumerクラスをストアフレームのためである:

import java.util.Map; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.Future; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.TimeUnit; 

public class Consumer implements Runnable { 

    private final BlockingQueue<Map.Entry<Long, Future<Frame>>> queue; 
    public Boolean continueProducing = Boolean.TRUE; 
    private final FFmpegFrameRecorder recorder; 

    public Consumer(FFmpegFrameRecorder recorder, 
        BlockingQueue<Map.Entry<Long, Future<Frame>>> queue) { 
     this.recorder = recorder; 
     this.queue = queue; 
    } 

    @Override 
    public void run() { 
     try { 
      Map.Entry<Long, Future<Frame>> entry = this.queue.poll(2, TimeUnit.SECONDS); 
      Frame editedFrame = entry.getValue().get(); 
      recorder.setTimestamp(entry.getKey()); 
      recorder.record(editedFrame); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

とタスクを管理する主要部分およびシャットダウンthreadPool

try (FFmpegFrameGrabber grabber = createGrabber()) { 
      grabber.start(); 
      try (FFmpegFrameRecorder recorder = createRecorder(grabber)) { 
       recorder.start(); 
       Frame frame; 
       ExecutorService threadPool = Executors.newWorkStealingPool(); 
       BlockingQueue<Map.Entry<Long, Future<Frame>>> queue = new LinkedBlockingQueue<>(); 
       threadPool.execute(new Consumer(recorder, queue)); 
       while ((frame = grabber.grab()) != null) { 
        queue.put(new Map.Entry<Long, Future<Frame>>() { 
         @Override 
         public Long getKey() { 
          return grabber.getTimestamp(); 
         } 

         @Override 
         public Future<Frame> getValue() { 
          return threadPool.submit(new Producer(frame)); // Frame editedFrame = filterFrame(frame); //This takes a long time. 
         } 

         @Override 
         public Future<Frame> setValue(Future<Frame> value) { 
          return null; 
         } 
        }); 
       } 
       threadPool.shutdownNow(); 
      } 
     } 

注:コピー&ペーストのソリューションではなく、コードのカスタマイズが必要です。より多くの情報を共有すると、私はそれを変更します

関連する問題