Android: Drop old frame in SurfaceTextureHelper.startListening()
Drop any pending texture frame when SurfaceTextureHelper.startListening() is called because the frame might be from the previous startListening()/stopListening() capture session. This typically happens when switching between the front/back camera, and an old frame will get incorrect rotation and mirroring because of the front/back camera mismatch. Dropping the frame in SurfaceTextureHelper also removes the need for the |dropNextFrame| logic in VideoCapturerAndroid. R=perkj@webrtc.org Review URL: https://codereview.webrtc.org/2002963002 . Cr-Commit-Position: refs/heads/master@{#12849}
This commit is contained in:
@ -309,8 +309,12 @@ class SurfaceTextureHelper {
|
||||
Logging.d(TAG, "Setting listener to " + pendingListener);
|
||||
listener = pendingListener;
|
||||
pendingListener = null;
|
||||
// May alredy have a pending frame - try delivering it.
|
||||
tryDeliverTextureFrame();
|
||||
// May have a pending frame from the previous capture session - drop it.
|
||||
if (hasPendingTexture) {
|
||||
// Calling updateTexImage() is neccessary in order to receive new frames.
|
||||
updateTexImage();
|
||||
hasPendingTexture = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -455,6 +459,15 @@ class SurfaceTextureHelper {
|
||||
getYuvConverter().convert(buf, width, height, stride, textureId, transformMatrix);
|
||||
}
|
||||
|
||||
private void updateTexImage() {
|
||||
// SurfaceTexture.updateTexImage apparently can compete and deadlock with eglSwapBuffers,
|
||||
// as observed on Nexus 5. Therefore, synchronize it with the EGL functions.
|
||||
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info.
|
||||
synchronized (EglBase.lock) {
|
||||
surfaceTexture.updateTexImage();
|
||||
}
|
||||
}
|
||||
|
||||
private void tryDeliverTextureFrame() {
|
||||
if (handler.getLooper().getThread() != Thread.currentThread()) {
|
||||
throw new IllegalStateException("Wrong thread.");
|
||||
@ -465,12 +478,7 @@ class SurfaceTextureHelper {
|
||||
isTextureInUse = true;
|
||||
hasPendingTexture = false;
|
||||
|
||||
// SurfaceTexture.updateTexImage apparently can compete and deadlock with eglSwapBuffers,
|
||||
// as observed on Nexus 5. Therefore, synchronize it with the EGL functions.
|
||||
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info.
|
||||
synchronized (EglBase.lock) {
|
||||
surfaceTexture.updateTexImage();
|
||||
}
|
||||
updateTexImage();
|
||||
|
||||
final float[] transformMatrix = new float[16];
|
||||
surfaceTexture.getTransformMatrix(transformMatrix);
|
||||
|
||||
@ -78,9 +78,6 @@ public class VideoCapturerAndroid implements
|
||||
private final Set<byte[]> queuedBuffers = new HashSet<byte[]>();
|
||||
private final boolean isCapturingToTexture;
|
||||
private SurfaceTextureHelper surfaceHelper;
|
||||
// The camera API can output one old frame after the camera has been switched or the resolution
|
||||
// has been changed. This flag is used for dropping the first frame after camera restart.
|
||||
private boolean dropNextFrame = false;
|
||||
private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3;
|
||||
private final static int OPEN_CAMERA_DELAY_MS = 500;
|
||||
private int openCameraAttempts;
|
||||
@ -462,7 +459,6 @@ public class VideoCapturerAndroid implements
|
||||
// Temporarily stop preview if it's already running.
|
||||
if (this.captureFormat != null) {
|
||||
camera.stopPreview();
|
||||
dropNextFrame = true;
|
||||
// Calling |setPreviewCallbackWithBuffer| with null should clear the internal camera buffer
|
||||
// queue, but sometimes we receive a frame with the old resolution after this call anyway.
|
||||
camera.setPreviewCallbackWithBuffer(null);
|
||||
@ -564,7 +560,6 @@ public class VideoCapturerAndroid implements
|
||||
synchronized (cameraIdLock) {
|
||||
id = (id + 1) % android.hardware.Camera.getNumberOfCameras();
|
||||
}
|
||||
dropNextFrame = true;
|
||||
startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramerate, frameObserver,
|
||||
applicationContext);
|
||||
Logging.d(TAG, "switchCameraOnCameraThread done");
|
||||
@ -654,11 +649,6 @@ public class VideoCapturerAndroid implements
|
||||
throw new RuntimeException("onTextureFrameAvailable() called after stopCapture().");
|
||||
}
|
||||
checkIsOnCameraThread();
|
||||
if (dropNextFrame) {
|
||||
surfaceHelper.returnTextureFrame();
|
||||
dropNextFrame = false;
|
||||
return;
|
||||
}
|
||||
if (eventsHandler != null && !firstFrameReported) {
|
||||
eventsHandler.onFirstFrameAvailable();
|
||||
firstFrameReported = true;
|
||||
|
||||
Reference in New Issue
Block a user