[英]Concurrent video frame processing using JavaCV
I have a code that filter a video frame by frame using JavaCV. 我有一个使用JavaCV逐帧过滤视频的代码。 The code is like below
代码如下
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);
}
}
}
Since the line Frame editedFrame = filterFrame(frame);
由于行
Frame editedFrame = filterFrame(frame);
takes quite a long time, is it possible to utilize multithreading so the whole process can be much faster? 需要很长时间,是否有可能利用多线程处理,从而使整个过程更快? I was thinking using something like
ExecutorService
or LinkedBlockingQueue
to process several frames in one time and then record the frame back according to the timestamp. 我正在考虑使用
ExecutorService
或LinkedBlockingQueue
类的东西一次处理多个帧,然后根据时间戳记录回帧。
It's pattern producer : 它是模式生产者 :
Producer class is for executing long task(filterFrame): 生产者类用于执行长任务(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 class is for store frames: 消费者类别适用于商店框架:
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();
}
}
}
And the main part which manage tasks and shutdown 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();
}
}
Note: It's no copy-paste solution and need some customization for your code. 注意:这不是复制粘贴解决方案,需要对您的代码进行一些自定义。 If you share more information i'll change it
如果您分享更多信息,我将对其进行更改
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.