Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Side by Side Diff: webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java

Issue 2127893002: AndroidVideoTrackSource implementation (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@magjed-init
Patch Set: Fix cpplint errors. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/api/api.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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, default to HD.
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, default to 30.
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
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
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();
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
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
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 }
OLDNEW
« no previous file with comments | « webrtc/api/api.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698