| Index: webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java
|
| diff --git a/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java b/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java
|
| index 939c86992fa5dc671037fd7d1becb9ec8e15091e..03168784971805829868165bf6444af24e4d6bcd 100644
|
| --- a/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java
|
| +++ b/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java
|
| @@ -11,6 +11,7 @@
|
| package org.webrtc;
|
|
|
| import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
|
| +import org.webrtc.Metrics.Histogram;
|
|
|
| import android.content.Context;
|
| import android.os.Handler;
|
| @@ -48,6 +49,10 @@ public class VideoCapturerAndroid
|
| SurfaceTextureHelper.OnTextureFrameAvailableListener {
|
| private static final String TAG = "VideoCapturerAndroid";
|
| private static final int CAMERA_STOP_TIMEOUT_MS = 7000;
|
| + private static final Histogram videoCapturerAndroidStartTimeMsHistogram =
|
| + Histogram.createCounts("WebRTC.Android.VideoCapturerAndroid.StartTimeMs", 1, 10000, 50);
|
| + private static final Histogram videoCapturerAndroidStopTimeMsHistogram =
|
| + Histogram.createCounts("WebRTC.Android.VideoCapturerAndroid.StopTimeMs", 1, 10000, 50);
|
|
|
| private android.hardware.Camera camera; // Only non-null while capturing.
|
| private final AtomicBoolean isCameraRunning = new AtomicBoolean();
|
| @@ -82,6 +87,9 @@ public class VideoCapturerAndroid
|
| private final static int OPEN_CAMERA_DELAY_MS = 500;
|
| private int openCameraAttempts;
|
|
|
| + // Used for statistics.
|
| + private long startStartTimeNs; // The time in nanoseconds when starting the camera began.
|
| +
|
| // Camera error callback.
|
| private final android.hardware.Camera.ErrorCallback cameraErrorCallback =
|
| new android.hardware.Camera.ErrorCallback() {
|
| @@ -296,6 +304,7 @@ public class VideoCapturerAndroid
|
|
|
| private void startCaptureOnCameraThread(final int width, final int height, final int framerate) {
|
| checkIsOnCameraThread();
|
| + startStartTimeNs = System.nanoTime();
|
| if (!isCameraRunning.get()) {
|
| Logging.e(TAG, "startCaptureOnCameraThread: Camera is stopped");
|
| return;
|
| @@ -478,6 +487,7 @@ public class VideoCapturerAndroid
|
| private void stopCaptureOnCameraThread(boolean stopHandler) {
|
| checkIsOnCameraThread();
|
| Logging.d(TAG, "stopCaptureOnCameraThread");
|
| + final long stopStartTime = System.nanoTime();
|
| // Note that the camera might still not be started here if startCaptureOnCameraThread failed
|
| // and we posted a retry.
|
|
|
| @@ -516,6 +526,8 @@ public class VideoCapturerAndroid
|
| if (eventsHandler != null) {
|
| eventsHandler.onCameraClosed();
|
| }
|
| + final int stopTimeMs = (int) TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - stopStartTime);
|
| + videoCapturerAndroidStopTimeMsHistogram.addSample(stopTimeMs);
|
| Logging.d(TAG, "stopCaptureOnCameraThread done");
|
| }
|
|
|
| @@ -582,11 +594,9 @@ public class VideoCapturerAndroid
|
|
|
| final long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime());
|
|
|
| - if (eventsHandler != null && !firstFrameReported) {
|
| - eventsHandler.onFirstFrameAvailable();
|
| - firstFrameReported = true;
|
| + if (!firstFrameReported) {
|
| + onFirstFrameAvailable();
|
| }
|
| -
|
| cameraStatistics.addFrame();
|
| frameObserver.onByteBufferFrameCaptured(
|
| data, captureFormat.width, captureFormat.height, getFrameOrientation(), captureTimeNs);
|
| @@ -601,11 +611,6 @@ public class VideoCapturerAndroid
|
| surfaceHelper.returnTextureFrame();
|
| return;
|
| }
|
| - if (eventsHandler != null && !firstFrameReported) {
|
| - eventsHandler.onFirstFrameAvailable();
|
| - firstFrameReported = true;
|
| - }
|
| -
|
| int rotation = getFrameOrientation();
|
| if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
| // Undo the mirror that the OS "helps" us with.
|
| @@ -613,11 +618,24 @@ public class VideoCapturerAndroid
|
| transformMatrix =
|
| RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.horizontalFlipMatrix());
|
| }
|
| + if (!firstFrameReported) {
|
| + onFirstFrameAvailable();
|
| + }
|
| cameraStatistics.addFrame();
|
| frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.height, oesTextureId,
|
| transformMatrix, rotation, timestampNs);
|
| }
|
|
|
| + private void onFirstFrameAvailable() {
|
| + if (eventsHandler != null) {
|
| + eventsHandler.onFirstFrameAvailable();
|
| + }
|
| + final int startTimeMs =
|
| + (int) TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startStartTimeNs);
|
| + videoCapturerAndroidStartTimeMsHistogram.addSample(startTimeMs);
|
| + firstFrameReported = true;
|
| + }
|
| +
|
| @Override
|
| public boolean isScreencast() {
|
| return false;
|
|
|