diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java index 9638fbbe0..6af77423c 100644 --- a/src/org/linphone/BandwidthManager.java +++ b/src/org/linphone/BandwidthManager.java @@ -19,13 +19,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package org.linphone; import org.linphone.core.AndroidCameraRecordManager; -import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCallParams; import org.linphone.core.LinphoneCore; import org.linphone.core.VideoSize; -import android.hardware.Camera.Size; - public class BandwidthManager { public static final int HIGH_RESOLUTION = 0; @@ -58,7 +55,6 @@ public class BandwidthManager { userRestriction = limit; computeNewProfile(); } - private boolean videoEnabledInSettings = true; private void computeNewProfile() { @@ -70,63 +66,63 @@ public class BandwidthManager { } private void onProfileChanged(int newProfile) { - // LinphoneCore lc = LinphoneService.instance().getLinphoneCore(); lc.setUploadBandwidth(bandwidthes[newProfile][0]); lc.setDownloadBandwidth(bandwidthes[newProfile][1]); + if (lc.isIncall()) { + InviteManager.getInstance().reinvite(); + } else { + updateWithProfileSettings(lc, null); + } + } + + + public void updateWithProfileSettings(LinphoneCore lc, LinphoneCallParams callParams) { // Setting Linphone Core Preferred Video Size - if (newProfile != LOW_BANDWIDTH) { - VideoSize targetVideoSize = getProfileVideoSize(newProfile); + AndroidCameraRecordManager cameraManager = AndroidCameraRecordManager.getInstance(); + + boolean bandwidthOKForVideo = isVideoPossible(); + if (bandwidthOKForVideo) { + VideoSize targetVideoSize = cameraManager.doYouSupportThisVideoSize(getMaximumVideoSize()); lc.setPreferredVideoSize(targetVideoSize); VideoSize actualVideoSize = lc.getPreferredVideoSize(); if (!targetVideoSize.equals(actualVideoSize)) { - lc.setPreferredVideoSize(VideoSize.createStandard(VideoSize.QCIF, portraitMode)); + lc.setPreferredVideoSize(VideoSize.createStandard(VideoSize.QCIF, targetVideoSize.isPortrait())); } } - if (lc.isIncall()) { - LinphoneCall lCall = lc.getCurrentCall(); - LinphoneCallParams params = lCall.getCurrentParamsCopy(); - + if (callParams != null) { // in call // Update video parm if - if (newProfile == LOW_BANDWIDTH) { // NO VIDEO - params.setVideoEnabled(false); - params.setAudioBandwidth(40); + if (!bandwidthOKForVideo) { // NO VIDEO + callParams.setVideoEnabled(false); + callParams.setAudioBandwidth(40); } else { - params.setVideoEnabled(true); - params.setAudioBandwidth(0); // disable limitation - + callParams.setVideoEnabled(true); + callParams.setAudioBandwidth(0); // disable limitation } - - lc.updateCall(lCall, params); } } - - private VideoSize getProfileVideoSize(int profile) { + + private VideoSize maximumVideoSize(int profile) { switch (profile) { case LOW_RESOLUTION: - return closestVideoSize(VideoSize.createStandard(VideoSize.QCIF, portraitMode)); + return VideoSize.createStandard(VideoSize.QCIF, portraitMode); case HIGH_RESOLUTION: - return closestVideoSize(VideoSize.createStandard(VideoSize.QVGA, portraitMode)); + return VideoSize.createStandard(VideoSize.QVGA, portraitMode); default: throw new RuntimeException("profile not managed : " + profile); } } - private VideoSize closestVideoSize(VideoSize vSize) { - boolean invert = vSize.getHeight() > vSize.getWidth(); - int testHeight = invert?vSize.getWidth():vSize.getHeight(); - int testWidth = invert?vSize.getHeight():vSize.getWidth(); - for (Size s : AndroidCameraRecordManager.getInstance().supportedVideoSizes()) { - if (s.height == testHeight && s.width == testWidth) { - return vSize; - } - } + public boolean isVideoPossible() { + return currentProfile != LOW_BANDWIDTH; + } - return VideoSize.createStandard(VideoSize.QCIF, portraitMode); + public VideoSize getMaximumVideoSize() { + return maximumVideoSize(currentProfile); } } diff --git a/src/org/linphone/DialerActivity.java b/src/org/linphone/DialerActivity.java index 43c8b3275..4fe5fa32b 100644 --- a/src/org/linphone/DialerActivity.java +++ b/src/org/linphone/DialerActivity.java @@ -167,17 +167,11 @@ public class DialerActivity extends Activity implements LinphoneCoreListener { mAddVideo = (ImageButton) findViewById(R.id.AddVideo); mAddVideo.setOnClickListener(new OnClickListener() { public void onClick(View v) { - LinphoneCore lLinphoneCore = LinphoneService.instance().getLinphoneCore(); - LinphoneCall lCall = lLinphoneCore.getCurrentCall(); - LinphoneCallParams params = lCall.getCurrentParamsCopy(); - if (params.getVideoEnabled()) { + // If no in video call; try to reinvite with video + boolean alreadyInVideoCall = InviteManager.getInstance().reinviteWithVideo(); + if (alreadyInVideoCall) { // In video call; going back to video call activity startVideoView(VIDEO_VIEW_ACTIVITY); - } else { - // Not in video call; should go try to reinvite with video - params.setVideoEnabled(true); - getVideoManager().setMuted(false); - lLinphoneCore.updateCall(lCall, params); } } }); @@ -457,6 +451,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener { enterIncalMode(lc); routeAudioToReceiver(); } else if (state == LinphoneCall.State.IncomingReceived) { + resetCameraFromPreferences(); callPending(); } else if (state == LinphoneCall.State.Connected) { enterIncalMode(lc); @@ -485,7 +480,6 @@ 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); @@ -597,33 +591,26 @@ public class DialerActivity extends Activity implements LinphoneCoreListener { lAddress = lLinphoneCore.interpretUrl(lto); } catch (LinphoneCoreException e) { Toast toast = Toast.makeText(DialerActivity.this - ,String.format(getString(R.string.warning_wrong_destination_address),mAddress.getText().toString()) - , Toast.LENGTH_LONG); + ,String.format(getString(R.string.warning_wrong_destination_address),mAddress.getText().toString()) + , Toast.LENGTH_LONG); toast.show(); return; } lAddress.setDisplayName(mDisplayName); - try { - LinphoneCallParams lParams = lLinphoneCore.createDefaultCallParameters(); - boolean prefVideoEnable = mPref.getBoolean(getString(R.string.pref_video_enable_key), false); - boolean prefInitiateWithVideo = mPref.getBoolean(getString(R.string.pref_video_initiate_call_with_video_key), false); + try { + boolean prefVideoEnable = mPref.getBoolean(getString(R.string.pref_video_enable_key), false); + boolean prefInitiateWithVideo = mPref.getBoolean(getString(R.string.pref_video_initiate_call_with_video_key), false); + resetCameraFromPreferences(); + InviteManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo); - if (prefVideoEnable && prefInitiateWithVideo && lParams.getVideoEnabled()) { - getVideoManager().setMuted(false); - lParams.setVideoEnabled(true); - } else { - lParams.setVideoEnabled(false); + } catch (LinphoneCoreException e) { + Toast toast = Toast.makeText(DialerActivity.this + ,String.format(getString(R.string.error_cannot_get_call_parameters),mAddress.getText().toString()) + ,Toast.LENGTH_LONG); + toast.show(); + return; } - lLinphoneCore.inviteAddressWithParams(lAddress, lParams); - - } catch (LinphoneCoreException e) { - Toast toast = Toast.makeText(DialerActivity.this - ,String.format(getString(R.string.error_cannot_get_call_parameters),mAddress.getText().toString()) - ,Toast.LENGTH_LONG); - toast.show(); - return; - } } private void setDigitListener(Button aButton,char dtmf) { class DialKeyListener implements OnClickListener ,OnTouchListener { diff --git a/src/org/linphone/InviteManager.java b/src/org/linphone/InviteManager.java new file mode 100644 index 000000000..0dcfb8c06 --- /dev/null +++ b/src/org/linphone/InviteManager.java @@ -0,0 +1,114 @@ +/* +InviteManager.java +Copyright (C) 2010 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +package org.linphone; + +import org.linphone.core.AndroidCameraRecordManager; +import org.linphone.core.LinphoneAddress; +import org.linphone.core.LinphoneCall; +import org.linphone.core.LinphoneCallParams; +import org.linphone.core.LinphoneCore; +import org.linphone.core.LinphoneCoreException; + +public class InviteManager { + + private static InviteManager instance; + + private InviteManager() {} + public static final synchronized InviteManager getInstance() { + if (instance == null) instance = new InviteManager(); + return instance; + } + + private LinphoneCore lc() { + return LinphoneService.instance().getLinphoneCore(); + } + private AndroidCameraRecordManager videoManager() { + return AndroidCameraRecordManager.getInstance(); + } + private BandwidthManager bm() { + return BandwidthManager.getInstance(); + } + + + + + public void inviteAddress(LinphoneAddress lAddress, boolean videoEnabled) throws LinphoneCoreException { + LinphoneCore lc = lc(); + + LinphoneCallParams params = lc.createDefaultCallParameters(); + bm().updateWithProfileSettings(lc, params); + + if (videoEnabled && params.getVideoEnabled()) { + videoManager().setMuted(false); + params.setVideoEnabled(true); + } else { + params.setVideoEnabled(false); + } + + lc.inviteAddressWithParams(lAddress, params); + } + + + + + /** + * Add video to a currently running voice only call. + * No re-invite is sent if the current call is already video + * or if the bandwidth settings are too low. + * @return if updateCall called + */ + public boolean reinviteWithVideo() { + LinphoneCore lc = lc(); + LinphoneCall lCall = lc.getCurrentCall(); + LinphoneCallParams params = lCall.getCurrentParamsCopy(); + + if (params.getVideoEnabled()) return false; + + + // Check if video possible regarding bandwidth limitations + bm().updateWithProfileSettings(lc, params); + if (!params.getVideoEnabled()) { + return false; + } + + // Not yet in video call: try to re-invite with video + params.setVideoEnabled(true); + videoManager().setMuted(false); + lc.updateCall(lCall, params); + return true; + } + + + + /** + * Re-invite with parameters updated from profile. + */ + public void reinvite() { + LinphoneCore lc = lc(); + LinphoneCall lCall = lc.getCurrentCall(); + LinphoneCallParams params = lCall.getCurrentParamsCopy(); + bm().updateWithProfileSettings(lc, params); + lc.updateCall(lCall, params); + } + + + + + +} diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java index 7faebaa14..3eeb52891 100644 --- a/src/org/linphone/VideoCallActivity.java +++ b/src/org/linphone/VideoCallActivity.java @@ -21,8 +21,6 @@ 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; @@ -131,10 +129,7 @@ public class VideoCallActivity extends Activity { 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); + InviteManager.getInstance().reinvite(); break; default: Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]"); diff --git a/src/org/linphone/core/AndroidCameraRecordManager.java b/src/org/linphone/core/AndroidCameraRecordManager.java index a19413eb7..c5f409394 100644 --- a/src/org/linphone/core/AndroidCameraRecordManager.java +++ b/src/org/linphone/core/AndroidCameraRecordManager.java @@ -184,7 +184,7 @@ public class AndroidCameraRecordManager { } // eventually null - + return supportedVideoSizes; } @@ -203,21 +203,33 @@ 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 + /** + * Naive simple version. + * @param askedSize + * @return + */ + public VideoSize doYouSupportThisVideoSize(VideoSize askedSize) { + Log.d(tag, "Asking camera if it supports size "+askedSize); + if (useFrontCamera && askedSize.isPortrait()) { + return askedSize.createInverted(); // only landscape supported } else { return askedSize; } } - private boolean isPortraitSize(int width, int height) { - return width < height; - } + + private VideoSize closestVideoSize(VideoSize vSize, int defaultSizeCode, boolean defaultIsPortrait) { + VideoSize testSize = vSize.isPortrait() ? vSize.createInverted() : vSize; + + for (Size s : AndroidCameraRecordManager.getInstance().supportedVideoSizes()) { + if (s.height == testSize.getHeight() && s.width == testSize.getWidth()) { + return vSize; + } + } + + return VideoSize.createStandard(defaultSizeCode, defaultIsPortrait); + } + private static final int rearCamId() {return 1;} private static final int frontCamId() {return 2;} private final int cameraId() {return useFrontCamera? frontCamId() : rearCamId(); } diff --git a/submodules/linphone b/submodules/linphone index 684c6fa54..e76588265 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 684c6fa545f0875b943b6d6741cd01ef05febfe4 +Subproject commit e76588265b63a1d51570dd80551fa1c342ae8ca1