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

时间:2014-07-28 15:22:13

标签: android multithreading opencv android-ndk java-native-interface

此问题与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;       
}

1 个答案:

答案 0 :(得分:0)

乍一看快速优化是为了避免为每个帧创建一个新线程。

创建一个新线程非常昂贵。

尝试以下方法:

  • 创建工作线程(保持对它的引用)
  • 创建同步队列以与工作线程进行通信
  • 将对象添加到工作线程队列并将其作为一组处理

我会尝试写下以下概念,并根据您的需求进行调整(请注意,代码未在适当的环境中进行测试)。

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)
        {
        }

    }
 }
}

您的新功能应如下所示:

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