Android 如何确保OnPreviewFrame()内线程内的方法调用(JNI调用)在再次调用之前完成

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

这个问题与Android多线程、OpenCV和JNI有关。在onCameraFrame内部进行的JNI调用是一种昂贵的图像处理操作,因此相机预览帧速率非常慢,并且有很多帧延迟。当从一个新线程在后台调用本机方法“FindSquare”时,性能会略有提高,但不会有太大提高

请建议最有效的方法来做我下面打算做的事情,以提高帧速率

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