summaryrefslogtreecommitdiffstats
path: root/dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java')
-rw-r--r--dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java216
1 files changed, 216 insertions, 0 deletions
diff --git a/dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java b/dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
new file mode 100644
index 0000000000..cc54009a7b
--- /dev/null
+++ b/dom/media/systemservices/android_video_capture/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2012 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.videoengine;
+
+import java.io.IOException;
+import java.util.List;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.mozilla.gecko.annotation.WebRTCJNITarget;
+
+import org.webrtc.CameraEnumerator;
+import org.webrtc.Camera1Enumerator;
+import org.webrtc.Camera2Enumerator;
+import org.webrtc.CameraVideoCapturer;
+import org.webrtc.CapturerObserver;
+import org.webrtc.EglBase;
+import org.webrtc.SurfaceTextureHelper;
+import org.webrtc.VideoFrame;
+import org.webrtc.VideoFrame.I420Buffer;
+
+public class VideoCaptureAndroid implements CameraVideoCapturer.CameraEventsHandler, CapturerObserver {
+ private final static String TAG = "WEBRTC-JC";
+
+ private final String deviceName;
+ private volatile long native_capturer; // |VideoCaptureAndroid*| in C++.
+ private Context context;
+ private CameraVideoCapturer cameraVideoCapturer;
+ private EglBase eglBase;
+ private SurfaceTextureHelper surfaceTextureHelper;
+
+ // This class is recreated everytime we start/stop capture, so we
+ // can safely create the CountDownLatches here.
+ private final CountDownLatch capturerStarted = new CountDownLatch(1);
+ private boolean capturerStartedSucceeded = false;
+ private final CountDownLatch capturerStopped = new CountDownLatch(1);
+
+ @WebRTCJNITarget
+ public VideoCaptureAndroid(String deviceName) {
+ // Remove the camera facing information from the name.
+ String[] parts = deviceName.split("Facing (front|back):");
+ if (parts.length == 2) {
+ this.deviceName = parts[1].replace(" (infrared)", "");
+ } else {
+ Log.e(TAG, "VideoCaptureAndroid: Expected facing mode as part of name: " + deviceName);
+ this.deviceName = deviceName;
+ }
+ this.context = GetContext();
+
+ CameraEnumerator enumerator;
+ if (Camera2Enumerator.isSupported(context)) {
+ enumerator = new Camera2Enumerator(context);
+ } else {
+ enumerator = new Camera1Enumerator();
+ }
+ try {
+ cameraVideoCapturer = enumerator.createCapturer(this.deviceName, this);
+ eglBase = EglBase.create();
+ surfaceTextureHelper = SurfaceTextureHelper.create("VideoCaptureAndroidSurfaceTextureHelper", eglBase.getEglBaseContext());
+ cameraVideoCapturer.initialize(surfaceTextureHelper, context, this);
+ } catch (java.lang.IllegalArgumentException e) {
+ Log.e(TAG, "VideoCaptureAndroid: Exception while creating capturer: " + e);
+ }
+ }
+
+ // Return the global application context.
+ @WebRTCJNITarget
+ private static native Context GetContext();
+
+ // Called by native code. Returns true if capturer is started.
+ //
+ // Note that this actually opens the camera, and Camera callbacks run on the
+ // thread that calls open(), so this is done on the CameraThread. Since ViE
+ // API needs a synchronous success return value we wait for the result.
+ @WebRTCJNITarget
+ private synchronized boolean startCapture(
+ final int width, final int height,
+ final int min_mfps, final int max_mfps,
+ long native_capturer) {
+ Log.d(TAG, "startCapture: " + width + "x" + height + "@" +
+ min_mfps + ":" + max_mfps);
+
+ if (cameraVideoCapturer == null) {
+ return false;
+ }
+
+ cameraVideoCapturer.startCapture(width, height, max_mfps);
+ try {
+ capturerStarted.await();
+ } catch (InterruptedException e) {
+ return false;
+ }
+ if (capturerStartedSucceeded) {
+ this.native_capturer = native_capturer;
+ }
+ return capturerStartedSucceeded;
+ }
+
+ // Called by native code. Returns true when camera is known to be stopped.
+ @WebRTCJNITarget
+ private synchronized boolean stopCapture() {
+ Log.d(TAG, "stopCapture");
+ if (cameraVideoCapturer == null) {
+ return false;
+ }
+
+ native_capturer = 0;
+ try {
+ cameraVideoCapturer.stopCapture();
+ capturerStopped.await();
+ } catch (InterruptedException e) {
+ return false;
+ }
+ Log.d(TAG, "stopCapture done");
+ return true;
+ }
+
+ @WebRTCJNITarget
+ private int getDeviceOrientation() {
+ int orientation = 0;
+ if (context != null) {
+ WindowManager wm = (WindowManager) context.getSystemService(
+ Context.WINDOW_SERVICE);
+ switch(wm.getDefaultDisplay().getRotation()) {
+ case Surface.ROTATION_90:
+ orientation = 90;
+ break;
+ case Surface.ROTATION_180:
+ orientation = 180;
+ break;
+ case Surface.ROTATION_270:
+ orientation = 270;
+ break;
+ case Surface.ROTATION_0:
+ default:
+ orientation = 0;
+ break;
+ }
+ }
+ return orientation;
+ }
+
+ @WebRTCJNITarget
+ private native void ProvideCameraFrame(
+ int width, int height,
+ java.nio.ByteBuffer dataY, int strideY,
+ java.nio.ByteBuffer dataU, int strideU,
+ java.nio.ByteBuffer dataV, int strideV,
+ int rotation, long timeStamp, long captureObject);
+
+ //
+ // CameraVideoCapturer.CameraEventsHandler interface
+ //
+
+ // Camera error handler - invoked when camera can not be opened
+ // or any camera exception happens on camera thread.
+ public void onCameraError(String errorDescription) {}
+
+ // Called when camera is disconnected.
+ public void onCameraDisconnected() {}
+
+ // Invoked when camera stops receiving frames.
+ public void onCameraFreezed(String errorDescription) {}
+
+ // Callback invoked when camera is opening.
+ public void onCameraOpening(String cameraName) {}
+
+ // Callback invoked when first camera frame is available after camera is started.
+ public void onFirstFrameAvailable() {}
+
+ // Callback invoked when camera is closed.
+ public void onCameraClosed() {}
+
+ //
+ // CapturerObserver interface
+ //
+
+ // Notify if the capturer have been started successfully or not.
+ public void onCapturerStarted(boolean success) {
+ capturerStartedSucceeded = success;
+ capturerStarted.countDown();
+ }
+
+ // Notify that the capturer has been stopped.
+ public void onCapturerStopped() {
+ capturerStopped.countDown();
+ }
+
+ // Delivers a captured frame.
+ public void onFrameCaptured(VideoFrame frame) {
+ if (native_capturer != 0) {
+ I420Buffer i420Buffer = frame.getBuffer().toI420();
+ ProvideCameraFrame(i420Buffer.getWidth(), i420Buffer.getHeight(),
+ i420Buffer.getDataY(), i420Buffer.getStrideY(),
+ i420Buffer.getDataU(), i420Buffer.getStrideU(),
+ i420Buffer.getDataV(), i420Buffer.getStrideV(),
+ frame.getRotation(),
+ frame.getTimestampNs() / 1000000, native_capturer);
+
+ i420Buffer.release();
+ }
+ }
+}