Тайм-аут транскодирования видео Android outputSurface.awaitNewImage иногда истекает

Эта проблема может быть похожа на метод onFrameAvailable() из SurfaceTexture всегда вызывается слишком поздно но я думаю, что это другое. Точно так же код, с которым я работаю, очень похож на http://bigflake.com/mediacodec/ExtractMpegFramesTest_egl14.java.txt

Мне нужно импортировать видео в приложение и перекодировать его. Процесс транскодирования является асинхронной задачей. В асинхронной задаче создается OutputSurface (очень похожий на CodecOutputSurface в примере с bigflake), который реализует SurfaceTexture.OnFrameAvailableListner. Проблема в том, что иногда после ожидания TIMEOUT_MS onFrameAvailable все еще не вызывается, и поэтому выдается исключение RuntimeException:

/**
 * Latches the next buffer into the texture.  Must be called from the thread that created
 * the OutputSurface object, after the onFrameAvailable callback has signaled that new
 * data is available.
 */
public void awaitNewImage() {
    final int TIMEOUT_MS = 500;
    synchronized (mFrameSyncObject) {
        while (!mFrameAvailable) {
            try {
                mFrameSyncObject.wait(TIMEOUT_MS);
                if (!mFrameAvailable) {
                    // TODO: if "spurious wakeup", continue while loop
                    throw new RuntimeException("Surface frame wait timed out");
                }
            } catch (InterruptedException ie) {
                // shouldn't happen
                throw new RuntimeException(ie);
            }
        }
        mFrameAvailable = false;
    }

    // Latch the data.
    mTextureRender.checkGlError("before updateTexImage");
    mSurfaceTexture.updateTexImage();
}

@Override
public void onFrameAvailable(SurfaceTexture st) {
    if (VERBOSE) Log.d(TAG, "new frame available");
    synchronized (mFrameSyncObject) {
        if (mFrameAvailable) {
            throw new RuntimeException("mFrameAvailable already set, frame could be dropped");
        }
        mFrameAvailable = true;
        mFrameSyncObject.notifyAll();
    }
}

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

OutputSurface создается в AsyncTask из потока пользовательского интерфейса, поэтому событие onFrameAvailable доставляется в основной цикл пользовательского интерфейса. Когда я отлаживаю, я вижу, что точки останова для этих двух методов срабатывают в разных потоках.

Тогда я не знаю, почему тайм-аут все еще иногда случается. Около 30% моих испытаний истекает по тайм-ауту. Это не относится к одному устройству или одному API. Я не хочу увеличивать TIMEOUT_MS, потому что это сделает процесс транскодирования еще медленнее (он уже довольно медленный). Любая помощь, если ценится! Спасибо!


person HeyThere    schedule 14.10.2016    source источник
comment
любое решение??   -  person Vishal Patel    schedule 29.08.2017
comment
Я поделился, как я смог решить проблему здесь. stackoverflow.com/a/55968224/2326325   -  person Gaurav Saluja    schedule 03.05.2019