Android Asynctask для обработки живых видеокадров

Я использую OpenCV, чтобы попытаться выполнить обработку видео в реальном времени. Поскольку обработка довольно тяжелая, она значительно задерживает выходные кадры, что делает живой поток неустойчивым.

Я хотел бы выгрузить часть обработки в AsyncTask. Я пробовал, и это на самом деле делает видео намного более плавным. Однако это заканчивается запуском большого количества задач сразу, а затем они медленно начнут возвращаться с некоторыми результатами.

есть ли способ замедлите это и дождитесь результата, используя инструкции Synchronize или какой-либо другой метод?

на каждом кадре, я запускаю одну из этих задач. DoImgProcessing выполняет длительную обработку и возвращает результат строки.

private class LongOperation extends AsyncTask<Mat, Void, String> {

    @Override
    protected String doInBackground(Mat... params) {
        Mat inputFrame = params[0];
        cropToCenter(inputFrame);
        return doImgProcessing(inputFrame);
    }      

    @Override
    protected void onPostExecute(String result) {
        Log.d(TAG, "on post execute: "+result);

    }

    @Override
    protected void onPreExecute() {
        Log.d(TAG, "on pre execute");
    }
}

public Mat onCameraFrame(Mat inputFrame) {
    inputFrame.copyTo(mRgba);//this will be used for the live stream
    LongOperation op = new LongOperation();
    op.execute(inputFrame);
    return mRgba;
}

2 ответов


Я бы сделал что-то вроде этого :

// Example value for a timeout.
private static final long TIMEOUT = 1000L;

private BlockingQueue<Mat> frames = new LinkedBlockingQueue<Mat>();

Thread worker = new Thread() {
    @Override
    public void run() {
        while (running) {
            Mat inputFrame = frames.poll(TIMEOUT, TimeUnit.MILLISECONDS);
            if (inputFrame == null) {
                // timeout. Also, with a try {} catch block poll can be interrupted via Thread.interrupt() so not to wait for the timeout.
                continue;
            }
            cropToCenter(inputFrame);
            String result = doImgProcessing(inputFrame);
        }
    }
};
worker.start();

public Mat onCameraFrame(Mat inputFrame) {
    inputFrame.copyTo(mRgba);//this will be used for the live stream
    frames.put(inputFrame);
    return mRgba;
}

onCameraFrame помещает кадр в очередь, рабочий поток опрашивает из очереди.

это decorelate прием и обработка рамки. Вы можете отслеживать рост очереди, используя frames.size().

это типичный пример производитель-потребитель.


Если вы делаете это на каждом кадре, похоже, вам нужен поток вместо этого. AsyncTask-это когда вы хотите выполнить одноразовое действие в другом потоке. Здесь вы хотите сделать это неоднократно. Просто создайте поток, и когда он закончит кадр, отправьте сообщение обработчику, чтобы запустить шаг post в потоке пользовательского интерфейса. Он может ждать на семафоре в верхней части своего цикла, чтобы следующий кадр был готов.