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

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

Issue 2077663003: Camera2 in AppRTC Android Demo. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@camera2_only
Patch Set: Create peer connection factory with the target context in the test 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
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
11 package org.appspot.apprtc; 11 package org.appspot.apprtc;
12 12
13 import org.appspot.apprtc.AppRTCClient.SignalingParameters; 13 import org.appspot.apprtc.AppRTCClient.SignalingParameters;
14 14
15 import android.content.Context; 15 import android.content.Context;
16 import android.os.Environment; 16 import android.os.Environment;
17 import android.os.ParcelFileDescriptor; 17 import android.os.ParcelFileDescriptor;
18 import android.util.Log; 18 import android.util.Log;
19 19
20 import org.webrtc.AudioSource; 20 import org.webrtc.AudioSource;
21 import org.webrtc.AudioTrack; 21 import org.webrtc.AudioTrack;
22 import org.webrtc.Camera1Enumerator;
23 import org.webrtc.Camera2Enumerator;
22 import org.webrtc.CameraEnumerationAndroid; 24 import org.webrtc.CameraEnumerationAndroid;
25 import org.webrtc.CameraEnumerator;
26 import org.webrtc.CameraVideoCapturer;
23 import org.webrtc.DataChannel; 27 import org.webrtc.DataChannel;
24 import org.webrtc.EglBase; 28 import org.webrtc.EglBase;
25 import org.webrtc.IceCandidate; 29 import org.webrtc.IceCandidate;
26 import org.webrtc.Logging; 30 import org.webrtc.Logging;
27 import org.webrtc.MediaCodecVideoEncoder; 31 import org.webrtc.MediaCodecVideoEncoder;
28 import org.webrtc.MediaConstraints; 32 import org.webrtc.MediaConstraints;
29 import org.webrtc.MediaConstraints.KeyValuePair; 33 import org.webrtc.MediaConstraints.KeyValuePair;
30 import org.webrtc.MediaStream; 34 import org.webrtc.MediaStream;
31 import org.webrtc.PeerConnection; 35 import org.webrtc.PeerConnection;
32 import org.webrtc.PeerConnection.IceConnectionState; 36 import org.webrtc.PeerConnection.IceConnectionState;
33 import org.webrtc.PeerConnectionFactory; 37 import org.webrtc.PeerConnectionFactory;
34 import org.webrtc.SdpObserver; 38 import org.webrtc.SdpObserver;
35 import org.webrtc.SessionDescription; 39 import org.webrtc.SessionDescription;
36 import org.webrtc.StatsObserver; 40 import org.webrtc.StatsObserver;
37 import org.webrtc.StatsReport; 41 import org.webrtc.StatsReport;
38 import org.webrtc.VideoCapturerAndroid; 42 import org.webrtc.VideoCapturer;
39 import org.webrtc.VideoRenderer; 43 import org.webrtc.VideoRenderer;
40 import org.webrtc.VideoSource; 44 import org.webrtc.VideoSource;
41 import org.webrtc.VideoTrack; 45 import org.webrtc.VideoTrack;
42 import org.webrtc.voiceengine.WebRtcAudioManager; 46 import org.webrtc.voiceengine.WebRtcAudioManager;
43 import org.webrtc.voiceengine.WebRtcAudioUtils; 47 import org.webrtc.voiceengine.WebRtcAudioUtils;
44 48
45 import java.io.File; 49 import java.io.File;
46 import java.io.IOException; 50 import java.io.IOException;
47 import java.util.EnumSet; 51 import java.util.EnumSet;
48 import java.util.LinkedList; 52 import java.util.LinkedList;
49 import java.util.Timer; 53 import java.util.Timer;
50 import java.util.TimerTask; 54 import java.util.TimerTask;
51 import java.util.concurrent.ExecutorService;
52 import java.util.concurrent.Executors; 55 import java.util.concurrent.Executors;
53 import java.util.concurrent.ScheduledExecutorService; 56 import java.util.concurrent.ScheduledExecutorService;
54 import java.util.regex.Matcher; 57 import java.util.regex.Matcher;
55 import java.util.regex.Pattern; 58 import java.util.regex.Pattern;
56 59
57 /** 60 /**
58 * Peer connection client implementation. 61 * Peer connection client implementation.
59 * 62 *
60 * <p>All public methods are routed to local looper thread. 63 * <p>All public methods are routed to local looper thread.
61 * All PeerConnectionEvents callbacks are invoked from the same looper thread. 64 * All PeerConnectionEvents callbacks are invoked from the same looper thread.
(...skipping 26 matching lines...) Expand all
88 private static final int HD_VIDEO_HEIGHT = 720; 91 private static final int HD_VIDEO_HEIGHT = 720;
89 private static final int MAX_VIDEO_WIDTH = 1280; 92 private static final int MAX_VIDEO_WIDTH = 1280;
90 private static final int MAX_VIDEO_HEIGHT = 1280; 93 private static final int MAX_VIDEO_HEIGHT = 1280;
91 private static final int MAX_VIDEO_FPS = 30; 94 private static final int MAX_VIDEO_FPS = 30;
92 95
93 private static final PeerConnectionClient instance = new PeerConnectionClient( ); 96 private static final PeerConnectionClient instance = new PeerConnectionClient( );
94 private final PCObserver pcObserver = new PCObserver(); 97 private final PCObserver pcObserver = new PCObserver();
95 private final SDPObserver sdpObserver = new SDPObserver(); 98 private final SDPObserver sdpObserver = new SDPObserver();
96 private final ScheduledExecutorService executor; 99 private final ScheduledExecutorService executor;
97 100
101 private Context context;
98 private PeerConnectionFactory factory; 102 private PeerConnectionFactory factory;
99 private PeerConnection peerConnection; 103 private PeerConnection peerConnection;
100 PeerConnectionFactory.Options options = null; 104 PeerConnectionFactory.Options options = null;
101 private AudioSource audioSource; 105 private AudioSource audioSource;
102 private VideoSource videoSource; 106 private VideoSource videoSource;
103 private boolean videoCallEnabled; 107 private boolean videoCallEnabled;
104 private boolean preferIsac; 108 private boolean preferIsac;
105 private String preferredVideoCodec; 109 private String preferredVideoCodec;
106 private boolean videoSourceStopped; 110 private boolean videoSourceStopped;
107 private boolean isError; 111 private boolean isError;
108 private Timer statsTimer; 112 private Timer statsTimer;
109 private VideoRenderer.Callbacks localRender; 113 private VideoRenderer.Callbacks localRender;
110 private VideoRenderer.Callbacks remoteRender; 114 private VideoRenderer.Callbacks remoteRender;
111 private SignalingParameters signalingParameters; 115 private SignalingParameters signalingParameters;
112 private MediaConstraints pcConstraints; 116 private MediaConstraints pcConstraints;
113 private MediaConstraints videoConstraints; 117 private MediaConstraints videoConstraints;
114 private MediaConstraints audioConstraints; 118 private MediaConstraints audioConstraints;
115 private ParcelFileDescriptor aecDumpFileDescriptor; 119 private ParcelFileDescriptor aecDumpFileDescriptor;
116 private MediaConstraints sdpMediaConstraints; 120 private MediaConstraints sdpMediaConstraints;
117 private PeerConnectionParameters peerConnectionParameters; 121 private PeerConnectionParameters peerConnectionParameters;
118 // Queued remote ICE candidates are consumed only after both local and 122 // Queued remote ICE candidates are consumed only after both local and
119 // remote descriptions are set. Similarly local ICE candidates are sent to 123 // remote descriptions are set. Similarly local ICE candidates are sent to
120 // remote peer after both local and remote description are set. 124 // remote peer after both local and remote description are set.
121 private LinkedList<IceCandidate> queuedRemoteCandidates; 125 private LinkedList<IceCandidate> queuedRemoteCandidates;
122 private PeerConnectionEvents events; 126 private PeerConnectionEvents events;
123 private boolean isInitiator; 127 private boolean isInitiator;
124 private SessionDescription localSdp; // either offer or answer SDP 128 private SessionDescription localSdp; // either offer or answer SDP
125 private MediaStream mediaStream; 129 private MediaStream mediaStream;
126 private int numberOfCameras; 130 private int numberOfCameras;
127 private VideoCapturerAndroid videoCapturer; 131 private CameraVideoCapturer videoCapturer;
128 // enableVideo is set to true if video should be rendered and sent. 132 // enableVideo is set to true if video should be rendered and sent.
129 private boolean renderVideo; 133 private boolean renderVideo;
130 private VideoTrack localVideoTrack; 134 private VideoTrack localVideoTrack;
131 private VideoTrack remoteVideoTrack; 135 private VideoTrack remoteVideoTrack;
132 // enableAudio is set to true if audio should be sent. 136 // enableAudio is set to true if audio should be sent.
133 private boolean enableAudio; 137 private boolean enableAudio;
134 private AudioTrack localAudioTrack; 138 private AudioTrack localAudioTrack;
135 139
136 /** 140 /**
137 * Peer connection parameters. 141 * Peer connection parameters.
138 */ 142 */
139 public static class PeerConnectionParameters { 143 public static class PeerConnectionParameters {
140 public final boolean videoCallEnabled; 144 public final boolean videoCallEnabled;
141 public final boolean loopback; 145 public final boolean loopback;
142 public final boolean tracing; 146 public final boolean tracing;
147 public final boolean useCamera2;
143 public final int videoWidth; 148 public final int videoWidth;
144 public final int videoHeight; 149 public final int videoHeight;
145 public final int videoFps; 150 public final int videoFps;
146 public final int videoStartBitrate; 151 public final int videoStartBitrate;
147 public final String videoCodec; 152 public final String videoCodec;
148 public final boolean videoCodecHwAcceleration; 153 public final boolean videoCodecHwAcceleration;
149 public final boolean captureToTexture; 154 public final boolean captureToTexture;
150 public final int audioStartBitrate; 155 public final int audioStartBitrate;
151 public final String audioCodec; 156 public final String audioCodec;
152 public final boolean noAudioProcessing; 157 public final boolean noAudioProcessing;
153 public final boolean aecDump; 158 public final boolean aecDump;
154 public final boolean useOpenSLES; 159 public final boolean useOpenSLES;
155 public final boolean disableBuiltInAEC; 160 public final boolean disableBuiltInAEC;
156 161
157 public PeerConnectionParameters( 162 public PeerConnectionParameters(
158 boolean videoCallEnabled, boolean loopback, boolean tracing, 163 boolean videoCallEnabled, boolean loopback, boolean tracing, boolean use Camera2,
159 int videoWidth, int videoHeight, int videoFps, int videoStartBitrate, 164 int videoWidth, int videoHeight, int videoFps,
160 String videoCodec, boolean videoCodecHwAcceleration, boolean captureToTe xture, 165 int videoStartBitrate, String videoCodec, boolean videoCodecHwAccelerati on,
161 int audioStartBitrate, String audioCodec, 166 boolean captureToTexture, int audioStartBitrate, String audioCodec,
162 boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES, 167 boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES,
163 boolean disableBuiltInAEC) { 168 boolean disableBuiltInAEC) {
164 this.videoCallEnabled = videoCallEnabled; 169 this.videoCallEnabled = videoCallEnabled;
170 this.useCamera2 = useCamera2;
165 this.loopback = loopback; 171 this.loopback = loopback;
166 this.tracing = tracing; 172 this.tracing = tracing;
167 this.videoWidth = videoWidth; 173 this.videoWidth = videoWidth;
168 this.videoHeight = videoHeight; 174 this.videoHeight = videoHeight;
169 this.videoFps = videoFps; 175 this.videoFps = videoFps;
170 this.videoStartBitrate = videoStartBitrate; 176 this.videoStartBitrate = videoStartBitrate;
171 this.videoCodec = videoCodec; 177 this.videoCodec = videoCodec;
172 this.videoCodecHwAcceleration = videoCodecHwAcceleration; 178 this.videoCodecHwAcceleration = videoCodecHwAcceleration;
173 this.captureToTexture = captureToTexture; 179 this.captureToTexture = captureToTexture;
174 this.audioStartBitrate = audioStartBitrate; 180 this.audioStartBitrate = audioStartBitrate;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 } 249 }
244 250
245 public void createPeerConnectionFactory( 251 public void createPeerConnectionFactory(
246 final Context context, 252 final Context context,
247 final PeerConnectionParameters peerConnectionParameters, 253 final PeerConnectionParameters peerConnectionParameters,
248 final PeerConnectionEvents events) { 254 final PeerConnectionEvents events) {
249 this.peerConnectionParameters = peerConnectionParameters; 255 this.peerConnectionParameters = peerConnectionParameters;
250 this.events = events; 256 this.events = events;
251 videoCallEnabled = peerConnectionParameters.videoCallEnabled; 257 videoCallEnabled = peerConnectionParameters.videoCallEnabled;
252 // Reset variables to initial states. 258 // Reset variables to initial states.
259 this.context = null;
253 factory = null; 260 factory = null;
254 peerConnection = null; 261 peerConnection = null;
255 preferIsac = false; 262 preferIsac = false;
256 videoSourceStopped = false; 263 videoSourceStopped = false;
257 isError = false; 264 isError = false;
258 queuedRemoteCandidates = null; 265 queuedRemoteCandidates = null;
259 localSdp = null; // either offer or answer SDP 266 localSdp = null; // either offer or answer SDP
260 mediaStream = null; 267 mediaStream = null;
261 videoCapturer = null; 268 videoCapturer = null;
262 renderVideo = true; 269 renderVideo = true;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 } 367 }
361 368
362 // Create peer connection factory. 369 // Create peer connection factory.
363 if (!PeerConnectionFactory.initializeAndroidGlobals(context, true, true, 370 if (!PeerConnectionFactory.initializeAndroidGlobals(context, true, true,
364 peerConnectionParameters.videoCodecHwAcceleration)) { 371 peerConnectionParameters.videoCodecHwAcceleration)) {
365 events.onPeerConnectionError("Failed to initializeAndroidGlobals"); 372 events.onPeerConnectionError("Failed to initializeAndroidGlobals");
366 } 373 }
367 if (options != null) { 374 if (options != null) {
368 Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMas k); 375 Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMas k);
369 } 376 }
377 this.context = context;
370 factory = new PeerConnectionFactory(options); 378 factory = new PeerConnectionFactory(options);
371 Log.d(TAG, "Peer connection factory created."); 379 Log.d(TAG, "Peer connection factory created.");
372 } 380 }
373 381
374 private void createMediaConstraintsInternal() { 382 private void createMediaConstraintsInternal() {
375 // Create peer connection constraints. 383 // Create peer connection constraints.
376 pcConstraints = new MediaConstraints(); 384 pcConstraints = new MediaConstraints();
377 // Enable DTLS for normal calls and disable for loopback calls. 385 // Enable DTLS for normal calls and disable for loopback calls.
378 if (peerConnectionParameters.loopback) { 386 if (peerConnectionParameters.loopback) {
379 pcConstraints.optional.add( 387 pcConstraints.optional.add(
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 "OfferToReceiveAudio", "true")); 457 "OfferToReceiveAudio", "true"));
450 if (videoCallEnabled || peerConnectionParameters.loopback) { 458 if (videoCallEnabled || peerConnectionParameters.loopback) {
451 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( 459 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
452 "OfferToReceiveVideo", "true")); 460 "OfferToReceiveVideo", "true"));
453 } else { 461 } else {
454 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair( 462 sdpMediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair(
455 "OfferToReceiveVideo", "false")); 463 "OfferToReceiveVideo", "false"));
456 } 464 }
457 } 465 }
458 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) {
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
459 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { 497 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) {
460 if (factory == null || isError) { 498 if (factory == null || isError) {
461 Log.e(TAG, "Peerconnection factory is not created"); 499 Log.e(TAG, "Peerconnection factory is not created");
462 return; 500 return;
463 } 501 }
464 Log.d(TAG, "Create peer connection."); 502 Log.d(TAG, "Create peer connection.");
465 503
466 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); 504 Log.d(TAG, "PCConstraints: " + pcConstraints.toString());
467 if (videoConstraints != null) { 505 if (videoConstraints != null) {
468 Log.d(TAG, "VideoConstraints: " + videoConstraints.toString()); 506 Log.d(TAG, "VideoConstraints: " + videoConstraints.toString());
(...skipping 22 matching lines...) Expand all
491 529
492 // Set default WebRTC tracing and INFO libjingle logging. 530 // Set default WebRTC tracing and INFO libjingle logging.
493 // NOTE: this _must_ happen while |factory| is alive! 531 // NOTE: this _must_ happen while |factory| is alive!
494 Logging.enableTracing( 532 Logging.enableTracing(
495 "logcat:", 533 "logcat:",
496 EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT)); 534 EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT));
497 Logging.enableLogToDebugOutput(Logging.Severity.LS_INFO); 535 Logging.enableLogToDebugOutput(Logging.Severity.LS_INFO);
498 536
499 mediaStream = factory.createLocalMediaStream("ARDAMS"); 537 mediaStream = factory.createLocalMediaStream("ARDAMS");
500 if (videoCallEnabled) { 538 if (videoCallEnabled) {
501 String cameraDeviceName = CameraEnumerationAndroid.getDeviceName(0); 539 if (peerConnectionParameters.useCamera2) {
502 String frontCameraDeviceName = 540 if (!peerConnectionParameters.captureToTexture) {
503 CameraEnumerationAndroid.getNameOfFrontFacingDevice(); 541 reportError(context.getString(R.string.camera2_texture_only_error));
504 if (numberOfCameras > 1 && frontCameraDeviceName != null) { 542 return;
505 cameraDeviceName = frontCameraDeviceName; 543 }
544
545 Logging.d(TAG, "Creating capturer using camera2 API.");
546 createCapturer(new Camera2Enumerator(context));
547 } else {
548 Logging.d(TAG, "Creating capturer using camera1 API.");
549 createCapturer(new Camera1Enumerator(peerConnectionParameters.captureToT exture));
506 } 550 }
507 Log.d(TAG, "Opening camera: " + cameraDeviceName); 551
508 videoCapturer = VideoCapturerAndroid.create(cameraDeviceName, null,
509 peerConnectionParameters.captureToTexture);
510 if (videoCapturer == null) { 552 if (videoCapturer == null) {
511 reportError("Failed to open camera"); 553 reportError("Failed to open camera");
512 return; 554 return;
513 } 555 }
514 mediaStream.addTrack(createVideoTrack(videoCapturer)); 556 mediaStream.addTrack(createVideoTrack(videoCapturer));
515 } 557 }
516 558
517 mediaStream.addTrack(createAudioTrack()); 559 mediaStream.addTrack(createAudioTrack());
518 peerConnection.addStream(mediaStream); 560 peerConnection.addStream(mediaStream);
519 561
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 }); 826 });
785 } 827 }
786 828
787 private AudioTrack createAudioTrack() { 829 private AudioTrack createAudioTrack() {
788 audioSource = factory.createAudioSource(audioConstraints); 830 audioSource = factory.createAudioSource(audioConstraints);
789 localAudioTrack = factory.createAudioTrack(AUDIO_TRACK_ID, audioSource); 831 localAudioTrack = factory.createAudioTrack(AUDIO_TRACK_ID, audioSource);
790 localAudioTrack.setEnabled(enableAudio); 832 localAudioTrack.setEnabled(enableAudio);
791 return localAudioTrack; 833 return localAudioTrack;
792 } 834 }
793 835
794 private VideoTrack createVideoTrack(VideoCapturerAndroid capturer) { 836 private VideoTrack createVideoTrack(VideoCapturer capturer) {
795 videoSource = factory.createVideoSource(capturer, videoConstraints); 837 videoSource = factory.createVideoSource(capturer, videoConstraints);
796 838
797 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); 839 localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
798 localVideoTrack.setEnabled(renderVideo); 840 localVideoTrack.setEnabled(renderVideo);
799 localVideoTrack.addRenderer(new VideoRenderer(localRender)); 841 localVideoTrack.addRenderer(new VideoRenderer(localRender));
800 return localVideoTrack; 842 return localVideoTrack;
801 } 843 }
802 844
803 private static String setStartBitrate(String codec, boolean isVideoCodec, 845 private static String setStartBitrate(String codec, boolean isVideoCodec,
804 String sdpDescription, int bitrateKbps) { 846 String sdpDescription, int bitrateKbps) {
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 public void onCreateFailure(final String error) { 1191 public void onCreateFailure(final String error) {
1150 reportError("createSDP error: " + error); 1192 reportError("createSDP error: " + error);
1151 } 1193 }
1152 1194
1153 @Override 1195 @Override
1154 public void onSetFailure(final String error) { 1196 public void onSetFailure(final String error) {
1155 reportError("setSDP error: " + error); 1197 reportError("setSDP error: " + error);
1156 } 1198 }
1157 } 1199 }
1158 } 1200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698