Merge branch 'master' of git.linphone.org:linphone-android
This commit is contained in:
commit
93e8705ed5
35 changed files with 296 additions and 2070 deletions
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry excluding="org/linphone/mediastream/MediastreamerActivity.java" kind="src" path="submodules/linphone/mediastreamer2/java/src"/>
|
||||
<classpathentry kind="src" path="submodules/linphone/java/j2se"/>
|
||||
<classpathentry kind="src" path="submodules/linphone/java/common"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
root-dir:=$(APP_PROJECT_PATH)
|
||||
# script expect linphone-root-dir variable to be set by parent !
|
||||
|
||||
#default values
|
||||
BUILD_AMR=light
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
BUILD_X264=1
|
||||
LINPHONE_VIDEO=1
|
||||
else
|
||||
LINPHONE_VIDEO=0
|
||||
BUILD_X264=0
|
||||
endif
|
||||
|
||||
|
||||
|
@ -11,93 +15,90 @@ endif
|
|||
ifeq ($(BUILD_GPLV3_ZRTP), 1)
|
||||
BUILD_SRTP=1
|
||||
ZRTP_C_INCLUDE= \
|
||||
$(root-dir)/submodules/externals/libzrtpcpp/src
|
||||
$(linphone-root-dir)/submodules/externals/libzrtpcpp/src
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRTP), 1)
|
||||
SRTP_C_INCLUDE= \
|
||||
$(root-dir)/submodules/externals/srtp/include \
|
||||
$(root-dir)/submodules/externals/srtp/crypto/include
|
||||
$(linphone-root-dir)/submodules/externals/srtp/include \
|
||||
$(linphone-root-dir)/submodules/externals/srtp/crypto/include
|
||||
endif
|
||||
#endif
|
||||
|
||||
|
||||
# Speex
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/speex.mk),)
|
||||
include $(root-dir)/submodules/externals/build/speex/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/speex.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/build/speex/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/speex.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/speex.mk
|
||||
endif
|
||||
|
||||
# Gsm
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/gsm.mk),)
|
||||
include $(root-dir)/submodules/externals/build/gsm/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/gsm.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/build/gsm/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/gsm.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/gsm.mk
|
||||
endif
|
||||
|
||||
include $(root-dir)/submodules/externals/build/exosip/Android.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/exosip/Android.mk
|
||||
|
||||
include $(root-dir)/submodules/externals/build/osip/Android.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/osip/Android.mk
|
||||
|
||||
# Openssl
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/ssl.mk),)
|
||||
include $(root-dir)/submodules/externals/openssl/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/ssl.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/openssl/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/ssl.mk
|
||||
include $(root-dir)/submodules/externals/prebuilts/crypto.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/ssl.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/crypto.mk
|
||||
endif
|
||||
|
||||
|
||||
include $(root-dir)/submodules/linphone/oRTP/build/android/Android.mk
|
||||
include $(linphone-root-dir)/submodules/linphone/oRTP/build/android/Android.mk
|
||||
|
||||
include $(root-dir)/submodules/linphone/mediastreamer2/build/android/Android.mk
|
||||
include $(root-dir)/submodules/linphone/mediastreamer2/tests/Android.mk
|
||||
include $(linphone-root-dir)/submodules/linphone/mediastreamer2/build/android/Android.mk
|
||||
include $(linphone-root-dir)/submodules/linphone/mediastreamer2/tests/Android.mk
|
||||
|
||||
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
include $(root-dir)/submodules/msilbc/Android.mk
|
||||
include $(linphone-root-dir)/submodules/msilbc/Android.mk
|
||||
|
||||
ifeq ($(BUILD_X264), 1)
|
||||
include $(root-dir)/submodules/msx264/Android.mk
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/x264.mk),)
|
||||
include $(root-dir)/submodules/externals/build/x264/Android.mk
|
||||
include $(linphone-root-dir)/submodules/msx264/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/x264.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/build/x264/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/x264.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/x264.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/ffmpeg.mk),)
|
||||
include $(root-dir)/submodules/externals/build/ffmpeg/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/ffmpeg.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/ffmpeg.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/ffmpeg.mk
|
||||
endif
|
||||
endif #armeabi-v7a
|
||||
|
||||
include $(root-dir)/submodules/externals/build/libvpx/Android.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/libvpx/Android.mk
|
||||
|
||||
|
||||
ifeq ($(BUILD_GPLV3_ZRTP), 1)
|
||||
ifeq ($(wildcard $(root-dir)/submodules/externals/prebuilts/zrtpcpp.mk),)
|
||||
include $(root-dir)/submodules/externals/build/libzrtpcpp/Android.mk
|
||||
ifeq ($(wildcard $(linphone-root-dir)/submodules/externals/prebuilts/zrtpcpp.mk),)
|
||||
include $(linphone-root-dir)/submodules/externals/build/libzrtpcpp/Android.mk
|
||||
else
|
||||
include $(root-dir)/submodules/externals/prebuilts/zrtpcpp.mk
|
||||
include $(linphone-root-dir)/submodules/externals/prebuilts/zrtpcpp.mk
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRTP), 1)
|
||||
include $(root-dir)/submodules/externals/build/srtp/Android.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/srtp/Android.mk
|
||||
endif
|
||||
|
||||
|
||||
include $(root-dir)/submodules/linphone/build/android/Android.mk
|
||||
include $(linphone-root-dir)/submodules/linphone/build/android/Android.mk
|
||||
|
||||
ifneq ($(BUILD_AMR), 0)
|
||||
include $(root-dir)/submodules/externals/build/opencore-amr/Android.mk
|
||||
include $(root-dir)/submodules/msamr/Android.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/opencore-amr/Android.mk
|
||||
include $(linphone-root-dir)/submodules/msamr/Android.mk
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -36,8 +36,9 @@ APP_MODULES += libsrtp
|
|||
endif
|
||||
endif
|
||||
|
||||
linphone-root-dir:=$(APP_PROJECT_PATH)
|
||||
|
||||
APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk
|
||||
APP_PLATFORM := android-8
|
||||
APP_ABI := armeabi armeabi-v7a
|
||||
APP_ABI := armeabi-v7a armeabi
|
||||
APP_CFLAGS:=-DDISABLE_NEON
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
android:id="@+id/video_frame" android:orientation="vertical"
|
||||
android:layout_height="fill_parent" android:layout_width="fill_parent">
|
||||
|
||||
<org.linphone.GL2JNIView android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></org.linphone.GL2JNIView>
|
||||
<org.linphone.mediastream.video.display.GL2JNIView android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></org.linphone.mediastream.video.display.GL2JNIView>
|
||||
<SurfaceView android:layout_height="72dip" android:layout_width="88dip" android:id="@+id/video_capture_surface" android:layout_gravity="right|bottom"
|
||||
android:layout_margin="15dip"></SurfaceView>
|
||||
</FrameLayout>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
android:id="@+id/video_frame"
|
||||
android:layout_height="fill_parent" android:layout_width="fill_parent">
|
||||
|
||||
<org.linphone.GL2JNIView android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></org.linphone.GL2JNIView>
|
||||
<org.linphone.mediastream.video.display.GL2JNIView android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/video_surface"></org.linphone.mediastream.video.display.GL2JNIView>
|
||||
<SurfaceView android:layout_height="88dip" android:layout_width="72dip" android:id="@+id/video_capture_surface" android:layout_gravity="right|bottom"
|
||||
android:layout_margin="15dip"></SurfaceView>
|
||||
</FrameLayout>
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
||||
android:orientation="vertical">
|
||||
<!--
|
||||
<LinearLayout android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
-->
|
||||
<!--
|
||||
<Button android:text="TEST" android:id="@+id/videotest_test"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"></Button>
|
||||
-->
|
||||
<LinearLayout android:id="@+id/LinearLayout01"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button android:text="Start" android:id="@+id/test_video_size"
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content" />
|
||||
<Button android:text="Change camera" android:id="@+id/test_video_camera"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
|
||||
<Button android:text="Change to portrait" android:id="@+id/test_video_orientation"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
|
||||
<TextView android:id="@+id/videotest_debug"
|
||||
android:layout_weight="1" android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"></TextView>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<SurfaceView android:id="@+id/videotest_surfaceView"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"></SurfaceView>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
|
@ -44,5 +44,5 @@ ng_floorgain=0.01
|
|||
|
||||
|
||||
[video]
|
||||
size=qvga-portrait
|
||||
size=vga
|
||||
|
||||
|
|
|
@ -18,14 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.LinphoneCallParams;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.VideoSize;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
|
||||
public class BandwidthManager {
|
||||
|
||||
|
@ -82,24 +76,9 @@ public class BandwidthManager {
|
|||
|
||||
|
||||
public void updateWithProfileSettings(LinphoneCore lc, LinphoneCallParams callParams) {
|
||||
// Setting Linphone Core Preferred Video Size
|
||||
boolean bandwidthOKForVideo = isVideoPossible();
|
||||
if (bandwidthOKForVideo && Version.isVideoCapable()) {
|
||||
AndroidCameraRecordManager acrm = AndroidCameraRecordManager.getInstance();
|
||||
boolean isPortrait=acrm.isFrameToBeShownPortrait();
|
||||
VideoSize targetVideoSize=maxSupportedVideoSize(isPortrait, getMaximumVideoSize(isPortrait),
|
||||
acrm.supportedVideoSizes());
|
||||
|
||||
lc.setPreferredVideoSize(targetVideoSize);
|
||||
VideoSize actualVideoSize = lc.getPreferredVideoSize();
|
||||
if (!targetVideoSize.equals(actualVideoSize)) {
|
||||
lc.setPreferredVideoSize(VideoSize.createStandard(VideoSize.QCIF, targetVideoSize.isPortrait()));
|
||||
}
|
||||
}
|
||||
|
||||
if (callParams != null) { // in call
|
||||
// Update video parm if
|
||||
if (!bandwidthOKForVideo) { // NO VIDEO
|
||||
if (!isVideoPossible()) { // NO VIDEO
|
||||
callParams.setVideoEnabled(false);
|
||||
callParams.setAudioBandwidth(40);
|
||||
} else {
|
||||
|
@ -109,44 +88,7 @@ public class BandwidthManager {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private VideoSize maxSupportedVideoSize(boolean isPortrait, VideoSize maximumVideoSize,
|
||||
List<VideoSize> supportedVideoSizes) {
|
||||
Log.d("Searching for maximum video size for ", isPortrait ? "portrait" : "landscape","capture from (",maximumVideoSize);
|
||||
VideoSize selected = VideoSize.createStandard(VideoSize.QCIF, isPortrait);
|
||||
for (VideoSize s : supportedVideoSizes) {
|
||||
int sW = s.width;
|
||||
int sH = s.height;
|
||||
if (s.isPortrait() != isPortrait) {
|
||||
sW=s.height;
|
||||
sH=s.width;
|
||||
}
|
||||
if (sW >maximumVideoSize.width || sH>maximumVideoSize.height) continue;
|
||||
if (selected.width <sW && selected.height <sH) {
|
||||
selected=new VideoSize(sW, sH);
|
||||
Log.d("A better video size has been found: ",selected);
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
private VideoSize maximumVideoSize(int profile, boolean cameraIsPortrait) {
|
||||
switch (profile) {
|
||||
case LOW_RESOLUTION:
|
||||
return VideoSize.createStandard(VideoSize.QCIF, cameraIsPortrait);
|
||||
case HIGH_RESOLUTION:
|
||||
return VideoSize.createStandard(VideoSize.QVGA, cameraIsPortrait);
|
||||
default:
|
||||
throw new RuntimeException("profile not managed : " + profile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isVideoPossible() {
|
||||
return currentProfile != LOW_BANDWIDTH;
|
||||
}
|
||||
|
||||
private VideoSize getMaximumVideoSize(boolean isPortrait) {
|
||||
return maximumVideoSize(currentProfile, isPortrait);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.linphone.core.LinphoneCallParams;
|
|||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -33,7 +32,7 @@ import org.linphone.core.video.AndroidCameraRecordManager;
|
|||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class CallManager {
|
||||
public class CallManager {
|
||||
|
||||
private static CallManager instance;
|
||||
|
||||
|
@ -43,9 +42,6 @@ class CallManager {
|
|||
return instance;
|
||||
}
|
||||
|
||||
private AndroidCameraRecordManager videoManager() {
|
||||
return AndroidCameraRecordManager.getInstance();
|
||||
}
|
||||
private BandwidthManager bm() {
|
||||
return BandwidthManager.getInstance();
|
||||
}
|
||||
|
@ -60,7 +56,6 @@ class CallManager {
|
|||
bm().updateWithProfileSettings(lc, params);
|
||||
|
||||
if (videoEnabled && params.getVideoEnabled()) {
|
||||
videoManager().setMuted(false);
|
||||
params.setVideoEnabled(true);
|
||||
} else {
|
||||
params.setVideoEnabled(false);
|
||||
|
@ -98,7 +93,6 @@ class CallManager {
|
|||
|
||||
// Not yet in video call: try to re-invite with video
|
||||
params.setVideoEnabled(true);
|
||||
videoManager().setMuted(false);
|
||||
lc.updateCall(lCall, params);
|
||||
return true;
|
||||
}
|
||||
|
@ -125,7 +119,7 @@ class CallManager {
|
|||
* Update current call, without reinvite.
|
||||
* The camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||
*/
|
||||
void updateCall() {
|
||||
public void updateCall() {
|
||||
LinphoneCore lc = LinphoneManager.getLc();
|
||||
LinphoneCall lCall = lc.getCurrentCall();
|
||||
if (lCall == null) {
|
||||
|
|
|
@ -22,11 +22,10 @@ import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
|
|||
import org.linphone.LinphoneService.LinphoneGuiListener;
|
||||
import org.linphone.core.CallDirection;
|
||||
import org.linphone.core.LinphoneCall;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.ui.AddVideoButton;
|
||||
import org.linphone.ui.AddressAware;
|
||||
import org.linphone.ui.AddressText;
|
||||
|
@ -327,7 +326,6 @@ public class DialerActivity extends SoftVolumeActivity implements LinphoneGuiLis
|
|||
int key = R.string.pref_video_automatically_share_my_video_key;
|
||||
boolean prefAutoShareMyCamera = mPref.getBoolean(getString(key), false);
|
||||
boolean videoMuted = !(prefVideoEnable && prefAutoShareMyCamera);
|
||||
AndroidCameraRecordManager.getInstance().setMuted(videoMuted);
|
||||
|
||||
LinphoneManager.getLc().getCurrentCall().enableCamera(prefAutoShareMyCamera);
|
||||
}
|
||||
|
@ -394,20 +392,29 @@ public class DialerActivity extends SoftVolumeActivity implements LinphoneGuiLis
|
|||
/* we are certainly exiting, ignore then.*/
|
||||
return;
|
||||
}
|
||||
if (state == LinphoneCall.State.OutgoingInit) {
|
||||
|
||||
if (state==LinphoneCall.State.OutgoingInit){
|
||||
enterIncallMode(lc);
|
||||
} else if (state == LinphoneCall.State.IncomingReceived) {
|
||||
if (!LinphoneManager.getInstance().shareMyCamera())
|
||||
call.enableCamera(false);
|
||||
LinphoneActivity.instance().startOrientationSensor();
|
||||
}else if (state==LinphoneCall.State.IncomingReceived){
|
||||
callPending(call);
|
||||
} else if (state == LinphoneCall.State.Connected) {
|
||||
if (!LinphoneManager.getInstance().shareMyCamera())
|
||||
call.enableCamera(false);
|
||||
LinphoneActivity.instance().startOrientationSensor();
|
||||
}else if (state==LinphoneCall.State.Connected){
|
||||
if (call.getDirection() == CallDirection.Incoming) {
|
||||
enterIncallMode(lc);
|
||||
}
|
||||
} else if (state == LinphoneCall.State.Error) {
|
||||
}else if (state==LinphoneCall.State.Error){
|
||||
if (mWakeLock.isHeld()) mWakeLock.release();
|
||||
showToast(R.string.call_error, message);
|
||||
exitCallMode();
|
||||
} else if (state == LinphoneCall.State.CallEnd) {
|
||||
LinphoneActivity.instance().stopOrientationSensor();
|
||||
}else if (state==LinphoneCall.State.CallEnd){
|
||||
exitCallMode();
|
||||
LinphoneActivity.instance().stopOrientationSensor();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.linphone.core.Log;
|
|||
import org.linphone.core.Version;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.TabActivity;
|
||||
|
@ -68,7 +69,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
import android.widget.TabHost.TabSpec;
|
||||
|
||||
public class LinphoneActivity extends TabActivity {
|
||||
public class LinphoneActivity extends TabActivity implements SensorEventListener {
|
||||
public static final String DIALER_TAB = "dialer";
|
||||
public static final String PREF_FIRST_LAUNCH = "pref_first_launch";
|
||||
private static final int video_activity = 100;
|
||||
|
@ -82,6 +83,8 @@ public class LinphoneActivity extends TabActivity {
|
|||
|
||||
private FrameLayout mMainFrame;
|
||||
private SensorManager mSensorManager;
|
||||
private Sensor mAccelerometer;
|
||||
private int previousRotation = -1;
|
||||
private static SensorEventListener mSensorEventListener;
|
||||
|
||||
private static final String SCREEN_IS_HIDDEN = "screen_is_hidden";
|
||||
|
@ -283,9 +286,29 @@ public class LinphoneActivity extends TabActivity {
|
|||
Toast.makeText(this, getString(R.string.dialer_null_on_new_intent), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
|
||||
}
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (event==null || event.sensor == mAccelerometer) {
|
||||
int rot;
|
||||
|
||||
rot=getWindowManager().getDefaultDisplay().getOrientation();
|
||||
|
||||
if (rot != previousRotation) {
|
||||
Log.d("New device rotation: ", rot);
|
||||
// Returning rotation FROM ITS NATURAL ORIENTATION
|
||||
LinphoneManager.getLc().setDeviceRotation(rot);
|
||||
previousRotation = rot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (isFinishing()) {
|
||||
//restore audio settings
|
||||
LinphoneManager.getInstance().routeAudioToReceiver();
|
||||
|
@ -368,6 +391,22 @@ public class LinphoneActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void startOrientationSensor() {
|
||||
if (mSensorManager!=null) {
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
|
||||
/* init LC orientation value on orientation sensor startup */
|
||||
previousRotation = -1;
|
||||
onSensorChanged(null);
|
||||
}
|
||||
|
||||
public synchronized void stopOrientationSensor() {
|
||||
if (mSensorManager!=null)
|
||||
mSensorManager.unregisterListener(this, mAccelerometer);
|
||||
}
|
||||
|
||||
protected synchronized void stopProxymitySensor() {
|
||||
if (mSensorManager!=null) {
|
||||
mSensorManager.unregisterListener(mSensorEventListener);
|
||||
|
|
|
@ -30,7 +30,6 @@ import static org.linphone.R.string.pref_codec_amr_key;
|
|||
import static org.linphone.R.string.pref_codec_ilbc_key;
|
||||
import static org.linphone.R.string.pref_codec_speex16_key;
|
||||
import static org.linphone.R.string.pref_codec_speex32_key;
|
||||
import static org.linphone.R.string.pref_echo_cancellation_key;
|
||||
import static org.linphone.R.string.pref_video_enable_key;
|
||||
import static org.linphone.core.LinphoneCall.State.CallEnd;
|
||||
import static org.linphone.core.LinphoneCall.State.Error;
|
||||
|
@ -43,7 +42,6 @@ import java.io.InputStream;
|
|||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.linphone.core.Hacks;
|
||||
import org.linphone.core.LinphoneAddress;
|
||||
import org.linphone.core.LinphoneAuthInfo;
|
||||
import org.linphone.core.LinphoneCall;
|
||||
|
@ -63,7 +61,10 @@ import org.linphone.core.LinphoneCore.FirewallPolicy;
|
|||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.core.LinphoneCore.Transports;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
import org.linphone.mediastream.video.capture.AndroidVideoApi5JniWrapper;
|
||||
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
|
||||
import org.linphone.mediastream.video.capture.hwconf.Hacks;
|
||||
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
|
@ -211,9 +212,9 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
instance = new LinphoneManager(c);
|
||||
instance.serviceListener = listener;
|
||||
instance.startLibLinphone(c);
|
||||
if (Version.isVideoCapable()) {
|
||||
AndroidCameraRecordManager.getInstance().startOrientationSensor(c.getApplicationContext());
|
||||
}
|
||||
|
||||
if (Version.isVideoCapable())
|
||||
AndroidVideoApi5JniWrapper.setAndroidSdkVersion(Build.VERSION.SDK_INT);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -261,7 +262,6 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
boolean prefVideoEnable = isVideoEnabled();
|
||||
int key = R.string.pref_video_initiate_call_with_video_key;
|
||||
boolean prefInitiateWithVideo = mPref.getBoolean(mR.getString(key), false);
|
||||
resetCameraFromPreferences();
|
||||
CallManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo);
|
||||
} else {
|
||||
CallManager.getInstance().inviteAddress(lAddress, false);
|
||||
|
@ -274,12 +274,19 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void resetCameraFromPreferences() {
|
||||
boolean useFrontCam = mPref.getBoolean(mR.getString(R.string.pref_video_use_front_camera_key), false);
|
||||
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
|
||||
|
||||
int camId = 0;
|
||||
AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
|
||||
for (AndroidCamera androidCamera : cameras) {
|
||||
if (androidCamera.frontFacing == useFrontCam)
|
||||
camId = androidCamera.id;
|
||||
}
|
||||
LinphoneManager.getLc().setVideoDevice(camId);
|
||||
}
|
||||
|
||||
|
||||
public static interface AddressType {
|
||||
void setText(CharSequence s);
|
||||
CharSequence getText();
|
||||
|
@ -294,6 +301,11 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
public void onAlreadyInCall();
|
||||
}
|
||||
|
||||
public void toggleEnableCamera() {
|
||||
if (mLc.isIncall()) {
|
||||
mLc.getCurrentCall().enableCamera(!mLc.getCurrentCall().cameraEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendStaticImage(boolean send) {
|
||||
if (mLc.isIncall()) {
|
||||
|
@ -324,20 +336,6 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||
*/
|
||||
public void switchCamera() {
|
||||
AndroidCameraRecordManager.getInstance().stopVideoRecording();
|
||||
AndroidCameraRecordManager.getInstance().toggleUseFrontCamera();
|
||||
CallManager.getInstance().updateCall();
|
||||
}
|
||||
|
||||
public void toggleCameraMuting() {
|
||||
AndroidCameraRecordManager rm = AndroidCameraRecordManager.getInstance();
|
||||
sendStaticImage(rm.toggleMute());
|
||||
}
|
||||
|
||||
private synchronized void startLibLinphone(final Context context) {
|
||||
try {
|
||||
copyAssetsFromPackage(context);
|
||||
|
@ -417,7 +415,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
|
||||
public void initFromConf(Context context) throws LinphoneConfigException {
|
||||
//traces
|
||||
boolean lIsDebug = mPref.getBoolean(getString(R.string.pref_debug_key), false);
|
||||
boolean lIsDebug = true;//mPref.getBoolean(getString(R.string.pref_debug_key), false);
|
||||
LinphoneCoreFactory.instance().setDebugMode(lIsDebug);
|
||||
|
||||
if (initialTransports == null)
|
||||
|
@ -845,6 +843,10 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
return mPref.getBoolean(getString(R.string.pref_video_enable_key), false);
|
||||
}
|
||||
|
||||
public boolean shareMyCamera() {
|
||||
return mPref.getBoolean(getString(R.string.pref_video_automatically_share_my_video), false);
|
||||
}
|
||||
|
||||
public void setAudioModeIncallForGalaxyS() {
|
||||
stopRinging();
|
||||
mAudioManager.setMode(MODE_IN_CALL);
|
||||
|
|
|
@ -32,12 +32,12 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
import org.linphone.LinphoneManager.EcCalibrationListener;
|
||||
import org.linphone.core.Hacks;
|
||||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
|
||||
import org.linphone.mediastream.video.capture.hwconf.Hacks;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
|
@ -98,7 +98,7 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E
|
|||
// No video
|
||||
if (!Version.isVideoCapable()) {
|
||||
uncheckAndDisableCheckbox(pref_video_enable_key);
|
||||
} else if (!AndroidCameraRecordManager.getInstance().hasFrontCamera()) {
|
||||
} else if (!AndroidCameraConfiguration.hasFrontCamera()) {
|
||||
uncheckDisableAndHideCheckbox(R.string.pref_video_use_front_camera_key);
|
||||
}
|
||||
if (prefs().getBoolean(LinphoneActivity.PREF_FIRST_LAUNCH,true)) {
|
||||
|
|
|
@ -22,13 +22,13 @@ import java.io.IOException;
|
|||
|
||||
import org.linphone.LinphoneManager.LinphoneServiceListener;
|
||||
import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
|
||||
import org.linphone.core.Hacks;
|
||||
import org.linphone.core.LinphoneCall;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.mediastream.video.capture.hwconf.Hacks;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
|
|
|
@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone;
|
||||
|
||||
import org.linphone.core.Hacks;
|
||||
import org.linphone.mediastream.video.capture.hwconf.Hacks;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.KeyEvent;
|
||||
|
|
|
@ -20,39 +20,33 @@ package org.linphone;
|
|||
|
||||
|
||||
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.VideoSize;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||
import org.linphone.core.video.AndroidCameraRecordManager.OnCapturingStateChangedListener;
|
||||
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
|
||||
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
|
||||
/**
|
||||
* For Android SDK >= 5
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
public class VideoCallActivity extends SoftVolumeActivity implements OnCapturingStateChangedListener {
|
||||
public class VideoCallActivity extends SoftVolumeActivity {
|
||||
private SurfaceView mVideoView;
|
||||
private SurfaceView mVideoCaptureView;
|
||||
private AndroidCameraRecordManager recordManager;
|
||||
public static boolean launched = false;
|
||||
private WakeLock mWakeLock;
|
||||
private static final int capturePreviewLargestDimension = 150;
|
||||
private Handler handler = new Handler();
|
||||
|
||||
AndroidVideoWindowImpl androidVideoWindowImpl;
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
launched = true;
|
||||
|
@ -61,48 +55,61 @@ public class VideoCallActivity extends SoftVolumeActivity implements OnCapturing
|
|||
setContentView(R.layout.videocall);
|
||||
|
||||
mVideoView = (SurfaceView) findViewById(R.id.video_surface);
|
||||
LinphoneCore lc = LinphoneManager.getLc();
|
||||
lc.setVideoWindow(mVideoView);
|
||||
|
||||
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
||||
mVideoCaptureView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
|
||||
recordManager = AndroidCameraRecordManager.getInstance();
|
||||
recordManager.setOnCapturingStateChanged(this);
|
||||
recordManager.setSurfaceView(mVideoCaptureView);
|
||||
/* force surfaces Z ordering */
|
||||
mVideoView.setZOrderOnTop(false);
|
||||
mVideoCaptureView.setZOrderOnTop(true);
|
||||
|
||||
if (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false);
|
||||
androidVideoWindowImpl = new AndroidVideoWindowImpl(mVideoView, mVideoCaptureView);
|
||||
androidVideoWindowImpl.setListener(new AndroidVideoWindowImpl.VideoWindowListener() {
|
||||
|
||||
public void onVideoRenderingSurfaceReady(AndroidVideoWindowImpl vw) {
|
||||
LinphoneManager.getLc().setVideoWindow(vw);
|
||||
}
|
||||
|
||||
public void onVideoRenderingSurfaceDestroyed(AndroidVideoWindowImpl vw) {
|
||||
Log.d("VIDEO WINDOW destroyed!\n");
|
||||
LinphoneManager.getLc().setVideoWindow(null);
|
||||
}
|
||||
|
||||
public void onVideoPreviewSurfaceReady(AndroidVideoWindowImpl vw) {
|
||||
LinphoneManager.getLc().setPreviewWindow(mVideoCaptureView);
|
||||
}
|
||||
|
||||
public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
androidVideoWindowImpl.init();
|
||||
|
||||
// When changing phone orientation _DURING_ a call, VideoCallActivity is destroyed then recreated
|
||||
// In this case, the following sequence happen:
|
||||
// * onDestroy -> sendStaticImage(true) => destroy video graph
|
||||
// * onCreate -> sendStaticImage(false) => recreate the video graph.
|
||||
// Before creating the graph, the orientation must be known to LC => this is done here
|
||||
LinphoneManager.getLc().setDeviceRotation(AndroidVideoWindowImpl.rotationToAngle(getWindowManager().getDefaultDisplay().getRotation()));
|
||||
|
||||
if (!LinphoneManager.getInstance().shareMyCamera())
|
||||
LinphoneManager.getInstance().sendStaticImage(false);
|
||||
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,Log.TAG);
|
||||
mWakeLock.acquire();
|
||||
|
||||
fixScreenOrientationForOldDevices();
|
||||
}
|
||||
|
||||
private void fixScreenOrientationForOldDevices() {
|
||||
if (Version.sdkAboveOrEqual(Version.API08_FROYO_22)) return;
|
||||
|
||||
// Force to display in portrait orientation for old devices
|
||||
// as they do not support surfaceView rotation
|
||||
setRequestedOrientation(recordManager.isCameraMountedPortrait() ?
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
resizeCapturePreview(mVideoCaptureView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (Version.sdkAboveOrEqual(8) && recordManager.isOutputOrientationMismatch(LinphoneManager.getLc())) {
|
||||
Log.i("Phone orientation has changed: updating call.");
|
||||
CallManager.getInstance().updateCall();
|
||||
// resizeCapturePreview by callback when recording started
|
||||
}
|
||||
super.onResume();
|
||||
((GLSurfaceView)mVideoView).onResume();
|
||||
}
|
||||
|
||||
|
||||
private void rewriteToggleCameraItem(MenuItem item) {
|
||||
if (recordManager.isRecording()) {
|
||||
if (LinphoneManager.getLc().getCurrentCall().cameraEnabled()) {
|
||||
item.setTitle(getString(R.string.menu_videocall_toggle_camera_disable));
|
||||
} else {
|
||||
item.setTitle(getString(R.string.menu_videocall_toggle_camera_enable));
|
||||
|
@ -128,38 +135,12 @@ public class VideoCallActivity extends SoftVolumeActivity implements OnCapturing
|
|||
rewriteToggleCameraItem(menu.findItem(R.id.videocall_menu_toggle_camera));
|
||||
rewriteChangeResolutionItem(menu.findItem(R.id.videocall_menu_change_resolution));
|
||||
|
||||
if (!recordManager.hasSeveralCameras()) {
|
||||
if (!AndroidCameraConfiguration.hasSeveralCameras()) {
|
||||
menu.findItem(R.id.videocall_menu_switch_camera).setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base capture frame on streamed dimensions and orientation.
|
||||
* @param sv capture surface view to resize the layout
|
||||
* @param vs video size from which to calculate the dimensions
|
||||
*/
|
||||
private void resizeCapturePreview(SurfaceView sv) {
|
||||
LayoutParams lp = sv.getLayoutParams();
|
||||
VideoSize vs = LinphoneManager.getLc().getPreferredVideoSize();
|
||||
|
||||
float newRatio = (float) vs.width / vs.height;
|
||||
|
||||
if (vs.isPortrait()) {
|
||||
lp.height = capturePreviewLargestDimension;
|
||||
lp.width = Math.round(lp.height * newRatio);
|
||||
} else {
|
||||
lp.width = capturePreviewLargestDimension;
|
||||
lp.height = Math.round(lp.width / newRatio);
|
||||
}
|
||||
|
||||
sv.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
@ -168,30 +149,37 @@ public class VideoCallActivity extends SoftVolumeActivity implements OnCapturing
|
|||
break;
|
||||
case R.id.videocall_menu_change_resolution:
|
||||
LinphoneManager.getInstance().changeResolution();
|
||||
// previous call will cause graph reconstruction -> regive preview window
|
||||
rewriteChangeResolutionItem(item);
|
||||
break;
|
||||
case R.id.videocall_menu_terminate_call:
|
||||
LinphoneManager.getInstance().terminateCall();
|
||||
break;
|
||||
case R.id.videocall_menu_toggle_camera:
|
||||
LinphoneManager.getInstance().toggleCameraMuting();
|
||||
LinphoneManager.getInstance().toggleEnableCamera();
|
||||
rewriteToggleCameraItem(item);
|
||||
// previous call will cause graph reconstruction -> regive preview window
|
||||
LinphoneManager.getLc().setPreviewWindow(mVideoCaptureView);
|
||||
break;
|
||||
case R.id.videocall_menu_switch_camera:
|
||||
LinphoneManager.getInstance().switchCamera();
|
||||
fixScreenOrientationForOldDevices();
|
||||
int id = LinphoneManager.getLc().getVideoDevice();
|
||||
id = (id + 1) % AndroidCameraConfiguration.retrieveCameras().length;
|
||||
LinphoneManager.getLc().setVideoDevice(id);
|
||||
CallManager.getInstance().updateCall();
|
||||
// previous call will cause graph reconstruction -> regive preview window
|
||||
LinphoneManager.getLc().setPreviewWindow(mVideoCaptureView);
|
||||
break;
|
||||
default:
|
||||
Log.e("Unknown menu item [",item,"]");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
androidVideoWindowImpl.release();
|
||||
launched = false;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
@ -199,20 +187,10 @@ public class VideoCallActivity extends SoftVolumeActivity implements OnCapturing
|
|||
@Override
|
||||
protected void onPause() {
|
||||
Log.d("onPause VideoCallActivity");
|
||||
LinphoneManager.getLc().setVideoWindow(null);
|
||||
LinphoneManager.getInstance().sendStaticImage(true);
|
||||
if (mWakeLock.isHeld()) mWakeLock.release();
|
||||
super.onPause();
|
||||
((GLSurfaceView)mVideoView).onPause();
|
||||
}
|
||||
|
||||
public void captureStarted() {
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
resizeCapturePreview(mVideoCaptureView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void captureStopped() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
package org.linphone.core;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import org.linphone.OpenGLESDisplay;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.Surface.OutOfResourcesException;
|
||||
import android.view.SurfaceHolder.Callback;
|
||||
|
||||
public class AndroidVideoWindowImpl {
|
||||
private boolean useGLrendering;
|
||||
private Bitmap mBitmap;
|
||||
private SurfaceView mView;
|
||||
private Surface mSurface;
|
||||
private VideoWindowListener mListener;
|
||||
private Renderer renderer;
|
||||
public static interface VideoWindowListener{
|
||||
void onSurfaceReady(AndroidVideoWindowImpl vw);
|
||||
void onSurfaceDestroyed(AndroidVideoWindowImpl vw);
|
||||
};
|
||||
public AndroidVideoWindowImpl(SurfaceView view){
|
||||
useGLrendering = (view instanceof GLSurfaceView);
|
||||
mView=view;
|
||||
mBitmap=null;
|
||||
mSurface=null;
|
||||
mListener=null;
|
||||
view.getHolder().addCallback(new Callback(){
|
||||
public void surfaceChanged(SurfaceHolder holder, int format,
|
||||
int width, int height) {
|
||||
Log.i("Surface is being changed.");
|
||||
if (!useGLrendering) {
|
||||
synchronized(AndroidVideoWindowImpl.this){
|
||||
mBitmap=Bitmap.createBitmap(width,height,Config.RGB_565);
|
||||
mSurface=holder.getSurface();
|
||||
}
|
||||
}
|
||||
if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this);
|
||||
Log.w("Video display surface changed");
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.w("Video display surface created");
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
if (!useGLrendering) {
|
||||
synchronized(AndroidVideoWindowImpl.this){
|
||||
mSurface=null;
|
||||
mBitmap=null;
|
||||
}
|
||||
}
|
||||
if (mListener!=null)
|
||||
mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this);
|
||||
Log.d("Video display surface destroyed");
|
||||
}
|
||||
});
|
||||
|
||||
if (useGLrendering) {
|
||||
renderer = new Renderer();
|
||||
((GLSurfaceView)mView).setRenderer(renderer);
|
||||
((GLSurfaceView)mView).setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||
}
|
||||
}
|
||||
static final int LANDSCAPE=0;
|
||||
static final int PORTRAIT=1;
|
||||
public void requestOrientation(int orientation){
|
||||
//Surface.setOrientation(0, orientation==LANDSCAPE ? 1 : 0);
|
||||
//Log.d("Orientation changed.");
|
||||
}
|
||||
public void setListener(VideoWindowListener l){
|
||||
mListener=l;
|
||||
}
|
||||
public Surface getSurface(){
|
||||
if (useGLrendering)
|
||||
Log.e("View class does not match Video display filter used (you must use a non-GL View)");
|
||||
return mView.getHolder().getSurface();
|
||||
}
|
||||
public Bitmap getBitmap(){
|
||||
if (useGLrendering)
|
||||
Log.e("View class does not match Video display filter used (you must use a non-GL View)");
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
public void setOpenGLESDisplay(int ptr) {
|
||||
if (!useGLrendering)
|
||||
Log.e("View class does not match Video display filter used (you must use a GL View)");
|
||||
renderer.setOpenGLESDisplay(ptr);
|
||||
}
|
||||
|
||||
public void requestRender() {
|
||||
((GLSurfaceView)mView).requestRender();
|
||||
}
|
||||
|
||||
//Called by the mediastreamer2 android display filter
|
||||
public synchronized void update(){
|
||||
if (mSurface!=null){
|
||||
try {
|
||||
Canvas canvas=mSurface.lockCanvas(null);
|
||||
canvas.drawBitmap(mBitmap, 0, 0, null);
|
||||
mSurface.unlockCanvasAndPost(canvas);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (OutOfResourcesException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Renderer implements GLSurfaceView.Renderer {
|
||||
int ptr;
|
||||
boolean initPending;
|
||||
int width=-1, height=-1;
|
||||
|
||||
public Renderer() {
|
||||
ptr = 0;
|
||||
initPending = false;
|
||||
}
|
||||
|
||||
public void setOpenGLESDisplay(int ptr) {
|
||||
this.ptr = ptr;
|
||||
// if dimension are set, we are recreating MS2 graph without
|
||||
// recreating the surface => need to force init
|
||||
if (width > 0 && height > 0) {
|
||||
initPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
if (ptr == 0)
|
||||
return;
|
||||
if (initPending) {
|
||||
OpenGLESDisplay.init(ptr, width, height);
|
||||
initPending = false;
|
||||
}
|
||||
OpenGLESDisplay.render(ptr);
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
/* delay init until ptr is set */
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
initPending = true;
|
||||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
Hacks.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.core;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
public final class Hacks {
|
||||
|
||||
private Hacks() {}
|
||||
|
||||
|
||||
public static boolean isGalaxySOrTabWithFrontCamera() {
|
||||
return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera();
|
||||
}
|
||||
private static boolean isGalaxySOrTabWithoutFrontCamera() {
|
||||
return isSC02B() || isSGHI896();
|
||||
}
|
||||
|
||||
|
||||
public static boolean isGalaxySOrTab() {
|
||||
return isGalaxyS() || isGalaxyTab();
|
||||
}
|
||||
|
||||
public static boolean isGalaxyTab() {
|
||||
return isGTP1000();
|
||||
}
|
||||
private static boolean isGalaxyS() {
|
||||
return isGT9000() || isSC02B() || isSGHI896() || isSPHD700();
|
||||
}
|
||||
|
||||
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) {
|
||||
Log.d(msg);
|
||||
return true;
|
||||
}*/
|
||||
|
||||
/* Not working as now
|
||||
* Calling from Galaxy S to PC is "usable" even with no hack; other side is not even with this one*/
|
||||
public static void galaxySSwitchToCallStreamUnMuteLowerVolume(AudioManager am) {
|
||||
// Switch to call audio channel (Galaxy S)
|
||||
am.setSpeakerphoneOn(false);
|
||||
sleep(200);
|
||||
|
||||
// Lower volume
|
||||
am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, 1, 0);
|
||||
|
||||
// Another way to select call channel
|
||||
am.setMode(AudioManager.MODE_NORMAL);
|
||||
sleep(200);
|
||||
|
||||
// Mic is muted if not doing this
|
||||
am.setMicrophoneMute(true);
|
||||
sleep(200);
|
||||
am.setMicrophoneMute(false);
|
||||
sleep(200);
|
||||
}
|
||||
|
||||
public static final void sleep(int time) {
|
||||
try {
|
||||
Thread.sleep(time);
|
||||
} catch(InterruptedException ie){}
|
||||
}
|
||||
|
||||
public static void dumpDeviceInformation() {
|
||||
StringBuilder sb = new StringBuilder(" ==== Phone information dump ====\n");
|
||||
sb.append("DEVICE=").append(Build.DEVICE).append("\n");
|
||||
sb.append("MODEL=").append(Build.MODEL).append("\n");
|
||||
//MANUFACTURER doesn't exist in android 1.5.
|
||||
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
|
||||
sb.append("SDK=").append(Build.VERSION.SDK);
|
||||
|
||||
Log.i(sb.toString());
|
||||
}
|
||||
|
||||
public static boolean needSoftvolume() {
|
||||
return isGalaxySOrTab();
|
||||
}
|
||||
|
||||
public static boolean needRoutingAPI() {
|
||||
return Version.sdkStrictlyBelow(5) /*<donut*/;
|
||||
}
|
||||
|
||||
public static boolean needGalaxySAudioHack() {
|
||||
return isGalaxySOrTab() && !isSC02B();
|
||||
}
|
||||
|
||||
public static boolean needPausingCallForSpeakers() {
|
||||
// return false;
|
||||
return isGalaxySOrTab() && !isSC02B();
|
||||
}
|
||||
|
||||
public static boolean hasTwoCameras() {
|
||||
return isSPHD700() || isGalaxySOrTabWithFrontCamera();
|
||||
}
|
||||
|
||||
public static boolean hasCamera() {
|
||||
if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
|
||||
int nb = 0;
|
||||
try {
|
||||
nb = (Integer) Camera.class.getMethod("getNumberOfCameras", (Class[])null).invoke(null);
|
||||
} catch (Exception e) {
|
||||
Log.e("Error getting number of cameras");
|
||||
}
|
||||
return nb > 0;
|
||||
}
|
||||
|
||||
Log.i("Hack: considering there IS a camera.\n"
|
||||
+ "If it is not the case, report DEVICE and MODEL to linphone-users@nongnu.org");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,7 @@ class LinphoneCallImpl implements LinphoneCall {
|
|||
native private int getState(long nativePtr);
|
||||
private native long getCurrentParamsCopy(long nativePtr);
|
||||
private native void enableCamera(long nativePtr, boolean enabled);
|
||||
private native boolean cameraEnabled(long nativePtr);
|
||||
private native void enableEchoCancellation(long nativePtr,boolean enable);
|
||||
private native boolean isEchoCancellationEnabled(long nativePtr) ;
|
||||
private native void enableEchoLimiter(long nativePtr,boolean enable);
|
||||
|
@ -79,6 +80,9 @@ class LinphoneCallImpl implements LinphoneCall {
|
|||
public void enableCamera(boolean enabled) {
|
||||
enableCamera(nativePtr, enabled);
|
||||
}
|
||||
public boolean cameraEnabled() {
|
||||
return cameraEnabled(nativePtr);
|
||||
}
|
||||
public boolean equals(Object call) {
|
||||
return nativePtr == ((LinphoneCallImpl)call).nativePtr;
|
||||
}
|
||||
|
@ -122,4 +126,8 @@ class LinphoneCallImpl implements LinphoneCall {
|
|||
public boolean areStreamsEncrypted() {
|
||||
return areStreamsEncrypted(nativePtr);
|
||||
}
|
||||
public boolean isInConference() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,11 @@ package org.linphone.core;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.view.SurfaceView;
|
||||
import org.linphone.LinphoneManager;
|
||||
import org.linphone.mediastream.video.AndroidVideoWindowImpl;
|
||||
|
||||
|
||||
class LinphoneCoreImpl implements LinphoneCore {
|
||||
|
@ -68,8 +70,7 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
private native void stopDtmf(long nativePtr);
|
||||
private native void setVideoWindowId(long nativePtr, Object wid);
|
||||
private native void setPreviewWindowId(long nativePtr, Object wid);
|
||||
private AndroidVideoWindowImpl mVideoWindow;
|
||||
private AndroidVideoWindowImpl mPreviewWindow;
|
||||
private native void setDeviceRotation(long nativePtr, int rotation);
|
||||
private native void addFriend(long nativePtr,long friend);
|
||||
private native void setPresenceInfo(long nativePtr,int minute_away, String alternative_contact,int status);
|
||||
private native long createChatRoom(long nativePtr,String to);
|
||||
|
@ -104,6 +105,8 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
private native void setDownloadPtime(long nativePtr, int ptime);
|
||||
private native void setZrtpSecretsCache(long nativePtr, String file);
|
||||
private native void enableEchoLimiter(long nativePtr2, boolean val);
|
||||
private native int setVideoDevice(long nativePtr2, int id);
|
||||
private native int getVideoDevice(long nativePtr2);
|
||||
|
||||
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
|
||||
mListener=listener;
|
||||
|
@ -327,33 +330,15 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
return new LinphoneChatRoomImpl(createChatRoom(nativePtr,to));
|
||||
}
|
||||
public synchronized void setPreviewWindow(Object w) {
|
||||
if (mPreviewWindow!=null)
|
||||
mPreviewWindow.setListener(null);
|
||||
mPreviewWindow=new AndroidVideoWindowImpl((SurfaceView)w);
|
||||
mPreviewWindow.setListener(new AndroidVideoWindowImpl.VideoWindowListener(){
|
||||
public void onSurfaceDestroyed(AndroidVideoWindowImpl vw) {
|
||||
setPreviewWindowId(nativePtr,null);
|
||||
}
|
||||
|
||||
public void onSurfaceReady(AndroidVideoWindowImpl vw) {
|
||||
setPreviewWindowId(nativePtr,vw);
|
||||
}
|
||||
});
|
||||
setPreviewWindowId(nativePtr,w);
|
||||
}
|
||||
public synchronized void setVideoWindow(Object w) {
|
||||
if (mVideoWindow!=null)
|
||||
mVideoWindow.setListener(null);
|
||||
mVideoWindow=new AndroidVideoWindowImpl((SurfaceView) w);
|
||||
mVideoWindow.setListener(new AndroidVideoWindowImpl.VideoWindowListener(){
|
||||
public void onSurfaceDestroyed(AndroidVideoWindowImpl vw) {
|
||||
setVideoWindowId(nativePtr,null);
|
||||
}
|
||||
|
||||
public void onSurfaceReady(AndroidVideoWindowImpl vw) {
|
||||
setVideoWindowId(nativePtr,vw);
|
||||
}
|
||||
});
|
||||
setVideoWindowId(nativePtr, w);
|
||||
}
|
||||
public synchronized void setDeviceRotation(int rotation) {
|
||||
setDeviceRotation(nativePtr, rotation);
|
||||
}
|
||||
|
||||
public synchronized void enableVideo(boolean vcap_enabled, boolean display_enabled) {
|
||||
enableVideo(nativePtr,vcap_enabled, display_enabled);
|
||||
}
|
||||
|
@ -507,5 +492,67 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
public void enableEchoLimiter(boolean val) {
|
||||
enableEchoLimiter(nativePtr,val);
|
||||
}
|
||||
public void setVideoDevice(int id) {
|
||||
Log.i("Setting camera id :", id);
|
||||
if (setVideoDevice(nativePtr, id) != 0) {
|
||||
Log.e("Failed to set video device to id:", id);
|
||||
}
|
||||
}
|
||||
public int getVideoDevice() {
|
||||
return getVideoDevice(nativePtr);
|
||||
}
|
||||
public void addAllToConference() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void addToConference(LinphoneCall call) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void enterConference() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public List getCalls() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
public int getCallsNb() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
public int getConferenceSize() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
public boolean isInConference() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
public void leaveConference() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void removeFromConference(LinphoneCall call) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void terminateAllCalls() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void terminateConference() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void transferCall(LinphoneCall call, String referTo) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
public void transferCallToAnother(LinphoneCall callToTransfer,
|
||||
LinphoneCall destination) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
package org.linphone.core;
|
||||
|
||||
import org.linphone.mediastream.video.capture.hwconf.Hacks;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
JavaCameraRecordImpl.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.core.tutorials;
|
||||
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.video.AndroidCameraRecord;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* This is an helper class, not a test activity.
|
||||
*
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
|
||||
|
||||
private TextView debug;
|
||||
private long count = 0;
|
||||
private float averageCalledRate;
|
||||
|
||||
private long startTime;
|
||||
private long endTime;
|
||||
private int fps;
|
||||
|
||||
|
||||
public JavaCameraRecordImpl(AndroidCameraRecord.RecorderParams parameters) {
|
||||
super(parameters);
|
||||
storePreviewCallBack(this);
|
||||
fps = Math.round(parameters.fps);
|
||||
}
|
||||
|
||||
|
||||
public void setDebug(TextView debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
|
||||
Size s = camera.getParameters().getPreviewSize();
|
||||
int expectedBuffLength = s.width * s.height * 3 /2;
|
||||
if (expectedBuffLength != data.length) {
|
||||
Log.e("onPreviewFrame called with bad buffer length ", data.length,
|
||||
" whereas expected is ", expectedBuffLength, " don't calling putImage");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((count % 2 * fps) == 0) {
|
||||
endTime = System.currentTimeMillis();
|
||||
averageCalledRate = (100000 * 2 * fps) / (endTime - startTime);
|
||||
averageCalledRate /= 100f;
|
||||
startTime = endTime;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
String msg = "Frame " + count + ": " + data.length + "bytes (avg="+averageCalledRate+"frames/s)";
|
||||
if (debug != null) debug.setText(msg);
|
||||
Log.d("onPreviewFrame:", msg);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
||||
camera.setPreviewCallback(cb);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
TutorialHelloWorldActivity.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.core.tutorials;
|
||||
|
||||
import static org.linphone.core.VideoSize.CIF;
|
||||
import static org.linphone.core.VideoSize.HVGA;
|
||||
import static org.linphone.core.VideoSize.QCIF;
|
||||
import static org.linphone.core.VideoSize.QVGA;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import org.linphone.R;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.VideoSize;
|
||||
import org.linphone.core.video.AndroidCameraRecord;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.SurfaceHolder.Callback;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Activity for displaying and starting the HelloWorld example on Android phone.
|
||||
*
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
public class TestVideoActivity extends Activity implements Callback, OnClickListener {
|
||||
|
||||
private SurfaceView surfaceView;
|
||||
private static final int rate = 7;
|
||||
private JavaCameraRecordImpl recorder;
|
||||
private TextView debugView;
|
||||
private Button nextSize;
|
||||
private Button changeCamera;
|
||||
private Button changeOrientation;
|
||||
private AndroidCameraRecord.RecorderParams params;
|
||||
|
||||
private Stack<VideoSize> videoSizes = createSizesToTest();
|
||||
private int currentCameraId = 2;
|
||||
private boolean currentOrientationIsPortrait = false;
|
||||
private int width;
|
||||
private int height;
|
||||
private boolean started;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.videotest);
|
||||
|
||||
surfaceView=(SurfaceView)findViewById(R.id.videotest_surfaceView);
|
||||
|
||||
nextSize = (Button) findViewById(R.id.test_video_size);
|
||||
nextSize.setOnClickListener(this);
|
||||
|
||||
changeCamera = (Button) findViewById(R.id.test_video_camera);
|
||||
changeCamera.setText("Cam"+otherCameraId(currentCameraId));
|
||||
changeCamera.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
changeCamera.setText("Cam"+currentCameraId);
|
||||
currentCameraId = otherCameraId(currentCameraId);
|
||||
updateRecording();
|
||||
}
|
||||
});
|
||||
|
||||
changeOrientation = (Button) findViewById(R.id.test_video_orientation);
|
||||
changeOrientation.setText(orientationToString(!currentOrientationIsPortrait));
|
||||
changeOrientation.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
currentOrientationIsPortrait = !currentOrientationIsPortrait;
|
||||
changeOrientation.setText(orientationToString(!currentOrientationIsPortrait));
|
||||
|
||||
if (width == 0 || height == 0) return;
|
||||
int newWidth = currentOrientationIsPortrait? Math.min(height, width) : Math.max(height, width);
|
||||
int newHeight = currentOrientationIsPortrait? Math.max(height, width) : Math.min(height, width);
|
||||
changeSurfaceViewLayout(newWidth, newHeight); // will change width and height on surfaceChanged
|
||||
}
|
||||
});
|
||||
|
||||
SurfaceHolder holder = surfaceView.getHolder();
|
||||
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
holder.addCallback(this);
|
||||
|
||||
|
||||
debugView = (TextView) findViewById(R.id.videotest_debug);
|
||||
}
|
||||
|
||||
protected void updateRecording() {
|
||||
if (width == 0 || height == 0) return;
|
||||
if (recorder != null) recorder.stopPreview();
|
||||
|
||||
params = new AndroidCameraRecord.RecorderParams(0);
|
||||
params.surfaceView = surfaceView;
|
||||
params.width = width;
|
||||
params.height = height;
|
||||
params.fps = rate;
|
||||
params.cameraId = currentCameraId;
|
||||
|
||||
recorder = new JavaCameraRecordImpl(params);
|
||||
// recorder.setDebug(debugView);
|
||||
debugView.setText(orientationToString(currentOrientationIsPortrait)
|
||||
+ " w="+width + " h="+height+ " cam"+currentCameraId);
|
||||
recorder.startPreview();
|
||||
|
||||
}
|
||||
|
||||
private String orientationToString(boolean orientationIsPortrait) {
|
||||
return orientationIsPortrait? "Por" : "Lan";
|
||||
}
|
||||
private int otherCameraId(int currentId) {
|
||||
return (currentId == 2) ? 1 : 2;
|
||||
}
|
||||
public void onClick(View v) {
|
||||
nextSize.setText("Next");
|
||||
started=true;
|
||||
if (videoSizes.isEmpty()) {
|
||||
videoSizes = createSizesToTest();
|
||||
}
|
||||
|
||||
VideoSize size = videoSizes.pop();
|
||||
changeSurfaceViewLayout(size.width, size.height);
|
||||
|
||||
// on surface changed the recorder will be restarted with new values
|
||||
// and the surface will be resized
|
||||
}
|
||||
|
||||
|
||||
private void changeSurfaceViewLayout(int width, int height) {
|
||||
LayoutParams params = surfaceView.getLayoutParams();
|
||||
params.height = height;
|
||||
params.width = width;
|
||||
surfaceView.setLayoutParams(params);
|
||||
|
||||
}
|
||||
|
||||
private Stack<VideoSize> createSizesToTest() {
|
||||
Stack<VideoSize> stack = new Stack<VideoSize>();
|
||||
|
||||
stack.push(VideoSize.createStandard(QCIF, false));
|
||||
stack.push(VideoSize.createStandard(CIF, false));
|
||||
stack.push(VideoSize.createStandard(QVGA, false));
|
||||
stack.push(VideoSize.createStandard(HVGA, false));
|
||||
stack.push(new VideoSize(640,480));
|
||||
stack.push(new VideoSize(800,480));
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
surfaceView = null;
|
||||
Log.d("Video capture surface destroyed");
|
||||
if (recorder != null) recorder.stopPreview();
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.d("Video capture surface created");
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
if (!started) return;
|
||||
if (recorder != null) recorder.stopPreview();
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
updateRecording();
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
AndroidCameraConf.java
|
||||
Copyright (C) 2011 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.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.VideoSize;
|
||||
|
||||
|
||||
/**
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
interface AndroidCameraConf {
|
||||
|
||||
AndroidCameras getFoundCameras();
|
||||
|
||||
int getNumberOfCameras();
|
||||
|
||||
int getCameraOrientation(int cameraId);
|
||||
|
||||
boolean isFrontCamera(int cameraId);
|
||||
|
||||
List<VideoSize> getSupportedPreviewSizes(int cameraId);
|
||||
|
||||
/**
|
||||
* Default: no front; rear=0; default=rear
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class AndroidCameras {
|
||||
Integer front;
|
||||
Integer rear = 0;
|
||||
Integer defaultC = rear;
|
||||
|
||||
boolean hasFrontCamera() { return front != null; }
|
||||
boolean hasRearCamera() { return rear != null; }
|
||||
boolean hasSeveralCameras() { return front != rear && front != null; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Cameras :");
|
||||
if (rear != null) sb.append(" rear=").append(rear);
|
||||
if (front != null) sb.append(" front=").append(front);
|
||||
if (defaultC != null) sb.append(" default=").append(defaultC);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
AndroidCameraConf.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.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.Hacks;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.VideoSize;
|
||||
|
||||
import android.hardware.Camera;
|
||||
|
||||
|
||||
class AndroidCameraConf5 implements AndroidCameraConf {
|
||||
private AndroidCameras foundCameras;
|
||||
public AndroidCameras getFoundCameras() {return foundCameras;}
|
||||
|
||||
public AndroidCameraConf5() {
|
||||
// Defaults
|
||||
foundCameras = new AndroidCameras();
|
||||
|
||||
if (Hacks.isGalaxySOrTab()) {
|
||||
Log.d("Hack Galaxy S : has one or more cameras");
|
||||
if (Hacks.isGalaxySOrTabWithFrontCamera()) {
|
||||
Log.d("Hack Galaxy S : HAS a front camera with id=2");
|
||||
foundCameras.front = 2;
|
||||
} else {
|
||||
Log.d("Hack Galaxy S : NO front camera");
|
||||
}
|
||||
Log.d("Hack Galaxy S : HAS a rear camera with id=1");
|
||||
foundCameras.rear = 1;
|
||||
foundCameras.defaultC = foundCameras.rear;
|
||||
} else if (Hacks.hasTwoCamerasRear0Front1()) {
|
||||
Log.d("Hack SPHD700 has 2 cameras a rear with id=0 and a front with id=1");
|
||||
foundCameras.front = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getNumberOfCameras() {
|
||||
Log.i("Detecting the number of cameras");
|
||||
if (Hacks.hasTwoCamerasRear0Front1() || Hacks.isGalaxySOrTabWithFrontCamera()) {
|
||||
Log.d("Hack: we know this model has 2 cameras");
|
||||
return 2;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getCameraOrientation(int cameraId) {
|
||||
// Use hacks to guess orientation of the camera
|
||||
if (Hacks.isGalaxySOrTab() && isFrontCamera(cameraId)) {
|
||||
Log.d("Hack Galaxy S : front camera mounted landscape");
|
||||
// mounted in landscape for a portrait phone orientation
|
||||
// |^^^^^^^^|
|
||||
// | ____ |
|
||||
// | |____| |
|
||||
// | |
|
||||
// | |
|
||||
// | Phone |
|
||||
// |________|
|
||||
return 180;
|
||||
}
|
||||
return 90;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isFrontCamera(int cameraId) {
|
||||
// Use hacks to guess facing of the camera
|
||||
if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
|
||||
Log.d("Hack Galaxy S : front camera has id=2");
|
||||
return true;
|
||||
} else if (cameraId == 1 && Hacks.hasTwoCamerasRear0Front1()) {
|
||||
Log.d("Hack SPHD700 : front camera has id=1");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<VideoSize> getSupportedPreviewSizes(int cameraId) {
|
||||
if (getNumberOfCameras() >1) {
|
||||
Log.w("Hack: on older devices, using video formats supported by default camera");
|
||||
}
|
||||
Log.i("Opening camera to retrieve supported video sizes");
|
||||
Camera c = Camera.open();
|
||||
List<VideoSize> sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes());
|
||||
c.release();
|
||||
Log.i("Camera opened to retrieve supported video sizes released");
|
||||
return sizes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
AndroidCameraConf9.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.core.video;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.VideoSize;
|
||||
|
||||
import android.hardware.Camera;
|
||||
|
||||
class AndroidCameraConf9 implements AndroidCameraConf {
|
||||
private AndroidCameras foundCameras;
|
||||
private Map<Integer,List<VideoSize>> supportedSizes = new HashMap<Integer, List<VideoSize>>();
|
||||
public AndroidCameras getFoundCameras() {return foundCameras;}
|
||||
|
||||
public AndroidCameraConf9() {
|
||||
foundCameras = new AndroidCameras();
|
||||
|
||||
for (int id=0; id < getNumberOfCameras(); id++) {
|
||||
if (foundCameras.defaultC == null)
|
||||
foundCameras.defaultC = id;
|
||||
|
||||
if (isFrontCamera(id)) {
|
||||
foundCameras.front = id;
|
||||
} else {
|
||||
foundCameras.rear = id;
|
||||
}
|
||||
supportedSizes.put(id, findSupportedVideoSizes(id));
|
||||
}
|
||||
}
|
||||
|
||||
private List<VideoSize> findSupportedVideoSizes(int id) {
|
||||
Log.i("Opening camera ",id," to retrieve supported video sizes");
|
||||
Camera c = Camera.open(id);
|
||||
List<VideoSize> sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes());
|
||||
c.release();
|
||||
Log.i("Camera ",id," opened to retrieve supported video sizes released");
|
||||
return sizes;
|
||||
}
|
||||
|
||||
public int getNumberOfCameras() {
|
||||
return Camera.getNumberOfCameras();
|
||||
}
|
||||
|
||||
public int getCameraOrientation(int cameraId) {
|
||||
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||
Camera.getCameraInfo(cameraId, info);
|
||||
Log.d("Camera info for ",cameraId,": orientation=",info.orientation);
|
||||
return info.orientation;
|
||||
}
|
||||
|
||||
public boolean isFrontCamera(int cameraId) {
|
||||
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||
Camera.getCameraInfo(cameraId, info);
|
||||
return info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? true : false;
|
||||
}
|
||||
|
||||
public List<VideoSize> getSupportedPreviewSizes(int cameraId) {
|
||||
return supportedSizes.get(cameraId);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
AndroidCameraRecordImpl.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.core.video;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.VideoSize;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.AutoFocusCallback;
|
||||
import android.hardware.Camera.ErrorCallback;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
|
||||
public abstract class AndroidCameraRecord implements AutoFocusCallback {
|
||||
|
||||
protected Camera camera;
|
||||
private RecorderParams params;
|
||||
|
||||
private PreviewCallback storedPreviewCallback;
|
||||
private boolean previewStarted;
|
||||
private List <VideoSize> supportedVideoSizes;
|
||||
private Size currentPreviewSize;
|
||||
|
||||
public AndroidCameraRecord(RecorderParams parameters) {
|
||||
this.params = parameters;
|
||||
}
|
||||
|
||||
protected List<Size> getSupportedPreviewSizes(Camera.Parameters parameters) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private int[] findClosestEnclosingFpsRange(int expectedFps, List<int[]> fpsRanges) {
|
||||
Log.d("Searching for closest fps range from ",expectedFps);
|
||||
int measure = Integer.MAX_VALUE;
|
||||
int[] closestRange = fpsRanges.get(0);
|
||||
for (int[] curRange : fpsRanges) {
|
||||
if (curRange[0] > expectedFps || curRange[1] < expectedFps) continue;
|
||||
int curMeasure = Math.abs(curRange[0] - expectedFps)
|
||||
+ Math.abs(curRange[1] - expectedFps);
|
||||
if (curMeasure < measure) {
|
||||
closestRange=curRange;
|
||||
Log.d("a better range has been found: w=",closestRange[0],",h=",closestRange[1]);
|
||||
}
|
||||
}
|
||||
Log.d("The closest fps range is w=",closestRange[0],",h=",closestRange[1]);
|
||||
return closestRange;
|
||||
}
|
||||
|
||||
public synchronized void startPreview() { // FIXME throws exception?
|
||||
if (previewStarted) {
|
||||
Log.w("Already started");
|
||||
throw new RuntimeException("Video recorder already started");
|
||||
// return
|
||||
}
|
||||
|
||||
if (params.surfaceView.getVisibility() != SurfaceView.VISIBLE) {
|
||||
// Illegal state
|
||||
Log.e("Illegal state: video capture surface view is not visible");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Log.d("Trying to open camera with id ", params.cameraId);
|
||||
if (camera != null) {
|
||||
Log.e("Camera is not null, ?already open? : aborting");
|
||||
return;
|
||||
}
|
||||
camera = openCamera(params.cameraId);
|
||||
camera.setErrorCallback(new ErrorCallback() {
|
||||
public void onError(int error, Camera camera) {
|
||||
Log.e("Camera error : ", error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Camera.Parameters parameters=camera.getParameters();
|
||||
if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) {
|
||||
parameters.set("camera-id",params.cameraId);
|
||||
}
|
||||
|
||||
if (supportedVideoSizes == null) {
|
||||
supportedVideoSizes = VideoUtil.createList(getSupportedPreviewSizes(parameters));
|
||||
}
|
||||
|
||||
|
||||
if (params.width >= params.height) {
|
||||
parameters.setPreviewSize(params.width, params.height);
|
||||
} else {
|
||||
// invert height and width
|
||||
parameters.setPreviewSize(params.height, params.width);
|
||||
}
|
||||
// should setParameters and get again to have the real one??
|
||||
currentPreviewSize = parameters.getPreviewSize();
|
||||
|
||||
// Frame rate
|
||||
if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) {
|
||||
// Select the supported fps just faster than the target rate
|
||||
List<Integer> supportedFrameRates=parameters.getSupportedPreviewFrameRates();
|
||||
if (supportedFrameRates != null && supportedFrameRates.size() > 0) {
|
||||
Collections.sort(supportedFrameRates);
|
||||
int selectedRate = -1;
|
||||
for (Integer rate : supportedFrameRates) {
|
||||
selectedRate=rate;
|
||||
if (rate >= params.fps) break;
|
||||
}
|
||||
parameters.setPreviewFrameRate(selectedRate);
|
||||
}
|
||||
} else {
|
||||
List<int[]> supportedRanges = parameters.getSupportedPreviewFpsRange();
|
||||
int[] range=findClosestEnclosingFpsRange((int)(1000*params.fps), supportedRanges);
|
||||
parameters.setPreviewFpsRange(range[0], range[1]);
|
||||
}
|
||||
|
||||
|
||||
onSettingCameraParameters(parameters);
|
||||
camera.setParameters(parameters);
|
||||
|
||||
SurfaceHolder holder = params.surfaceView.getHolder();
|
||||
try {
|
||||
camera.setPreviewDisplay(holder);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Log.e(t,"Exception in Video capture setPreviewDisplay()");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
camera.startPreview();
|
||||
} catch (Throwable e) {
|
||||
Log.e("Error, can't start camera preview. Releasing camera!");
|
||||
camera.release();
|
||||
camera = null;
|
||||
return;
|
||||
}
|
||||
|
||||
previewStarted = true;
|
||||
|
||||
// Activate autofocus
|
||||
if (Camera.Parameters.FOCUS_MODE_AUTO.equals(parameters.getFocusMode())) {
|
||||
OnClickListener svClickListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
Log.i("Auto focus requested");
|
||||
camera.autoFocus(AndroidCameraRecord.this);
|
||||
}
|
||||
};
|
||||
params.surfaceView.setOnClickListener(svClickListener);
|
||||
// svClickListener.onClick(null);
|
||||
} else {
|
||||
params.surfaceView.setOnClickListener(null);
|
||||
}
|
||||
|
||||
// Register callback to get capture buffer
|
||||
lowLevelSetPreviewCallback(camera, storedPreviewCallback);
|
||||
|
||||
|
||||
onPreviewStarted(camera);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected Camera openCamera(int cameraId) {
|
||||
return Camera.open();
|
||||
}
|
||||
|
||||
protected void onSettingCameraParameters(Parameters parameters) {}
|
||||
|
||||
/**
|
||||
* Hook.
|
||||
* @param camera
|
||||
*/
|
||||
public void onPreviewStarted(Camera camera) {}
|
||||
|
||||
public void storePreviewCallBack(PreviewCallback cb) {
|
||||
this.storedPreviewCallback = cb;
|
||||
if (camera == null) {
|
||||
Log.w("Capture camera not ready, storing preview callback");
|
||||
return;
|
||||
}
|
||||
|
||||
lowLevelSetPreviewCallback(camera, cb);
|
||||
}
|
||||
|
||||
|
||||
public void stopPreview() {
|
||||
if (!previewStarted) return;
|
||||
lowLevelSetPreviewCallback(camera, null);
|
||||
camera.stopPreview();
|
||||
camera.release();
|
||||
camera=null;
|
||||
Log.d("Camera released");
|
||||
currentPreviewSize = null;
|
||||
previewStarted = false;
|
||||
}
|
||||
|
||||
|
||||
public void stopCaptureCallback() {
|
||||
if (camera != null) {
|
||||
lowLevelSetPreviewCallback(camera, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb);
|
||||
|
||||
|
||||
|
||||
public static class RecorderParams {
|
||||
public static enum MirrorType {NO, HORIZONTAL, CENTRAL, VERTICAL};
|
||||
|
||||
public float fps;
|
||||
public int height;
|
||||
public int width;
|
||||
|
||||
final long filterDataNativePtr;
|
||||
public int cameraId;
|
||||
public boolean isFrontCamera;
|
||||
public int rotation;
|
||||
public SurfaceView surfaceView;
|
||||
|
||||
public MirrorType mirror = MirrorType.NO;
|
||||
public int phoneOrientation;
|
||||
|
||||
public RecorderParams(long ptr) {
|
||||
filterDataNativePtr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isStarted() {
|
||||
return previewStarted;
|
||||
}
|
||||
|
||||
public List<VideoSize> getSupportedVideoSizes() {
|
||||
return supportedVideoSizes;
|
||||
}
|
||||
|
||||
|
||||
protected int getExpectedBufferLength() {
|
||||
if (currentPreviewSize == null) return -1;
|
||||
|
||||
return currentPreviewSize.width * currentPreviewSize.height * 3 /2;
|
||||
}
|
||||
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
if (success) Log.i("Autofocus success");
|
||||
else Log.i("Autofocus failure");
|
||||
}
|
||||
|
||||
public int getStoredPhoneOrientation() {
|
||||
return params.phoneOrientation;
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
AndroidCameraRecordImpl.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.core.video;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.video.AndroidCameraRecord.RecorderParams.MirrorType;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
|
||||
/**
|
||||
* Record from Android camera.
|
||||
* Android >= 5 (2.0) version.
|
||||
*
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class AndroidCameraRecord5 extends AndroidCameraRecord implements PreviewCallback {
|
||||
|
||||
private long filterCtxPtr;
|
||||
private double timeElapsedBetweenFrames = 0;
|
||||
private long lastFrameTime = 0;
|
||||
private final double expectedTimeBetweenFrames;
|
||||
protected final int rotation;
|
||||
private MirrorType mirror;
|
||||
// private boolean isUsingFrontCamera;
|
||||
|
||||
public AndroidCameraRecord5(RecorderParams parameters) {
|
||||
super(parameters);
|
||||
expectedTimeBetweenFrames = 1d / Math.round(parameters.fps);
|
||||
filterCtxPtr = parameters.filterDataNativePtr;
|
||||
rotation = parameters.rotation;
|
||||
mirror = parameters.mirror;
|
||||
// isUsingFrontCamera = parameters.isFrontCamera;
|
||||
|
||||
storePreviewCallBack(this);
|
||||
}
|
||||
|
||||
|
||||
private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, int mirror);
|
||||
|
||||
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
if (data == null) {
|
||||
Log.e("onPreviewFrame Called with null buffer");
|
||||
return;
|
||||
}
|
||||
if (filterCtxPtr == 0l) {
|
||||
Log.e("onPreviewFrame Called with no filterCtxPtr set");
|
||||
return;
|
||||
}
|
||||
|
||||
int expectedBuffLength = getExpectedBufferLength();
|
||||
if (expectedBuffLength != data.length) {
|
||||
Log.e("onPreviewFrame called with bad buffer length ", data.length,
|
||||
" whereas expected is ", expectedBuffLength, " don't calling putImage");
|
||||
return;
|
||||
}
|
||||
|
||||
long curTime = System.currentTimeMillis();
|
||||
if (lastFrameTime == 0) {
|
||||
lastFrameTime = curTime;
|
||||
putImage(filterCtxPtr, data, rotation, mirror.ordinal());
|
||||
return;
|
||||
}
|
||||
|
||||
double currentTimeElapsed = 0.8 * (curTime - lastFrameTime) / 1000 + 0.2 * timeElapsedBetweenFrames;
|
||||
if (currentTimeElapsed < expectedTimeBetweenFrames) {
|
||||
// Log.d("Clipping frame ", Math.round(1 / currentTimeElapsed), " > ", fps);
|
||||
return;
|
||||
}
|
||||
lastFrameTime = curTime;
|
||||
timeElapsedBetweenFrames = currentTimeElapsed;
|
||||
|
||||
// Log.d("onPreviewFrame: ", Integer.toString(data.length));
|
||||
putImage(filterCtxPtr, data, rotation, mirror.ordinal());
|
||||
}
|
||||
|
||||
protected String selectFocusMode(final List<String> supportedFocusModes) {/*
|
||||
if (isUsingFrontCamera && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
|
||||
return Camera.Parameters.FOCUS_MODE_FIXED;
|
||||
}
|
||||
if (!isUsingFrontCamera && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
|
||||
return Camera.Parameters.FOCUS_MODE_INFINITY;
|
||||
}*/
|
||||
|
||||
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
||||
return Camera.Parameters.FOCUS_MODE_AUTO;
|
||||
}
|
||||
|
||||
return null; // Should not occur?
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSettingCameraParameters(Parameters parameters) {
|
||||
super.onSettingCameraParameters(parameters);
|
||||
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
|
||||
String focusMode = selectFocusMode(supportedFocusModes);
|
||||
if (focusMode != null) {
|
||||
Log.w("Selected focus mode: ", focusMode);
|
||||
parameters.setFocusMode(focusMode);
|
||||
} else {
|
||||
Log.i("No suitable focus mode found in : ", Arrays.toString(supportedFocusModes.toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Size> getSupportedPreviewSizes(Parameters parameters) {
|
||||
return parameters.getSupportedPreviewSizes();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
||||
camera.setPreviewCallback(cb);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
AndroidCameraRecord8Impl.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.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.Log;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.Parameters;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.hardware.Camera.Size;
|
||||
|
||||
/**
|
||||
*
|
||||
* Android >= 8 (2.2) version.
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class AndroidCameraRecord8 extends AndroidCameraRecord5 {
|
||||
|
||||
|
||||
public AndroidCameraRecord8(RecorderParams parameters) {
|
||||
super(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
||||
if (cb != null) {
|
||||
Log.d("Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!");
|
||||
}
|
||||
camera.setPreviewCallbackWithBuffer(cb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewStarted(Camera camera) {
|
||||
super.onPreviewStarted(camera);
|
||||
|
||||
Size s = camera.getParameters().getPreviewSize();
|
||||
int wishedBufferSize = s.height * s.width * 3 / 2;
|
||||
|
||||
camera.addCallbackBuffer(new byte[wishedBufferSize]);
|
||||
camera.addCallbackBuffer(new byte[wishedBufferSize]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
super.onPreviewFrame(data, camera);
|
||||
camera.addCallbackBuffer(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSettingCameraParameters(Parameters parameters) {
|
||||
super.onSettingCameraParameters(parameters);
|
||||
// Only on v8 hardware
|
||||
camera.setDisplayOrientation(rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String selectFocusMode(final List<String> supportedFocusModes) {
|
||||
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_EDOF)) {
|
||||
return Camera.Parameters.FOCUS_MODE_EDOF;
|
||||
} else
|
||||
return super.selectFocusMode(supportedFocusModes);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
AndroidCameraRecord9Impl.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.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.hardware.Camera;
|
||||
|
||||
/**
|
||||
*
|
||||
* Android >= 9 (2.3) version.
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
class AndroidCameraRecord9 extends AndroidCameraRecord8 {
|
||||
|
||||
|
||||
public AndroidCameraRecord9(RecorderParams parameters) {
|
||||
super(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Camera openCamera(int cameraId) {
|
||||
return Camera.open(cameraId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String selectFocusMode(final List<String> supportedFocusModes) {
|
||||
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
|
||||
return Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
|
||||
} else
|
||||
return super.selectFocusMode(supportedFocusModes);
|
||||
}
|
||||
}
|
|
@ -1,362 +0,0 @@
|
|||
/*
|
||||
AndroidCameraRecordManager.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.core.video;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.Log;
|
||||
import org.linphone.core.Version;
|
||||
import org.linphone.core.VideoSize;
|
||||
import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.SurfaceHolder.Callback;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Manage the video capture, only one for all cameras.
|
||||
*
|
||||
* @author Guillaume Beraudo
|
||||
*
|
||||
*/
|
||||
public class AndroidCameraRecordManager {
|
||||
private static AndroidCameraRecordManager instance;
|
||||
private OrientationEventListener orientationEventListener;
|
||||
private OnCapturingStateChangedListener capturingStateChangedListener;
|
||||
|
||||
/**
|
||||
* @return instance
|
||||
*/
|
||||
public static final synchronized AndroidCameraRecordManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AndroidCameraRecordManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private AndroidCameraRecord.RecorderParams parameters;
|
||||
private final AndroidCameraConf cc;
|
||||
private SurfaceView surfaceView;
|
||||
private boolean muted;
|
||||
private int cameraId;
|
||||
|
||||
private AndroidCameraRecord recorder;
|
||||
private int mAlwaysChangingPhoneOrientation=0;
|
||||
|
||||
|
||||
// singleton
|
||||
private AndroidCameraRecordManager() {
|
||||
if (!Version.isVideoCapable()) { // imply sdk>=5
|
||||
throw new RuntimeException("AndroidCameraRecordManager: hardware is not video capable");
|
||||
}
|
||||
cc = Version.sdkAboveOrEqual(9) ? new AndroidCameraConf9() : new AndroidCameraConf5();
|
||||
Log.i("=== Detected " + cc.getFoundCameras()+ " ===");
|
||||
cameraId = cc.getFoundCameras().defaultC;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean hasSeveralCameras() {
|
||||
return cc.getFoundCameras().hasSeveralCameras();
|
||||
}
|
||||
public boolean hasFrontCamera() {
|
||||
return cc.getFoundCameras().front != null;
|
||||
}
|
||||
|
||||
|
||||
public void setUseFrontCamera(boolean value) {
|
||||
if (!hasFrontCamera()) {
|
||||
Log.e("setUseFrontCamera(true) while no front camera detected on device: using rear");
|
||||
value = false;
|
||||
}
|
||||
if (cc.isFrontCamera(cameraId) == value) return; // already OK
|
||||
toggleUseFrontCamera();
|
||||
}
|
||||
|
||||
public boolean isUseFrontCamera() {return cc.isFrontCamera(cameraId);}
|
||||
public boolean toggleUseFrontCamera() {
|
||||
boolean previousUseFront = cc.isFrontCamera(cameraId);
|
||||
|
||||
cameraId = previousUseFront ? cc.getFoundCameras().rear : cc.getFoundCameras().front;
|
||||
|
||||
if (parameters != null) {
|
||||
parameters.cameraId = cameraId;
|
||||
parameters.isFrontCamera = !previousUseFront;
|
||||
if (isRecording()) {
|
||||
stopVideoRecording();
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
}
|
||||
|
||||
return !previousUseFront;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) {
|
||||
if (recorder != null) {
|
||||
Log.w("Recorder should not be running");
|
||||
stopVideoRecording();
|
||||
}
|
||||
RecorderParams p = new RecorderParams(filterDataPtr);
|
||||
p.fps = fps;
|
||||
p.width = width;
|
||||
p.height = height;
|
||||
p.cameraId = cameraId;
|
||||
p.isFrontCamera = isUseFrontCamera();
|
||||
parameters = p;
|
||||
|
||||
// Mirror the sent frames in order to make them readable
|
||||
// (otherwise it is mirrored and thus unreadable)
|
||||
if (p.isFrontCamera) {
|
||||
if (!isCameraMountedPortrait()) {
|
||||
// Code for Nexus S
|
||||
if (isFrameToBeShownPortrait())
|
||||
p.mirror = RecorderParams.MirrorType.CENTRAL;
|
||||
} else {
|
||||
// Code for Galaxy S like: camera mounted landscape when phone hold portrait
|
||||
p.mirror = RecorderParams.MirrorType.HORIZONTAL;
|
||||
}
|
||||
}
|
||||
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
|
||||
|
||||
public final void setSurfaceView(final SurfaceView sv) {
|
||||
SurfaceHolder holder = sv.getHolder();
|
||||
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
|
||||
holder.addCallback(new Callback() {
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
surfaceView = null;
|
||||
Log.d("Video capture surface destroyed");
|
||||
stopVideoRecording();
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
surfaceView = sv;
|
||||
Log.d("Video capture surface created");
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width,
|
||||
int height) {
|
||||
Log.d("Video capture surface changed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param muteState
|
||||
* @return true if mute state changed
|
||||
*/
|
||||
public boolean setMuted(boolean muteState) {
|
||||
if (muteState == muted) return false;
|
||||
muted = muteState;
|
||||
if (muted) {
|
||||
stopVideoRecording();
|
||||
} else {
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean toggleMute() {
|
||||
setMuted(!muted);
|
||||
return muted;
|
||||
}
|
||||
public boolean isMuted() {
|
||||
return muted;
|
||||
}
|
||||
|
||||
public void tryResumingVideoRecording() {
|
||||
if (isRecording()) return;
|
||||
tryToStartVideoRecording();
|
||||
}
|
||||
|
||||
private synchronized void tryToStartVideoRecording() {
|
||||
if (orientationEventListener == null) {
|
||||
throw new RuntimeException("startOrientationSensor was not called");
|
||||
}
|
||||
|
||||
if (muted || surfaceView == null || parameters == null) return;
|
||||
|
||||
if (recorder != null) {
|
||||
Log.e("Recorder already present");
|
||||
stopVideoRecording();
|
||||
}
|
||||
|
||||
parameters.rotation = bufferRotationToCompensateCameraAndPhoneOrientations();
|
||||
|
||||
parameters.surfaceView = surfaceView;
|
||||
if (Version.sdkAboveOrEqual(9)) {
|
||||
recorder = new AndroidCameraRecord9(parameters);
|
||||
} else if (Version.sdkAboveOrEqual(8)) {
|
||||
recorder = new AndroidCameraRecord8(parameters);
|
||||
} else if (Version.sdkAboveOrEqual(5)) {
|
||||
recorder = new AndroidCameraRecord5(parameters);
|
||||
} else {
|
||||
throw new RuntimeException("SDK version unsupported " + Version.sdk());
|
||||
}
|
||||
|
||||
recorder.startPreview();
|
||||
|
||||
if (capturingStateChangedListener != null) {
|
||||
capturingStateChangedListener.captureStarted();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stopVideoRecording() {
|
||||
if (recorder != null) {
|
||||
recorder.stopPreview();
|
||||
recorder = null;
|
||||
if (capturingStateChangedListener != null) {
|
||||
capturingStateChangedListener.captureStopped();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<VideoSize> supportedVideoSizes() {
|
||||
Log.d("Using supportedVideoSizes of camera ",cameraId);
|
||||
return cc.getSupportedPreviewSizes(cameraId);
|
||||
}
|
||||
|
||||
|
||||
public boolean isRecording() {
|
||||
if (recorder != null) {
|
||||
return recorder.isStarted();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void invalidateParameters() {
|
||||
stopVideoRecording();
|
||||
parameters = null;
|
||||
}
|
||||
|
||||
/** Depends on currently selected camera, camera mounted portrait/landscape, current phone orientation */
|
||||
public boolean isFrameToBeShownPortrait() {
|
||||
final int rotation = bufferRotationToCompensateCameraAndPhoneOrientations();
|
||||
|
||||
boolean isPortrait;
|
||||
if (isCameraMountedPortrait()) {
|
||||
// Nexus S
|
||||
isPortrait = (rotation % 180) == 0;
|
||||
} else {
|
||||
isPortrait = (rotation % 180) == 90;
|
||||
}
|
||||
|
||||
Log.d("The frame to be shown and sent to remote is ", isPortrait? "portrait":"landscape"," orientation.");
|
||||
return isPortrait;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean isCameraMountedPortrait() {
|
||||
return (cc.getCameraOrientation(cameraId) % 180) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private int bufferRotationToCompensateCameraAndPhoneOrientations() {
|
||||
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);
|
||||
int frontCameraCorrection = 0;
|
||||
if (cc.isFrontCamera(cameraId)) {
|
||||
frontCameraCorrection=180; // hack that "just works" on Galaxy S and Nexus S.
|
||||
// See also magic with mirrors in setParametersFromFilter
|
||||
}
|
||||
final int rotation = (cameraOrientation + phoneOrientation + frontCameraCorrection) % 360;
|
||||
Log.d("Capture video buffer of cameraId=",cameraId,
|
||||
" will need a rotation of ",rotation,
|
||||
" degrees: camera_orientation=",cameraOrientation,
|
||||
" phone_orientation=", phoneOrientation);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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("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(LinphoneCore lc) {
|
||||
final boolean currentlyPortrait = lc.getPreferredVideoSize().isPortrait();
|
||||
final boolean shouldBePortrait = isFrameToBeShownPortrait();
|
||||
return currentlyPortrait ^ shouldBePortrait;
|
||||
}
|
||||
|
||||
public void setOnCapturingStateChanged(OnCapturingStateChangedListener listener) {
|
||||
this.capturingStateChangedListener=listener;
|
||||
}
|
||||
|
||||
public static interface OnCapturingStateChangedListener {
|
||||
void captureStarted();
|
||||
void captureStopped();
|
||||
}
|
||||
|
||||
|
||||
}
|
9
submodules/externals/build/ffmpeg/Android.mk
vendored
9
submodules/externals/build/ffmpeg/Android.mk
vendored
|
@ -1,5 +1,4 @@
|
|||
include $(root-dir)/submodules/externals/build/ffmpeg/Android_libavutil.mk
|
||||
include $(root-dir)/submodules/externals/build/ffmpeg/Android_libavcodec.mk
|
||||
include $(root-dir)/submodules/externals/build/ffmpeg/Android_libswscale.mk
|
||||
include $(root-dir)/submodules/externals/build/ffmpeg/Android_libavcore.mk
|
||||
|
||||
include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android_libavutil.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android_libavcodec.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android_libswscale.mk
|
||||
include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android_libavcore.mk
|
||||
|
|
3
submodules/externals/build/libvpx/Android.mk
vendored
3
submodules/externals/build/libvpx/Android.mk
vendored
|
@ -213,6 +213,8 @@ ASM_FILES += \
|
|||
vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.$(ASM) \
|
||||
vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.$(ASM) \
|
||||
|
||||
LOCAL_SRC_FILES += vpx_ports/arm_cpudetect.c
|
||||
|
||||
LOCAL_SRC_FILES += $(ASM_FILES)
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
|
@ -231,4 +233,3 @@ LOCAL_C_INCLUDES += \
|
|||
$(LOCAL_PATH)/vpx_codec
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#define CONFIG_MD5 1
|
||||
#define CONFIG_DEQUANT_TOKENS 0
|
||||
#define CONFIG_DC_RECON 0
|
||||
#define CONFIG_RUNTIME_CPU_DETECT 0
|
||||
#define CONFIG_RUNTIME_CPU_DETECT 1
|
||||
#define CONFIG_POSTPROC 0
|
||||
#define CONFIG_MULTITHREAD 1
|
||||
#define CONFIG_INTERNAL_STATS 0
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 09bf68a5f14d756872bb28a9a860c853bf9ad06a
|
||||
Subproject commit ef7dc050f57967cb63a0b2e6a8d294ca504816b8
|
Loading…
Reference in a new issue