Video hacks + disabled mirroring of capture.

This commit is contained in:
Guillaume Beraudo 2011-05-20 12:55:40 +02:00
parent e9dadc8965
commit 6d530bd16f
7 changed files with 95 additions and 37 deletions

View file

@ -26,14 +26,14 @@ public final class Hacks {
private Hacks() {} private Hacks() {}
public static boolean isGalaxyS() {
return isGT9000() || isSC02B();
}
public static boolean isGalaxySOrTabWithFrontCamera() { public static boolean isGalaxySOrTabWithFrontCamera() {
return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera(); return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera();
} }
private static boolean isGalaxySOrTabWithoutFrontCamera() {
return isSC02B() || isSGHI896();
}
public static boolean isGalaxySOrTab() { public static boolean isGalaxySOrTab() {
return isGalaxyS() || isGalaxyTab(); return isGalaxyS() || isGalaxyTab();
@ -42,14 +42,27 @@ public final class Hacks {
public static boolean isGalaxyTab() { public static boolean isGalaxyTab() {
return isGTP1000(); return isGTP1000();
} }
private static boolean isGalaxyS() {
private static boolean isGT9000() {return Build.DEVICE.startsWith("GT-I9000");} return isGT9000() || isSC02B() || isSGHI896() || isSPHD700();
private static boolean isSC02B() {return Build.DEVICE.startsWith("SC-02B");}
private static boolean isGTP1000() {return Build.DEVICE.startsWith("GT-P1000");}
private static boolean isGalaxySOrTabWithoutFrontCamera() {
return isSC02B();
} }
public static final boolean hasTwoCamerasRear0Front1() {
return isSPHD700() || isADR6400();
}
// HTC
private static final boolean isADR6400() {
return Build.MODEL.startsWith("ADR6400") || Build.DEVICE.startsWith("ADR6400");
} // HTC Thunderbolt
// Galaxy S variants
private static final boolean isSPHD700() {return Build.DEVICE.startsWith("SPH-D700");} // Epic
private static boolean isSGHI896() {return Build.DEVICE.startsWith("SGH-I896");} // Captivate
private static boolean isGT9000() {return Build.DEVICE.startsWith("GT-I9000");} // Galaxy S
private static boolean isSC02B() {return Build.DEVICE.startsWith("SC-02B");} // Docomo
private static boolean isGTP1000() {return Build.DEVICE.startsWith("GT-P1000");} // Tab
/* private static final boolean log(final String msg) { /* private static final boolean log(final String msg) {
Log.d("Linphone", msg); Log.d("Linphone", msg);
return true; return true;
@ -109,4 +122,8 @@ public final class Hacks {
// return false; // return false;
return isGalaxySOrTab() && !isSC02B(); return isGalaxySOrTab() && !isSC02B();
} }
public static boolean hasTwoCameras() {
return isSPHD700() || isGalaxySOrTabWithFrontCamera();
}
} }

View file

@ -36,21 +36,25 @@ class AndroidCameraConf5 implements AndroidCameraConf {
if (Hacks.isGalaxySOrTab()) { if (Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : has one or more cameras"); Log.d(tag, "Hack Galaxy S : has one or more cameras");
if (Hacks.isGalaxySOrTabWithFrontCamera()) { if (Hacks.isGalaxySOrTabWithFrontCamera()) {
Log.d(tag, "Hack Galaxy S : HAVE a front camera"); Log.d(tag, "Hack Galaxy S : HAS a front camera with id=2");
foundCameras.front = 2; foundCameras.front = 2;
} else { } else {
Log.d(tag, "Hack Galaxy S : NO front camera"); Log.d(tag, "Hack Galaxy S : NO front camera");
} }
Log.d(tag, "Hack Galaxy S : HAS a rear camera with id=1");
foundCameras.rear = 1; foundCameras.rear = 1;
foundCameras.defaultC = foundCameras.rear; foundCameras.defaultC = foundCameras.rear;
} else if (Hacks.hasTwoCamerasRear0Front1()) {
Log.d(tag, "Hack SPHD700 has 2 cameras a rear with id=0 and a front with id=1");
foundCameras.front = 1;
} }
} }
public int getNumberOfCameras() { public int getNumberOfCameras() {
Log.i(tag, "Detecting the number of cameras"); Log.i(tag, "Detecting the number of cameras");
if (Hacks.isGalaxySOrTabWithFrontCamera()) { if (Hacks.hasTwoCamerasRear0Front1() || Hacks.isGalaxySOrTabWithFrontCamera()) {
Log.d(tag, "Hack Galaxy S : has 2 cameras"); Log.d(tag, "Hack: we know this model has 2 cameras");
return 2; return 2;
} else } else
return 1; return 1;
@ -82,6 +86,9 @@ class AndroidCameraConf5 implements AndroidCameraConf {
if (cameraId == 2 && Hacks.isGalaxySOrTab()) { if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
Log.d(tag, "Hack Galaxy S : front camera has id=2"); Log.d(tag, "Hack Galaxy S : front camera has id=2");
return true; return true;
} else if (cameraId == 1 && Hacks.hasTwoCamerasRear0Front1()) {
Log.d(tag, "Hack SPHD700 : front camera has id=1");
return true;
} }
return false; return false;

View file

@ -18,7 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
package org.linphone.core.video; package org.linphone.core.video;
import org.linphone.LinphoneManager;
import android.hardware.Camera; import android.hardware.Camera;
import android.util.Log;
class AndroidCameraConf9 implements AndroidCameraConf { class AndroidCameraConf9 implements AndroidCameraConf {
private AndroidCameras foundCameras; private AndroidCameras foundCameras;
@ -46,6 +49,10 @@ class AndroidCameraConf9 implements AndroidCameraConf {
public int getCameraOrientation(int cameraId) { public int getCameraOrientation(int cameraId) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info); Camera.getCameraInfo(cameraId, info);
Log.d(LinphoneManager.TAG, String.format("Camera info for %i: orientation=%i returned=%i ",
cameraId,
info.orientation,
(info.orientation - 90) %360));
return (info.orientation - 90) %360; return (info.orientation - 90) %360;
} }

View file

@ -53,7 +53,7 @@ public abstract class AndroidCameraRecord {
return Collections.emptyList(); return Collections.emptyList();
} }
public void startPreview() { // FIXME throws exception? public synchronized void startPreview() { // FIXME throws exception?
if (previewStarted) { if (previewStarted) {
Log.w(tag, "Already started"); Log.w(tag, "Already started");
throw new RuntimeException("Video recorder already started"); throw new RuntimeException("Video recorder already started");
@ -68,6 +68,10 @@ public abstract class AndroidCameraRecord {
Log.d(tag, "Trying to open camera with id " + params.cameraId); Log.d(tag, "Trying to open camera with id " + params.cameraId);
if (camera != null) {
Log.e(tag, "Camera is not null, ?already open? : aborting");
return;
}
camera = openCamera(params.cameraId); camera = openCamera(params.cameraId);
camera.setErrorCallback(new ErrorCallback() { camera.setErrorCallback(new ErrorCallback() {
public void onError(int error, Camera camera) { public void onError(int error, Camera camera) {
@ -79,8 +83,6 @@ public abstract class AndroidCameraRecord {
Camera.Parameters parameters=camera.getParameters(); Camera.Parameters parameters=camera.getParameters();
if (Version.sdkStrictlyBelow(9)) { if (Version.sdkStrictlyBelow(9)) {
parameters.set("camera-id",params.cameraId); parameters.set("camera-id",params.cameraId);
camera.setParameters(parameters);
parameters = camera.getParameters();
} }
if (supportedVideoSizes == null) { if (supportedVideoSizes == null) {
@ -94,14 +96,15 @@ public abstract class AndroidCameraRecord {
// invert height and width // invert height and width
parameters.setPreviewSize(params.height, params.width); parameters.setPreviewSize(params.height, params.width);
} }
// should setParameters and get again to have the real one??
currentPreviewSize = parameters.getPreviewSize();
parameters.setPreviewFrameRate(Math.round(params.fps)); parameters.setPreviewFrameRate(Math.round(params.fps));
onSettingCameraParameters(parameters); onSettingCameraParameters(parameters);
camera.setParameters(parameters); camera.setParameters(parameters);
currentPreviewSize = camera.getParameters().getPreviewSize();
SurfaceHolder holder = params.surfaceView.getHolder(); SurfaceHolder holder = params.surfaceView.getHolder();
try { try {
camera.setPreviewDisplay(holder); camera.setPreviewDisplay(holder);
@ -113,9 +116,11 @@ public abstract class AndroidCameraRecord {
try { try {
camera.startPreview(); camera.startPreview();
previewStarted = true;
} catch (Throwable e) { } catch (Throwable e) {
Log.e(tag, "Can't start camera preview"); Log.e(tag, "Error, can't start camera preview. Releasing camera!");
camera.release();
camera = null;
return;
} }
previewStarted = true; previewStarted = true;
@ -160,7 +165,7 @@ public abstract class AndroidCameraRecord {
camera.stopPreview(); camera.stopPreview();
camera.release(); camera.release();
camera=null; camera=null;
if (currentPreviewSize != null) currentPreviewSize = null; currentPreviewSize = null;
previewStarted = false; previewStarted = false;
} }
@ -176,6 +181,8 @@ public abstract class AndroidCameraRecord {
public static class RecorderParams { public static class RecorderParams {
public static enum MirrorType {NO, HORIZONTAL, CENTRAL, VERTICAL};
public float fps; public float fps;
public int height; public int height;
public int width; public int width;
@ -185,6 +192,8 @@ public abstract class AndroidCameraRecord {
public int rotation; public int rotation;
public SurfaceView surfaceView; public SurfaceView surfaceView;
public MirrorType mirror = MirrorType.NO;
public RecorderParams(long ptr) { public RecorderParams(long ptr) {
filterDataNativePtr = ptr; filterDataNativePtr = ptr;
} }

View file

@ -20,6 +20,8 @@ package org.linphone.core.video;
import java.util.List; import java.util.List;
import org.linphone.core.video.AndroidCameraRecord.RecorderParams.MirrorType;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Camera.Parameters; import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.PreviewCallback;
@ -40,18 +42,20 @@ class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCall
private long lastFrameTime = 0; private long lastFrameTime = 0;
private final double expectedTimeBetweenFrames; private final double expectedTimeBetweenFrames;
protected final int rotation; protected final int rotation;
private MirrorType mirror;
public AndroidCameraRecordImpl(RecorderParams parameters) { public AndroidCameraRecordImpl(RecorderParams parameters) {
super(parameters); super(parameters);
expectedTimeBetweenFrames = 1d / Math.round(parameters.fps); expectedTimeBetweenFrames = 1d / Math.round(parameters.fps);
filterCtxPtr = parameters.filterDataNativePtr; filterCtxPtr = parameters.filterDataNativePtr;
rotation = parameters.rotation; rotation = parameters.rotation;
mirror = parameters.mirror;
storePreviewCallBack(this); storePreviewCallBack(this);
} }
private native void putImage(long filterCtxPtr, byte[] buffer, int rotate); private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, int mirror);
public void onPreviewFrame(byte[] data, Camera camera) { public void onPreviewFrame(byte[] data, Camera camera) {
@ -74,7 +78,7 @@ class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCall
long curTime = System.currentTimeMillis(); long curTime = System.currentTimeMillis();
if (lastFrameTime == 0) { if (lastFrameTime == 0) {
lastFrameTime = curTime; lastFrameTime = curTime;
putImage(filterCtxPtr, data, rotation); putImage(filterCtxPtr, data, rotation, mirror.ordinal());
return; return;
} }
@ -87,7 +91,7 @@ class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCall
timeElapsedBetweenFrames = currentTimeElapsed; timeElapsedBetweenFrames = currentTimeElapsed;
// Log.d("onPreviewFrame: ", Integer.toString(data.length)); // Log.d("onPreviewFrame: ", Integer.toString(data.length));
putImage(filterCtxPtr, data, rotation); putImage(filterCtxPtr, data, rotation, mirror.ordinal());
} }
@Override @Override

View file

@ -118,6 +118,17 @@ public class AndroidCameraRecordManager {
p.height = height; p.height = height;
p.cameraId = cameraId; p.cameraId = cameraId;
parameters = p; parameters = p;
/* Need first a working camera to test
if (isUseFrontCamera()) {
if (isCameraOrientationPortrait()) {
p.mirror = RecorderParams.MirrorType.CENTRAL;
} else {
p.mirror = RecorderParams.MirrorType.HORIZONTAL;
}
} // else no mirror
*/
tryToStartVideoRecording(); tryToStartVideoRecording();
} }
@ -174,7 +185,7 @@ public class AndroidCameraRecordManager {
tryToStartVideoRecording(); tryToStartVideoRecording();
} }
private void tryToStartVideoRecording() { private synchronized void tryToStartVideoRecording() {
if (muted || surfaceView == null || parameters == null) return; if (muted || surfaceView == null || parameters == null) return;
parameters.rotation = bufferRotationForCorrectImageOrientation(); parameters.rotation = bufferRotationForCorrectImageOrientation();
@ -193,7 +204,7 @@ public class AndroidCameraRecordManager {
recorder.startPreview(); recorder.startPreview();
} }
public void stopVideoRecording() { public synchronized void stopVideoRecording() {
if (recorder != null) { if (recorder != null) {
recorder.stopPreview(); recorder.stopPreview();
recorder = null; recorder = null;
@ -244,7 +255,7 @@ public class AndroidCameraRecordManager {
final int rotation = bufferRotationForCorrectImageOrientation(); final int rotation = bufferRotationForCorrectImageOrientation();
final boolean isPortrait = (rotation % 180) == 90; final boolean isPortrait = (rotation % 180) == 90;
Log.d(tag, "Camera sensor in portrait orientation ?" + isPortrait); Log.d(tag, "Camera sensor in portrait orientation? " + isPortrait);
return isPortrait; return isPortrait;
} }
@ -260,13 +271,16 @@ public class AndroidCameraRecordManager {
private int bufferRotationForCorrectImageOrientation() { private int bufferRotationForCorrectImageOrientation() {
final int cameraOrientation = cc.getCameraOrientation(cameraId); if (Version.sdkAboveOrEqual(8)) {
final int rotation = Version.sdkAboveOrEqual(8) ? final int cameraOrientation = cc.getCameraOrientation(cameraId);
(360 - cameraOrientation + 90 - phoneOrientation) % 360 final int rotation = (360 - cameraOrientation + 90 - phoneOrientation) % 360;
: 0; Log.d(tag, String.format(
Log.d(tag, "Capture video buffer will need a rotation of " + rotation "Capture video buffer of cameraId=%d will need a rotation of "
+ " degrees : camera " + cameraOrientation + "%d degrees: camera_orientation=%d, phone_orientation=%d",
+ ", phone " + phoneOrientation); cameraId, rotation, cameraOrientation, phoneOrientation));
return rotation; return rotation;
}
return 0;
} }
} }

@ -1 +1 @@
Subproject commit adc7838132946ce02074d686dd581eb86a468228 Subproject commit 6fde352364127eec92490b2a7f88d856f60342a6