| Index: media/base/android/java/src/org/chromium/media/VideoCapture.java
|
| diff --git a/media/base/android/java/src/org/chromium/media/VideoCapture.java b/media/base/android/java/src/org/chromium/media/VideoCapture.java
|
| index 9d008652cc802c484d1f486153fb801c5ec041cd..06eae1d1c8955b742855178f9073eb2ac949434a 100644
|
| --- a/media/base/android/java/src/org/chromium/media/VideoCapture.java
|
| +++ b/media/base/android/java/src/org/chromium/media/VideoCapture.java
|
| @@ -6,25 +6,17 @@ package org.chromium.media;
|
|
|
| import android.content.Context;
|
| import android.graphics.ImageFormat;
|
| -import android.graphics.SurfaceTexture;
|
| -import android.opengl.GLES20;
|
| -import android.util.Log;
|
| -import android.view.Surface;
|
| -import android.view.WindowManager;
|
|
|
| import org.chromium.base.CalledByNative;
|
| import org.chromium.base.JNINamespace;
|
|
|
| -import java.io.IOException;
|
| -import java.util.List;
|
| -import java.util.concurrent.locks.ReentrantLock;
|
| -
|
| /**
|
| - * Video Capture Device base class to interface to native Chromium.
|
| + * Video Capture Device base class, defines a set of methods that native code
|
| + * needs to use to configure, start capture, and to be reached by callbacks and
|
| + * provides some neccesary data type(s) with accessors.
|
| **/
|
| @JNINamespace("media")
|
| -@SuppressWarnings("deprecation")
|
| -public abstract class VideoCapture implements android.hardware.Camera.PreviewCallback {
|
| +public abstract class VideoCapture {
|
|
|
| protected static class CaptureFormat {
|
| int mWidth;
|
| @@ -57,37 +49,11 @@ public abstract class VideoCapture implements android.hardware.Camera.PreviewCal
|
| }
|
| }
|
|
|
| - protected android.hardware.Camera mCamera;
|
| protected CaptureFormat mCaptureFormat = null;
|
| - // Lock to mutually exclude execution of OnPreviewFrame {start/stop}Capture.
|
| - protected ReentrantLock mPreviewBufferLock = new ReentrantLock();
|
| - protected Context mContext = null;
|
| - // True when native code has started capture.
|
| - protected boolean mIsRunning = false;
|
| -
|
| - protected int mId;
|
| + protected final Context mContext;
|
| + protected final int mId;
|
| // Native callback context variable.
|
| - protected long mNativeVideoCaptureDeviceAndroid;
|
| - protected int[] mGlTextures = null;
|
| - protected SurfaceTexture mSurfaceTexture = null;
|
| - protected static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
|
| -
|
| - protected int mCameraOrientation;
|
| - protected int mCameraFacing;
|
| - protected int mDeviceOrientation;
|
| - private static final String TAG = "VideoCapture";
|
| -
|
| - static android.hardware.Camera.CameraInfo getCameraInfo(int id) {
|
| - android.hardware.Camera.CameraInfo cameraInfo =
|
| - new android.hardware.Camera.CameraInfo();
|
| - try {
|
| - android.hardware.Camera.getCameraInfo(id, cameraInfo);
|
| - } catch (RuntimeException ex) {
|
| - Log.e(TAG, "getCameraInfo: Camera.getCameraInfo: " + ex);
|
| - return null;
|
| - }
|
| - return cameraInfo;
|
| - }
|
| + protected final long mNativeVideoCaptureDeviceAndroid;
|
|
|
| VideoCapture(Context context,
|
| int id,
|
| @@ -98,236 +64,38 @@ public abstract class VideoCapture implements android.hardware.Camera.PreviewCal
|
| }
|
|
|
| @CalledByNative
|
| - boolean allocate(int width, int height, int frameRate) {
|
| - Log.d(TAG, "allocate: requested (" + width + "x" + height + ")@" +
|
| - frameRate + "fps");
|
| - try {
|
| - mCamera = android.hardware.Camera.open(mId);
|
| - } catch (RuntimeException ex) {
|
| - Log.e(TAG, "allocate: Camera.open: " + ex);
|
| - return false;
|
| - }
|
| -
|
| - android.hardware.Camera.CameraInfo cameraInfo = VideoCapture.getCameraInfo(mId);
|
| - if (cameraInfo == null) {
|
| - mCamera.release();
|
| - mCamera = null;
|
| - return false;
|
| - }
|
| -
|
| - mCameraOrientation = cameraInfo.orientation;
|
| - mCameraFacing = cameraInfo.facing;
|
| - mDeviceOrientation = getDeviceOrientation();
|
| - Log.d(TAG, "allocate: orientation dev=" + mDeviceOrientation +
|
| - ", cam=" + mCameraOrientation + ", facing=" + mCameraFacing);
|
| -
|
| - android.hardware.Camera.Parameters parameters = getCameraParameters(mCamera);
|
| - if (parameters == null) {
|
| - mCamera = null;
|
| - return false;
|
| - }
|
| -
|
| - // getSupportedPreviewFpsRange() returns a List with at least one
|
| - // element, but when camera is in bad state, it can return null pointer.
|
| - List<int[]> listFpsRange = parameters.getSupportedPreviewFpsRange();
|
| - if (listFpsRange == null || listFpsRange.size() == 0) {
|
| - Log.e(TAG, "allocate: no fps range found");
|
| - return false;
|
| - }
|
| - // Use the first range as the default chosen range.
|
| - int[] chosenFpsRange = listFpsRange.get(0);
|
| - int chosenFrameRate = (chosenFpsRange[0] + 999) / 1000;
|
| - int fpsRangeSize = Integer.MAX_VALUE;
|
| - // API fps ranges are scaled up x1000 to avoid floating point.
|
| - int frameRateScaled = frameRate * 1000;
|
| - for (int[] fpsRange : listFpsRange) {
|
| - if (fpsRange[0] <= frameRateScaled && frameRateScaled <= fpsRange[1] &&
|
| - (fpsRange[1] - fpsRange[0]) <= fpsRangeSize) {
|
| - chosenFpsRange = fpsRange;
|
| - chosenFrameRate = frameRate;
|
| - fpsRangeSize = fpsRange[1] - fpsRange[0];
|
| - }
|
| - }
|
| - Log.d(TAG, "allocate: fps set to " + chosenFrameRate + ", [" +
|
| - chosenFpsRange[0] + "-" + chosenFpsRange[1] + "]");
|
| -
|
| - // Calculate size.
|
| - List<android.hardware.Camera.Size> listCameraSize =
|
| - parameters.getSupportedPreviewSizes();
|
| - int minDiff = Integer.MAX_VALUE;
|
| - int matchedWidth = width;
|
| - int matchedHeight = height;
|
| - for (android.hardware.Camera.Size size : listCameraSize) {
|
| - int diff = Math.abs(size.width - width) +
|
| - Math.abs(size.height - height);
|
| - Log.d(TAG, "allocate: supported (" +
|
| - size.width + ", " + size.height + "), diff=" + diff);
|
| - // TODO(wjia): Remove this hack (forcing width to be multiple
|
| - // of 32) by supporting stride in video frame buffer.
|
| - // Right now, VideoCaptureController requires compact YV12
|
| - // (i.e., with no padding).
|
| - if (diff < minDiff && (size.width % 32 == 0)) {
|
| - minDiff = diff;
|
| - matchedWidth = size.width;
|
| - matchedHeight = size.height;
|
| - }
|
| - }
|
| - if (minDiff == Integer.MAX_VALUE) {
|
| - Log.e(TAG, "allocate: can not find a multiple-of-32 resolution");
|
| - return false;
|
| - }
|
| - Log.d(TAG, "allocate: matched (" + matchedWidth + "x" + matchedHeight + ")");
|
| -
|
| - if (parameters.isVideoStabilizationSupported()) {
|
| - Log.d(TAG, "Image stabilization supported, currently: " +
|
| - parameters.getVideoStabilization() + ", setting it.");
|
| - parameters.setVideoStabilization(true);
|
| - } else {
|
| - Log.d(TAG, "Image stabilization not supported.");
|
| - }
|
| -
|
| - setCaptureParameters(matchedWidth, matchedHeight, chosenFrameRate, parameters);
|
| - parameters.setPreviewSize(mCaptureFormat.mWidth,
|
| - mCaptureFormat.mHeight);
|
| - parameters.setPreviewFpsRange(chosenFpsRange[0], chosenFpsRange[1]);
|
| - parameters.setPreviewFormat(mCaptureFormat.mPixelFormat);
|
| - try {
|
| - mCamera.setParameters(parameters);
|
| - } catch (RuntimeException ex) {
|
| - Log.e(TAG, "setParameters: " + ex);
|
| - return false;
|
| - }
|
| -
|
| - // Set SurfaceTexture. Android Capture needs a SurfaceTexture even if
|
| - // it is not going to be used.
|
| - mGlTextures = new int[1];
|
| - // Generate one texture pointer and bind it as an external texture.
|
| - GLES20.glGenTextures(1, mGlTextures, 0);
|
| - GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mGlTextures[0]);
|
| - // No mip-mapping with camera source.
|
| - GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
|
| - GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
|
| - GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
|
| - GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
| - // Clamp to edge is only option.
|
| - GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
| - GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
|
| - GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
| - GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
|
| -
|
| - mSurfaceTexture = new SurfaceTexture(mGlTextures[0]);
|
| - mSurfaceTexture.setOnFrameAvailableListener(null);
|
| - try {
|
| - mCamera.setPreviewTexture(mSurfaceTexture);
|
| - } catch (IOException ex) {
|
| - Log.e(TAG, "allocate: " + ex);
|
| - return false;
|
| - }
|
| -
|
| - allocateBuffers();
|
| - return true;
|
| - }
|
| + abstract boolean allocate(int width, int height, int frameRate);
|
|
|
| @CalledByNative
|
| - public int startCapture() {
|
| - if (mCamera == null) {
|
| - Log.e(TAG, "startCapture: camera is null");
|
| - return -1;
|
| - }
|
| -
|
| - mPreviewBufferLock.lock();
|
| - try {
|
| - if (mIsRunning) {
|
| - return 0;
|
| - }
|
| - mIsRunning = true;
|
| - } finally {
|
| - mPreviewBufferLock.unlock();
|
| - }
|
| - setPreviewCallback(this);
|
| - try {
|
| - mCamera.startPreview();
|
| - } catch (RuntimeException ex) {
|
| - Log.e(TAG, "startCapture: Camera.startPreview: " + ex);
|
| - return -1;
|
| - }
|
| - return 0;
|
| - }
|
| + abstract int startCapture();
|
|
|
| @CalledByNative
|
| - public int stopCapture() {
|
| - if (mCamera == null) {
|
| - Log.e(TAG, "stopCapture: camera is null");
|
| - return 0;
|
| - }
|
| -
|
| - mPreviewBufferLock.lock();
|
| - try {
|
| - if (!mIsRunning) {
|
| - return 0;
|
| - }
|
| - mIsRunning = false;
|
| - } finally {
|
| - mPreviewBufferLock.unlock();
|
| - }
|
| -
|
| - mCamera.stopPreview();
|
| - setPreviewCallback(null);
|
| - return 0;
|
| - }
|
| + abstract int stopCapture();
|
|
|
| @CalledByNative
|
| - public void deallocate() {
|
| - if (mCamera == null)
|
| - return;
|
| -
|
| - stopCapture();
|
| - try {
|
| - mCamera.setPreviewTexture(null);
|
| - if (mGlTextures != null)
|
| - GLES20.glDeleteTextures(1, mGlTextures, 0);
|
| - mCaptureFormat = null;
|
| - mCamera.release();
|
| - mCamera = null;
|
| - } catch (IOException ex) {
|
| - Log.e(TAG, "deallocate: failed to deallocate camera, " + ex);
|
| - return;
|
| - }
|
| - }
|
| -
|
| - // Local hook to allow derived classes to fill capture format and modify
|
| - // camera parameters as they see fit.
|
| - abstract void setCaptureParameters(
|
| - int width,
|
| - int height,
|
| - int frameRate,
|
| - android.hardware.Camera.Parameters cameraParameters);
|
| + abstract void deallocate();
|
|
|
| // Local hook to allow derived classes to configure and plug capture
|
| // buffers if needed.
|
| abstract void allocateBuffers();
|
|
|
| - // Local method to be overriden with the particular setPreviewCallback to be
|
| - // used in the implementations.
|
| - abstract void setPreviewCallback(android.hardware.Camera.PreviewCallback cb);
|
| -
|
| @CalledByNative
|
| - public int queryWidth() {
|
| + public final int queryWidth() {
|
| return mCaptureFormat.mWidth;
|
| }
|
|
|
| @CalledByNative
|
| - public int queryHeight() {
|
| + public final int queryHeight() {
|
| return mCaptureFormat.mHeight;
|
| }
|
|
|
| @CalledByNative
|
| - public int queryFrameRate() {
|
| + public final int queryFrameRate() {
|
| return mCaptureFormat.mFramerate;
|
| }
|
|
|
| @CalledByNative
|
| - public int getColorspace() {
|
| + public final int getColorspace() {
|
| switch (mCaptureFormat.mPixelFormat) {
|
| case ImageFormat.YV12:
|
| return AndroidImageFormat.YV12;
|
| @@ -339,48 +107,10 @@ public abstract class VideoCapture implements android.hardware.Camera.PreviewCal
|
| }
|
| }
|
|
|
| - protected int getDeviceOrientation() {
|
| - int orientation = 0;
|
| - if (mContext != null) {
|
| - WindowManager wm = (WindowManager) mContext.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;
|
| - }
|
| -
|
| // Method for VideoCapture implementations to call back native code.
|
| public native void nativeOnFrameAvailable(
|
| long nativeVideoCaptureDeviceAndroid,
|
| byte[] data,
|
| int length,
|
| int rotation);
|
| -
|
| - protected static android.hardware.Camera.Parameters getCameraParameters(
|
| - android.hardware.Camera camera) {
|
| - android.hardware.Camera.Parameters parameters;
|
| - try {
|
| - parameters = camera.getParameters();
|
| - } catch (RuntimeException ex) {
|
| - Log.e(TAG, "getCameraParameters: android.hardware.Camera.getParameters: " + ex);
|
| - camera.release();
|
| - return null;
|
| - }
|
| - return parameters;
|
| - }
|
| -
|
| }
|
|
|