Rework video capture. Fix high/low resolution switch.
This commit is contained in:
parent
afb615ac9d
commit
228982d53f
9 changed files with 158 additions and 83 deletions
|
@ -120,6 +120,6 @@ public class BandwidthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public VideoSize getMaximumVideoSize() {
|
public VideoSize getMaximumVideoSize() {
|
||||||
return maximumVideoSize(currentProfile, AndroidCameraRecordManager.getInstance().outputIsPortrait());
|
return maximumVideoSize(currentProfile, AndroidCameraRecordManager.getInstance().isOutputPortraitDependingOnCameraAndPhoneOrientations());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ class CallManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Change the preferred video size used by linphone core. (impact landscape/portrait buffer).
|
||||||
* Update current call, without reinvite.
|
* Update current call, without reinvite.
|
||||||
* The camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
* The camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -85,7 +85,6 @@ import android.preference.PreferenceManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.Settings.SettingNotFoundException;
|
import android.provider.Settings.SettingNotFoundException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.OrientationEventListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -110,7 +109,6 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
||||||
private SharedPreferences mPref;
|
private SharedPreferences mPref;
|
||||||
private Resources mR;
|
private Resources mR;
|
||||||
private LinphoneCore mLc;
|
private LinphoneCore mLc;
|
||||||
private int mPhoneOrientation;
|
|
||||||
private static Transports initialTransports;
|
private static Transports initialTransports;
|
||||||
private static LinphonePreferenceManager lpm;
|
private static LinphonePreferenceManager lpm;
|
||||||
|
|
||||||
|
@ -130,19 +128,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
||||||
mPowerManager = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
|
mPowerManager = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
|
||||||
mR = c.getResources();
|
mR = c.getResources();
|
||||||
|
|
||||||
// Register a sensor to track phoneOrientation for placing new calls.
|
AndroidCameraRecordManager.getInstance().startOrientationSensor(c.getApplicationContext());
|
||||||
new OrientationEventListener(c) {
|
|
||||||
@Override
|
|
||||||
public void onOrientationChanged(int o) {
|
|
||||||
if (o == OrientationEventListener.ORIENTATION_UNKNOWN) return;
|
|
||||||
|
|
||||||
o = 90 * (o / 90);
|
|
||||||
|
|
||||||
if (Math.abs(mPhoneOrientation - o) < 90) return;
|
|
||||||
|
|
||||||
mPhoneOrientation = o;
|
|
||||||
}
|
|
||||||
}.enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String TAG=Version.TAG;
|
public static final String TAG=Version.TAG;
|
||||||
|
@ -268,7 +254,6 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
||||||
public void resetCameraFromPreferences() {
|
public void resetCameraFromPreferences() {
|
||||||
boolean useFrontCam = mPref.getBoolean(mR.getString(R.string.pref_video_use_front_camera_key), false);
|
boolean useFrontCam = mPref.getBoolean(mR.getString(R.string.pref_video_use_front_camera_key), false);
|
||||||
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
|
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
|
||||||
AndroidCameraRecordManager.getInstance().setPhoneOrientation(mPhoneOrientation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface AddressType {
|
public static interface AddressType {
|
||||||
|
@ -307,7 +292,6 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
||||||
public void changeResolution() {
|
public void changeResolution() {
|
||||||
BandwidthManager manager = BandwidthManager.getInstance();
|
BandwidthManager manager = BandwidthManager.getInstance();
|
||||||
manager.setUserRestriction(!manager.isUserRestriction());
|
manager.setUserRestriction(!manager.isUserRestriction());
|
||||||
sendStaticImage(AndroidCameraRecordManager.getInstance().isMuted());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void terminateCall() {
|
public void terminateCall() {
|
||||||
|
@ -320,9 +304,8 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
||||||
* Camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
* Camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||||
*/
|
*/
|
||||||
public void switchCamera() {
|
public void switchCamera() {
|
||||||
AndroidCameraRecordManager rm = AndroidCameraRecordManager.getInstance();
|
AndroidCameraRecordManager.getInstance().stopVideoRecording();
|
||||||
rm.stopVideoRecording();
|
AndroidCameraRecordManager.getInstance().toggleUseFrontCamera();
|
||||||
rm.toggleUseFrontCamera();
|
|
||||||
CallManager.getInstance().updateCall();
|
CallManager.getInstance().updateCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.linphone.LinphoneManager.LinphoneServiceListener;
|
import org.linphone.LinphoneManager.LinphoneServiceListener;
|
||||||
import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
|
import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
|
||||||
|
@ -28,6 +29,7 @@ import org.linphone.core.LinphoneCall.State;
|
||||||
import org.linphone.core.LinphoneCore.GlobalState;
|
import org.linphone.core.LinphoneCore.GlobalState;
|
||||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
@ -234,9 +236,11 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
|
||||||
.setClass(this, LinphoneActivity.class)
|
.setClass(this, LinphoneActivity.class)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||||
} else if (state == LinphoneCall.State.StreamsRunning) {
|
} else if (state == LinphoneCall.State.StreamsRunning) {
|
||||||
if (LinphoneActivity.isInstanciated()
|
if (!VideoCallActivity.launched && LinphoneActivity.isInstanciated()
|
||||||
&& getResources().getBoolean(R.bool.use_video_activity)
|
&& getResources().getBoolean(R.bool.use_video_activity)
|
||||||
&& call.getCurrentParamsCopy().getVideoEnabled()) {
|
&& call.getCurrentParamsCopy().getVideoEnabled()) {
|
||||||
|
// Do not call if video activity already launched as it would cause a pause() of the launched one
|
||||||
|
// and a race condition with capture surfaceview leading to a crash
|
||||||
LinphoneActivity.instance().startVideoActivity();
|
LinphoneActivity.instance().startVideoActivity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,10 +24,12 @@ import org.linphone.core.LinphoneCore;
|
||||||
import org.linphone.core.Version;
|
import org.linphone.core.Version;
|
||||||
import org.linphone.core.VideoSize;
|
import org.linphone.core.VideoSize;
|
||||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecordManager.OnCapturingStateChangedListener;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -42,7 +44,7 @@ import android.view.ViewGroup.LayoutParams;
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class VideoCallActivity extends SoftVolumeActivity {
|
public class VideoCallActivity extends SoftVolumeActivity implements OnCapturingStateChangedListener {
|
||||||
private SurfaceView mVideoView;
|
private SurfaceView mVideoView;
|
||||||
private SurfaceView mVideoCaptureView;
|
private SurfaceView mVideoCaptureView;
|
||||||
private AndroidCameraRecordManager recordManager;
|
private AndroidCameraRecordManager recordManager;
|
||||||
|
@ -50,8 +52,8 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
public static boolean launched = false;
|
public static boolean launched = false;
|
||||||
private WakeLock mWakeLock;
|
private WakeLock mWakeLock;
|
||||||
private static final int capturePreviewLargestDimension = 150;
|
private static final int capturePreviewLargestDimension = 150;
|
||||||
private int previousPhoneOrientation;
|
private Handler handler = new Handler();
|
||||||
private int phoneOrientation;
|
|
||||||
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
launched = true;
|
launched = true;
|
||||||
|
@ -65,10 +67,9 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
|
|
||||||
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
||||||
|
|
||||||
previousPhoneOrientation = AndroidCameraRecordManager.getInstance().getPhoneOrientation();
|
|
||||||
phoneOrientation = 90 * getWindowManager().getDefaultDisplay().getOrientation();
|
|
||||||
recordManager = AndroidCameraRecordManager.getInstance();
|
recordManager = AndroidCameraRecordManager.getInstance();
|
||||||
recordManager.setSurfaceView(mVideoCaptureView, phoneOrientation);
|
recordManager.setOnCapturingStateChanged(this);
|
||||||
|
recordManager.setSurfaceView(mVideoCaptureView);
|
||||||
mVideoCaptureView.setZOrderOnTop(true);
|
mVideoCaptureView.setZOrderOnTop(true);
|
||||||
|
|
||||||
if (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false);
|
if (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false);
|
||||||
|
@ -76,24 +77,26 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
|
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
|
|
||||||
if (Version.sdkStrictlyBelow(8)) {
|
fixScreenOrientationForOldDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixScreenOrientationForOldDevices() {
|
||||||
|
if (Version.sdkAboveOrEqual(Version.API08_FROYO_22)) return;
|
||||||
|
|
||||||
// Force to display in portrait orientation for old devices
|
// Force to display in portrait orientation for old devices
|
||||||
// as they do not support surfaceView rotation
|
// as they do not support surfaceView rotation
|
||||||
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
|
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
|
||||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
|
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
|
||||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
|
||||||
|
|
||||||
resizeCapturePreview(mVideoCaptureView);
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
// Update call if orientation changed
|
if (Version.sdkAboveOrEqual(8) && recordManager.isOutputOrientationMismatch()) {
|
||||||
if (Version.sdkAboveOrEqual(8) && previousPhoneOrientation != phoneOrientation) {
|
Log.i(tag,"Phone orientation has changed: updating call.");
|
||||||
CallManager.getInstance().updateCall();
|
CallManager.getInstance().updateCall();
|
||||||
resizeCapturePreview(mVideoCaptureView);
|
// resizeCapturePreview by callback when recording started
|
||||||
}
|
}
|
||||||
super.onResume();
|
super.onResume();
|
||||||
}
|
}
|
||||||
|
@ -162,14 +165,11 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.videocall_menu_back_to_dialer:
|
case R.id.videocall_menu_back_to_dialer:
|
||||||
if (!recordManager.isMuted())
|
|
||||||
LinphoneManager.getInstance().sendStaticImage(true);
|
|
||||||
finish();
|
finish();
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_change_resolution:
|
case R.id.videocall_menu_change_resolution:
|
||||||
LinphoneManager.getInstance().changeResolution();
|
LinphoneManager.getInstance().changeResolution();
|
||||||
rewriteChangeResolutionItem(item);
|
rewriteChangeResolutionItem(item);
|
||||||
resizeCapturePreview(mVideoCaptureView);
|
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_terminate_call:
|
case R.id.videocall_menu_terminate_call:
|
||||||
LinphoneManager.getInstance().terminateCall();
|
LinphoneManager.getInstance().terminateCall();
|
||||||
|
@ -181,7 +181,7 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_switch_camera:
|
case R.id.videocall_menu_switch_camera:
|
||||||
LinphoneManager.getInstance().switchCamera();
|
LinphoneManager.getInstance().switchCamera();
|
||||||
resizeCapturePreview(mVideoCaptureView);
|
fixScreenOrientationForOldDevices();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]");
|
Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]");
|
||||||
|
@ -206,4 +206,15 @@ public class VideoCallActivity extends SoftVolumeActivity {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void captureStarted() {
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void captureStopped() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,9 +74,9 @@ class AndroidCameraConf5 implements AndroidCameraConf {
|
||||||
// | |
|
// | |
|
||||||
// | Phone |
|
// | Phone |
|
||||||
// |________|
|
// |________|
|
||||||
return 90;
|
return 180;
|
||||||
}
|
}
|
||||||
return 0;
|
return 90;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,11 +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(Version.TAG, String.format("Camera info for %d: orientation=%d returned=%d ",
|
Log.d(Version.TAG, String.format("Camera info for %d: orientation=%d",
|
||||||
cameraId,
|
cameraId,
|
||||||
info.orientation,
|
info.orientation));
|
||||||
(info.orientation - 90) %360));
|
return info.orientation;
|
||||||
return (info.orientation - 90) %360;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFrontCamera(int cameraId) {
|
public boolean isFrontCamera(int cameraId) {
|
||||||
|
|
|
@ -211,6 +211,7 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
||||||
public SurfaceView surfaceView;
|
public SurfaceView surfaceView;
|
||||||
|
|
||||||
public MirrorType mirror = MirrorType.NO;
|
public MirrorType mirror = MirrorType.NO;
|
||||||
|
public int phoneOrientation;
|
||||||
|
|
||||||
public RecorderParams(long ptr) {
|
public RecorderParams(long ptr) {
|
||||||
filterDataNativePtr = ptr;
|
filterDataNativePtr = ptr;
|
||||||
|
@ -238,4 +239,8 @@ public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
||||||
if (success) Log.i(tag, "Autofocus success");
|
if (success) Log.i(tag, "Autofocus success");
|
||||||
else Log.i(tag, "Autofocus failure");
|
else Log.i(tag, "Autofocus failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStoredPhoneOrientation() {
|
||||||
|
return params.phoneOrientation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,14 @@ package org.linphone.core.video;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.core.Version;
|
import org.linphone.core.Version;
|
||||||
import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
|
import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.hardware.Camera.Size;
|
import android.hardware.Camera.Size;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.SurfaceHolder.Callback;
|
import android.view.SurfaceHolder.Callback;
|
||||||
|
@ -40,6 +43,8 @@ import android.view.SurfaceHolder.Callback;
|
||||||
public class AndroidCameraRecordManager {
|
public class AndroidCameraRecordManager {
|
||||||
private static final String tag = "Linphone";
|
private static final String tag = "Linphone";
|
||||||
private static AndroidCameraRecordManager instance;
|
private static AndroidCameraRecordManager instance;
|
||||||
|
private OrientationEventListener orientationEventListener;
|
||||||
|
private OnCapturingStateChangedListener capturingStateChangedListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return instance
|
* @return instance
|
||||||
|
@ -59,9 +64,7 @@ public class AndroidCameraRecordManager {
|
||||||
|
|
||||||
private AndroidCameraRecord recorder;
|
private AndroidCameraRecord recorder;
|
||||||
private List<Size> supportedVideoSizes;
|
private List<Size> supportedVideoSizes;
|
||||||
private int phoneOrientation;
|
private int mAlwaysChangingPhoneOrientation=0;
|
||||||
public int getPhoneOrientation() {return phoneOrientation;}
|
|
||||||
public void setPhoneOrientation(int degrees) {this.phoneOrientation = degrees;}
|
|
||||||
|
|
||||||
|
|
||||||
// singleton
|
// singleton
|
||||||
|
@ -112,7 +115,10 @@ public class AndroidCameraRecordManager {
|
||||||
|
|
||||||
|
|
||||||
public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) {
|
public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) {
|
||||||
|
if (recorder != null) {
|
||||||
|
Log.w(tag, "Recorder should not be running");
|
||||||
stopVideoRecording();
|
stopVideoRecording();
|
||||||
|
}
|
||||||
RecorderParams p = new RecorderParams(filterDataPtr);
|
RecorderParams p = new RecorderParams(filterDataPtr);
|
||||||
p.fps = fps;
|
p.fps = fps;
|
||||||
p.width = width;
|
p.width = width;
|
||||||
|
@ -135,8 +141,7 @@ public class AndroidCameraRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final void setSurfaceView(final SurfaceView sv, final int phoneOrientation) {
|
public final void setSurfaceView(final SurfaceView sv) {
|
||||||
this.phoneOrientation = phoneOrientation;
|
|
||||||
SurfaceHolder holder = sv.getHolder();
|
SurfaceHolder holder = sv.getHolder();
|
||||||
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||||
|
|
||||||
|
@ -188,9 +193,18 @@ public class AndroidCameraRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void tryToStartVideoRecording() {
|
private synchronized void tryToStartVideoRecording() {
|
||||||
|
if (orientationEventListener == null) {
|
||||||
|
throw new RuntimeException("startOrientationSensor was not called");
|
||||||
|
}
|
||||||
|
|
||||||
if (muted || surfaceView == null || parameters == null) return;
|
if (muted || surfaceView == null || parameters == null) return;
|
||||||
|
|
||||||
parameters.rotation = bufferRotationForCorrectImageOrientation();
|
if (recorder != null) {
|
||||||
|
Log.e(tag, "Recorder already present");
|
||||||
|
stopVideoRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters.rotation = bufferRotationToCompensateCameraAndPhoneOrientations();
|
||||||
|
|
||||||
parameters.surfaceView = surfaceView;
|
parameters.surfaceView = surfaceView;
|
||||||
if (Version.sdkAboveOrEqual(9)) {
|
if (Version.sdkAboveOrEqual(9)) {
|
||||||
|
@ -204,20 +218,26 @@ public class AndroidCameraRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder.startPreview();
|
recorder.startPreview();
|
||||||
|
|
||||||
|
if (capturingStateChangedListener != null) {
|
||||||
|
capturingStateChangedListener.captureStarted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stopVideoRecording() {
|
public synchronized void stopVideoRecording() {
|
||||||
if (recorder != null) {
|
if (recorder != null) {
|
||||||
recorder.stopPreview();
|
recorder.stopPreview();
|
||||||
recorder = null;
|
recorder = null;
|
||||||
|
if (capturingStateChangedListener != null) {
|
||||||
|
capturingStateChangedListener.captureStopped();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FIXME select right camera
|
|
||||||
/**
|
/**
|
||||||
* Eventually null if API < 5.
|
* FIXME select right camera
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public List<Size> supportedVideoSizes() {
|
public List<Size> supportedVideoSizes() {
|
||||||
if (supportedVideoSizes != null) {
|
if (supportedVideoSizes != null) {
|
||||||
|
@ -229,8 +249,6 @@ public class AndroidCameraRecordManager {
|
||||||
if (supportedVideoSizes != null) return supportedVideoSizes;
|
if (supportedVideoSizes != null) return supportedVideoSizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eventually null
|
|
||||||
|
|
||||||
return supportedVideoSizes;
|
return supportedVideoSizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,11 +267,11 @@ public class AndroidCameraRecordManager {
|
||||||
parameters = null;
|
parameters = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean outputIsPortrait() {
|
public boolean isOutputPortraitDependingOnCameraAndPhoneOrientations() {
|
||||||
final int rotation = bufferRotationForCorrectImageOrientation();
|
final int rotation = bufferRotationToCompensateCameraAndPhoneOrientations();
|
||||||
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 " + (isPortrait? "portrait":"landscape") + " orientation.");
|
||||||
return isPortrait;
|
return isPortrait;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,15 +281,21 @@ public class AndroidCameraRecordManager {
|
||||||
|
|
||||||
|
|
||||||
public boolean isCameraOrientationPortrait() {
|
public boolean isCameraOrientationPortrait() {
|
||||||
return (cc.getCameraOrientation(cameraId) % 180) == 90;
|
return (cc.getCameraOrientation(cameraId) % 180) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private int bufferRotationForCorrectImageOrientation() {
|
private int bufferRotationToCompensateCameraAndPhoneOrientations() {
|
||||||
if (Version.sdkAboveOrEqual(8)) {
|
if (Version.sdkStrictlyBelow(Version.API08_FROYO_22)) {
|
||||||
|
// Don't perform any rotation
|
||||||
|
// Phone screen should use fitting orientation
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int phoneOrientation = mAlwaysChangingPhoneOrientation;
|
||||||
final int cameraOrientation = cc.getCameraOrientation(cameraId);
|
final int cameraOrientation = cc.getCameraOrientation(cameraId);
|
||||||
final int rotation = (360 - cameraOrientation + 90 - phoneOrientation) % 360;
|
final int rotation = (cameraOrientation + phoneOrientation) % 360;
|
||||||
Log.d(tag, String.format(
|
Log.d(tag, String.format(
|
||||||
"Capture video buffer of cameraId=%d will need a rotation of "
|
"Capture video buffer of cameraId=%d will need a rotation of "
|
||||||
+ "%d degrees: camera_orientation=%d, phone_orientation=%d",
|
+ "%d degrees: camera_orientation=%d, phone_orientation=%d",
|
||||||
|
@ -279,6 +303,54 @@ public class AndroidCameraRecordManager {
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
/**
|
||||||
|
* Register a sensor to track phoneOrientation changes
|
||||||
|
*/
|
||||||
|
public void startOrientationSensor(Context c) {
|
||||||
|
if (orientationEventListener == null) {
|
||||||
|
orientationEventListener = new LocalOrientationEventListener(c);
|
||||||
|
orientationEventListener.enable();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LocalOrientationEventListener extends OrientationEventListener {
|
||||||
|
public LocalOrientationEventListener(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(final int o) {
|
||||||
|
if (o == OrientationEventListener.ORIENTATION_UNKNOWN) return;
|
||||||
|
|
||||||
|
int degrees=270;
|
||||||
|
if (o < 45 || o >315) degrees=0;
|
||||||
|
else if (o<135) degrees=90;
|
||||||
|
else if (o<225) degrees=180;
|
||||||
|
|
||||||
|
if (mAlwaysChangingPhoneOrientation == degrees) return;
|
||||||
|
|
||||||
|
Log.i(tag, "Phone orientation changed to " + degrees);
|
||||||
|
mAlwaysChangingPhoneOrientation = degrees;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if linphone core configured to send a A buffer while phone orientation induces !A buffer (A=landscape or portrait)
|
||||||
|
*/
|
||||||
|
public boolean isOutputOrientationMismatch() {
|
||||||
|
final boolean currentlyPortrait = LinphoneManager.getLc().getPreferredVideoSize().isPortrait();
|
||||||
|
final boolean shouldBePortrait = isOutputPortraitDependingOnCameraAndPhoneOrientations();
|
||||||
|
return currentlyPortrait ^ shouldBePortrait;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnCapturingStateChanged(OnCapturingStateChangedListener listener) {
|
||||||
|
this.capturingStateChangedListener=listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface OnCapturingStateChangedListener {
|
||||||
|
void captureStarted();
|
||||||
|
void captureStopped();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue