Revert of Android: Make base interface for camera1 and camera2 (patchset #1 id:1 of https://codereview.webrtc.org/1994893002/ )

Reason for revert:
Still breaks downstream import.

Original issue's description:
> Reland of Android: Make base interface for camera1 and camera2 (patchset #1 id:1 of https://codereview.webrtc.org/1979583002/ )
>
> Reason for revert:
> Downstream code has been updated.
>
> Original issue's description:
> > Revert of Android: Make base interface for camera1 and camera2 (patchset #3 id:80001 of https://codereview.webrtc.org/1895483002/ )
> >
> > Reason for revert:
> > Breaks downstream import.
> >
> > Original issue's description:
> > > Android: Make base interface for camera1 and camera2
> > >
> > > This CL adds a new interface CameraVideoCapturer that extends VideoCapturer with a switchCamera() function. It also moves moves CameraEventsHandler, CameraStatistics, and CameraSwitchHandler from VideoCapturerAndroid to this new interface. The purpose is to prepare for a camera2 implementation that will use the same interfaces and helper class.
> > >
> > > BUG=webrtc:5519
> > >
> > > Committed: https://crrev.com/6bdacaddfb18edef1f0cdd778209f6b05a8f9210
> > > Cr-Commit-Position: refs/heads/master@{#12723}
> >
> > TBR=perkj@webrtc.org
> > # Skipping CQ checks because original CL landed less than 1 days ago.
> > NOPRESUBMIT=true
> > NOTREECHECKS=true
> > NOTRY=true
> > BUG=webrtc:5519
> >
> > Committed: https://crrev.com/181b5ffdf036427d92929667d9d43bbcff560435
> > Cr-Commit-Position: refs/heads/master@{#12727}
>
> TBR=perkj@webrtc.org
> # Not skipping CQ checks because original CL landed more than 1 days ago.
> BUG=webrtc:5519
>
> Committed: https://crrev.com/d269b023bfe1c321798fe9c8dbd631a562914fe1
> Cr-Commit-Position: refs/heads/master@{#12807}

TBR=perkj@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:5519

Review-Url: https://codereview.webrtc.org/1994013004
Cr-Commit-Position: refs/heads/master@{#12809}
This commit is contained in:
magjed
2016-05-19 04:22:58 -07:00
committed by Commit bot
parent efafd7f90c
commit bd76607abb
2 changed files with 86 additions and 137 deletions

View File

@ -1,128 +0,0 @@
/*
* Copyright 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
/**
* Base interface for camera1 and camera2 implementations. Extends VideoCapturer with a
* switchCamera() function. Also provides subinterfaces for handling camera events, and a helper
* class for detecting camera freezes.
*/
public interface CameraVideoCapturer extends VideoCapturer {
/**
* Camera events handler - can be used to be notifed about camera events. The callbacks are
* executed from an arbitrary thread.
*/
public interface CameraEventsHandler {
// Camera error handler - invoked when camera can not be opened
// or any camera exception happens on camera thread.
void onCameraError(String errorDescription);
// Invoked when camera stops receiving frames.
void onCameraFreezed(String errorDescription);
// Callback invoked when camera is opening.
void onCameraOpening(int cameraId);
// Callback invoked when first camera frame is available after camera is started.
void onFirstFrameAvailable();
// Callback invoked when camera is closed.
void onCameraClosed();
}
/**
* Camera switch handler - one of these functions are invoked with the result of switchCamera().
* The callback may be called on an arbitrary thread.
*/
public interface CameraSwitchHandler {
// Invoked on success. |isFrontCamera| is true if the new camera is front facing.
void onCameraSwitchDone(boolean isFrontCamera);
// Invoked on failure, e.g. camera is stopped or only one camera available.
void onCameraSwitchError(String errorDescription);
}
/**
* Switch camera to the next valid camera id. This can only be called while the camera is running.
* This function can be called from any thread.
*/
void switchCamera(CameraSwitchHandler switchEventsHandler);
/**
* Helper class to log framerate and detect if the camera freezes. It will run periodic callbacks
* on the SurfaceTextureHelper thread passed in the ctor, and should only be operated from that
* thread.
*/
public static class CameraStatistics {
private final static String TAG = "CameraStatistics";
private final static int CAMERA_OBSERVER_PERIOD_MS = 2000;
private final static int CAMERA_FREEZE_REPORT_TIMOUT_MS = 4000;
private final SurfaceTextureHelper surfaceTextureHelper;
private final CameraEventsHandler eventsHandler;
private int frameCount;
private int freezePeriodCount;
// Camera observer - monitors camera framerate. Observer is executed on camera thread.
private final Runnable cameraObserver = new Runnable() {
@Override
public void run() {
final int cameraFps = Math.round(frameCount * 1000.0f / CAMERA_OBSERVER_PERIOD_MS);
Logging.d(TAG, "Camera fps: " + cameraFps +".");
if (frameCount == 0) {
++freezePeriodCount;
if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount >= CAMERA_FREEZE_REPORT_TIMOUT_MS
&& eventsHandler != null) {
Logging.e(TAG, "Camera freezed.");
if (surfaceTextureHelper.isTextureInUse()) {
// This can only happen if we are capturing to textures.
eventsHandler.onCameraFreezed("Camera failure. Client must return video buffers.");
} else {
eventsHandler.onCameraFreezed("Camera failure.");
}
return;
}
} else {
freezePeriodCount = 0;
}
frameCount = 0;
surfaceTextureHelper.getHandler().postDelayed(this, CAMERA_OBSERVER_PERIOD_MS);
}
};
public CameraStatistics(
SurfaceTextureHelper surfaceTextureHelper, CameraEventsHandler eventsHandler) {
if (surfaceTextureHelper == null) {
throw new IllegalArgumentException("SurfaceTextureHelper is null");
}
this.surfaceTextureHelper = surfaceTextureHelper;
this.eventsHandler = eventsHandler;
this.frameCount = 0;
this.freezePeriodCount = 0;
surfaceTextureHelper.getHandler().postDelayed(cameraObserver, CAMERA_OBSERVER_PERIOD_MS);
}
private void checkThread() {
if (Thread.currentThread() != surfaceTextureHelper.getHandler().getLooper().getThread()) {
throw new IllegalStateException("Wrong thread");
}
}
public void addFrame() {
checkThread();
++frameCount;
}
public void release() {
checkThread();
surfaceTextureHelper.getHandler().removeCallbacks(cameraObserver);
}
}
}

View File

@ -38,13 +38,14 @@ import java.util.concurrent.TimeUnit;
// arbitrary Java threads. All public entry points are thread safe, and delegate the work to the
// camera thread. The internal *OnCameraThread() methods must check |camera| for null to check if
// the camera has been stopped.
// TODO(magjed): This class name is now confusing - rename to Camera1VideoCapturer.
@SuppressWarnings("deprecation")
public class VideoCapturerAndroid implements
CameraVideoCapturer,
VideoCapturer,
android.hardware.Camera.PreviewCallback,
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 = 4000;
private static final int CAMERA_STOP_TIMEOUT_MS = 7000;
private boolean isDisposed = false;
@ -59,7 +60,7 @@ public class VideoCapturerAndroid implements
private final Object cameraIdLock = new Object();
private int id;
private android.hardware.Camera.CameraInfo info;
private CameraStatistics cameraStatistics;
private final CameraStatistics cameraStatistics;
// Remember the requested format in case we want to switch cameras.
private int requestedWidth;
private int requestedHeight;
@ -103,6 +104,84 @@ public class VideoCapturerAndroid implements
}
};
// 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();
int cameraFps = (cameraFramesCount * 1000 + CAMERA_OBSERVER_PERIOD_MS / 2)
/ CAMERA_OBSERVER_PERIOD_MS;
Logging.d(TAG, "Camera fps: " + cameraFps +".");
if (cameraFramesCount == 0) {
++freezePeriodCount;
if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount >= CAMERA_FREEZE_REPORT_TIMOUT_MS
&& eventsHandler != null) {
Logging.e(TAG, "Camera freezed.");
if (surfaceHelper.isTextureInUse()) {
// This can only happen if we are capturing to textures.
eventsHandler.onCameraFreezed("Camera failure. Client must return video buffers.");
} else {
eventsHandler.onCameraFreezed("Camera failure.");
}
return;
}
} else {
freezePeriodCount = 0;
}
maybePostDelayedOnCameraThread(CAMERA_OBSERVER_PERIOD_MS, this);
}
};
private static class CameraStatistics {
private int frameCount = 0;
private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker();
CameraStatistics() {
threadChecker.detachThread();
}
public void addFrame() {
threadChecker.checkIsOnValidThread();
++frameCount;
}
public int getAndResetFrameCount() {
threadChecker.checkIsOnValidThread();
int count = frameCount;
frameCount = 0;
return count;
}
}
public static interface CameraEventsHandler {
// Camera error handler - invoked when camera can not be opened
// or any camera exception happens on camera thread.
void onCameraError(String errorDescription);
// Invoked when camera stops receiving frames
void onCameraFreezed(String errorDescription);
// Callback invoked when camera is opening.
void onCameraOpening(int cameraId);
// Callback invoked when first camera frame is available after camera is opened.
void onFirstFrameAvailable();
// Callback invoked when camera closed.
void onCameraClosed();
}
// Camera switch handler - one of these functions are invoked with the result of switchCamera().
// The callback may be called on an arbitrary thread.
public interface CameraSwitchHandler {
// Invoked on success. |isFrontCamera| is true if the new camera is front facing.
void onCameraSwitchDone(boolean isFrontCamera);
// Invoked on failure, e.g. camera is stopped or only one camera available.
void onCameraSwitchError(String errorDescription);
}
public static VideoCapturerAndroid create(String name,
CameraEventsHandler eventsHandler) {
return VideoCapturerAndroid.create(name, eventsHandler, false /* captureToTexture */);
@ -137,7 +216,6 @@ public class VideoCapturerAndroid implements
// Switch camera to the next valid camera id. This can only be called while
// the camera is running.
@Override
public void switchCamera(final CameraSwitchHandler switchEventsHandler) {
if (android.hardware.Camera.getNumberOfCameras() < 2) {
if (switchEventsHandler != null) {
@ -221,6 +299,7 @@ public class VideoCapturerAndroid implements
this.id = cameraId;
this.eventsHandler = eventsHandler;
isCapturingToTexture = captureToTexture;
cameraStatistics = new CameraStatistics();
Logging.d(TAG, "VideoCapturerAndroid isCapturingToTexture : " + isCapturingToTexture);
}
@ -381,7 +460,7 @@ public class VideoCapturerAndroid implements
}
// Start camera observer.
cameraStatistics = new CameraStatistics(surfaceHelper, eventsHandler);
maybePostDelayedOnCameraThread(CAMERA_OBSERVER_PERIOD_MS, cameraObserver);
return;
} catch (RuntimeException e) {
error = e;
@ -534,10 +613,8 @@ public class VideoCapturerAndroid implements
if (surfaceHelper != null) {
surfaceHelper.stopListening();
}
if (cameraStatistics != null) {
cameraStatistics.release();
cameraStatistics = null;
}
cameraThreadHandler.removeCallbacks(cameraObserver);
cameraStatistics.getAndResetFrameCount();
Logging.d(TAG, "Stop preview.");
if (camera != null) {
camera.stopPreview();