@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 + ". Pending buffers: " + cameraStatistics.pendingFramesTimeStamps()); if (cameraFramesCount == 0) { ++freezePeriodCount; if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount > CAMERA_FREEZE_REPORT_TIMOUT_MS && eventsHandler != null) { Logging.e(TAG, "Camera freezed."); if (cameraStatistics.pendingFramesCount() == cameraStatistics.maxPendingFrames) { eventsHandler.onCameraError("Camera failure. Client must return video buffers."); } else { eventsHandler.onCameraError("Camera failure."); } return; } } else { freezePeriodCount = 0; } cameraThreadHandler.postDelayed(this, CAMERA_OBSERVER_PERIOD_MS); }
// Called on cameraThread so must not "synchronized". @Override public void onPreviewFrame(byte[] data, Camera callbackCamera) { checkIsOnCameraThread(); if (camera == null) { return; } if (camera != callbackCamera) { throw new RuntimeException("Unexpected camera in callback!"); } final long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime()); if (eventsHandler != null && !firstFrameReported) { eventsHandler.onFirstFrameAvailable(); firstFrameReported = true; } // Mark the frame owning |data| as used. // Note that since data is directBuffer, // data.length >= videoBuffers.frameSize. if (videoBuffers.reserveByteBuffer(data, captureTimeNs)) { cameraStatistics.addPendingFrame(captureTimeNs); frameObserver.onByteBufferFrameCaptured( data, videoBuffers.frameSize, captureFormat.width, captureFormat.height, getFrameOrientation(), captureTimeNs); } else { Logging.w(TAG, "reserveByteBuffer failed - dropping frame."); } }
private void stopCaptureOnCameraThread() { checkIsOnCameraThread(); Logging.d(TAG, "stopCaptureOnCameraThread"); if (openCameraOnCodecThreadRunner != null) { cameraThreadHandler.removeCallbacks(openCameraOnCodecThreadRunner); } openCameraAttempts = 0; if (camera == null) { Logging.e(TAG, "Calling stopCapture() for already stopped camera."); return; } cameraThreadHandler.removeCallbacks(cameraObserver); cameraStatistics.getAndResetFrameCount(); Logging.d(TAG, "Stop preview."); camera.stopPreview(); camera.setPreviewCallbackWithBuffer(null); if (!isCapturingToTexture()) { videoBuffers.stopReturnBuffersToCamera(); Logging.d( TAG, "stopReturnBuffersToCamera called." + (cameraStatistics.pendingFramesCount() == 0 ? " All buffers have been returned." : " Pending buffers: " + cameraStatistics.pendingFramesTimeStamps() + ".")); } captureFormat = null; Logging.d(TAG, "Release camera."); camera.release(); camera = null; if (eventsHandler != null) { eventsHandler.onCameraClosed(); } }
@Override public void onError(int error, Camera camera) { String errorMessage; if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { errorMessage = "Camera server died!"; } else { errorMessage = "Camera error: " + error; } Logging.e(TAG, errorMessage); if (eventsHandler != null) { eventsHandler.onCameraError(errorMessage); } }
private void startCaptureOnCameraThread( final int width, final int height, final int framerate, final CapturerObserver frameObserver, final Context applicationContext) { Throwable error = null; checkIsOnCameraThread(); if (camera != null) { throw new RuntimeException("Camera has already been started."); } this.applicationContext = applicationContext; this.frameObserver = frameObserver; this.firstFrameReported = false; try { try { synchronized (cameraIdLock) { Logging.d(TAG, "Opening camera " + id); if (eventsHandler != null) { eventsHandler.onCameraOpening(id); } camera = Camera.open(id); info = new Camera.CameraInfo(); Camera.getCameraInfo(id, info); } } catch (RuntimeException e) { openCameraAttempts++; if (openCameraAttempts < MAX_OPEN_CAMERA_ATTEMPTS) { Logging.e(TAG, "Camera.open failed, retrying", e); openCameraOnCodecThreadRunner = new Runnable() { @Override public void run() { startCaptureOnCameraThread( width, height, framerate, frameObserver, applicationContext); } }; cameraThreadHandler.postDelayed(openCameraOnCodecThreadRunner, OPEN_CAMERA_DELAY_MS); return; } openCameraAttempts = 0; throw e; } try { camera.setPreviewTexture(surfaceHelper.getSurfaceTexture()); } catch (IOException e) { Logging.e(TAG, "setPreviewTexture failed", error); throw new RuntimeException(e); } Logging.d( TAG, "Camera orientation: " + info.orientation + " .Device orientation: " + getDeviceOrientation()); camera.setErrorCallback(cameraErrorCallback); startPreviewOnCameraThread(width, height, framerate); frameObserver.onCapturerStarted(true); // Start camera observer. cameraThreadHandler.postDelayed(cameraObserver, CAMERA_OBSERVER_PERIOD_MS); return; } catch (RuntimeException e) { error = e; } Logging.e(TAG, "startCapture failed", error); stopCaptureOnCameraThread(); frameObserver.onCapturerStarted(false); if (eventsHandler != null) { eventsHandler.onCameraError("Camera can not be started."); } return; }