OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2013 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 implements PeerConnection.Observer, VideoRenderer.Callbacks, DataChannel.O
bserver, | 57 implements PeerConnection.Observer, VideoRenderer.Callbacks, DataChannel.O
bserver, |
58 StatsObserver, RTCStatsCollectorCallback, RtpReceiver.Observer
{ | 58 StatsObserver, RTCStatsCollectorCallback, RtpReceiver.Observer
{ |
59 private final String name; | 59 private final String name; |
60 private int expectedIceCandidates = 0; | 60 private int expectedIceCandidates = 0; |
61 private int expectedErrors = 0; | 61 private int expectedErrors = 0; |
62 private int expectedRenegotiations = 0; | 62 private int expectedRenegotiations = 0; |
63 private int expectedWidth = 0; | 63 private int expectedWidth = 0; |
64 private int expectedHeight = 0; | 64 private int expectedHeight = 0; |
65 private int expectedFramesDelivered = 0; | 65 private int expectedFramesDelivered = 0; |
66 private int expectedTracksAdded = 0; | 66 private int expectedTracksAdded = 0; |
| 67 private int expectedTracksRemoved = 0; |
67 private LinkedList<SignalingState> expectedSignalingChanges = new LinkedList
<SignalingState>(); | 68 private LinkedList<SignalingState> expectedSignalingChanges = new LinkedList
<SignalingState>(); |
68 private LinkedList<IceConnectionState> expectedIceConnectionChanges = | 69 private LinkedList<IceConnectionState> expectedIceConnectionChanges = |
69 new LinkedList<IceConnectionState>(); | 70 new LinkedList<IceConnectionState>(); |
70 private LinkedList<IceGatheringState> expectedIceGatheringChanges = | 71 private LinkedList<IceGatheringState> expectedIceGatheringChanges = |
71 new LinkedList<IceGatheringState>(); | 72 new LinkedList<IceGatheringState>(); |
72 private LinkedList<String> expectedAddStreamLabels = new LinkedList<String>(
); | 73 private LinkedList<String> expectedAddStreamLabels = new LinkedList<String>(
); |
73 private LinkedList<String> expectedRemoveStreamLabels = new LinkedList<Strin
g>(); | 74 private LinkedList<String> expectedRemoveStreamLabels = new LinkedList<Strin
g>(); |
74 private final LinkedList<IceCandidate> gotIceCandidates = new LinkedList<Ice
Candidate>(); | 75 private final LinkedList<IceCandidate> gotIceCandidates = new LinkedList<Ice
Candidate>(); |
75 private Map<MediaStream, WeakReference<VideoRenderer>> renderers = | 76 private Map<VideoTrack, WeakReference<VideoRenderer>> renderers = |
76 new IdentityHashMap<MediaStream, WeakReference<VideoRenderer>>(); | 77 new IdentityHashMap<VideoTrack, WeakReference<VideoRenderer>>(); |
77 private DataChannel dataChannel; | 78 private DataChannel dataChannel; |
78 private LinkedList<DataChannel.Buffer> expectedBuffers = new LinkedList<Data
Channel.Buffer>(); | 79 private LinkedList<DataChannel.Buffer> expectedBuffers = new LinkedList<Data
Channel.Buffer>(); |
79 private LinkedList<DataChannel.State> expectedStateChanges = | 80 private LinkedList<DataChannel.State> expectedStateChanges = |
80 new LinkedList<DataChannel.State>(); | 81 new LinkedList<DataChannel.State>(); |
81 private LinkedList<String> expectedRemoteDataChannelLabels = new LinkedList<
String>(); | 82 private LinkedList<String> expectedRemoteDataChannelLabels = new LinkedList<
String>(); |
82 private int expectedOldStatsCallbacks = 0; | 83 private int expectedOldStatsCallbacks = 0; |
83 private int expectedNewStatsCallbacks = 0; | 84 private int expectedNewStatsCallbacks = 0; |
84 private LinkedList<StatsReport[]> gotStatsReports = new LinkedList<StatsRepo
rt[]>(); | 85 private LinkedList<StatsReport[]> gotStatsReports = new LinkedList<StatsRepo
rt[]>(); |
85 private final HashSet<MediaStream> gotRemoteStreams = new HashSet<MediaStrea
m>(); | 86 private final HashSet<MediaStream> gotRemoteStreams = new HashSet<MediaStrea
m>(); |
86 private int expectedFirstAudioPacket = 0; | 87 private int expectedFirstAudioPacket = 0; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 | 192 |
192 @Override | 193 @Override |
193 public synchronized void onAddStream(MediaStream stream) { | 194 public synchronized void onAddStream(MediaStream stream) { |
194 assertEquals(expectedAddStreamLabels.removeFirst(), stream.label()); | 195 assertEquals(expectedAddStreamLabels.removeFirst(), stream.label()); |
195 assertEquals(1, stream.videoTracks.size()); | 196 assertEquals(1, stream.videoTracks.size()); |
196 assertEquals(1, stream.audioTracks.size()); | 197 assertEquals(1, stream.audioTracks.size()); |
197 assertTrue(stream.videoTracks.get(0).id().endsWith("VideoTrack")); | 198 assertTrue(stream.videoTracks.get(0).id().endsWith("VideoTrack")); |
198 assertTrue(stream.audioTracks.get(0).id().endsWith("AudioTrack")); | 199 assertTrue(stream.audioTracks.get(0).id().endsWith("AudioTrack")); |
199 assertEquals("video", stream.videoTracks.get(0).kind()); | 200 assertEquals("video", stream.videoTracks.get(0).kind()); |
200 assertEquals("audio", stream.audioTracks.get(0).kind()); | 201 assertEquals("audio", stream.audioTracks.get(0).kind()); |
201 VideoRenderer renderer = createVideoRenderer(this); | |
202 stream.videoTracks.get(0).addRenderer(renderer); | |
203 assertNull(renderers.put(stream, new WeakReference<VideoRenderer>(renderer
))); | |
204 gotRemoteStreams.add(stream); | 202 gotRemoteStreams.add(stream); |
205 } | 203 } |
206 | 204 |
207 public synchronized void expectRemoveStream(String label) { | 205 public synchronized void expectRemoveStream(String label) { |
208 expectedRemoveStreamLabels.add(label); | 206 expectedRemoveStreamLabels.add(label); |
209 } | 207 } |
210 | 208 |
211 @Override | 209 @Override |
212 public synchronized void onRemoveStream(MediaStream stream) { | 210 public synchronized void onRemoveStream(MediaStream stream) { |
213 assertEquals(expectedRemoveStreamLabels.removeFirst(), stream.label()); | 211 assertEquals(expectedRemoveStreamLabels.removeFirst(), stream.label()); |
214 WeakReference<VideoRenderer> renderer = renderers.remove(stream); | 212 assertEquals(0, stream.videoTracks.size()); |
215 assertNotNull(renderer); | |
216 assertNotNull(renderer.get()); | |
217 assertEquals(1, stream.videoTracks.size()); | |
218 stream.videoTracks.get(0).removeRenderer(renderer.get()); | |
219 gotRemoteStreams.remove(stream); | 213 gotRemoteStreams.remove(stream); |
220 } | 214 } |
221 | 215 |
222 public synchronized void expectDataChannel(String label) { | 216 public synchronized void expectDataChannel(String label) { |
223 expectedRemoteDataChannelLabels.add(label); | 217 expectedRemoteDataChannelLabels.add(label); |
224 } | 218 } |
225 | 219 |
226 @Override | 220 @Override |
227 public synchronized void onDataChannel(DataChannel remoteDataChannel) { | 221 public synchronized void onDataChannel(DataChannel remoteDataChannel) { |
228 assertEquals(expectedRemoteDataChannelLabels.removeFirst(), remoteDataChan
nel.label()); | 222 assertEquals(expectedRemoteDataChannelLabels.removeFirst(), remoteDataChan
nel.label()); |
229 setDataChannel(remoteDataChannel); | 223 setDataChannel(remoteDataChannel); |
230 assertEquals(DataChannel.State.CONNECTING, dataChannel.state()); | 224 assertEquals(DataChannel.State.CONNECTING, dataChannel.state()); |
231 } | 225 } |
232 | 226 |
233 public synchronized void expectRenegotiationNeeded() { | 227 public synchronized void expectRenegotiationNeeded() { |
234 ++expectedRenegotiations; | 228 ++expectedRenegotiations; |
235 } | 229 } |
236 | 230 |
237 @Override | 231 @Override |
238 public synchronized void onRenegotiationNeeded() { | 232 public synchronized void onRenegotiationNeeded() { |
239 assertTrue(--expectedRenegotiations >= 0); | 233 assertTrue(--expectedRenegotiations >= 0); |
240 } | 234 } |
241 | 235 |
242 public synchronized void expectAddTrack(int expectedTracksAdded) { | 236 public synchronized void expectAddTrack(int expectedTracksAdded) { |
243 this.expectedTracksAdded = expectedTracksAdded; | 237 this.expectedTracksAdded = expectedTracksAdded; |
244 } | 238 } |
245 | 239 |
| 240 public synchronized void expectRemoveTrack(int expectedTracksRemove) { |
| 241 this.expectedTracksRemoved = expectedTracksRemove; |
| 242 } |
| 243 |
246 @Override | 244 @Override |
247 public synchronized void onAddTrack(RtpReceiver receiver, MediaStream[] medi
aStreams) { | 245 public synchronized void onAddTrack(RtpReceiver receiver, MediaStream[] medi
aStreams) { |
248 expectedTracksAdded--; | 246 expectedTracksAdded--; |
| 247 if (receiver.track() instanceof VideoTrack) { |
| 248 VideoTrack vt = (VideoTrack) receiver.track(); |
| 249 VideoRenderer renderer = createVideoRenderer(this); |
| 250 vt.addRenderer(renderer); |
| 251 assertNull(renderers.put(vt, new WeakReference<VideoRenderer>(renderer))
); |
| 252 } |
| 253 } |
| 254 |
| 255 @Override |
| 256 public void onRemoveTrack(RtpReceiver receiver, MediaStream[] mediaStreams)
{ |
| 257 expectedTracksRemoved--; |
| 258 if (receiver.track() instanceof VideoTrack) { |
| 259 VideoTrack vt = (VideoTrack) receiver.track(); |
| 260 WeakReference<VideoRenderer> renderer = renderers.remove(vt); |
| 261 assertNotNull(renderer); |
| 262 assertNotNull(renderer.get()); |
| 263 vt.removeRenderer(renderer.get()); |
| 264 } |
249 } | 265 } |
250 | 266 |
251 public synchronized void expectMessage(ByteBuffer expectedBuffer, boolean ex
pectedBinary) { | 267 public synchronized void expectMessage(ByteBuffer expectedBuffer, boolean ex
pectedBinary) { |
252 expectedBuffers.add(new DataChannel.Buffer(expectedBuffer, expectedBinary)
); | 268 expectedBuffers.add(new DataChannel.Buffer(expectedBuffer, expectedBinary)
); |
253 } | 269 } |
254 | 270 |
255 @Override | 271 @Override |
256 public synchronized void onMessage(DataChannel.Buffer buffer) { | 272 public synchronized void onMessage(DataChannel.Buffer buffer) { |
257 DataChannel.Buffer expected = expectedBuffers.removeFirst(); | 273 DataChannel.Buffer expected = expectedBuffers.removeFirst(); |
258 assertEquals(expected.binary, buffer.binary); | 274 assertEquals(expected.binary, buffer.binary); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 } | 388 } |
373 if (expectedFirstAudioPacket > 0) { | 389 if (expectedFirstAudioPacket > 0) { |
374 stillWaitingForExpectations.add("expectedFirstAudioPacket: " + expectedF
irstAudioPacket); | 390 stillWaitingForExpectations.add("expectedFirstAudioPacket: " + expectedF
irstAudioPacket); |
375 } | 391 } |
376 if (expectedFirstVideoPacket > 0) { | 392 if (expectedFirstVideoPacket > 0) { |
377 stillWaitingForExpectations.add("expectedFirstVideoPacket: " + expectedF
irstVideoPacket); | 393 stillWaitingForExpectations.add("expectedFirstVideoPacket: " + expectedF
irstVideoPacket); |
378 } | 394 } |
379 if (expectedTracksAdded != 0) { | 395 if (expectedTracksAdded != 0) { |
380 stillWaitingForExpectations.add("expectedAddedTrack: " + expectedTracksA
dded); | 396 stillWaitingForExpectations.add("expectedAddedTrack: " + expectedTracksA
dded); |
381 } | 397 } |
| 398 if (expectedTracksRemoved != 0) { |
| 399 stillWaitingForExpectations.add("expectedTracksRemoved: " + expectedTrac
ksRemoved); |
| 400 } |
382 return stillWaitingForExpectations; | 401 return stillWaitingForExpectations; |
383 } | 402 } |
384 | 403 |
385 public boolean waitForAllExpectationsToBeSatisfied(int timeoutSeconds) { | 404 public boolean waitForAllExpectationsToBeSatisfied(int timeoutSeconds) { |
386 // TODO(fischman): problems with this approach: | 405 // TODO(fischman): problems with this approach: |
387 // - come up with something better than a poll loop | 406 // - come up with something better than a poll loop |
388 // - avoid serializing expectations explicitly; the test is not as robust | 407 // - avoid serializing expectations explicitly; the test is not as robust |
389 // as it could be because it must place expectations between wait | 408 // as it could be because it must place expectations between wait |
390 // statements very precisely (e.g. frame must not arrive before its | 409 // statements very precisely (e.g. frame must not arrive before its |
391 // expectation, and expectation must not be registered so early as to | 410 // expectation, and expectation must not be registered so early as to |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 | 1134 |
1116 assertEquals(PeerConnection.SignalingState.STABLE, offeringPC.signalingState
()); | 1135 assertEquals(PeerConnection.SignalingState.STABLE, offeringPC.signalingState
()); |
1117 assertEquals(PeerConnection.SignalingState.STABLE, answeringPC.signalingStat
e()); | 1136 assertEquals(PeerConnection.SignalingState.STABLE, answeringPC.signalingStat
e()); |
1118 | 1137 |
1119 // Now do another negotiation, removing the video track from one peer. | 1138 // Now do another negotiation, removing the video track from one peer. |
1120 // This previously caused a crash on pc.dispose(). | 1139 // This previously caused a crash on pc.dispose(). |
1121 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5128 | 1140 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5128 |
1122 VideoTrack offererVideoTrack = oLMS.get().videoTracks.get(0); | 1141 VideoTrack offererVideoTrack = oLMS.get().videoTracks.get(0); |
1123 // Note that when we call removeTrack, we regain responsibility for | 1142 // Note that when we call removeTrack, we regain responsibility for |
1124 // disposing of the track. | 1143 // disposing of the track. |
| 1144 offeringExpectations.expectRenegotiationNeeded(); |
| 1145 answeringExpectations.expectRemoveTrack(1); |
1125 oLMS.get().removeTrack(offererVideoTrack); | 1146 oLMS.get().removeTrack(offererVideoTrack); |
1126 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); | 1147 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); |
1127 | 1148 |
1128 // Make sure the track was really removed. | 1149 // Make sure the track was really removed. |
1129 // TODO(deadbeef): Currently the expectation is that the video track's | |
1130 // state will be set to "ended". However, in the future, it's likely that | |
1131 // the video track will be completely removed from the remote stream | |
1132 // (as it is on the C++ level). | |
1133 MediaStream aRMS = answeringExpectations.gotRemoteStreams.iterator().next(); | 1150 MediaStream aRMS = answeringExpectations.gotRemoteStreams.iterator().next(); |
1134 assertEquals(aRMS.videoTracks.get(0).state(), MediaStreamTrack.State.ENDED); | 1151 assertEquals(0, aRMS.videoTracks.size()); |
1135 | 1152 |
1136 // Add the video track to test if the answeringPC will create a new track | 1153 // Add the video track to test if the answeringPC will create a new track |
1137 // for the updated remote description. | 1154 // for the updated remote description. |
| 1155 offeringExpectations.expectRenegotiationNeeded(); |
1138 oLMS.get().addTrack(offererVideoTrack); | 1156 oLMS.get().addTrack(offererVideoTrack); |
1139 // The answeringPC sets the updated remote description with a track added. | 1157 // The answeringPC sets the updated remote description with a track added. |
1140 // So the onAddTrack callback is expected to be called once. | 1158 // So the onAddTrack callback is expected to be called once. |
1141 answeringExpectations.expectAddTrack(1); | 1159 answeringExpectations.expectAddTrack(1); |
1142 offeringExpectations.expectAddTrack(0); | 1160 offeringExpectations.expectAddTrack(0); |
1143 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); | 1161 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); |
| 1162 assertEquals(1, aRMS.videoTracks.size()); |
1144 | 1163 |
1145 // Finally, remove both the audio and video tracks, which should completely | 1164 // Finally, remove both the audio and video tracks, which should completely |
1146 // remove the remote stream. This used to trigger an assert. | 1165 // remove the remote stream. This used to trigger an assert. |
1147 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5128 | 1166 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5128 |
| 1167 offeringExpectations.expectRenegotiationNeeded(); |
1148 oLMS.get().removeTrack(offererVideoTrack); | 1168 oLMS.get().removeTrack(offererVideoTrack); |
1149 AudioTrack offererAudioTrack = oLMS.get().audioTracks.get(0); | 1169 AudioTrack offererAudioTrack = oLMS.get().audioTracks.get(0); |
| 1170 offeringExpectations.expectRenegotiationNeeded(); |
1150 oLMS.get().removeTrack(offererAudioTrack); | 1171 oLMS.get().removeTrack(offererAudioTrack); |
1151 | 1172 |
1152 answeringExpectations.expectRemoveStream("offeredMediaStream"); | 1173 answeringExpectations.expectRemoveStream("offeredMediaStream"); |
| 1174 answeringExpectations.expectRemoveTrack(2); |
1153 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); | 1175 negotiate(offeringPC, offeringExpectations, answeringPC, answeringExpectatio
ns); |
| 1176 assertEquals(0, aRMS.videoTracks.size()); |
| 1177 assertEquals(0, aRMS.audioTracks.size()); |
1154 | 1178 |
1155 // Make sure the stream was really removed. | 1179 // Make sure the stream was really removed. |
1156 assertTrue(answeringExpectations.gotRemoteStreams.isEmpty()); | 1180 assertTrue(answeringExpectations.gotRemoteStreams.isEmpty()); |
1157 | 1181 |
1158 // Free the Java-land objects and collect them. | 1182 // Free the Java-land objects and collect them. |
1159 shutdownPC(offeringPC, offeringExpectations); | 1183 shutdownPC(offeringPC, offeringExpectations); |
1160 offeringPC = null; | 1184 offeringPC = null; |
1161 shutdownPC(answeringPC, answeringExpectations); | 1185 shutdownPC(answeringPC, answeringExpectations); |
1162 answeringPC = null; | 1186 answeringPC = null; |
1163 offererVideoTrack.dispose(); | 1187 offererVideoTrack.dispose(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 TreeSet<String> threads = new TreeSet<String>(); | 1297 TreeSet<String> threads = new TreeSet<String>(); |
1274 // This pokes at /proc instead of using the Java APIs because we're also | 1298 // This pokes at /proc instead of using the Java APIs because we're also |
1275 // looking for libjingle/webrtc native threads, most of which won't have | 1299 // looking for libjingle/webrtc native threads, most of which won't have |
1276 // attached to the JVM. | 1300 // attached to the JVM. |
1277 for (String threadId : (new File("/proc/self/task")).list()) { | 1301 for (String threadId : (new File("/proc/self/task")).list()) { |
1278 threads.add(threadId); | 1302 threads.add(threadId); |
1279 } | 1303 } |
1280 return threads; | 1304 return threads; |
1281 } | 1305 } |
1282 } | 1306 } |
OLD | NEW |