Changed timeout to 6s for reporting android camera freeze.

Also distinguish between camera failures and failures due to that buffers has not been returned.
Adds unit tests for making sure CameraEventHandler.onError is triggered if frames are not returned.

BUG=b/25514149

Review URL: https://codereview.webrtc.org/1415013006

Cr-Commit-Position: refs/heads/master@{#10555}
This commit is contained in:
perkj 2015-11-08 06:58:15 -08:00 committed by Commit bot
parent e2e1de494f
commit 3bfef44a4d
3 changed files with 62 additions and 5 deletions

View File

@ -258,4 +258,16 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT);
VideoCapturerAndroidTestFixtures.returnBufferLateEndToEnd(capturer);
}
@MediumTest
// This test that CameraEventsHandler.onError is triggered if video buffers are not returned to
// the capturer.
public void testCameraErrorEventOnBufferStarvation() throws InterruptedException {
VideoCapturerAndroidTestFixtures.CameraEvents cameraEvents =
VideoCapturerAndroidTestFixtures.createCameraEvents();
VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", cameraEvents);
VideoCapturerAndroidTestFixtures.cameraErrorEventOnBufferStarvation(capturer,
cameraEvents, getInstrumentation().getContext());
}
}

View File

@ -174,9 +174,16 @@ public class VideoCapturerAndroidTestFixtures {
VideoCapturerAndroid.CameraEventsHandler {
public boolean onCameraOpeningCalled;
public boolean onFirstFrameAvailableCalled;
public final Object onCameraErrorLock = new Object();
private String onCameraErrorDescription;
@Override
public void onCameraError(String errorDescription) { }
public void onCameraError(String errorDescription) {
synchronized (onCameraErrorLock) {
onCameraErrorDescription = errorDescription;
onCameraErrorLock.notifyAll();
}
}
@Override
public void onCameraOpening(int cameraId) {
@ -190,6 +197,13 @@ public class VideoCapturerAndroidTestFixtures {
@Override
public void onCameraClosed() { }
public String WaitForCameraError() throws InterruptedException {
synchronized (onCameraErrorLock) {
onCameraErrorLock.wait();
return onCameraErrorDescription;
}
}
}
static public CameraEvents createCameraEvents() {
@ -440,4 +454,25 @@ public class VideoCapturerAndroidTestFixtures {
// Check that frames have successfully returned. This will cause |capturer| to be released.
assertTrue(capturer.isReleased());
}
static public void cameraErrorEventOnBufferStarvation(VideoCapturerAndroid capturer,
CameraEvents events, Context appContext) throws InterruptedException {
final List<CaptureFormat> formats = capturer.getSupportedFormats();
final CameraEnumerationAndroid.CaptureFormat format = formats.get(0);
final FakeCapturerObserver observer = new FakeCapturerObserver();
capturer.startCapture(format.width, format.height, format.maxFramerate,
appContext, observer);
// Make sure camera is started.
assertTrue(observer.WaitForCapturerToStart());
// Since we don't call returnBuffer, we should get a starvation message.
assertEquals("Camera failure. Client must return video buffers.", events.WaitForCameraError());
capturer.stopCapture();
for (long timeStamp : observer.getCopyAndResetListOftimeStamps()) {
capturer.returnBuffer(timeStamp);
}
capturer.dispose();
assertTrue(capturer.isReleased());
}
}

View File

@ -72,6 +72,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
SurfaceTextureHelper.OnTextureFrameAvailableListener {
private final static String TAG = "VideoCapturerAndroid";
private final static int CAMERA_OBSERVER_PERIOD_MS = 2000;
private final static int CAMERA_FREEZE_REPORT_TIMOUT_MS = 6000;
private Camera camera; // Only non-null while capturing.
private HandlerThread cameraThread;
@ -120,6 +121,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
// Camera observer - monitors camera framerate. Observer is executed on camera thread.
private final Runnable cameraObserver = new Runnable() {
private int freezePeriodCount;
@Override
public void run() {
int cameraFramesCount = cameraStatistics.getAndResetFrameCount();
@ -129,13 +131,21 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
Logging.d(TAG, "Camera fps: " + cameraFps +
". Pending buffers: " + cameraStatistics.pendingFramesTimeStamps());
if (cameraFramesCount == 0) {
Logging.e(TAG, "Camera freezed.");
if (eventsHandler != null) {
eventsHandler.onCameraError("Camera failure.");
++freezePeriodCount;
if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount > CAMERA_FREEZE_REPORT_TIMOUT_MS &&
eventsHandler != null) {
Logging.e(TAG, "Camera freezed.");
if (cameraStatistics.pendingFramesCount() > 0) {
eventsHandler.onCameraError("Camera failure. Client must return video buffers.");
} else {
eventsHandler.onCameraError("Camera failure.");
}
return;
}
} else {
cameraThreadHandler.postDelayed(this, CAMERA_OBSERVER_PERIOD_MS);
freezePeriodCount = 0;
}
cameraThreadHandler.postDelayed(this, CAMERA_OBSERVER_PERIOD_MS);
}
};