簡體   English   中英

使用JavaCV並發視頻幀處理

[英]Concurrent video frame processing using 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); 需要很長時間,是否有可能利用多線程處理,從而使整個過程更快? 我正在考慮使用ExecutorServiceLinkedBlockingQueue類的東西一次處理多個幀,然后根據時間戳記錄回幀。

它是模式生產者

生產者類用於執行長任務(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);
    }
}

消費者類別適用於商店框架:

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();
        }
    }
}

以及管理任務和關閉線程的主要部分

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();
            }
        }

注意:這不是復制粘貼解決方案,需要對您的代碼進行一些自定義。 如果您分享更多信息,我將對其進行更改

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM