Android 如何确保OnPreviewFrame()内线程内的方法调用(JNI调用)在再次调用之前完成
这个问题与Android多线程、OpenCV和JNI有关。在onCameraFrame内部进行的JNI调用是一种昂贵的图像处理操作,因此相机预览帧速率非常慢,并且有很多帧延迟。当从一个新线程在后台调用本机方法“FindSquare”时,性能会略有提高,但不会有太大提高 请建议最有效的方法来做我下面打算做的事情,以提高帧速率Android 如何确保OnPreviewFrame()内线程内的方法调用(JNI调用)在再次调用之前完成,android,multithreading,opencv,android-ndk,java-native-interface,Android,Multithreading,Opencv,Android Ndk,Java Native Interface,这个问题与Android多线程、OpenCV和JNI有关。在onCameraFrame内部进行的JNI调用是一种昂贵的图像处理操作,因此相机预览帧速率非常慢,并且有很多帧延迟。当从一个新线程在后台调用本机方法“FindSquare”时,性能会略有提高,但不会有太大提高 请建议最有效的方法来做我下面打算做的事情,以提高帧速率 boolean isCallFinished = false; public Mat onCameraFrame(Mat inputFrame) { Size or
boolean isCallFinished = false;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
new Thread(new Runnable() {
public void run() {
Message msg = new Message();
if(!isCallFinished) {
msg.arg1 = FindSquares(mDstImg.getNativeObjAddr()); // JNI call
isCallFinished = true;
messageHandler.sendMessage(msg);
}
}
}).start();
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}
乍一看,快速优化可以避免为每个帧创建新线程 创建新线程非常昂贵 尝试以下方法: 创建工作线程并保留对它的引用 创建同步队列以与工作线程通信 将对象添加到工作线程队列,并将其作为一个组进行处理 我将试着写下下面的概念,并使其适应您的需要。请注意,代码没有在适当的环境中进行测试
public class MyWorkerThread extends Thread
{
ArrayList<FrameEvent> frameList;
boolean runWorkerThread;
public WorkerThread
{
super("FrameEventsWorkerThread");
runWorkerThread=true;
frameList= new ArrayList<FrameEvent>();
}
public synchronized AddFrameEvent(FrameEvent aEvent)
{
frameList.add(aEvent);
}
public void kill ()
{
runWorkerThread=true;
}
public void run()
{
while (true && runWorkerThread)
{
synchronized(this)
{
if (frameList.size()>0)
{
for (int i=0;i<frameList.size();i++)
{
Message msg = new Message();
if (!isCallFinished) { // don't quite understand what you want with this
FrameEvent evt = frameList.get(i);
msg.arg1 = FindSquares(evt.dstImg.getNativeObjAddr());
isCallFinished=true;
messageHandler.sendMessage(msg);
}
}
frameList.clear();
}
}
try {
Thread.sleep(10);
} catch (Exception e)
{
}
}
}
}
谢谢。我试试这个。我知道每次创建新线程都会很昂贵。同时,我也在寻找如何重用单个线程。似乎ExecutorService也是一种选择。有什么建议吗?isCallFinished布尔标志是确保JNI方法在返回/完成之前不会被多次调用的简单方法。请使用我上面编写的工作线程代码以避免线程生成。当你使用一个线程时,它可以满足你的需要。您可以将其设置为单例,并通过实现不同的消息类型在程序中使用它。
boolean isCallFinished = false;
MyWorkerThread theThread;
public Mat onCameraFrame(Mat inputFrame) {
Size originalSize = inputFrame.size();
Imgproc.cvtColor(inputFrame, mDstImg, Imgproc.COLOR_RGBA2BGR);
Imgproc.resize(inputFrame, mDstImg, new Size(mScreenWidth,
mScreenHeight)); // 2048, 1536
FrameEvent newEvt = new FrameEvent();
newEvt.dstImg = mDstImg;
theThread.AddFrameEvent(newEvt); // avoid creating new threads
if (mDraw == 1) {
Imgproc.resize(mDstImg, inputFrame, originalSize);
}
return inputFrame;
}