Video hacks + disabled mirroring of capture.
This commit is contained in:
parent
e9dadc8965
commit
6d530bd16f
7 changed files with 95 additions and 37 deletions
|
@ -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,13 +42,26 @@ 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);
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -184,7 +191,9 @@ public abstract class AndroidCameraRecord {
|
||||||
public int cameraId;
|
public int cameraId;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in a new issue