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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 private static final String AUDIO_ECHO_CANCELLATION_CONSTRAINT = "googEchoCanc ellation"; | 96 private static final String AUDIO_ECHO_CANCELLATION_CONSTRAINT = "googEchoCanc ellation"; |
97 private static final String AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT = "googAutoGain Control"; | 97 private static final String AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT = "googAutoGain Control"; |
98 private static final String AUDIO_HIGH_PASS_FILTER_CONSTRAINT = "googHighpassF ilter"; | 98 private static final String AUDIO_HIGH_PASS_FILTER_CONSTRAINT = "googHighpassF ilter"; |
99 private static final String AUDIO_NOISE_SUPPRESSION_CONSTRAINT = "googNoiseSup pression"; | 99 private static final String AUDIO_NOISE_SUPPRESSION_CONSTRAINT = "googNoiseSup pression"; |
100 private static final String AUDIO_LEVEL_CONTROL_CONSTRAINT = "levelControl"; | 100 private static final String AUDIO_LEVEL_CONTROL_CONSTRAINT = "levelControl"; |
101 private static final String DTLS_SRTP_KEY_AGREEMENT_CONSTRAINT = "DtlsSrtpKeyA greement"; | 101 private static final String DTLS_SRTP_KEY_AGREEMENT_CONSTRAINT = "DtlsSrtpKeyA greement"; |
102 private static final int HD_VIDEO_WIDTH = 1280; | 102 private static final int HD_VIDEO_WIDTH = 1280; |
103 private static final int HD_VIDEO_HEIGHT = 720; | 103 private static final int HD_VIDEO_HEIGHT = 720; |
104 private static final int BPS_IN_KBPS = 1000; | 104 private static final int BPS_IN_KBPS = 1000; |
105 | 105 |
106 private static final PeerConnectionClient instance = new PeerConnectionClient( ); | 106 // Executor thread is started once in private ctor and is used for all |
107 // peer connection API calls to ensure new peer connection factory is | |
108 // created on the same thread as previously destroyed factory. | |
magjed_webrtc
2017/08/31 11:28:59
Do we need this to avoid the crash in issue 8135?
sakal
2017/08/31 14:18:55
This is needed because close in asynchronous.
| |
109 private static final ExecutorService executor = Executors.newSingleThreadExecu tor(); | |
110 | |
107 private final PCObserver pcObserver = new PCObserver(); | 111 private final PCObserver pcObserver = new PCObserver(); |
108 private final SDPObserver sdpObserver = new SDPObserver(); | 112 private final SDPObserver sdpObserver = new SDPObserver(); |
109 private final ExecutorService executor; | |
110 | 113 |
114 private final EglBase rootEglBase; | |
111 private PeerConnectionFactory factory; | 115 private PeerConnectionFactory factory; |
112 private PeerConnection peerConnection; | 116 private PeerConnection peerConnection; |
113 PeerConnectionFactory.Options options = null; | 117 PeerConnectionFactory.Options options = null; |
114 private AudioSource audioSource; | 118 private AudioSource audioSource; |
115 private VideoSource videoSource; | 119 private VideoSource videoSource; |
116 private boolean videoCallEnabled; | 120 private boolean videoCallEnabled; |
117 private boolean preferIsac; | 121 private boolean preferIsac; |
118 private String preferredVideoCodec; | 122 private String preferredVideoCodec; |
119 private boolean videoCapturerStopped; | 123 private boolean videoCapturerStopped; |
120 private boolean isError; | 124 private boolean isError; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 * Callback fired once peer connection statistics is ready. | 285 * Callback fired once peer connection statistics is ready. |
282 */ | 286 */ |
283 void onPeerConnectionStatsReady(final StatsReport[] reports); | 287 void onPeerConnectionStatsReady(final StatsReport[] reports); |
284 | 288 |
285 /** | 289 /** |
286 * Callback fired once peer connection error happened. | 290 * Callback fired once peer connection error happened. |
287 */ | 291 */ |
288 void onPeerConnectionError(final String description); | 292 void onPeerConnectionError(final String description); |
289 } | 293 } |
290 | 294 |
291 private PeerConnectionClient() { | 295 public PeerConnectionClient() { |
292 // Executor thread is started once in private ctor and is used for all | 296 rootEglBase = EglBase.create(); |
293 // peer connection API calls to ensure new peer connection factory is | |
294 // created on the same thread as previously destroyed factory. | |
295 executor = Executors.newSingleThreadExecutor(); | |
296 } | |
297 | |
298 public static PeerConnectionClient getInstance() { | |
299 return instance; | |
300 } | 297 } |
301 | 298 |
302 public void setPeerConnectionFactoryOptions(PeerConnectionFactory.Options opti ons) { | 299 public void setPeerConnectionFactoryOptions(PeerConnectionFactory.Options opti ons) { |
303 this.options = options; | 300 this.options = options; |
304 } | 301 } |
305 | 302 |
306 public void createPeerConnectionFactory(final Context context, | 303 public void createPeerConnectionFactory(final Context context, |
307 final PeerConnectionParameters peerConnectionParameters, final PeerConnect ionEvents events) { | 304 final PeerConnectionParameters peerConnectionParameters, final PeerConnect ionEvents events) { |
308 this.peerConnectionParameters = peerConnectionParameters; | 305 this.peerConnectionParameters = peerConnectionParameters; |
309 this.events = events; | 306 this.events = events; |
(...skipping 18 matching lines...) Expand all Loading... | |
328 statsTimer = new Timer(); | 325 statsTimer = new Timer(); |
329 | 326 |
330 executor.execute(new Runnable() { | 327 executor.execute(new Runnable() { |
331 @Override | 328 @Override |
332 public void run() { | 329 public void run() { |
333 createPeerConnectionFactoryInternal(context); | 330 createPeerConnectionFactoryInternal(context); |
334 } | 331 } |
335 }); | 332 }); |
336 } | 333 } |
337 | 334 |
338 public void createPeerConnection(final EglBase.Context renderEGLContext, | 335 public void createPeerConnection(final VideoRenderer.Callbacks localRender, |
339 final VideoRenderer.Callbacks localRender, final VideoRenderer.Callbacks r emoteRender, | 336 final VideoRenderer.Callbacks remoteRender, final VideoCapturer videoCaptu rer, |
340 final VideoCapturer videoCapturer, final SignalingParameters signalingPara meters) { | 337 final SignalingParameters signalingParameters) { |
341 createPeerConnection(renderEGLContext, localRender, Collections.singletonLis t(remoteRender), | 338 createPeerConnection( |
342 videoCapturer, signalingParameters); | 339 localRender, Collections.singletonList(remoteRender), videoCapturer, sig nalingParameters); |
343 } | 340 } |
344 public void createPeerConnection(final EglBase.Context renderEGLContext, | 341 public void createPeerConnection(final VideoRenderer.Callbacks localRender, |
345 final VideoRenderer.Callbacks localRender, final List<VideoRenderer.Callba cks> remoteRenders, | 342 final List<VideoRenderer.Callbacks> remoteRenders, final VideoCapturer vid eoCapturer, |
346 final VideoCapturer videoCapturer, final SignalingParameters signalingPara meters) { | 343 final SignalingParameters signalingParameters) { |
347 if (peerConnectionParameters == null) { | 344 if (peerConnectionParameters == null) { |
348 Log.e(TAG, "Creating peer connection without initializing factory."); | 345 Log.e(TAG, "Creating peer connection without initializing factory."); |
349 return; | 346 return; |
350 } | 347 } |
351 this.localRender = localRender; | 348 this.localRender = localRender; |
352 this.remoteRenders = remoteRenders; | 349 this.remoteRenders = remoteRenders; |
353 this.videoCapturer = videoCapturer; | 350 this.videoCapturer = videoCapturer; |
354 this.signalingParameters = signalingParameters; | 351 this.signalingParameters = signalingParameters; |
355 executor.execute(new Runnable() { | 352 executor.execute(new Runnable() { |
356 @Override | 353 @Override |
357 public void run() { | 354 public void run() { |
358 try { | 355 try { |
359 createMediaConstraintsInternal(); | 356 createMediaConstraintsInternal(); |
360 createPeerConnectionInternal(renderEGLContext); | 357 createPeerConnectionInternal(); |
361 } catch (Exception e) { | 358 } catch (Exception e) { |
362 reportError("Failed to create peer connection: " + e.getMessage()); | 359 reportError("Failed to create peer connection: " + e.getMessage()); |
363 throw e; | 360 throw e; |
364 } | 361 } |
365 } | 362 } |
366 }); | 363 }); |
367 } | 364 } |
368 | 365 |
369 public void close() { | 366 public void close() { |
370 executor.execute(new Runnable() { | 367 executor.execute(new Runnable() { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
576 new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")); | 573 new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")); |
577 if (videoCallEnabled || peerConnectionParameters.loopback) { | 574 if (videoCallEnabled || peerConnectionParameters.loopback) { |
578 sdpMediaConstraints.mandatory.add( | 575 sdpMediaConstraints.mandatory.add( |
579 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true")); | 576 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true")); |
580 } else { | 577 } else { |
581 sdpMediaConstraints.mandatory.add( | 578 sdpMediaConstraints.mandatory.add( |
582 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false")); | 579 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false")); |
583 } | 580 } |
584 } | 581 } |
585 | 582 |
586 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { | 583 private void createPeerConnectionInternal() { |
587 if (factory == null || isError) { | 584 if (factory == null || isError) { |
588 Log.e(TAG, "Peerconnection factory is not created"); | 585 Log.e(TAG, "Peerconnection factory is not created"); |
589 return; | 586 return; |
590 } | 587 } |
591 Log.d(TAG, "Create peer connection."); | 588 Log.d(TAG, "Create peer connection."); |
592 | 589 |
593 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); | 590 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); |
594 queuedRemoteCandidates = new LinkedList<IceCandidate>(); | 591 queuedRemoteCandidates = new LinkedList<IceCandidate>(); |
595 | 592 |
596 if (videoCallEnabled) { | 593 if (videoCallEnabled) { |
597 Log.d(TAG, "EGLContext: " + renderEGLContext); | 594 factory.setVideoHwAccelerationOptions( |
598 factory.setVideoHwAccelerationOptions(renderEGLContext, renderEGLContext); | 595 rootEglBase.getEglBaseContext(), rootEglBase.getEglBaseContext()); |
599 } | 596 } |
600 | 597 |
601 PeerConnection.RTCConfiguration rtcConfig = | 598 PeerConnection.RTCConfiguration rtcConfig = |
602 new PeerConnection.RTCConfiguration(signalingParameters.iceServers); | 599 new PeerConnection.RTCConfiguration(signalingParameters.iceServers); |
603 // TCP candidates are only useful when connecting to a server that supports | 600 // TCP candidates are only useful when connecting to a server that supports |
604 // ICE-TCP. | 601 // ICE-TCP. |
605 rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.DISABLED; | 602 rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.DISABLED; |
606 rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE; | 603 rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE; |
607 rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE; | 604 rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE; |
608 rtcConfig.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy .GATHER_CONTINUALLY; | 605 rtcConfig.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy .GATHER_CONTINUALLY; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 videoSource = null; | 688 videoSource = null; |
692 } | 689 } |
693 localRender = null; | 690 localRender = null; |
694 remoteRenders = null; | 691 remoteRenders = null; |
695 Log.d(TAG, "Closing peer connection factory."); | 692 Log.d(TAG, "Closing peer connection factory."); |
696 if (factory != null) { | 693 if (factory != null) { |
697 factory.dispose(); | 694 factory.dispose(); |
698 factory = null; | 695 factory = null; |
699 } | 696 } |
700 options = null; | 697 options = null; |
698 rootEglBase.release(); | |
701 Log.d(TAG, "Closing peer connection done."); | 699 Log.d(TAG, "Closing peer connection done."); |
702 events.onPeerConnectionClosed(); | 700 events.onPeerConnectionClosed(); |
703 PeerConnectionFactory.stopInternalTracingCapture(); | 701 PeerConnectionFactory.stopInternalTracingCapture(); |
704 PeerConnectionFactory.shutdownInternalTracer(); | 702 PeerConnectionFactory.shutdownInternalTracer(); |
705 events = null; | 703 events = null; |
706 } | 704 } |
707 | 705 |
708 public boolean isHDVideo() { | 706 public boolean isHDVideo() { |
709 if (!videoCallEnabled) { | 707 if (!videoCallEnabled) { |
710 return false; | 708 return false; |
711 } | 709 } |
712 | 710 |
713 return videoWidth * videoHeight >= 1280 * 720; | 711 return videoWidth * videoHeight >= 1280 * 720; |
714 } | 712 } |
715 | 713 |
714 public EglBase.Context getRenderContext() { | |
715 return rootEglBase.getEglBaseContext(); | |
716 } | |
717 | |
716 private void getStats() { | 718 private void getStats() { |
717 if (peerConnection == null || isError) { | 719 if (peerConnection == null || isError) { |
718 return; | 720 return; |
719 } | 721 } |
720 boolean success = peerConnection.getStats(new StatsObserver() { | 722 boolean success = peerConnection.getStats(new StatsObserver() { |
721 @Override | 723 @Override |
722 public void onComplete(final StatsReport[] reports) { | 724 public void onComplete(final StatsReport[] reports) { |
723 events.onPeerConnectionStatsReady(reports); | 725 events.onPeerConnectionStatsReady(reports); |
724 } | 726 } |
725 }, null); | 727 }, null); |
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1356 public void onCreateFailure(final String error) { | 1358 public void onCreateFailure(final String error) { |
1357 reportError("createSDP error: " + error); | 1359 reportError("createSDP error: " + error); |
1358 } | 1360 } |
1359 | 1361 |
1360 @Override | 1362 @Override |
1361 public void onSetFailure(final String error) { | 1363 public void onSetFailure(final String error) { |
1362 reportError("setSDP error: " + error); | 1364 reportError("setSDP error: " + error); |
1363 } | 1365 } |
1364 } | 1366 } |
1365 } | 1367 } |
OLD | NEW |