Chromium Code Reviews| Index: webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java |
| diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java |
| index a1ea8a457d2ed2e1589e56e1828ea23e6c5a4bfe..6a64e53b6900cc8175bb8e69426e58283bc7e536 100644 |
| --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java |
| +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java |
| @@ -29,14 +29,26 @@ import android.view.Window; |
| import android.view.WindowManager.LayoutParams; |
| import android.widget.Toast; |
| +import java.io.IOException; |
| +import java.lang.RuntimeException; |
| +import java.util.ArrayList; |
| +import java.util.List; |
| + |
| +import org.webrtc.Camera1Enumerator; |
| import org.webrtc.Camera2Enumerator; |
| +import org.webrtc.CameraEnumerator; |
| import org.webrtc.EglBase; |
| +import org.webrtc.FileVideoCapturer; |
| +import org.webrtc.VideoFileRenderer; |
| import org.webrtc.IceCandidate; |
| +import org.webrtc.Logging; |
| import org.webrtc.PeerConnectionFactory; |
| import org.webrtc.RendererCommon.ScalingType; |
| import org.webrtc.SessionDescription; |
| import org.webrtc.StatsReport; |
| import org.webrtc.SurfaceViewRenderer; |
| +import org.webrtc.VideoCapturer; |
| +import org.webrtc.VideoRenderer; |
| /** |
| * Activity for peer connection call setup, call waiting |
| @@ -96,6 +108,16 @@ public class CallActivity extends Activity |
| "org.appspot.apprtc.CMDLINE"; |
| public static final String EXTRA_RUNTIME = |
| "org.appspot.apprtc.RUNTIME"; |
| + public static final String EXTRA_VIDEO_FILE_AS_CAMERA = |
| + "org.appspot.apprtc.VIDEO_FILE_AS_CAMERA"; |
|
sakal
2016/10/05 13:28:41
Please correct the indentation on this and followi
mandermo
2016/10/07 11:33:41
Done.
|
| + public static final String EXTRA_SAVE_REMOTE_VIDEO_TO_FILE = |
| + "org.appspot.apprtc.SAVE_REMOTE_VIDEO_TO_FILE"; |
| + public static final String EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH = |
| + "org.appspot.apprtc.SAVE_REMOTE_VIDEO_TO_FILE_WIDTH"; |
| + public static final String EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT = |
| + "org.appspot.apprtc.SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT"; |
| + public static final String EXTRA_USE_VALUES_FROM_INTENT = |
| + "org.appspot.apprtc.USE_VALUES_FROM_INTENT"; |
| private static final String TAG = "CallRTCClient"; |
| // List of mandatory application permissions. |
| @@ -128,7 +150,9 @@ public class CallActivity extends Activity |
| private AppRTCAudioManager audioManager = null; |
| private EglBase rootEglBase; |
| private SurfaceViewRenderer localRender; |
| - private SurfaceViewRenderer remoteRender; |
| + private SurfaceViewRenderer remoteRenderScreen; |
| + private VideoFileRenderer videoFileRenderer; |
| + private List<VideoRenderer.Callbacks> remoteRenders = new ArrayList<VideoRenderer.Callbacks>(); |
|
sakal
2016/10/05 13:28:41
final
mandermo
2016/10/07 11:33:40
Made remoteRenders final and changed name to remot
|
| private PercentFrameLayout localRenderLayout; |
| private PercentFrameLayout remoteRenderLayout; |
| private ScalingType scalingType; |
| @@ -176,7 +200,7 @@ public class CallActivity extends Activity |
| // Create UI controls. |
| localRender = (SurfaceViewRenderer) findViewById(R.id.local_video_view); |
| - remoteRender = (SurfaceViewRenderer) findViewById(R.id.remote_video_view); |
| + remoteRenderScreen = (SurfaceViewRenderer) findViewById(R.id.remote_video_view); |
| localRenderLayout = (PercentFrameLayout) findViewById(R.id.local_video_layout); |
| remoteRenderLayout = (PercentFrameLayout) findViewById(R.id.remote_video_layout); |
| callFragment = new CallFragment(); |
| @@ -191,12 +215,31 @@ public class CallActivity extends Activity |
| }; |
| localRender.setOnClickListener(listener); |
| - remoteRender.setOnClickListener(listener); |
| + remoteRenderScreen.setOnClickListener(listener); |
| + remoteRenders.add(remoteRenderScreen); |
| + |
| + final Intent intent = getIntent(); |
| // Create video renderers. |
| rootEglBase = EglBase.create(); |
| localRender.init(rootEglBase.getEglBaseContext(), null); |
| - remoteRender.init(rootEglBase.getEglBaseContext(), null); |
| + String saveRemoteVideoToFile = intent.getStringExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE); |
| + |
| + // When saveRemoveToFile is set we save the video from the remote to a file. |
|
sakal
2016/10/05 13:28:41
saveRemoveToFile -> saveRemoteVideoToFile
mandermo
2016/10/07 11:33:41
Done.
|
| + if (saveRemoteVideoToFile != null) { |
| + int videoOutWidth = intent.getIntExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH, 0); |
| + int videoOutHeight = intent.getIntExtra(EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT, 0); |
| + try { |
| + videoFileRenderer = new VideoFileRenderer( |
| + saveRemoteVideoToFile, videoOutWidth, videoOutHeight, |
| + rootEglBase.getEglBaseContext()); |
| + remoteRenders.add(videoFileRenderer); |
| + } catch (IOException e) { |
| + throw new RuntimeException("Failed to open video file for output: " + saveRemoteVideoToFile, e); |
| + } |
| + } |
| + remoteRenderScreen.init(rootEglBase.getEglBaseContext(), null); |
| + |
| localRender.setZOrderMediaOverlay(true); |
| updateVideoView(); |
| @@ -211,7 +254,6 @@ public class CallActivity extends Activity |
| } |
| // Get Intent parameters. |
|
sakal
2016/10/05 13:28:41
nit: move comment
mandermo
2016/10/07 11:33:41
Moved to before String roomId = intent.getStringEx
|
| - final Intent intent = getIntent(); |
| Uri roomUri = intent.getData(); |
| if (roomUri == null) { |
| logAndToast(getString(R.string.missing_url)); |
| @@ -221,6 +263,7 @@ public class CallActivity extends Activity |
| return; |
| } |
| String roomId = intent.getStringExtra(EXTRA_ROOMID); |
| + Log.d(TAG, "Room ID: " + roomId); |
| if (roomId == null || roomId.length() == 0) { |
| logAndToast(getString(R.string.missing_url)); |
| Log.e(TAG, "Incorrect room ID in intent!"); |
| @@ -232,21 +275,16 @@ public class CallActivity extends Activity |
| boolean loopback = intent.getBooleanExtra(EXTRA_LOOPBACK, false); |
| boolean tracing = intent.getBooleanExtra(EXTRA_TRACING, false); |
| - boolean useCamera2 = Camera2Enumerator.isSupported() |
| - && intent.getBooleanExtra(EXTRA_CAMERA2, true); |
| - |
| peerConnectionParameters = new PeerConnectionParameters( |
| intent.getBooleanExtra(EXTRA_VIDEO_CALL, true), |
| loopback, |
| tracing, |
| - useCamera2, |
| intent.getIntExtra(EXTRA_VIDEO_WIDTH, 0), |
| intent.getIntExtra(EXTRA_VIDEO_HEIGHT, 0), |
| intent.getIntExtra(EXTRA_VIDEO_FPS, 0), |
| intent.getIntExtra(EXTRA_VIDEO_BITRATE, 0), |
| intent.getStringExtra(EXTRA_VIDEOCODEC), |
| intent.getBooleanExtra(EXTRA_HWCODEC_ENABLED, true), |
| - intent.getBooleanExtra(EXTRA_CAPTURETOTEXTURE_ENABLED, false), |
| intent.getIntExtra(EXTRA_AUDIO_BITRATE, 0), |
| intent.getStringExtra(EXTRA_AUDIOCODEC), |
| intent.getBooleanExtra(EXTRA_NOAUDIOPROCESSING_ENABLED, false), |
| @@ -256,9 +294,10 @@ public class CallActivity extends Activity |
| intent.getBooleanExtra(EXTRA_DISABLE_BUILT_IN_AGC, false), |
| intent.getBooleanExtra(EXTRA_DISABLE_BUILT_IN_NS, false), |
| intent.getBooleanExtra(EXTRA_ENABLE_LEVEL_CONTROL, false)); |
| - commandLineRun = intent.getBooleanExtra(EXTRA_CMDLINE, false); |
| runTimeMs = intent.getIntExtra(EXTRA_RUNTIME, 0); |
| + Log.d(TAG, "VIDEO_FILE: '" + intent.getStringExtra(EXTRA_VIDEO_FILE_AS_CAMERA) + "'"); |
| + |
| // Create connection client. Use DirectRTCClient if room name is an IP otherwise use the |
| // standard WebSocketRTCClient. |
| if (loopback || !DirectRTCClient.IP_PATTERN.matcher(roomId).matches()) { |
| @@ -305,6 +344,47 @@ public class CallActivity extends Activity |
| CallActivity.this, peerConnectionParameters, CallActivity.this); |
| } |
| + private boolean useCamera2() { |
| + return Camera2Enumerator.isSupported() |
| + && getIntent().getBooleanExtra(EXTRA_CAMERA2, true); |
| + } |
| + |
| + private boolean captureToTexture() { |
| + return getIntent().getBooleanExtra(EXTRA_CAPTURETOTEXTURE_ENABLED, false); |
| + } |
| + |
| + private VideoCapturer createCapturer(CameraEnumerator enumerator) { |
|
sakal
2016/10/05 13:28:41
nit: rename to createCameraCapturer
mandermo
2016/10/07 11:33:41
Done. Change name of createVideoCapturer in PeerCo
|
| + final String[] deviceNames = enumerator.getDeviceNames(); |
| + |
| + // First, try to find front facing camera |
| + Logging.d(TAG, "Looking for front facing cameras."); |
| + for (String deviceName : deviceNames) { |
| + if (enumerator.isFrontFacing(deviceName)) { |
| + Logging.d(TAG, "Creating front facing camera capturer."); |
| + VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null); |
| + |
| + if (videoCapturer != null) { |
| + return videoCapturer; |
| + } |
| + } |
| + } |
| + |
| + // Front facing camera not found, try something else |
| + Logging.d(TAG, "Looking for other cameras."); |
| + for (String deviceName : deviceNames) { |
| + if (!enumerator.isFrontFacing(deviceName)) { |
| + Logging.d(TAG, "Creating other camera capturer."); |
| + VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null); |
| + |
| + if (videoCapturer != null) { |
| + return videoCapturer; |
| + } |
| + } |
| + } |
| + |
| + return null; |
| + } |
| + |
| // Activity interfaces |
| @Override |
| public void onPause() { |
| @@ -393,8 +473,8 @@ public class CallActivity extends Activity |
| private void updateVideoView() { |
| remoteRenderLayout.setPosition(REMOTE_X, REMOTE_Y, REMOTE_WIDTH, REMOTE_HEIGHT); |
| - remoteRender.setScalingType(scalingType); |
| - remoteRender.setMirror(false); |
| + remoteRenderScreen.setScalingType(scalingType); |
| + remoteRenderScreen.setMirror(false); |
| if (iceConnected) { |
| localRenderLayout.setPosition( |
| @@ -408,7 +488,7 @@ public class CallActivity extends Activity |
| localRender.setMirror(true); |
| localRender.requestLayout(); |
| - remoteRender.requestLayout(); |
| + remoteRenderScreen.requestLayout(); |
| } |
| private void startCall() { |
| @@ -474,9 +554,13 @@ public class CallActivity extends Activity |
| localRender.release(); |
| localRender = null; |
| } |
| - if (remoteRender != null) { |
| - remoteRender.release(); |
| - remoteRender = null; |
| + if (videoFileRenderer != null) { |
| + videoFileRenderer.release(); |
| + videoFileRenderer = null; |
| + } |
| + if (remoteRenderScreen != null) { |
| + remoteRenderScreen.release(); |
| + remoteRenderScreen = null; |
| } |
| if (audioManager != null) { |
| audioManager.close(); |
| @@ -531,6 +615,36 @@ public class CallActivity extends Activity |
| }); |
| } |
| + private VideoCapturer createVideoCapturer() { |
| + VideoCapturer videoCapturer = null; |
| + String videoFileAsCamera = getIntent().getStringExtra(EXTRA_VIDEO_FILE_AS_CAMERA); |
| + if (videoFileAsCamera != null) { |
| + videoCapturer = FileVideoCapturer.create( |
| + videoFileAsCamera); |
| + |
| + if (videoCapturer == null) { |
| + reportError("Failed to open video file for emulated camera"); |
| + return null; |
| + } |
| + } else if (useCamera2()) { |
| + if (!captureToTexture()) { |
| + reportError(getString(R.string.camera2_texture_only_error)); |
| + return null; |
| + } |
| + |
| + Logging.d(TAG, "Creating capturer using camera2 API."); |
| + videoCapturer = createCapturer(new Camera2Enumerator(this)); |
| + } else { |
| + Logging.d(TAG, "Creating capturer using camera1 API."); |
| + videoCapturer = createCapturer(new Camera1Enumerator(captureToTexture())); |
| + } |
| + if (videoCapturer == null) { |
| + reportError("Failed to open camera"); |
| + return null; |
| + } |
| + return videoCapturer; |
| + } |
| + |
| // -----Implementation of AppRTCClient.AppRTCSignalingEvents --------------- |
| // All callbacks are invoked from websocket signaling looper thread and |
| // are routed to UI thread. |
| @@ -539,8 +653,12 @@ public class CallActivity extends Activity |
| signalingParameters = params; |
| logAndToast("Creating peer connection, delay=" + delta + "ms"); |
| + VideoCapturer videoCapturer = null; |
| + if (peerConnectionParameters.videoCallEnabled) { |
| + videoCapturer = createVideoCapturer(); |
| + } |
| peerConnectionClient.createPeerConnection(rootEglBase.getEglBaseContext(), |
| - localRender, remoteRender, signalingParameters); |
| + localRender, remoteRenders, videoCapturer, signalingParameters); |
| if (signalingParameters.initiator) { |
| logAndToast("Creating OFFER..."); |