OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 package org.webrtc; |
| 12 |
| 13 /** |
| 14 * Base interface for camera1 and camera2 implementations. Extends VideoCapturer
with a |
| 15 * switchCamera() function. Also provides subinterfaces for handling camera even
ts, and a helper |
| 16 * class for detecting camera freezes. |
| 17 */ |
| 18 public interface CameraVideoCapturer extends VideoCapturer { |
| 19 /** |
| 20 * Camera events handler - can be used to be notifed about camera events. The
callbacks are |
| 21 * executed from an arbitrary thread. |
| 22 */ |
| 23 public interface CameraEventsHandler { |
| 24 // Camera error handler - invoked when camera can not be opened |
| 25 // or any camera exception happens on camera thread. |
| 26 void onCameraError(String errorDescription); |
| 27 |
| 28 // Invoked when camera stops receiving frames. |
| 29 void onCameraFreezed(String errorDescription); |
| 30 |
| 31 // Callback invoked when camera is opening. |
| 32 void onCameraOpening(int cameraId); |
| 33 |
| 34 // Callback invoked when first camera frame is available after camera is sta
rted. |
| 35 void onFirstFrameAvailable(); |
| 36 |
| 37 // Callback invoked when camera is closed. |
| 38 void onCameraClosed(); |
| 39 } |
| 40 |
| 41 /** |
| 42 * Camera switch handler - one of these functions are invoked with the result
of switchCamera(). |
| 43 * The callback may be called on an arbitrary thread. |
| 44 */ |
| 45 public interface CameraSwitchHandler { |
| 46 // Invoked on success. |isFrontCamera| is true if the new camera is front fa
cing. |
| 47 void onCameraSwitchDone(boolean isFrontCamera); |
| 48 |
| 49 // Invoked on failure, e.g. camera is stopped or only one camera available. |
| 50 void onCameraSwitchError(String errorDescription); |
| 51 } |
| 52 |
| 53 /** |
| 54 * Switch camera to the next valid camera id. This can only be called while th
e camera is running. |
| 55 * This function can be called from any thread. |
| 56 */ |
| 57 void switchCamera(CameraSwitchHandler switchEventsHandler); |
| 58 |
| 59 /** |
| 60 * Helper class to log framerate and detect if the camera freezes. It will run
periodic callbacks |
| 61 * on the SurfaceTextureHelper thread passed in the ctor, and should only be o
perated from that |
| 62 * thread. |
| 63 */ |
| 64 public static class CameraStatistics { |
| 65 private final static String TAG = "CameraStatistics"; |
| 66 private final static int CAMERA_OBSERVER_PERIOD_MS = 2000; |
| 67 private final static int CAMERA_FREEZE_REPORT_TIMOUT_MS = 4000; |
| 68 |
| 69 private final SurfaceTextureHelper surfaceTextureHelper; |
| 70 private final CameraEventsHandler eventsHandler; |
| 71 private int frameCount; |
| 72 private int freezePeriodCount; |
| 73 // Camera observer - monitors camera framerate. Observer is executed on came
ra thread. |
| 74 private final Runnable cameraObserver = new Runnable() { |
| 75 @Override |
| 76 public void run() { |
| 77 final int cameraFps = Math.round(frameCount * 1000.0f / CAMERA_OBSERVER_
PERIOD_MS); |
| 78 Logging.d(TAG, "Camera fps: " + cameraFps +"."); |
| 79 if (frameCount == 0) { |
| 80 ++freezePeriodCount; |
| 81 if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount >= CAMERA_FREEZE_REP
ORT_TIMOUT_MS |
| 82 && eventsHandler != null) { |
| 83 Logging.e(TAG, "Camera freezed."); |
| 84 if (surfaceTextureHelper.isTextureInUse()) { |
| 85 // This can only happen if we are capturing to textures. |
| 86 eventsHandler.onCameraFreezed("Camera failure. Client must return
video buffers."); |
| 87 } else { |
| 88 eventsHandler.onCameraFreezed("Camera failure."); |
| 89 } |
| 90 return; |
| 91 } |
| 92 } else { |
| 93 freezePeriodCount = 0; |
| 94 } |
| 95 frameCount = 0; |
| 96 surfaceTextureHelper.getHandler().postDelayed(this, CAMERA_OBSERVER_PERI
OD_MS); |
| 97 } |
| 98 }; |
| 99 |
| 100 public CameraStatistics( |
| 101 SurfaceTextureHelper surfaceTextureHelper, CameraEventsHandler eventsHan
dler) { |
| 102 if (surfaceTextureHelper == null) { |
| 103 throw new IllegalArgumentException("SurfaceTextureHelper is null"); |
| 104 } |
| 105 this.surfaceTextureHelper = surfaceTextureHelper; |
| 106 this.eventsHandler = eventsHandler; |
| 107 this.frameCount = 0; |
| 108 this.freezePeriodCount = 0; |
| 109 surfaceTextureHelper.getHandler().postDelayed(cameraObserver, CAMERA_OBSER
VER_PERIOD_MS); |
| 110 } |
| 111 |
| 112 private void checkThread() { |
| 113 if (Thread.currentThread() != surfaceTextureHelper.getHandler().getLooper(
).getThread()) { |
| 114 throw new IllegalStateException("Wrong thread"); |
| 115 } |
| 116 } |
| 117 |
| 118 public void addFrame() { |
| 119 checkThread(); |
| 120 ++frameCount; |
| 121 } |
| 122 |
| 123 public void release() { |
| 124 checkThread(); |
| 125 surfaceTextureHelper.getHandler().removeCallbacks(cameraObserver); |
| 126 } |
| 127 } |
| 128 } |
OLD | NEW |