diff --git a/.classpath b/.classpath index c16c4b45f..73e3fe0d3 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + diff --git a/jni/Android.mk b/jni/Android.mk index 404bb77b5..10dfa2522 100755 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -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 - - - diff --git a/jni/Application.mk b/jni/Application.mk index ce9a953d5..9eb68e381 100644 --- a/jni/Application.mk +++ b/jni/Application.mk @@ -3,7 +3,7 @@ APP_MODULES :=libspeex libgsm libortp libosip2 libeXosip2 libmediastreamer2 APP_STL := stlport_static ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) -APP_MODULES +=libmsilbc +APP_MODULES +=libmsilbc endif ifeq ($(LINPHONE_VIDEO),1) @@ -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 diff --git a/res/layout-land/videocall.xml b/res/layout-land/videocall.xml index cf2f4ec7b..038b827be 100644 --- a/res/layout-land/videocall.xml +++ b/res/layout-land/videocall.xml @@ -4,7 +4,7 @@ android:id="@+id/video_frame" android:orientation="vertical" android:layout_height="fill_parent" android:layout_width="fill_parent"> - + diff --git a/res/layout/videocall.xml b/res/layout/videocall.xml index 377b07f04..fd47b054a 100644 --- a/res/layout/videocall.xml +++ b/res/layout/videocall.xml @@ -4,7 +4,7 @@ android:id="@+id/video_frame" android:layout_height="fill_parent" android:layout_width="fill_parent"> - + \ No newline at end of file diff --git a/res/layout/videotest.xml b/res/layout/videotest.xml deleted file mode 100644 index a1a269a06..000000000 --- a/res/layout/videotest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/res/raw/linphonerc b/res/raw/linphonerc index 65e507487..b490f57df 100644 --- a/res/raw/linphonerc +++ b/res/raw/linphonerc @@ -44,5 +44,5 @@ ng_floorgain=0.01 [video] -size=qvga-portrait +size=vga diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java index f5df85e87..686a4314a 100644 --- a/src/org/linphone/BandwidthManager.java +++ b/src/org/linphone/BandwidthManager.java @@ -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 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 0) { @@ -367,6 +390,22 @@ public class LinphoneActivity extends TabActivity { Log.i("Proximity sensor detected, registering"); } } + + 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) { diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index b99fd67ed..83d2acba0 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -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); @@ -273,13 +273,20 @@ public final class LinphoneManager implements LinphoneCoreListener { return; } } - 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,7 +301,12 @@ 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()) { mLc.getCurrentCall().enableCamera(!send); @@ -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) @@ -844,6 +842,10 @@ public final class LinphoneManager implements LinphoneCoreListener { public boolean isVideoEnabled() { 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(); diff --git a/src/org/linphone/LinphonePreferencesActivity.java b/src/org/linphone/LinphonePreferencesActivity.java index 92dc31205..8ff041c5e 100644 --- a/src/org/linphone/LinphonePreferencesActivity.java +++ b/src/org/linphone/LinphonePreferencesActivity.java @@ -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)) { diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java index 4def606b9..a0effd66e 100644 --- a/src/org/linphone/LinphoneService.java +++ b/src/org/linphone/LinphoneService.java @@ -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; diff --git a/src/org/linphone/SoftVolumeActivity.java b/src/org/linphone/SoftVolumeActivity.java index 4975bf880..8f8d6dddb 100644 --- a/src/org/linphone/SoftVolumeActivity.java +++ b/src/org/linphone/SoftVolumeActivity.java @@ -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; diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java index c57a4216e..2b7e1a847 100644 --- a/src/org/linphone/VideoCallActivity.java +++ b/src/org/linphone/VideoCallActivity.java @@ -20,89 +20,96 @@ 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) { + public void onCreate(Bundle savedInstanceState) { launched = true; Log.d("onCreate VideoCallActivity"); super.onCreate(savedInstanceState); 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); + + 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 (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false); + 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() { - } - } diff --git a/src/org/linphone/core/AndroidVideoWindowImpl.java b/src/org/linphone/core/AndroidVideoWindowImpl.java deleted file mode 100644 index 4fc213f5f..000000000 --- a/src/org/linphone/core/AndroidVideoWindowImpl.java +++ /dev/null @@ -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) { - - } - } -} - - diff --git a/src/org/linphone/core/Hacks.java b/src/org/linphone/core/Hacks.java deleted file mode 100644 index ceca9ee80..000000000 --- a/src/org/linphone/core/Hacks.java +++ /dev/null @@ -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) /* 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; - } - -} diff --git a/src/org/linphone/core/LinphoneCallImpl.java b/src/org/linphone/core/LinphoneCallImpl.java index 55d3baedf..db8b3f733 100644 --- a/src/org/linphone/core/LinphoneCallImpl.java +++ b/src/org/linphone/core/LinphoneCallImpl.java @@ -20,7 +20,7 @@ package org.linphone.core; class LinphoneCallImpl implements LinphoneCall { - + protected final long nativePtr; boolean ownPtr = false; native private void ref(long ownPtr); @@ -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); @@ -48,7 +49,7 @@ class LinphoneCallImpl implements LinphoneCall { ref(nativePtr); } protected void finalize() throws Throwable { - unref(nativePtr); + unref(nativePtr); } public LinphoneCallLog getCallLog() { long lNativePtr = getCallLog(nativePtr); @@ -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; + } } diff --git a/src/org/linphone/core/LinphoneCoreImpl.java b/src/org/linphone/core/LinphoneCoreImpl.java index 23a8d3914..01517762d 100644 --- a/src/org/linphone/core/LinphoneCoreImpl.java +++ b/src/org/linphone/core/LinphoneCoreImpl.java @@ -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 + + } } diff --git a/src/org/linphone/core/Version.java b/src/org/linphone/core/Version.java index 53ae2e05f..edbb25e8e 100644 --- a/src/org/linphone/core/Version.java +++ b/src/org/linphone/core/Version.java @@ -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; /** diff --git a/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java b/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java deleted file mode 100644 index 4772c7a5b..000000000 --- a/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java +++ /dev/null @@ -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); - } - -} diff --git a/src/org/linphone/core/tutorials/TestVideoActivity.java b/src/org/linphone/core/tutorials/TestVideoActivity.java deleted file mode 100644 index 7523cb0ff..000000000 --- a/src/org/linphone/core/tutorials/TestVideoActivity.java +++ /dev/null @@ -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 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 createSizesToTest() { - Stack stack = new Stack(); - - 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(); - } -} diff --git a/src/org/linphone/core/video/AndroidCameraConf.java b/src/org/linphone/core/video/AndroidCameraConf.java deleted file mode 100644 index 874a6d2da..000000000 --- a/src/org/linphone/core/video/AndroidCameraConf.java +++ /dev/null @@ -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 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(); - } - } -} \ No newline at end of file diff --git a/src/org/linphone/core/video/AndroidCameraConf5.java b/src/org/linphone/core/video/AndroidCameraConf5.java deleted file mode 100644 index 06c266d7a..000000000 --- a/src/org/linphone/core/video/AndroidCameraConf5.java +++ /dev/null @@ -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 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 sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes()); - c.release(); - Log.i("Camera opened to retrieve supported video sizes released"); - return sizes; - } - - - -} diff --git a/src/org/linphone/core/video/AndroidCameraConf9.java b/src/org/linphone/core/video/AndroidCameraConf9.java deleted file mode 100644 index 02e909895..000000000 --- a/src/org/linphone/core/video/AndroidCameraConf9.java +++ /dev/null @@ -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> supportedSizes = new HashMap>(); - 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 findSupportedVideoSizes(int id) { - Log.i("Opening camera ",id," to retrieve supported video sizes"); - Camera c = Camera.open(id); - List 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 getSupportedPreviewSizes(int cameraId) { - return supportedSizes.get(cameraId); - } - -} diff --git a/src/org/linphone/core/video/AndroidCameraRecord.java b/src/org/linphone/core/video/AndroidCameraRecord.java deleted file mode 100644 index 9d4dd29fe..000000000 --- a/src/org/linphone/core/video/AndroidCameraRecord.java +++ /dev/null @@ -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 supportedVideoSizes; - private Size currentPreviewSize; - - public AndroidCameraRecord(RecorderParams parameters) { - this.params = parameters; - } - - protected List getSupportedPreviewSizes(Camera.Parameters parameters) { - return Collections.emptyList(); - } - - private int[] findClosestEnclosingFpsRange(int expectedFps, List 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 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 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 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; - } -} diff --git a/src/org/linphone/core/video/AndroidCameraRecord5.java b/src/org/linphone/core/video/AndroidCameraRecord5.java deleted file mode 100644 index 45f94cd29..000000000 --- a/src/org/linphone/core/video/AndroidCameraRecord5.java +++ /dev/null @@ -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 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 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 getSupportedPreviewSizes(Parameters parameters) { - return parameters.getSupportedPreviewSizes(); - } - - @Override - protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) { - camera.setPreviewCallback(cb); - } - - -} diff --git a/src/org/linphone/core/video/AndroidCameraRecord8.java b/src/org/linphone/core/video/AndroidCameraRecord8.java deleted file mode 100644 index c5fda6774..000000000 --- a/src/org/linphone/core/video/AndroidCameraRecord8.java +++ /dev/null @@ -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 supportedFocusModes) { - if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_EDOF)) { - return Camera.Parameters.FOCUS_MODE_EDOF; - } else - return super.selectFocusMode(supportedFocusModes); - } -} diff --git a/src/org/linphone/core/video/AndroidCameraRecord9.java b/src/org/linphone/core/video/AndroidCameraRecord9.java deleted file mode 100644 index f0023ef57..000000000 --- a/src/org/linphone/core/video/AndroidCameraRecord9.java +++ /dev/null @@ -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 supportedFocusModes) { - if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - return Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO; - } else - return super.selectFocusMode(supportedFocusModes); - } -} diff --git a/src/org/linphone/core/video/AndroidCameraRecordManager.java b/src/org/linphone/core/video/AndroidCameraRecordManager.java deleted file mode 100644 index 7e8e8b613..000000000 --- a/src/org/linphone/core/video/AndroidCameraRecordManager.java +++ /dev/null @@ -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 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(); - } - - -} diff --git a/submodules/externals/build/ffmpeg/Android.mk b/submodules/externals/build/ffmpeg/Android.mk index d4c5f3df5..a4b3f1c41 100755 --- a/submodules/externals/build/ffmpeg/Android.mk +++ b/submodules/externals/build/ffmpeg/Android.mk @@ -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 diff --git a/submodules/externals/build/libvpx/Android.mk b/submodules/externals/build/libvpx/Android.mk index eb00e45bf..37b208d29 100755 --- a/submodules/externals/build/libvpx/Android.mk +++ b/submodules/externals/build/libvpx/Android.mk @@ -195,7 +195,7 @@ ASM_FILES += \ vp8/decoder/arm/armv6/dequant_dc_idct_v6.$(ASM) \ vp8/decoder/arm/armv6/dequant_idct_v6.$(ASM) \ vp8/decoder/arm/armv6/dequantize_v6.$(ASM) - + # vpx_mem subfolder [vpx_mem.mk] LOCAL_SRC_FILES += vpx_mem/vpx_mem.c @@ -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) - diff --git a/submodules/externals/build/libvpx/vpx_config.h b/submodules/externals/build/libvpx/vpx_config.h index 88e0aec32..8cecad7e6 100644 --- a/submodules/externals/build/libvpx/vpx_config.h +++ b/submodules/externals/build/libvpx/vpx_config.h @@ -1,7 +1,7 @@ /* This file automatically generated by configure. Do not edit! */ #ifndef VPX_CONFIG_H #define VPX_CONFIG_H -#define RESTRICT +#define RESTRICT #define ARCH_ARM 1 #define ARCH_MIPS 0 #define ARCH_X86 0 @@ -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 diff --git a/submodules/linphone b/submodules/linphone index 09bf68a5f..ef7dc050f 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 09bf68a5f14d756872bb28a9a860c853bf9ad06a +Subproject commit ef7dc050f57967cb63a0b2e6a8d294ca504816b8