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 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 | 100 |
101 private Context context; | 101 private Context context; |
102 private PeerConnectionFactory factory; | 102 private PeerConnectionFactory factory; |
103 private PeerConnection peerConnection; | 103 private PeerConnection peerConnection; |
104 PeerConnectionFactory.Options options = null; | 104 PeerConnectionFactory.Options options = null; |
105 private AudioSource audioSource; | 105 private AudioSource audioSource; |
106 private VideoSource videoSource; | 106 private VideoSource videoSource; |
107 private boolean videoCallEnabled; | 107 private boolean videoCallEnabled; |
108 private boolean preferIsac; | 108 private boolean preferIsac; |
109 private String preferredVideoCodec; | 109 private String preferredVideoCodec; |
110 private boolean videoSourceStopped; | 110 private boolean videoCapturerStopped; |
111 private boolean isError; | 111 private boolean isError; |
112 private Timer statsTimer; | 112 private Timer statsTimer; |
113 private VideoRenderer.Callbacks localRender; | 113 private VideoRenderer.Callbacks localRender; |
114 private VideoRenderer.Callbacks remoteRender; | 114 private VideoRenderer.Callbacks remoteRender; |
115 private SignalingParameters signalingParameters; | 115 private SignalingParameters signalingParameters; |
116 private MediaConstraints pcConstraints; | 116 private MediaConstraints pcConstraints; |
117 private MediaConstraints videoConstraints; | 117 private int videoWidth; |
118 private int videoHeight; | |
119 private int videoFps; | |
118 private MediaConstraints audioConstraints; | 120 private MediaConstraints audioConstraints; |
119 private ParcelFileDescriptor aecDumpFileDescriptor; | 121 private ParcelFileDescriptor aecDumpFileDescriptor; |
120 private MediaConstraints sdpMediaConstraints; | 122 private MediaConstraints sdpMediaConstraints; |
121 private PeerConnectionParameters peerConnectionParameters; | 123 private PeerConnectionParameters peerConnectionParameters; |
122 // Queued remote ICE candidates are consumed only after both local and | 124 // Queued remote ICE candidates are consumed only after both local and |
123 // remote descriptions are set. Similarly local ICE candidates are sent to | 125 // remote descriptions are set. Similarly local ICE candidates are sent to |
124 // remote peer after both local and remote description are set. | 126 // remote peer after both local and remote description are set. |
125 private LinkedList<IceCandidate> queuedRemoteCandidates; | 127 private LinkedList<IceCandidate> queuedRemoteCandidates; |
126 private PeerConnectionEvents events; | 128 private PeerConnectionEvents events; |
127 private boolean isInitiator; | 129 private boolean isInitiator; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 final PeerConnectionParameters peerConnectionParameters, | 255 final PeerConnectionParameters peerConnectionParameters, |
254 final PeerConnectionEvents events) { | 256 final PeerConnectionEvents events) { |
255 this.peerConnectionParameters = peerConnectionParameters; | 257 this.peerConnectionParameters = peerConnectionParameters; |
256 this.events = events; | 258 this.events = events; |
257 videoCallEnabled = peerConnectionParameters.videoCallEnabled; | 259 videoCallEnabled = peerConnectionParameters.videoCallEnabled; |
258 // Reset variables to initial states. | 260 // Reset variables to initial states. |
259 this.context = null; | 261 this.context = null; |
260 factory = null; | 262 factory = null; |
261 peerConnection = null; | 263 peerConnection = null; |
262 preferIsac = false; | 264 preferIsac = false; |
263 videoSourceStopped = false; | 265 videoCapturerStopped = false; |
264 isError = false; | 266 isError = false; |
265 queuedRemoteCandidates = null; | 267 queuedRemoteCandidates = null; |
266 localSdp = null; // either offer or answer SDP | 268 localSdp = null; // either offer or answer SDP |
267 mediaStream = null; | 269 mediaStream = null; |
268 videoCapturer = null; | 270 videoCapturer = null; |
269 renderVideo = true; | 271 renderVideo = true; |
270 localVideoTrack = null; | 272 localVideoTrack = null; |
271 remoteVideoTrack = null; | 273 remoteVideoTrack = null; |
272 enableAudio = true; | 274 enableAudio = true; |
273 localAudioTrack = null; | 275 localAudioTrack = null; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 } | 394 } |
393 | 395 |
394 // Check if there is a camera on device and disable video call if not. | 396 // Check if there is a camera on device and disable video call if not. |
395 numberOfCameras = CameraEnumerationAndroid.getDeviceCount(); | 397 numberOfCameras = CameraEnumerationAndroid.getDeviceCount(); |
396 if (numberOfCameras == 0) { | 398 if (numberOfCameras == 0) { |
397 Log.w(TAG, "No camera on device. Switch to audio only call."); | 399 Log.w(TAG, "No camera on device. Switch to audio only call."); |
398 videoCallEnabled = false; | 400 videoCallEnabled = false; |
399 } | 401 } |
400 // Create video constraints if video call is enabled. | 402 // Create video constraints if video call is enabled. |
401 if (videoCallEnabled) { | 403 if (videoCallEnabled) { |
402 videoConstraints = new MediaConstraints(); | 404 videoWidth = peerConnectionParameters.videoWidth; |
403 int videoWidth = peerConnectionParameters.videoWidth; | 405 videoHeight = peerConnectionParameters.videoHeight; |
404 int videoHeight = peerConnectionParameters.videoHeight; | 406 videoFps = peerConnectionParameters.videoFps; |
405 | 407 |
406 // If VP8 HW video encoder is supported and video resolution is not | 408 // If video resolution is not specified, force it to HD. |
magjed_webrtc
2016/07/19 12:57:47
I think you should change the comment to something
sakal
2016/07/19 13:46:23
Done.
| |
407 // specified force it to HD. | 409 if (videoWidth == 0 || videoHeight == 0) { |
408 if ((videoWidth == 0 || videoHeight == 0) | |
409 && peerConnectionParameters.videoCodecHwAcceleration | |
410 && MediaCodecVideoEncoder.isVp8HwSupported()) { | |
411 videoWidth = HD_VIDEO_WIDTH; | 410 videoWidth = HD_VIDEO_WIDTH; |
412 videoHeight = HD_VIDEO_HEIGHT; | 411 videoHeight = HD_VIDEO_HEIGHT; |
413 } | 412 } |
414 | 413 |
415 // Add video resolution constraints. | 414 // If fps is not specified, force it to 30. |
magjed_webrtc
2016/07/19 12:57:47
ditto: update comment.
sakal
2016/07/19 13:46:23
Done.
| |
416 if (videoWidth > 0 && videoHeight > 0) { | 415 if (videoFps == 0) { |
417 videoWidth = Math.min(videoWidth, MAX_VIDEO_WIDTH); | 416 videoFps = 30; |
418 videoHeight = Math.min(videoHeight, MAX_VIDEO_HEIGHT); | |
419 videoConstraints.mandatory.add(new KeyValuePair( | |
420 MIN_VIDEO_WIDTH_CONSTRAINT, Integer.toString(videoWidth))); | |
421 videoConstraints.mandatory.add(new KeyValuePair( | |
422 MAX_VIDEO_WIDTH_CONSTRAINT, Integer.toString(videoWidth))); | |
423 videoConstraints.mandatory.add(new KeyValuePair( | |
424 MIN_VIDEO_HEIGHT_CONSTRAINT, Integer.toString(videoHeight))); | |
425 videoConstraints.mandatory.add(new KeyValuePair( | |
426 MAX_VIDEO_HEIGHT_CONSTRAINT, Integer.toString(videoHeight))); | |
427 } | 417 } |
428 | 418 |
429 // Add fps constraints. | 419 videoWidth = Math.min(videoWidth, MAX_VIDEO_WIDTH); |
430 int videoFps = peerConnectionParameters.videoFps; | 420 videoHeight = Math.min(videoHeight, MAX_VIDEO_HEIGHT); |
431 if (videoFps > 0) { | 421 videoFps = Math.min(videoFps, MAX_VIDEO_FPS); |
432 videoFps = Math.min(videoFps, MAX_VIDEO_FPS); | |
433 videoConstraints.mandatory.add(new KeyValuePair( | |
434 MIN_VIDEO_FPS_CONSTRAINT, Integer.toString(videoFps))); | |
435 videoConstraints.mandatory.add(new KeyValuePair( | |
436 MAX_VIDEO_FPS_CONSTRAINT, Integer.toString(videoFps))); | |
437 } | |
438 } | 422 } |
439 | 423 |
440 // Create audio constraints. | 424 // Create audio constraints. |
441 audioConstraints = new MediaConstraints(); | 425 audioConstraints = new MediaConstraints(); |
442 // added for audio performance measurements | 426 // added for audio performance measurements |
443 if (peerConnectionParameters.noAudioProcessing) { | 427 if (peerConnectionParameters.noAudioProcessing) { |
444 Log.d(TAG, "Disabling audio processing"); | 428 Log.d(TAG, "Disabling audio processing"); |
445 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair( | 429 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair( |
446 AUDIO_ECHO_CANCELLATION_CONSTRAINT, "false")); | 430 AUDIO_ECHO_CANCELLATION_CONSTRAINT, "false")); |
447 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair( | 431 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 } | 479 } |
496 | 480 |
497 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { | 481 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { |
498 if (factory == null || isError) { | 482 if (factory == null || isError) { |
499 Log.e(TAG, "Peerconnection factory is not created"); | 483 Log.e(TAG, "Peerconnection factory is not created"); |
500 return; | 484 return; |
501 } | 485 } |
502 Log.d(TAG, "Create peer connection."); | 486 Log.d(TAG, "Create peer connection."); |
503 | 487 |
504 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); | 488 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); |
505 if (videoConstraints != null) { | |
506 Log.d(TAG, "VideoConstraints: " + videoConstraints.toString()); | |
507 } | |
508 queuedRemoteCandidates = new LinkedList<IceCandidate>(); | 489 queuedRemoteCandidates = new LinkedList<IceCandidate>(); |
509 | 490 |
510 if (videoCallEnabled) { | 491 if (videoCallEnabled) { |
511 Log.d(TAG, "EGLContext: " + renderEGLContext); | 492 Log.d(TAG, "EGLContext: " + renderEGLContext); |
512 factory.setVideoHwAccelerationOptions(renderEGLContext, renderEGLContext); | 493 factory.setVideoHwAccelerationOptions(renderEGLContext, renderEGLContext); |
513 } | 494 } |
514 | 495 |
515 PeerConnection.RTCConfiguration rtcConfig = | 496 PeerConnection.RTCConfiguration rtcConfig = |
516 new PeerConnection.RTCConfiguration(signalingParameters.iceServers); | 497 new PeerConnection.RTCConfiguration(signalingParameters.iceServers); |
517 // TCP candidates are only useful when connecting to a server that supports | 498 // TCP candidates are only useful when connecting to a server that supports |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 statsTimer.cancel(); | 566 statsTimer.cancel(); |
586 if (peerConnection != null) { | 567 if (peerConnection != null) { |
587 peerConnection.dispose(); | 568 peerConnection.dispose(); |
588 peerConnection = null; | 569 peerConnection = null; |
589 } | 570 } |
590 Log.d(TAG, "Closing audio source."); | 571 Log.d(TAG, "Closing audio source."); |
591 if (audioSource != null) { | 572 if (audioSource != null) { |
592 audioSource.dispose(); | 573 audioSource.dispose(); |
593 audioSource = null; | 574 audioSource = null; |
594 } | 575 } |
576 Log.d(TAG, "Stopping capture."); | |
577 if (videoCapturer != null) { | |
578 try { | |
579 videoCapturer.stopCapture(); | |
magjed_webrtc
2016/07/19 12:57:47
Maybe we shouldn't throw InterruptedException now
sakal
2016/07/19 13:46:23
Agree, will handle this in a separate CL.
| |
580 } catch(InterruptedException e) { | |
581 throw new RuntimeException(e); | |
582 } | |
583 videoCapturer.dispose(); | |
584 videoCapturer = null; | |
585 } | |
595 Log.d(TAG, "Closing video source."); | 586 Log.d(TAG, "Closing video source."); |
596 if (videoSource != null) { | 587 if (videoSource != null) { |
597 videoSource.dispose(); | 588 videoSource.dispose(); |
598 videoSource = null; | 589 videoSource = null; |
599 } | 590 } |
600 Log.d(TAG, "Closing peer connection factory."); | 591 Log.d(TAG, "Closing peer connection factory."); |
601 if (factory != null) { | 592 if (factory != null) { |
602 factory.dispose(); | 593 factory.dispose(); |
603 factory = null; | 594 factory = null; |
604 } | 595 } |
605 options = null; | 596 options = null; |
606 Log.d(TAG, "Closing peer connection done."); | 597 Log.d(TAG, "Closing peer connection done."); |
607 events.onPeerConnectionClosed(); | 598 events.onPeerConnectionClosed(); |
608 PeerConnectionFactory.stopInternalTracingCapture(); | 599 PeerConnectionFactory.stopInternalTracingCapture(); |
609 PeerConnectionFactory.shutdownInternalTracer(); | 600 PeerConnectionFactory.shutdownInternalTracer(); |
610 } | 601 } |
611 | 602 |
612 public boolean isHDVideo() { | 603 public boolean isHDVideo() { |
613 if (!videoCallEnabled) { | 604 if (!videoCallEnabled) { |
614 return false; | 605 return false; |
615 } | 606 } |
616 int minWidth = 0; | 607 |
617 int minHeight = 0; | 608 return videoWidth * videoHeight >= 1280 * 720; |
618 for (KeyValuePair keyValuePair : videoConstraints.mandatory) { | |
619 if (keyValuePair.getKey().equals("minWidth")) { | |
620 try { | |
621 minWidth = Integer.parseInt(keyValuePair.getValue()); | |
622 } catch (NumberFormatException e) { | |
623 Log.e(TAG, "Can not parse video width from video constraints"); | |
624 } | |
625 } else if (keyValuePair.getKey().equals("minHeight")) { | |
626 try { | |
627 minHeight = Integer.parseInt(keyValuePair.getValue()); | |
628 } catch (NumberFormatException e) { | |
629 Log.e(TAG, "Can not parse video height from video constraints"); | |
630 } | |
631 } | |
632 } | |
633 return minWidth * minHeight >= 1280 * 720; | |
634 } | 609 } |
635 | 610 |
636 private void getStats() { | 611 private void getStats() { |
637 if (peerConnection == null || isError) { | 612 if (peerConnection == null || isError) { |
638 return; | 613 return; |
639 } | 614 } |
640 boolean success = peerConnection.getStats(new StatsObserver() { | 615 boolean success = peerConnection.getStats(new StatsObserver() { |
641 @Override | 616 @Override |
642 public void onComplete(final StatsReport[] reports) { | 617 public void onComplete(final StatsReport[] reports) { |
643 events.onPeerConnectionStatsReady(reports); | 618 events.onPeerConnectionStatsReady(reports); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 sdp.type, sdpDescription); | 759 sdp.type, sdpDescription); |
785 peerConnection.setRemoteDescription(sdpObserver, sdpRemote); | 760 peerConnection.setRemoteDescription(sdpObserver, sdpRemote); |
786 } | 761 } |
787 }); | 762 }); |
788 } | 763 } |
789 | 764 |
790 public void stopVideoSource() { | 765 public void stopVideoSource() { |
791 executor.execute(new Runnable() { | 766 executor.execute(new Runnable() { |
792 @Override | 767 @Override |
793 public void run() { | 768 public void run() { |
794 if (videoSource != null && !videoSourceStopped) { | 769 if (videoCapturer != null && !videoCapturerStopped) { |
795 Log.d(TAG, "Stop video source."); | 770 Log.d(TAG, "Stop video source."); |
796 videoSource.stop(); | 771 try { |
797 videoSourceStopped = true; | 772 videoCapturer.stopCapture(); |
773 } catch (InterruptedException e) {} | |
774 videoCapturerStopped = true; | |
798 } | 775 } |
799 } | 776 } |
800 }); | 777 }); |
801 } | 778 } |
802 | 779 |
803 public void startVideoSource() { | 780 public void startVideoSource() { |
804 executor.execute(new Runnable() { | 781 executor.execute(new Runnable() { |
805 @Override | 782 @Override |
806 public void run() { | 783 public void run() { |
807 if (videoSource != null && videoSourceStopped) { | 784 if (videoCapturer != null && videoCapturerStopped) { |
808 Log.d(TAG, "Restart video source."); | 785 Log.d(TAG, "Restart video source."); |
809 videoSource.restart(); | 786 videoCapturer.startCapture(videoWidth, videoHeight, videoFps); |
810 videoSourceStopped = false; | 787 videoCapturerStopped = false; |
811 } | 788 } |
812 } | 789 } |
813 }); | 790 }); |
814 } | 791 } |
815 | 792 |
816 private void reportError(final String errorMessage) { | 793 private void reportError(final String errorMessage) { |
817 Log.e(TAG, "Peerconnection error: " + errorMessage); | 794 Log.e(TAG, "Peerconnection error: " + errorMessage); |
818 executor.execute(new Runnable() { | 795 executor.execute(new Runnable() { |
819 @Override | 796 @Override |
820 public void run() { | 797 public void run() { |
821 if (!isError) { | 798 if (!isError) { |
822 events.onPeerConnectionError(errorMessage); | 799 events.onPeerConnectionError(errorMessage); |
823 isError = true; | 800 isError = true; |
824 } | 801 } |
825 } | 802 } |
826 }); | 803 }); |
827 } | 804 } |
828 | 805 |
829 private AudioTrack createAudioTrack() { | 806 private AudioTrack createAudioTrack() { |
830 audioSource = factory.createAudioSource(audioConstraints); | 807 audioSource = factory.createAudioSource(audioConstraints); |
831 localAudioTrack = factory.createAudioTrack(AUDIO_TRACK_ID, audioSource); | 808 localAudioTrack = factory.createAudioTrack(AUDIO_TRACK_ID, audioSource); |
832 localAudioTrack.setEnabled(enableAudio); | 809 localAudioTrack.setEnabled(enableAudio); |
833 return localAudioTrack; | 810 return localAudioTrack; |
834 } | 811 } |
835 | 812 |
836 private VideoTrack createVideoTrack(VideoCapturer capturer) { | 813 private VideoTrack createVideoTrack(VideoCapturer capturer) { |
837 videoSource = factory.createVideoSource(capturer, videoConstraints); | 814 videoSource = factory.createVideoSource(capturer); |
815 capturer.startCapture(videoWidth, videoHeight, videoFps); | |
838 | 816 |
839 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); | 817 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); |
840 localVideoTrack.setEnabled(renderVideo); | 818 localVideoTrack.setEnabled(renderVideo); |
841 localVideoTrack.addRenderer(new VideoRenderer(localRender)); | 819 localVideoTrack.addRenderer(new VideoRenderer(localRender)); |
842 return localVideoTrack; | 820 return localVideoTrack; |
843 } | 821 } |
844 | 822 |
845 private static String setStartBitrate(String codec, boolean isVideoCodec, | 823 private static String setStartBitrate(String codec, boolean isVideoCodec, |
846 String sdpDescription, int bitrateKbps) { | 824 String sdpDescription, int bitrateKbps) { |
847 String[] lines = sdpDescription.split("\r\n"); | 825 String[] lines = sdpDescription.split("\r\n"); |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1191 public void onCreateFailure(final String error) { | 1169 public void onCreateFailure(final String error) { |
1192 reportError("createSDP error: " + error); | 1170 reportError("createSDP error: " + error); |
1193 } | 1171 } |
1194 | 1172 |
1195 @Override | 1173 @Override |
1196 public void onSetFailure(final String error) { | 1174 public void onSetFailure(final String error) { |
1197 reportError("setSDP error: " + error); | 1175 reportError("setSDP error: " + error); |
1198 } | 1176 } |
1199 } | 1177 } |
1200 } | 1178 } |
OLD | NEW |