diff --git a/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java b/webrtc/api/android/java/src/org/webrtc/VideoCapturerAndroid.java index e0b0dcd46f..8abe6ac7a9 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() { @@ -300,6 +308,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; @@ -482,6 +491,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. @@ -520,6 +530,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"); } @@ -586,11 +598,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); @@ -605,11 +615,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. @@ -617,11 +622,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;