Preliminary support for front camera.
This commit is contained in:
parent
36efd26291
commit
1c113d3074
12 changed files with 119 additions and 58 deletions
|
@ -8,4 +8,5 @@
|
|||
<item android:id="@+id/videocall_menu_terminate_call" android:title="@string/menu_videocall_terminate_call_title"></item>
|
||||
<item android:id="@+id/videocall_menu_change_resolution" android:title="@string/menu_videocall_change_resolution_title"></item>
|
||||
<item android:id="@+id/videocall_menu_back_to_dialer" android:title="@string/menu_videocall_back_to_dialer_title"></item>
|
||||
<item android:title="@string/menu_videocall_switch_camera_title" android:id="@+id/videocall_menu_switch_camera"></item>
|
||||
</menu>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pref_video_use_front_camera_title">Use front camera (if any)</string>
|
||||
<string name="pref_video_use_front_camera_key">pref_video_use_front_camera_key</string>
|
||||
<string name="pref_video">Video</string>
|
||||
<string name="pref_preferences">Preferences</string>
|
||||
<string name="pref_video_codec_h263_title">H263</string>
|
||||
|
@ -11,6 +13,7 @@
|
|||
<string name="pref_video_codecs_title">Video codecs</string>
|
||||
<string name="pref_video_codecs_key">pref_video_codecs_key</string>
|
||||
<string name="menu_videocall_back_to_dialer_title">Display dialer</string>
|
||||
<string name="menu_videocall_switch_camera_title">Front/Rear Camera</string>
|
||||
<string name="menu_videocall_change_resolution_when_low_resolution">Try High resolution</string>
|
||||
<string name="menu_videocall_change_resolution_when_high_resolution">Low resolution</string>
|
||||
<string name="menu_videocall_change_resolution_title">Change resolution</string>
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
android:defaultValue="false" android:selectable="false"></CheckBoxPreference>
|
||||
</PreferenceScreen>
|
||||
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_video_settings_title"
|
||||
android:dependency="@string/pref_video_enable_key"
|
||||
android:shouldDisableView="true">
|
||||
|
@ -98,7 +99,8 @@
|
|||
android:summary="@string/pref_video_automatically_share_my_video"
|
||||
android:dependency="@string/pref_video_enable_key"></CheckBoxPreference>
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
<CheckBoxPreference android:key="@string/pref_video_use_front_camera_key" android:title="@string/pref_video_use_front_camera_title"></CheckBoxPreference>
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -91,10 +91,12 @@ public class BandwidthManager {
|
|||
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
||||
|
||||
// Update video parm if
|
||||
if (newProfile == LOW_BANDWIDTH) {
|
||||
if (newProfile == LOW_BANDWIDTH) { // NO VIDEO
|
||||
params.setVideoEnabled(false);
|
||||
params.setAudioBandwidth(40);
|
||||
} else {
|
||||
params.setVideoEnabled(true);
|
||||
params.setAudioBandwidth(0); // disable limitation
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -485,7 +485,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
|
|||
}
|
||||
|
||||
private void enterIncalMode(LinphoneCore lc) {
|
||||
|
||||
resetCameraFromPreferences();
|
||||
mCallControlRow.setVisibility(View.GONE);
|
||||
mInCallControlRow.setVisibility(View.VISIBLE);
|
||||
mAddressLayout.setVisibility(View.GONE);
|
||||
|
@ -522,6 +522,12 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
|
|||
mSpeaker.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetCameraFromPreferences() {
|
||||
boolean useFrontCam = mPref.getBoolean(getString(R.string.pref_video_use_front_camera_key), false);
|
||||
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
|
||||
}
|
||||
|
||||
private void exitCallMode() {
|
||||
mCallControlRow.setVisibility(View.VISIBLE);
|
||||
mInCallControlRow.setVisibility(View.GONE);
|
||||
|
@ -539,6 +545,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
|
|||
mSpeaker.setChecked(false);
|
||||
routeAudioToReceiver();
|
||||
BandwidthManager.getInstance().setUserRestriction(false);
|
||||
resetCameraFromPreferences();
|
||||
}
|
||||
private void routeAudioToSpeaker() {
|
||||
if (Integer.parseInt(Build.VERSION.SDK) <= 4 /*<donut*/) {
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.linphone;
|
|||
|
||||
|
||||
import org.linphone.core.AndroidCameraRecordManager;
|
||||
import org.linphone.core.LinphoneCall;
|
||||
import org.linphone.core.LinphoneCallParams;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
|
||||
import android.app.Activity;
|
||||
|
@ -52,8 +54,8 @@ public class VideoCallActivity extends Activity {
|
|||
LinphoneService.instance().getLinphoneCore().setVideoWindow(mVideoView);
|
||||
|
||||
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
||||
|
||||
final int rotation = getWindowManager().getDefaultDisplay().getRotation();
|
||||
|
||||
final int rotation = getWindowManager().getDefaultDisplay().getOrientation();
|
||||
recordManager = AndroidCameraRecordManager.getInstance();
|
||||
recordManager.setSurfaceView(mVideoCaptureView, rotation);
|
||||
mVideoCaptureView.setZOrderOnTop(true);
|
||||
|
@ -126,6 +128,14 @@ public class VideoCallActivity extends Activity {
|
|||
sendStaticImage(recordManager.isMuted());
|
||||
rewriteToggleCameraItem(item);
|
||||
break;
|
||||
case R.id.videocall_menu_switch_camera:
|
||||
recordManager.stopVideoRecording();
|
||||
recordManager.setUseFrontCamera(!recordManager.isUseFrontCamera());
|
||||
LinphoneCore lc = LinphoneService.instance().getLinphoneCore();
|
||||
LinphoneCall lCall = lc.getCurrentCall();
|
||||
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
||||
lc.updateCall(lCall, params);
|
||||
break;
|
||||
default:
|
||||
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
|
||||
break;
|
||||
|
|
|
@ -39,13 +39,14 @@ public abstract class AndroidCameraRecord {
|
|||
|
||||
private PreviewCallback storedPreviewCallback;
|
||||
private boolean previewStarted;
|
||||
protected int orientationCode;
|
||||
protected int displayOrientation;
|
||||
protected static final String tag="Linphone";
|
||||
private List <Size> supportedVideoSizes;
|
||||
private Size currentPreviewSize;
|
||||
|
||||
public AndroidCameraRecord(RecorderParams parameters) {
|
||||
this.params = parameters;
|
||||
setRotation(parameters.rotation);
|
||||
setDisplayOrientation(parameters.rotation);
|
||||
}
|
||||
|
||||
protected List<Size> getSupportedPreviewSizes(Camera.Parameters parameters) {
|
||||
|
@ -75,11 +76,14 @@ public abstract class AndroidCameraRecord {
|
|||
|
||||
|
||||
Camera.Parameters parameters=camera.getParameters();
|
||||
parameters.set("camera-id",params.cameraId);
|
||||
camera.setParameters(parameters);
|
||||
parameters = camera.getParameters();
|
||||
if (supportedVideoSizes == null) {
|
||||
supportedVideoSizes = getSupportedPreviewSizes(camera.getParameters());
|
||||
supportedVideoSizes = new ArrayList<Size>(getSupportedPreviewSizes(parameters));
|
||||
}
|
||||
|
||||
parameters.set("camera-id", params.cameraId);
|
||||
|
||||
if (!params.videoDimensionsInverted) {
|
||||
parameters.setPreviewSize(params.width, params.height);
|
||||
} else {
|
||||
|
@ -91,6 +95,7 @@ public abstract class AndroidCameraRecord {
|
|||
onSettingCameraParameters(parameters);
|
||||
camera.setParameters(parameters);
|
||||
|
||||
currentPreviewSize = camera.getParameters().getPreviewSize();
|
||||
|
||||
SurfaceHolder holder = params.surfaceView.getHolder();
|
||||
try {
|
||||
|
@ -140,12 +145,13 @@ public abstract class AndroidCameraRecord {
|
|||
}
|
||||
|
||||
|
||||
void stopPreview() {
|
||||
public void stopPreview() {
|
||||
if (!previewStarted) return;
|
||||
lowLevelSetPreviewCallback(camera, null);
|
||||
camera.stopPreview();
|
||||
camera.release();
|
||||
camera=null;
|
||||
if (currentPreviewSize != null) currentPreviewSize = null;
|
||||
previewStarted = false;
|
||||
}
|
||||
|
||||
|
@ -158,12 +164,16 @@ public abstract class AndroidCameraRecord {
|
|||
|
||||
protected abstract void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb);
|
||||
|
||||
public void setRotation(int rotation) {
|
||||
orientationCode = (4 + 1 - rotation) % 4;
|
||||
public void setDisplayOrientation(int rotation) {
|
||||
displayOrientation = rotation;
|
||||
}
|
||||
|
||||
protected int getOrientationCode() {
|
||||
return orientationCode;
|
||||
protected int rotateCapturedFrame() {
|
||||
if (params.cameraId == 2) {
|
||||
return 0;
|
||||
} else {
|
||||
return (4 + 1 - displayOrientation) % 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,10 +185,10 @@ public abstract class AndroidCameraRecord {
|
|||
public int width;
|
||||
|
||||
final long filterDataNativePtr;
|
||||
int cameraId;
|
||||
int rotation;
|
||||
public int cameraId;
|
||||
public int rotation;
|
||||
public SurfaceView surfaceView;
|
||||
boolean videoDimensionsInverted;
|
||||
public boolean videoDimensionsInverted;
|
||||
|
||||
public RecorderParams(long ptr) {
|
||||
filterDataNativePtr = ptr;
|
||||
|
@ -195,4 +205,11 @@ public abstract class AndroidCameraRecord {
|
|||
public List<Size> getSupportedVideoSizes() {
|
||||
return new ArrayList<Size>(supportedVideoSizes);
|
||||
}
|
||||
|
||||
|
||||
protected int getExpectedBufferLength() {
|
||||
if (currentPreviewSize == null) return -1;
|
||||
|
||||
return currentPreviewSize.width * currentPreviewSize.height * 3 /2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public class AndroidCameraRecordBufferedImpl extends AndroidCameraRecordImplAPI5
|
|||
protected void onSettingCameraParameters(Parameters parameters) {
|
||||
super.onSettingCameraParameters(parameters);
|
||||
// Only on v8 hardware
|
||||
camera.setDisplayOrientation(90 * orientationCode);
|
||||
camera.setDisplayOrientation(90 * displayOrientation);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.linphone.core;
|
|||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
|
@ -35,19 +34,19 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
|||
private double timeElapsedBetweenFrames = 0;
|
||||
private long lastFrameTime = 0;
|
||||
private final double expectedTimeBetweenFrames;
|
||||
private boolean videoDimensionsInverted;
|
||||
private boolean sizesInverted;
|
||||
|
||||
public AndroidCameraRecordImpl(RecorderParams parameters) {
|
||||
super(parameters);
|
||||
expectedTimeBetweenFrames = 1d / Math.round(parameters.fps);
|
||||
filterCtxPtr = parameters.filterDataNativePtr;
|
||||
videoDimensionsInverted = parameters.videoDimensionsInverted;
|
||||
sizesInverted = parameters.videoDimensionsInverted;
|
||||
|
||||
storePreviewCallBack(this);
|
||||
}
|
||||
|
||||
|
||||
private native void putImage(long filterCtxPtr, byte[] buffer, int orientation, boolean videoDimensionsInverted);
|
||||
private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, boolean sizesInverted);
|
||||
|
||||
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
|
@ -60,8 +59,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
|||
return;
|
||||
}
|
||||
|
||||
Size s = camera.getParameters().getPreviewSize();
|
||||
int expectedBuffLength = s.width * s.height * 3 /2;
|
||||
int expectedBuffLength = getExpectedBufferLength();
|
||||
if (expectedBuffLength != data.length) {
|
||||
Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
|
||||
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
|
||||
|
@ -71,7 +69,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
|||
long curTime = System.currentTimeMillis();
|
||||
if (lastFrameTime == 0) {
|
||||
lastFrameTime = curTime;
|
||||
putImage(filterCtxPtr, data, getOrientationCode(), videoDimensionsInverted);
|
||||
putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -84,10 +82,11 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
|||
timeElapsedBetweenFrames = currentTimeElapsed;
|
||||
|
||||
// Log.d("onPreviewFrame: ", Integer.toString(data.length));
|
||||
putImage(filterCtxPtr, data, getOrientationCode(), videoDimensionsInverted);
|
||||
putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
||||
camera.setPreviewCallback(cb);
|
||||
|
|
|
@ -18,9 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.linphone.core.AndroidCameraRecord.RecorderParams;
|
||||
|
||||
|
@ -41,38 +39,21 @@ import android.view.SurfaceHolder.Callback;
|
|||
*/
|
||||
public class AndroidCameraRecordManager {
|
||||
private static final int version = Integer.parseInt(Build.VERSION.SDK);
|
||||
private static Map<Integer, AndroidCameraRecordManager> instances = new HashMap<Integer, AndroidCameraRecordManager>();
|
||||
|
||||
private static final String tag = "Linphone";
|
||||
private static AndroidCameraRecordManager instance;
|
||||
|
||||
// singleton
|
||||
private AndroidCameraRecordManager(int cameraId) {
|
||||
this.cameraId = cameraId;
|
||||
}
|
||||
private AndroidCameraRecordManager() {}
|
||||
|
||||
/**
|
||||
* Instance for a given camera
|
||||
* @param cameraId : starting from 0
|
||||
* @return
|
||||
*/
|
||||
public static final synchronized AndroidCameraRecordManager getInstance(int cameraId) {
|
||||
if (cameraId < 0) {
|
||||
Log.e("Linphone", "Asking unmanageable camera " + cameraId);
|
||||
return null;
|
||||
}
|
||||
|
||||
AndroidCameraRecordManager m = instances.get(cameraId);
|
||||
if (m == null) {
|
||||
m = new AndroidCameraRecordManager(cameraId);
|
||||
instances.put(cameraId, m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return instance for the default camera
|
||||
* @return instance
|
||||
*/
|
||||
public static final synchronized AndroidCameraRecordManager getInstance() {
|
||||
return getInstance(0);
|
||||
if (instance == null) {
|
||||
instance = new AndroidCameraRecordManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private AndroidCameraRecord.RecorderParams parameters;
|
||||
|
@ -81,11 +62,26 @@ public class AndroidCameraRecordManager {
|
|||
|
||||
|
||||
private AndroidCameraRecord recorder;
|
||||
private final Integer cameraId;
|
||||
|
||||
|
||||
private List<Size> supportedVideoSizes;
|
||||
private int rotation;
|
||||
private static final String tag = "Linphone";
|
||||
|
||||
private boolean useFrontCamera;
|
||||
public void setUseFrontCamera(boolean value) {
|
||||
if (useFrontCamera == value) return;
|
||||
this.useFrontCamera = value;
|
||||
|
||||
if (parameters != null) {
|
||||
parameters.cameraId = cameraId();
|
||||
if (isRecording()) {
|
||||
stopVideoRecording();
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean isUseFrontCamera() {return useFrontCamera;}
|
||||
|
||||
|
||||
|
||||
public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) {
|
||||
|
@ -94,15 +90,16 @@ public class AndroidCameraRecordManager {
|
|||
p.fps = fps;
|
||||
p.width = width;
|
||||
p.height = height;
|
||||
p.cameraId = cameraId;
|
||||
p.cameraId = cameraId();
|
||||
p.videoDimensionsInverted = width < height;
|
||||
// width and height will be inverted in Recorder on startPreview
|
||||
parameters = p;
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
|
||||
|
||||
public final void setSurfaceView(final SurfaceView sv, final int rotation) {
|
||||
this.rotation = rotation;
|
||||
this.rotation = useFrontCamera ? 1 : rotation;
|
||||
SurfaceHolder holder = sv.getHolder();
|
||||
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
|
||||
|
@ -206,4 +203,22 @@ public class AndroidCameraRecordManager {
|
|||
parameters = null;
|
||||
}
|
||||
|
||||
public int[] doYouSupportThisVideoSize(int[] askedSize) {
|
||||
final int askedW = askedSize[0];
|
||||
final int askedH = askedSize[1];
|
||||
Log.d(tag, "w"+askedW);
|
||||
Log.d(tag, "h"+askedH);
|
||||
if (useFrontCamera && isPortraitSize(askedW, askedH)) {
|
||||
return new int[] {askedH, askedW}; // only landscape supported
|
||||
} else {
|
||||
return askedSize;
|
||||
}
|
||||
}
|
||||
private boolean isPortraitSize(int width, int height) {
|
||||
return width < height;
|
||||
}
|
||||
|
||||
private static final int rearCamId() {return 1;}
|
||||
private static final int frontCamId() {return 2;}
|
||||
private final int cameraId() {return useFrontCamera? frontCamId() : rearCamId(); }
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
|
|||
|
||||
private native void enableVideo(long nativePtr, boolean b);
|
||||
private native boolean getVideoEnabled(long nativePtr);
|
||||
private native void audioBandwidth(long nativePtr, int bw);
|
||||
private native void destroy(long nativePtr);
|
||||
|
||||
|
||||
|
@ -43,4 +44,8 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
|
|||
destroy(nativePtr);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
public void setAudioBandwidth(int value) {
|
||||
audioBandwidth(nativePtr, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9fc45b990045768c65a346e5b41a37ab8087d0b5
|
||||
Subproject commit 684c6fa545f0875b943b6d6741cd01ef05febfe4
|
Loading…
Reference in a new issue