Эта проблема может быть похожа на метод 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, потому что это сделает процесс транскодирования еще медленнее (он уже довольно медленный). Любая помощь, если ценится! Спасибо!