pull/696/head
Mattia Iavarone 6 years ago
parent 475a9d31a5
commit 4e007b7a6c
  1. 48
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  2. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/AudioMediaEncoder.java

@ -406,20 +406,28 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
@Override @Override
public void onDisconnected(@NonNull CameraDevice camera) { public void onDisconnected(@NonNull CameraDevice camera) {
// Not sure if this is called INSTEAD of onOpened() or can be called after // Not sure if this is called INSTEAD of onOpened() or can be called after
// as well. However, using trySetException should address this problem - // as well. Cover both cases with an unrecoverable exception so that the
// it will only trigger if the task has no result. // engine is properly destroyed.
// CameraException exception
// Docs say to release this camera instance, however, since we throw an = new CameraException(CameraException.REASON_DISCONNECTED);
// unrecoverable CameraException, this will trigger a stop() through the if (!task.getTask().isComplete()) {
// exception handler. task.trySetException(exception);
task.trySetException(new CameraException(CameraException.REASON_DISCONNECTED)); } else {
LOG.i("CameraDevice.StateCallback reported disconnection.");
throw exception;
}
} }
@Override @Override
public void onError(@NonNull CameraDevice camera, int error) { public void onError(@NonNull CameraDevice camera, int error) {
// TODO provide a better implementation if (!task.getTask().isComplete()) {
LOG.e("CameraDevice.StateCallback reported an error:", error); task.trySetException(createCameraException(error));
task.trySetException(createCameraException(error)); } else {
// This happened while the engine is running. Throw unrecoverable exception
// so that engine is properly destroyed.
LOG.e("CameraDevice.StateCallback reported an error:", error);
throw new CameraException(CameraException.REASON_DISCONNECTED);
}
} }
}, null); }, null);
} catch (CameraAccessException e) { } catch (CameraAccessException e) {
@ -556,6 +564,12 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
String message = LOG.e("onConfigureFailed! Session", session); String message = LOG.e("onConfigureFailed! Session", session);
throw new RuntimeException(message); throw new RuntimeException(message);
} }
@Override
public void onReady(@NonNull CameraCaptureSession session) {
super.onReady(session);
LOG.i("CameraCaptureSession.StateCallback reported onReady.");
}
}, null); }, null);
} catch (CameraAccessException e) { } catch (CameraAccessException e) {
throw createCameraException(e); throw createCameraException(e);
@ -623,14 +637,20 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
getFrameManager().release(); getFrameManager().release();
} }
try { try {
// NOTE: should we wait for onReady() like docs say? // Preferring this over stopRepeating() so we're sure that all in-flights operations
// Leaving this synchronous for now. // are discarded as fast as possible, which is exactly what we want.
mSession.stopRepeating(); // NOTE: this call is asynchronous. Should find a good way to wait for the outcome.
LOG.i("onStopPreview:", "calling abortCaptures().");
mSession.abortCaptures();
LOG.i("onStopPreview:", "called abortCaptures().");
} catch (CameraAccessException e) { } catch (CameraAccessException e) {
// This tells us that we should stop everything. It's better to throw an unrecoverable // This tells us that we should stop everything. It's better to throw an unrecoverable
// exception rather than just swallow this, so everything gets stopped. // exception rather than just swallow this, so everything gets stopped.
LOG.w("stopRepeating failed!", e); LOG.w("onStopPreview:", "abortCaptures failed!", e);
throw createCameraException(e); throw createCameraException(e);
} catch (IllegalStateException e) {
// This tells us that the session was already closed.
// Not sure if this can happen, but we can swallow it.
} }
removeRepeatingRequestBuilderSurfaces(); removeRepeatingRequestBuilderSurfaces();
mLastRepeatingResult = null; mLastRepeatingResult = null;

@ -349,14 +349,17 @@ public class AudioMediaEncoder extends MediaEncoder {
*/ */
private class AudioEncodingThread extends Thread { private class AudioEncodingThread extends Thread {
private AudioEncodingThread() { private AudioEncodingThread() {
setPriority(Thread.MAX_PRIORITY); // Not sure about this... This thread can do VERY time consuming operations,
// and slowing down the preview/camera threads can break them e.g. hit internal
// timeouts for camera requests to be consumed.
// setPriority(Thread.MAX_PRIORITY);
} }
@Override @Override
public void run() { public void run() {
encoding: while (true) { encoding: while (true) {
if (mInputBufferQueue.isEmpty()) { if (mInputBufferQueue.isEmpty()) {
skipFrames(2); skipFrames(3);
} else { } else {
LOG.v("encoding thread - performing", mInputBufferQueue.size(), LOG.v("encoding thread - performing", mInputBufferQueue.size(),
"pending operations."); "pending operations.");
@ -387,7 +390,7 @@ public class AudioMediaEncoder extends MediaEncoder {
} else if (tryAcquireInputBuffer(inputBuffer)) { } else if (tryAcquireInputBuffer(inputBuffer)) {
encode(inputBuffer); encode(inputBuffer);
} else { } else {
skipFrames(1); skipFrames(3);
} }
} }
} }

Loading…
Cancel
Save