OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 package org.appspot.apprtc; | 11 package org.appspot.apprtc; |
12 | 12 |
13 import android.content.Context; | 13 import android.content.Context; |
14 import android.os.ParcelFileDescriptor; | 14 import android.os.ParcelFileDescriptor; |
15 import android.os.Environment; | 15 import android.os.Environment; |
16 import android.util.Log; | 16 import android.util.Log; |
17 | 17 |
18 import org.appspot.apprtc.AppRTCClient.SignalingParameters; | 18 import org.appspot.apprtc.AppRTCClient.SignalingParameters; |
19 import org.webrtc.AudioTrack; | 19 import org.webrtc.AudioTrack; |
20 import org.webrtc.Camera1Enumerator; | |
21 import org.webrtc.Camera2Enumerator; | |
22 import org.webrtc.CameraEnumerator; | |
20 import org.webrtc.CameraEnumerationAndroid; | 23 import org.webrtc.CameraEnumerationAndroid; |
24 import org.webrtc.CameraVideoCapturer; | |
21 import org.webrtc.DataChannel; | 25 import org.webrtc.DataChannel; |
22 import org.webrtc.EglBase; | 26 import org.webrtc.EglBase; |
23 import org.webrtc.IceCandidate; | 27 import org.webrtc.IceCandidate; |
24 import org.webrtc.Logging; | 28 import org.webrtc.Logging; |
25 import org.webrtc.MediaCodecVideoEncoder; | 29 import org.webrtc.MediaCodecVideoEncoder; |
26 import org.webrtc.MediaConstraints; | 30 import org.webrtc.MediaConstraints; |
27 import org.webrtc.MediaConstraints.KeyValuePair; | 31 import org.webrtc.MediaConstraints.KeyValuePair; |
28 import org.webrtc.MediaStream; | 32 import org.webrtc.MediaStream; |
29 import org.webrtc.PeerConnection; | 33 import org.webrtc.PeerConnection; |
30 import org.webrtc.PeerConnection.IceConnectionState; | 34 import org.webrtc.PeerConnection.IceConnectionState; |
31 import org.webrtc.PeerConnectionFactory; | 35 import org.webrtc.PeerConnectionFactory; |
32 import org.webrtc.SdpObserver; | 36 import org.webrtc.SdpObserver; |
33 import org.webrtc.SessionDescription; | 37 import org.webrtc.SessionDescription; |
34 import org.webrtc.StatsObserver; | 38 import org.webrtc.StatsObserver; |
35 import org.webrtc.StatsReport; | 39 import org.webrtc.StatsReport; |
36 import org.webrtc.VideoCapturerAndroid; | 40 import org.webrtc.VideoCapturer; |
37 import org.webrtc.VideoRenderer; | 41 import org.webrtc.VideoRenderer; |
38 import org.webrtc.VideoSource; | 42 import org.webrtc.VideoSource; |
39 import org.webrtc.VideoTrack; | 43 import org.webrtc.VideoTrack; |
40 import org.webrtc.voiceengine.WebRtcAudioManager; | 44 import org.webrtc.voiceengine.WebRtcAudioManager; |
41 import org.webrtc.voiceengine.WebRtcAudioUtils; | 45 import org.webrtc.voiceengine.WebRtcAudioUtils; |
42 | 46 |
43 import java.io.File; | 47 import java.io.File; |
44 import java.io.IOException; | 48 import java.io.IOException; |
45 import java.util.EnumSet; | 49 import java.util.EnumSet; |
46 import java.util.LinkedList; | 50 import java.util.LinkedList; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 private static final int HD_VIDEO_HEIGHT = 720; | 90 private static final int HD_VIDEO_HEIGHT = 720; |
87 private static final int MAX_VIDEO_WIDTH = 1280; | 91 private static final int MAX_VIDEO_WIDTH = 1280; |
88 private static final int MAX_VIDEO_HEIGHT = 1280; | 92 private static final int MAX_VIDEO_HEIGHT = 1280; |
89 private static final int MAX_VIDEO_FPS = 30; | 93 private static final int MAX_VIDEO_FPS = 30; |
90 | 94 |
91 private static final PeerConnectionClient instance = new PeerConnectionClient( ); | 95 private static final PeerConnectionClient instance = new PeerConnectionClient( ); |
92 private final PCObserver pcObserver = new PCObserver(); | 96 private final PCObserver pcObserver = new PCObserver(); |
93 private final SDPObserver sdpObserver = new SDPObserver(); | 97 private final SDPObserver sdpObserver = new SDPObserver(); |
94 private final ScheduledExecutorService executor; | 98 private final ScheduledExecutorService executor; |
95 | 99 |
100 private Context context; | |
96 private PeerConnectionFactory factory; | 101 private PeerConnectionFactory factory; |
97 private PeerConnection peerConnection; | 102 private PeerConnection peerConnection; |
98 PeerConnectionFactory.Options options = null; | 103 PeerConnectionFactory.Options options = null; |
99 private VideoSource videoSource; | 104 private VideoSource videoSource; |
100 private boolean videoCallEnabled; | 105 private boolean videoCallEnabled; |
101 private boolean preferIsac; | 106 private boolean preferIsac; |
102 private String preferredVideoCodec; | 107 private String preferredVideoCodec; |
103 private boolean videoSourceStopped; | 108 private boolean videoSourceStopped; |
104 private boolean isError; | 109 private boolean isError; |
105 private Timer statsTimer; | 110 private Timer statsTimer; |
106 private VideoRenderer.Callbacks localRender; | 111 private VideoRenderer.Callbacks localRender; |
107 private VideoRenderer.Callbacks remoteRender; | 112 private VideoRenderer.Callbacks remoteRender; |
108 private SignalingParameters signalingParameters; | 113 private SignalingParameters signalingParameters; |
109 private MediaConstraints pcConstraints; | 114 private MediaConstraints pcConstraints; |
110 private MediaConstraints videoConstraints; | 115 private MediaConstraints videoConstraints; |
111 private MediaConstraints audioConstraints; | 116 private MediaConstraints audioConstraints; |
112 private ParcelFileDescriptor aecDumpFileDescriptor; | 117 private ParcelFileDescriptor aecDumpFileDescriptor; |
113 private MediaConstraints sdpMediaConstraints; | 118 private MediaConstraints sdpMediaConstraints; |
114 private PeerConnectionParameters peerConnectionParameters; | 119 private PeerConnectionParameters peerConnectionParameters; |
115 // Queued remote ICE candidates are consumed only after both local and | 120 // Queued remote ICE candidates are consumed only after both local and |
116 // remote descriptions are set. Similarly local ICE candidates are sent to | 121 // remote descriptions are set. Similarly local ICE candidates are sent to |
117 // remote peer after both local and remote description are set. | 122 // remote peer after both local and remote description are set. |
118 private LinkedList<IceCandidate> queuedRemoteCandidates; | 123 private LinkedList<IceCandidate> queuedRemoteCandidates; |
119 private PeerConnectionEvents events; | 124 private PeerConnectionEvents events; |
120 private boolean isInitiator; | 125 private boolean isInitiator; |
121 private SessionDescription localSdp; // either offer or answer SDP | 126 private SessionDescription localSdp; // either offer or answer SDP |
122 private MediaStream mediaStream; | 127 private MediaStream mediaStream; |
123 private int numberOfCameras; | 128 private int numberOfCameras; |
124 private VideoCapturerAndroid videoCapturer; | 129 private CameraVideoCapturer videoCapturer; |
125 // enableVideo is set to true if video should be rendered and sent. | 130 // enableVideo is set to true if video should be rendered and sent. |
126 private boolean renderVideo; | 131 private boolean renderVideo; |
127 private VideoTrack localVideoTrack; | 132 private VideoTrack localVideoTrack; |
128 private VideoTrack remoteVideoTrack; | 133 private VideoTrack remoteVideoTrack; |
129 // enableAudio is set to true if audio should be sent. | 134 // enableAudio is set to true if audio should be sent. |
130 private boolean enableAudio; | 135 private boolean enableAudio; |
131 private AudioTrack localAudioTrack; | 136 private AudioTrack localAudioTrack; |
132 | 137 |
133 /** | 138 /** |
134 * Peer connection parameters. | 139 * Peer connection parameters. |
135 */ | 140 */ |
136 public static class PeerConnectionParameters { | 141 public static class PeerConnectionParameters { |
137 public final boolean videoCallEnabled; | 142 public final boolean videoCallEnabled; |
138 public final boolean loopback; | 143 public final boolean loopback; |
139 public final boolean tracing; | 144 public final boolean tracing; |
145 public final boolean camera2Enabled; | |
146 public final boolean camera1Enabled; | |
140 public final int videoWidth; | 147 public final int videoWidth; |
141 public final int videoHeight; | 148 public final int videoHeight; |
142 public final int videoFps; | 149 public final int videoFps; |
143 public final int videoStartBitrate; | 150 public final int videoStartBitrate; |
144 public final String videoCodec; | 151 public final String videoCodec; |
145 public final boolean videoCodecHwAcceleration; | 152 public final boolean videoCodecHwAcceleration; |
146 public final boolean captureToTexture; | 153 public final boolean captureToTexture; |
147 public final int audioStartBitrate; | 154 public final int audioStartBitrate; |
148 public final String audioCodec; | 155 public final String audioCodec; |
149 public final boolean noAudioProcessing; | 156 public final boolean noAudioProcessing; |
150 public final boolean aecDump; | 157 public final boolean aecDump; |
151 public final boolean useOpenSLES; | 158 public final boolean useOpenSLES; |
152 public final boolean disableBuiltInAEC; | 159 public final boolean disableBuiltInAEC; |
153 | 160 |
154 public PeerConnectionParameters( | 161 public PeerConnectionParameters( |
155 boolean videoCallEnabled, boolean loopback, boolean tracing, | 162 boolean videoCallEnabled, boolean loopback, boolean tracing, boolean cam era2Enabled, |
156 int videoWidth, int videoHeight, int videoFps, int videoStartBitrate, | 163 boolean camera1Enabled, int videoWidth, int videoHeight, int videoFps, |
157 String videoCodec, boolean videoCodecHwAcceleration, boolean captureToTe xture, | 164 int videoStartBitrate, String videoCodec, boolean videoCodecHwAccelerati on, |
158 int audioStartBitrate, String audioCodec, | 165 boolean captureToTexture, int audioStartBitrate, String audioCodec, |
159 boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES, | 166 boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES, |
160 boolean disableBuiltInAEC) { | 167 boolean disableBuiltInAEC) { |
161 this.videoCallEnabled = videoCallEnabled; | 168 this.videoCallEnabled = videoCallEnabled; |
169 this.camera2Enabled = camera2Enabled; | |
170 this.camera1Enabled = camera1Enabled; | |
162 this.loopback = loopback; | 171 this.loopback = loopback; |
163 this.tracing = tracing; | 172 this.tracing = tracing; |
164 this.videoWidth = videoWidth; | 173 this.videoWidth = videoWidth; |
165 this.videoHeight = videoHeight; | 174 this.videoHeight = videoHeight; |
166 this.videoFps = videoFps; | 175 this.videoFps = videoFps; |
167 this.videoStartBitrate = videoStartBitrate; | 176 this.videoStartBitrate = videoStartBitrate; |
168 this.videoCodec = videoCodec; | 177 this.videoCodec = videoCodec; |
169 this.videoCodecHwAcceleration = videoCodecHwAcceleration; | 178 this.videoCodecHwAcceleration = videoCodecHwAcceleration; |
170 this.captureToTexture = captureToTexture; | 179 this.captureToTexture = captureToTexture; |
171 this.audioStartBitrate = audioStartBitrate; | 180 this.audioStartBitrate = audioStartBitrate; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } | 249 } |
241 | 250 |
242 public void createPeerConnectionFactory( | 251 public void createPeerConnectionFactory( |
243 final Context context, | 252 final Context context, |
244 final PeerConnectionParameters peerConnectionParameters, | 253 final PeerConnectionParameters peerConnectionParameters, |
245 final PeerConnectionEvents events) { | 254 final PeerConnectionEvents events) { |
246 this.peerConnectionParameters = peerConnectionParameters; | 255 this.peerConnectionParameters = peerConnectionParameters; |
247 this.events = events; | 256 this.events = events; |
248 videoCallEnabled = peerConnectionParameters.videoCallEnabled; | 257 videoCallEnabled = peerConnectionParameters.videoCallEnabled; |
249 // Reset variables to initial states. | 258 // Reset variables to initial states. |
259 this.context = null; | |
250 factory = null; | 260 factory = null; |
251 peerConnection = null; | 261 peerConnection = null; |
252 preferIsac = false; | 262 preferIsac = false; |
253 videoSourceStopped = false; | 263 videoSourceStopped = false; |
254 isError = false; | 264 isError = false; |
255 queuedRemoteCandidates = null; | 265 queuedRemoteCandidates = null; |
256 localSdp = null; // either offer or answer SDP | 266 localSdp = null; // either offer or answer SDP |
257 mediaStream = null; | 267 mediaStream = null; |
258 videoCapturer = null; | 268 videoCapturer = null; |
259 renderVideo = true; | 269 renderVideo = true; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 } | 367 } |
358 | 368 |
359 // Create peer connection factory. | 369 // Create peer connection factory. |
360 if (!PeerConnectionFactory.initializeAndroidGlobals(context, true, true, | 370 if (!PeerConnectionFactory.initializeAndroidGlobals(context, true, true, |
361 peerConnectionParameters.videoCodecHwAcceleration)) { | 371 peerConnectionParameters.videoCodecHwAcceleration)) { |
362 events.onPeerConnectionError("Failed to initializeAndroidGlobals"); | 372 events.onPeerConnectionError("Failed to initializeAndroidGlobals"); |
363 } | 373 } |
364 if (options != null) { | 374 if (options != null) { |
365 Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMas k); | 375 Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMas k); |
366 } | 376 } |
377 this.context = context; | |
367 factory = new PeerConnectionFactory(options); | 378 factory = new PeerConnectionFactory(options); |
368 Log.d(TAG, "Peer connection factory created."); | 379 Log.d(TAG, "Peer connection factory created."); |
369 } | 380 } |
370 | 381 |
371 private void createMediaConstraintsInternal() { | 382 private void createMediaConstraintsInternal() { |
372 // Create peer connection constraints. | 383 // Create peer connection constraints. |
373 pcConstraints = new MediaConstraints(); | 384 pcConstraints = new MediaConstraints(); |
374 // Enable DTLS for normal calls and disable for loopback calls. | 385 // Enable DTLS for normal calls and disable for loopback calls. |
375 if (peerConnectionParameters.loopback) { | 386 if (peerConnectionParameters.loopback) { |
376 pcConstraints.optional.add( | 387 pcConstraints.optional.add( |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 "OfferToReceiveAudio", "true")); | 457 "OfferToReceiveAudio", "true")); |
447 if (videoCallEnabled || peerConnectionParameters.loopback) { | 458 if (videoCallEnabled || peerConnectionParameters.loopback) { |
448 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( | 459 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( |
449 "OfferToReceiveVideo", "true")); | 460 "OfferToReceiveVideo", "true")); |
450 } else { | 461 } else { |
451 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( | 462 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( |
452 "OfferToReceiveVideo", "false")); | 463 "OfferToReceiveVideo", "false")); |
453 } | 464 } |
454 } | 465 } |
455 | 466 |
467 private void createCapturer(CameraEnumerator enumerator) { | |
468 final String[] deviceNames = enumerator.getDeviceNames(); | |
469 | |
470 // First, try to find front facing camera | |
471 Logging.d(TAG, "Looking for front facing cameras."); | |
472 for (String deviceName : deviceNames) { | |
473 if (enumerator.isFrontFacing(deviceName)) { | |
474 Logging.d(TAG, "Creating front facing camera capturer."); | |
475 videoCapturer = enumerator.createCapturer(deviceName, null); | |
476 | |
477 if (videoCapturer != null) { | |
magjed_webrtc
2016/06/29 13:36:45
There is no need for this null check (with the cur
sakal
2016/06/30 09:14:52
I'd rather keep it. It used to be Camera2Enumerato
| |
478 return; | |
479 } | |
480 } | |
481 } | |
482 | |
483 // Front facing camera not found, try something else | |
484 Logging.d(TAG, "Looking for other cameras."); | |
485 for (String deviceName : deviceNames) { | |
486 if (!enumerator.isFrontFacing(deviceName)) { | |
487 Logging.d(TAG, "Creating other camera capturer."); | |
488 videoCapturer = enumerator.createCapturer(deviceName, null); | |
489 | |
490 if (videoCapturer != null) { | |
491 return; | |
492 } | |
493 } | |
494 } | |
495 } | |
496 | |
456 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { | 497 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { |
457 if (factory == null || isError) { | 498 if (factory == null || isError) { |
458 Log.e(TAG, "Peerconnection factory is not created"); | 499 Log.e(TAG, "Peerconnection factory is not created"); |
459 return; | 500 return; |
460 } | 501 } |
461 Log.d(TAG, "Create peer connection."); | 502 Log.d(TAG, "Create peer connection."); |
462 | 503 |
463 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); | 504 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); |
464 if (videoConstraints != null) { | 505 if (videoConstraints != null) { |
465 Log.d(TAG, "VideoConstraints: " + videoConstraints.toString()); | 506 Log.d(TAG, "VideoConstraints: " + videoConstraints.toString()); |
(...skipping 22 matching lines...) Expand all Loading... | |
488 | 529 |
489 // Set default WebRTC tracing and INFO libjingle logging. | 530 // Set default WebRTC tracing and INFO libjingle logging. |
490 // NOTE: this _must_ happen while |factory| is alive! | 531 // NOTE: this _must_ happen while |factory| is alive! |
491 Logging.enableTracing( | 532 Logging.enableTracing( |
492 "logcat:", | 533 "logcat:", |
493 EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT), | 534 EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT), |
494 Logging.Severity.LS_INFO); | 535 Logging.Severity.LS_INFO); |
495 | 536 |
496 mediaStream = factory.createLocalMediaStream("ARDAMS"); | 537 mediaStream = factory.createLocalMediaStream("ARDAMS"); |
497 if (videoCallEnabled) { | 538 if (videoCallEnabled) { |
498 String cameraDeviceName = CameraEnumerationAndroid.getDeviceName(0); | 539 if (Camera2Enumerator.isSupported() && peerConnectionParameters.camera2Ena bled) { |
499 String frontCameraDeviceName = | 540 Logging.d(TAG, "Creating capturer using camera2 API."); |
500 CameraEnumerationAndroid.getNameOfFrontFacingDevice(); | 541 createCapturer(new Camera2Enumerator(context)); |
501 if (numberOfCameras > 1 && frontCameraDeviceName != null) { | |
502 cameraDeviceName = frontCameraDeviceName; | |
503 } | 542 } |
504 Log.d(TAG, "Opening camera: " + cameraDeviceName); | 543 |
505 videoCapturer = VideoCapturerAndroid.create(cameraDeviceName, null, | 544 if (videoCapturer == null && peerConnectionParameters.camera1Enabled) { |
506 peerConnectionParameters.captureToTexture); | 545 Logging.d(TAG, "Creating capturer using camera1 API."); |
546 createCapturer(new Camera1Enumerator()); | |
547 } | |
548 | |
507 if (videoCapturer == null) { | 549 if (videoCapturer == null) { |
508 reportError("Failed to open camera"); | 550 reportError("Failed to open camera"); |
509 return; | 551 return; |
510 } | 552 } |
511 mediaStream.addTrack(createVideoTrack(videoCapturer)); | 553 mediaStream.addTrack(createVideoTrack(videoCapturer)); |
512 } | 554 } |
513 | 555 |
514 mediaStream.addTrack(createAudioTrack()); | 556 mediaStream.addTrack(createAudioTrack()); |
515 peerConnection.addStream(mediaStream); | 557 peerConnection.addStream(mediaStream); |
516 | 558 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 } | 819 } |
778 | 820 |
779 private AudioTrack createAudioTrack() { | 821 private AudioTrack createAudioTrack() { |
780 localAudioTrack = factory.createAudioTrack( | 822 localAudioTrack = factory.createAudioTrack( |
781 AUDIO_TRACK_ID, | 823 AUDIO_TRACK_ID, |
782 factory.createAudioSource(audioConstraints)); | 824 factory.createAudioSource(audioConstraints)); |
783 localAudioTrack.setEnabled(enableAudio); | 825 localAudioTrack.setEnabled(enableAudio); |
784 return localAudioTrack; | 826 return localAudioTrack; |
785 } | 827 } |
786 | 828 |
787 private VideoTrack createVideoTrack(VideoCapturerAndroid capturer) { | 829 private VideoTrack createVideoTrack(VideoCapturer capturer) { |
788 videoSource = factory.createVideoSource(capturer, videoConstraints); | 830 videoSource = factory.createVideoSource(capturer, videoConstraints); |
789 | 831 |
790 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); | 832 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); |
791 localVideoTrack.setEnabled(renderVideo); | 833 localVideoTrack.setEnabled(renderVideo); |
792 localVideoTrack.addRenderer(new VideoRenderer(localRender)); | 834 localVideoTrack.addRenderer(new VideoRenderer(localRender)); |
793 return localVideoTrack; | 835 return localVideoTrack; |
794 } | 836 } |
795 | 837 |
796 private static String setStartBitrate(String codec, boolean isVideoCodec, | 838 private static String setStartBitrate(String codec, boolean isVideoCodec, |
797 String sdpDescription, int bitrateKbps) { | 839 String sdpDescription, int bitrateKbps) { |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1142 public void onCreateFailure(final String error) { | 1184 public void onCreateFailure(final String error) { |
1143 reportError("createSDP error: " + error); | 1185 reportError("createSDP error: " + error); |
1144 } | 1186 } |
1145 | 1187 |
1146 @Override | 1188 @Override |
1147 public void onSetFailure(final String error) { | 1189 public void onSetFailure(final String error) { |
1148 reportError("setSDP error: " + error); | 1190 reportError("setSDP error: " + error); |
1149 } | 1191 } |
1150 } | 1192 } |
1151 } | 1193 } |
OLD | NEW |