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

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

Issue 2273573003: Support for video file instead of camera and output video out to file (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixed review comments. Unittests in follow up CL. Created 4 years, 2 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
(...skipping 23 matching lines...) Expand all
34 import org.webrtc.PeerConnection.IceConnectionState; 34 import org.webrtc.PeerConnection.IceConnectionState;
35 import org.webrtc.PeerConnectionFactory; 35 import org.webrtc.PeerConnectionFactory;
36 import org.webrtc.RtpParameters; 36 import org.webrtc.RtpParameters;
37 import org.webrtc.RtpSender; 37 import org.webrtc.RtpSender;
38 import org.webrtc.SdpObserver; 38 import org.webrtc.SdpObserver;
39 import org.webrtc.SessionDescription; 39 import org.webrtc.SessionDescription;
40 import org.webrtc.StatsObserver; 40 import org.webrtc.StatsObserver;
41 import org.webrtc.StatsReport; 41 import org.webrtc.StatsReport;
42 import org.webrtc.VideoCapturer; 42 import org.webrtc.VideoCapturer;
43 import org.webrtc.VideoRenderer; 43 import org.webrtc.VideoRenderer;
44 import org.webrtc.VideoCapturerAndroid;
45 import org.webrtc.CameraVideoCapturer;
46 import org.webrtc.FileVideoCapturer;
44 import org.webrtc.VideoSource; 47 import org.webrtc.VideoSource;
45 import org.webrtc.VideoTrack; 48 import org.webrtc.VideoTrack;
46 import org.webrtc.voiceengine.WebRtcAudioManager; 49 import org.webrtc.voiceengine.WebRtcAudioManager;
47 import org.webrtc.voiceengine.WebRtcAudioUtils; 50 import org.webrtc.voiceengine.WebRtcAudioUtils;
48 51
49 import java.io.File; 52 import java.io.File;
50 import java.io.IOException; 53 import java.io.IOException;
54 import java.util.Collections;
51 import java.util.EnumSet; 55 import java.util.EnumSet;
52 import java.util.LinkedList; 56 import java.util.LinkedList;
57 import java.util.List;
53 import java.util.Timer; 58 import java.util.Timer;
54 import java.util.TimerTask; 59 import java.util.TimerTask;
55 import java.util.concurrent.Executors; 60 import java.util.concurrent.Executors;
56 import java.util.concurrent.ScheduledExecutorService; 61 import java.util.concurrent.ScheduledExecutorService;
57 import java.util.regex.Matcher; 62 import java.util.regex.Matcher;
58 import java.util.regex.Pattern; 63 import java.util.regex.Pattern;
59 64
60 /** 65 /**
61 * Peer connection client implementation. 66 * Peer connection client implementation.
62 * 67 *
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 PeerConnectionFactory.Options options = null; 105 PeerConnectionFactory.Options options = null;
101 private AudioSource audioSource; 106 private AudioSource audioSource;
102 private VideoSource videoSource; 107 private VideoSource videoSource;
103 private boolean videoCallEnabled; 108 private boolean videoCallEnabled;
104 private boolean preferIsac; 109 private boolean preferIsac;
105 private String preferredVideoCodec; 110 private String preferredVideoCodec;
106 private boolean videoCapturerStopped; 111 private boolean videoCapturerStopped;
107 private boolean isError; 112 private boolean isError;
108 private Timer statsTimer; 113 private Timer statsTimer;
109 private VideoRenderer.Callbacks localRender; 114 private VideoRenderer.Callbacks localRender;
110 private VideoRenderer.Callbacks remoteRender; 115 private List<VideoRenderer.Callbacks> remoteRenders;
111 private SignalingParameters signalingParameters; 116 private SignalingParameters signalingParameters;
112 private MediaConstraints pcConstraints; 117 private MediaConstraints pcConstraints;
113 private int videoWidth; 118 private int videoWidth;
114 private int videoHeight; 119 private int videoHeight;
115 private int videoFps; 120 private int videoFps;
116 private MediaConstraints audioConstraints; 121 private MediaConstraints audioConstraints;
117 private ParcelFileDescriptor aecDumpFileDescriptor; 122 private ParcelFileDescriptor aecDumpFileDescriptor;
118 private MediaConstraints sdpMediaConstraints; 123 private MediaConstraints sdpMediaConstraints;
119 private PeerConnectionParameters peerConnectionParameters; 124 private PeerConnectionParameters peerConnectionParameters;
120 // Queued remote ICE candidates are consumed only after both local and 125 // Queued remote ICE candidates are consumed only after both local and
121 // remote descriptions are set. Similarly local ICE candidates are sent to 126 // remote descriptions are set. Similarly local ICE candidates are sent to
122 // remote peer after both local and remote description are set. 127 // remote peer after both local and remote description are set.
123 private LinkedList<IceCandidate> queuedRemoteCandidates; 128 private LinkedList<IceCandidate> queuedRemoteCandidates;
124 private PeerConnectionEvents events; 129 private PeerConnectionEvents events;
125 private boolean isInitiator; 130 private boolean isInitiator;
126 private SessionDescription localSdp; // either offer or answer SDP 131 private SessionDescription localSdp; // either offer or answer SDP
127 private MediaStream mediaStream; 132 private MediaStream mediaStream;
128 private int numberOfCameras; 133 private int numberOfCameras;
129 private CameraVideoCapturer videoCapturer; 134 private VideoCapturer videoCapturer;
130 // enableVideo is set to true if video should be rendered and sent. 135 // enableVideo is set to true if video should be rendered and sent.
131 private boolean renderVideo; 136 private boolean renderVideo;
132 private VideoTrack localVideoTrack; 137 private VideoTrack localVideoTrack;
133 private VideoTrack remoteVideoTrack; 138 private VideoTrack remoteVideoTrack;
134 private RtpSender localVideoSender; 139 private RtpSender localVideoSender;
135 // enableAudio is set to true if audio should be sent. 140 // enableAudio is set to true if audio should be sent.
136 private boolean enableAudio; 141 private boolean enableAudio;
137 private AudioTrack localAudioTrack; 142 private AudioTrack localAudioTrack;
138 143
139 /** 144 /**
140 * Peer connection parameters. 145 * Peer connection parameters.
141 */ 146 */
142 public static class PeerConnectionParameters { 147 public static class PeerConnectionParameters {
143 public final boolean videoCallEnabled; 148 public final boolean videoCallEnabled;
144 public final boolean loopback; 149 public final boolean loopback;
145 public final boolean tracing; 150 public final boolean tracing;
146 public final boolean useCamera2;
147 public final int videoWidth; 151 public final int videoWidth;
148 public final int videoHeight; 152 public final int videoHeight;
149 public final int videoFps; 153 public final int videoFps;
150 public final int videoMaxBitrate; 154 public final int videoMaxBitrate;
151 public final String videoCodec; 155 public final String videoCodec;
152 public final boolean videoCodecHwAcceleration; 156 public final boolean videoCodecHwAcceleration;
153 public final boolean captureToTexture;
154 public final int audioStartBitrate; 157 public final int audioStartBitrate;
155 public final String audioCodec; 158 public final String audioCodec;
156 public final boolean noAudioProcessing; 159 public final boolean noAudioProcessing;
157 public final boolean aecDump; 160 public final boolean aecDump;
158 public final boolean useOpenSLES; 161 public final boolean useOpenSLES;
159 public final boolean disableBuiltInAEC; 162 public final boolean disableBuiltInAEC;
160 public final boolean disableBuiltInAGC; 163 public final boolean disableBuiltInAGC;
161 public final boolean disableBuiltInNS; 164 public final boolean disableBuiltInNS;
162 public final boolean enableLevelControl; 165 public final boolean enableLevelControl;
163 166
164 public PeerConnectionParameters(boolean videoCallEnabled, boolean loopback, boolean tracing, 167 public PeerConnectionParameters(
165 boolean useCamera2, int videoWidth, int videoHeight, int videoFps, int v ideoMaxBitrate, 168 boolean videoCallEnabled, boolean loopback, boolean tracing,
166 String videoCodec, boolean videoCodecHwAcceleration, boolean captureToTe xture, 169 int videoWidth, int videoHeight, int videoFps,
167 int audioStartBitrate, String audioCodec, boolean noAudioProcessing, boo lean aecDump, 170 int videoMaxBitrate, String videoCodec, boolean videoCodecHwAcceleration ,
168 boolean useOpenSLES, boolean disableBuiltInAEC, boolean disableBuiltInAG C, 171 int audioStartBitrate, String audioCodec,
169 boolean disableBuiltInNS, boolean enableLevelControl) { 172 boolean noAudioProcessing, boolean aecDump, boolean useOpenSLES,
173 boolean disableBuiltInAEC, boolean disableBuiltInAGC, boolean disableBui ltInNS,
174 boolean enableLevelControl) {
175
170 this.videoCallEnabled = videoCallEnabled; 176 this.videoCallEnabled = videoCallEnabled;
171 this.useCamera2 = useCamera2;
172 this.loopback = loopback; 177 this.loopback = loopback;
173 this.tracing = tracing; 178 this.tracing = tracing;
174 this.videoWidth = videoWidth; 179 this.videoWidth = videoWidth;
175 this.videoHeight = videoHeight; 180 this.videoHeight = videoHeight;
176 this.videoFps = videoFps; 181 this.videoFps = videoFps;
177 this.videoMaxBitrate = videoMaxBitrate; 182 this.videoMaxBitrate = videoMaxBitrate;
178 this.videoCodec = videoCodec; 183 this.videoCodec = videoCodec;
179 this.videoCodecHwAcceleration = videoCodecHwAcceleration; 184 this.videoCodecHwAcceleration = videoCodecHwAcceleration;
180 this.captureToTexture = captureToTexture;
181 this.audioStartBitrate = audioStartBitrate; 185 this.audioStartBitrate = audioStartBitrate;
182 this.audioCodec = audioCodec; 186 this.audioCodec = audioCodec;
183 this.noAudioProcessing = noAudioProcessing; 187 this.noAudioProcessing = noAudioProcessing;
184 this.aecDump = aecDump; 188 this.aecDump = aecDump;
185 this.useOpenSLES = useOpenSLES; 189 this.useOpenSLES = useOpenSLES;
186 this.disableBuiltInAEC = disableBuiltInAEC; 190 this.disableBuiltInAEC = disableBuiltInAEC;
187 this.disableBuiltInAGC = disableBuiltInAGC; 191 this.disableBuiltInAGC = disableBuiltInAGC;
188 this.disableBuiltInNS = disableBuiltInNS; 192 this.disableBuiltInNS = disableBuiltInNS;
189 this.enableLevelControl = enableLevelControl; 193 this.enableLevelControl = enableLevelControl;
190 } 194 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 statsTimer = new Timer(); 281 statsTimer = new Timer();
278 282
279 executor.execute(new Runnable() { 283 executor.execute(new Runnable() {
280 @Override 284 @Override
281 public void run() { 285 public void run() {
282 createPeerConnectionFactoryInternal(context); 286 createPeerConnectionFactoryInternal(context);
283 } 287 }
284 }); 288 });
285 } 289 }
286 290
287 public void createPeerConnection(final EglBase.Context renderEGLContext, 291 public void createPeerConnection(
288 final VideoRenderer.Callbacks localRender, final VideoRenderer.Callbacks r emoteRender, 292 final EglBase.Context renderEGLContext,
293 final VideoRenderer.Callbacks localRender,
294 final VideoRenderer.Callbacks remoteRender,
295 final VideoCapturer videoCapturer,
296 final SignalingParameters signalingParameters) {
297 createPeerConnection(
298 renderEGLContext,
299 localRender,
300 Collections.singletonList(remoteRender),
301 videoCapturer,
302 signalingParameters);
303 }
304 public void createPeerConnection(
305 final EglBase.Context renderEGLContext,
306 final VideoRenderer.Callbacks localRender,
307 final List<VideoRenderer.Callbacks> remoteRenders,
308 final VideoCapturer videoCapturer,
289 final SignalingParameters signalingParameters) { 309 final SignalingParameters signalingParameters) {
290 if (peerConnectionParameters == null) { 310 if (peerConnectionParameters == null) {
291 Log.e(TAG, "Creating peer connection without initializing factory."); 311 Log.e(TAG, "Creating peer connection without initializing factory.");
292 return; 312 return;
293 } 313 }
294 this.localRender = localRender; 314 this.localRender = localRender;
295 this.remoteRender = remoteRender; 315 this.remoteRenders = remoteRenders;
316 this.videoCapturer = videoCapturer;
296 this.signalingParameters = signalingParameters; 317 this.signalingParameters = signalingParameters;
297 executor.execute(new Runnable() { 318 executor.execute(new Runnable() {
298 @Override 319 @Override
299 public void run() { 320 public void run() {
300 try { 321 try {
301 createMediaConstraintsInternal(); 322 createMediaConstraintsInternal();
302 createPeerConnectionInternal(renderEGLContext); 323 createPeerConnectionInternal(renderEGLContext);
303 } catch (Exception e) { 324 } catch (Exception e) {
304 reportError("Failed to create peer connection: " + e.getMessage()); 325 reportError("Failed to create peer connection: " + e.getMessage());
305 throw e; 326 throw e;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")); 482 new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
462 if (videoCallEnabled || peerConnectionParameters.loopback) { 483 if (videoCallEnabled || peerConnectionParameters.loopback) {
463 sdpMediaConstraints.mandatory.add( 484 sdpMediaConstraints.mandatory.add(
464 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true")); 485 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
465 } else { 486 } else {
466 sdpMediaConstraints.mandatory.add( 487 sdpMediaConstraints.mandatory.add(
467 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false")); 488 new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "false"));
468 } 489 }
469 } 490 }
470 491
471 private void createCapturer(CameraEnumerator enumerator) {
472 final String[] deviceNames = enumerator.getDeviceNames();
473
474 // First, try to find front facing camera
475 Logging.d(TAG, "Looking for front facing cameras.");
476 for (String deviceName : deviceNames) {
477 if (enumerator.isFrontFacing(deviceName)) {
478 Logging.d(TAG, "Creating front facing camera capturer.");
479 videoCapturer = enumerator.createCapturer(deviceName, null);
480
481 if (videoCapturer != null) {
482 return;
483 }
484 }
485 }
486
487 // Front facing camera not found, try something else
488 Logging.d(TAG, "Looking for other cameras.");
489 for (String deviceName : deviceNames) {
490 if (!enumerator.isFrontFacing(deviceName)) {
491 Logging.d(TAG, "Creating other camera capturer.");
492 videoCapturer = enumerator.createCapturer(deviceName, null);
493
494 if (videoCapturer != null) {
495 return;
496 }
497 }
498 }
499 }
500
501 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) { 492 private void createPeerConnectionInternal(EglBase.Context renderEGLContext) {
502 if (factory == null || isError) { 493 if (factory == null || isError) {
503 Log.e(TAG, "Peerconnection factory is not created"); 494 Log.e(TAG, "Peerconnection factory is not created");
504 return; 495 return;
505 } 496 }
506 Log.d(TAG, "Create peer connection."); 497 Log.d(TAG, "Create peer connection.");
507 498
508 Log.d(TAG, "PCConstraints: " + pcConstraints.toString()); 499 Log.d(TAG, "PCConstraints: " + pcConstraints.toString());
509 queuedRemoteCandidates = new LinkedList<IceCandidate>(); 500 queuedRemoteCandidates = new LinkedList<IceCandidate>();
510 501
(...skipping 16 matching lines...) Expand all
527 peerConnection = factory.createPeerConnection(rtcConfig, pcConstraints, pcOb server); 518 peerConnection = factory.createPeerConnection(rtcConfig, pcConstraints, pcOb server);
528 isInitiator = false; 519 isInitiator = false;
529 520
530 // Set default WebRTC tracing and INFO libjingle logging. 521 // Set default WebRTC tracing and INFO libjingle logging.
531 // NOTE: this _must_ happen while |factory| is alive! 522 // NOTE: this _must_ happen while |factory| is alive!
532 Logging.enableTracing("logcat:", EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT )); 523 Logging.enableTracing("logcat:", EnumSet.of(Logging.TraceLevel.TRACE_DEFAULT ));
533 Logging.enableLogToDebugOutput(Logging.Severity.LS_INFO); 524 Logging.enableLogToDebugOutput(Logging.Severity.LS_INFO);
534 525
535 mediaStream = factory.createLocalMediaStream("ARDAMS"); 526 mediaStream = factory.createLocalMediaStream("ARDAMS");
536 if (videoCallEnabled) { 527 if (videoCallEnabled) {
537 if (peerConnectionParameters.useCamera2) {
538 if (!peerConnectionParameters.captureToTexture) {
539 reportError(context.getString(R.string.camera2_texture_only_error));
540 return;
541 }
542
543 Logging.d(TAG, "Creating capturer using camera2 API.");
544 createCapturer(new Camera2Enumerator(context));
545 } else {
546 Logging.d(TAG, "Creating capturer using camera1 API.");
547 createCapturer(new Camera1Enumerator(peerConnectionParameters.captureToT exture));
548 }
549
550 if (videoCapturer == null) {
551 reportError("Failed to open camera");
552 return;
553 }
554 mediaStream.addTrack(createVideoTrack(videoCapturer)); 528 mediaStream.addTrack(createVideoTrack(videoCapturer));
555 } 529 }
556 530
557 mediaStream.addTrack(createAudioTrack()); 531 mediaStream.addTrack(createAudioTrack());
558 peerConnection.addStream(mediaStream); 532 peerConnection.addStream(mediaStream);
559 if (videoCallEnabled) { 533 if (videoCallEnabled) {
560 findVideoSender(); 534 findVideoSender();
561 } 535 }
562 536
563 if (peerConnectionParameters.aecDump) { 537 if (peerConnectionParameters.aecDump) {
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 if (queuedRemoteCandidates != null) { 970 if (queuedRemoteCandidates != null) {
997 Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates"); 971 Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates");
998 for (IceCandidate candidate : queuedRemoteCandidates) { 972 for (IceCandidate candidate : queuedRemoteCandidates) {
999 peerConnection.addIceCandidate(candidate); 973 peerConnection.addIceCandidate(candidate);
1000 } 974 }
1001 queuedRemoteCandidates = null; 975 queuedRemoteCandidates = null;
1002 } 976 }
1003 } 977 }
1004 978
1005 private void switchCameraInternal() { 979 private void switchCameraInternal() {
1006 if (!videoCallEnabled || numberOfCameras < 2 || isError || videoCapturer == null) { 980 if (videoCapturer instanceof CameraVideoCapturer) {
1007 Log.e(TAG, "Failed to switch camera. Video: " + videoCallEnabled + ". Erro r : " + isError 981 if (!videoCallEnabled || numberOfCameras < 2 || isError || videoCapturer = = null) {
1008 + ". Number of cameras: " + numberOfCameras); 982 Log.e(TAG, "Failed to switch camera. Video: " + videoCallEnabled +
1009 return; // No video is sent or only one camera is available or error happe ned. 983 ". Error : " + isError + ". Number of cameras: " + numberOfCameras);
984 return; // No video is sent or only one camera is available or error hap pened.
985 }
986 Log.d(TAG, "Switch camera");
987 CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer)videoCaptur er;
988 cameraVideoCapturer.switchCamera(null);
989 } else {
990 Log.d(TAG, "Will not switch camera, video caputurer is not a camera");
1010 } 991 }
1011 Log.d(TAG, "Switch camera");
1012 videoCapturer.switchCamera(null);
1013 } 992 }
1014 993
1015 public void switchCamera() { 994 public void switchCamera() {
1016 executor.execute(new Runnable() { 995 executor.execute(new Runnable() {
1017 @Override 996 @Override
1018 public void run() { 997 public void run() {
1019 switchCameraInternal(); 998 switchCameraInternal();
1020 } 999 }
1021 }); 1000 });
1022 } 1001 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 if (peerConnection == null || isError) { 1081 if (peerConnection == null || isError) {
1103 return; 1082 return;
1104 } 1083 }
1105 if (stream.audioTracks.size() > 1 || stream.videoTracks.size() > 1) { 1084 if (stream.audioTracks.size() > 1 || stream.videoTracks.size() > 1) {
1106 reportError("Weird-looking stream: " + stream); 1085 reportError("Weird-looking stream: " + stream);
1107 return; 1086 return;
1108 } 1087 }
1109 if (stream.videoTracks.size() == 1) { 1088 if (stream.videoTracks.size() == 1) {
1110 remoteVideoTrack = stream.videoTracks.get(0); 1089 remoteVideoTrack = stream.videoTracks.get(0);
1111 remoteVideoTrack.setEnabled(renderVideo); 1090 remoteVideoTrack.setEnabled(renderVideo);
1112 remoteVideoTrack.addRenderer(new VideoRenderer(remoteRender)); 1091 for (VideoRenderer.Callbacks remoteRender : remoteRenders) {
1092 remoteVideoTrack.addRenderer(new VideoRenderer(remoteRender));
1093 }
1113 } 1094 }
1114 } 1095 }
1115 }); 1096 });
1116 } 1097 }
1117 1098
1118 @Override 1099 @Override
1119 public void onRemoveStream(final MediaStream stream) { 1100 public void onRemoveStream(final MediaStream stream) {
1120 executor.execute(new Runnable() { 1101 executor.execute(new Runnable() {
1121 @Override 1102 @Override
1122 public void run() { 1103 public void run() {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 public void onCreateFailure(final String error) { 1191 public void onCreateFailure(final String error) {
1211 reportError("createSDP error: " + error); 1192 reportError("createSDP error: " + error);
1212 } 1193 }
1213 1194
1214 @Override 1195 @Override
1215 public void onSetFailure(final String error) { 1196 public void onSetFailure(final String error) {
1216 reportError("setSDP error: " + error); 1197 reportError("setSDP error: " + error);
1217 } 1198 }
1218 } 1199 }
1219 } 1200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698