Bug 840244 - Calculate camera and device rotation, rotate video to compensate. r=blassey

This commit is contained in:
Gian-Carlo Pascutto 2013-02-22 11:12:25 +01:00
parent 4ee5c65e2f
commit 14361d21a0
3 changed files with 79 additions and 9 deletions

View File

@ -24,6 +24,7 @@ import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
@ -36,6 +37,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
private final static String TAG = "WEBRTC-JC";
private Camera camera;
private int cameraId;
private AndroidVideoCaptureDevice currentDevice = null;
public ReentrantLock previewBufferLock = new ReentrantLock();
// This lock takes sync with StartCapture and SurfaceChanged
@ -88,10 +90,12 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
}
public VideoCaptureAndroid(int in_id, long in_context, Camera in_camera,
AndroidVideoCaptureDevice in_device) {
AndroidVideoCaptureDevice in_device,
int in_cameraId) {
id = in_id;
context = in_context;
camera = in_camera;
cameraId = in_cameraId;
currentDevice = in_device;
try {
@ -114,6 +118,30 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
}
}
public int GetRotateAmount() {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
private int tryStartCapture(int width, int height, int frameRate) {
if (camera == null) {
Log.e(TAG, "Camera not initialized %d" + id);
@ -164,7 +192,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
}
catch (Exception ex) {
Log.e(TAG, "Failed to start camera");
Log.e(TAG, "Failed to start camera: " + ex.getMessage());
return -1;
}
@ -230,13 +258,14 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
// Sets the rotation of the preview render window.
// Does not affect the captured video image.
public void SetPreviewRotation(int rotation) {
Log.v(TAG, "SetPreviewRotation:" + rotation);
Log.v(TAG, "SetPreviewRotation: " + rotation);
if (camera != null) {
previewBufferLock.lock();
int width = 0;
int height = 0;
int framerate = 0;
boolean wasCaptureRunning = isCaptureRunning;
if (isCaptureRunning) {
width = mCaptureWidth;
@ -259,7 +288,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
}
camera.setDisplayOrientation(resultRotation);
if (isCaptureRunning) {
if (wasCaptureRunning) {
StartCapture(width, height, framerate);
}
previewBufferLock.unlock();

View File

@ -258,6 +258,7 @@ public class VideoCaptureDeviceInfoAndroid {
Log.d(TAG, "AllocateCamera " + deviceUniqueId);
Camera camera = null;
int cameraId = 0;
AndroidVideoCaptureDevice deviceToUse = null;
for (AndroidVideoCaptureDevice device: deviceList) {
if(device.deviceUniqueName.equals(deviceUniqueId)) {
@ -272,10 +273,12 @@ public class VideoCaptureDeviceInfoAndroid {
break;
default:
// From Android 2.3 and onwards)
if(android.os.Build.VERSION.SDK_INT>8)
camera=Camera.open(device.index);
else
camera=Camera.open(); // Default camera
if(android.os.Build.VERSION.SDK_INT>8) {
cameraId = device.index;
camera = Camera.open(device.index);
} else {
camera = Camera.open(); // Default_ camera
}
}
}
}
@ -285,7 +288,7 @@ public class VideoCaptureDeviceInfoAndroid {
}
Log.v(TAG, "AllocateCamera - creating VideoCaptureAndroid");
return new VideoCaptureAndroid(id, context, camera, deviceToUse);
return new VideoCaptureAndroid(id, context, camera, deviceToUse, cameraId);
}catch (Exception ex) {
Log.e(TAG, "AllocateCamera Failed to open camera- ex " +

View File

@ -442,6 +442,7 @@ WebRtc_Word32 VideoCaptureAndroid::StartCapture(
bool isAttached = false;
WebRtc_Word32 result = 0;
WebRtc_Word32 rotation = 0;
// get the JNI env for this thread
JNIEnv *env;
if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
@ -488,6 +489,21 @@ WebRtc_Word32 VideoCaptureAndroid::StartCapture(
"%s: Failed to find StartCapture id", __FUNCTION__);
}
// get the method ID for the Android Java
// CaptureClass static GetRotateAmount method.
cid = env->GetMethodID(g_javaCmClass, "GetRotateAmount", "()I");
if (cid != NULL) {
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
"%s: Call GetRotateAmount", __FUNCTION__);
rotation = env->CallIntMethod(_javaCaptureObj, cid);
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
"%s, GetRotateAmount = %d", __FUNCTION__, rotation);
}
else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
"%s: Failed to find GetRotateAmount id", __FUNCTION__);
}
// Detach this thread if it was attached
if (isAttached) {
if (g_jvm->DetachCurrentThread() < 0) {
@ -495,6 +511,28 @@ WebRtc_Word32 VideoCaptureAndroid::StartCapture(
"%s: Could not detach thread from JVM", __FUNCTION__);
}
}
// I guess the libyuv rotate is CCW vs Android being CW,
// so we need to invert.
// Note that SetCaptureRotation calls SetDisplayOrientation,
// but we don't use a visible Surface so we can ignore that one.
rotation = (360 - rotation) % 360;
switch (rotation) {
case 90:
SetCaptureRotation(kCameraRotate90);
break;
case 180:
SetCaptureRotation(kCameraRotate180);
break;
case 270:
SetCaptureRotation(kCameraRotate270);
break;
case 0:
default:
SetCaptureRotation(kCameraRotate0);
break;
}
if (result == 0) {
_requestedCapability = capability;
_captureStarted = true;