3 * Copyright 2012, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "talk/app/webrtc/audiotrack.h"
32 #include "talk/app/webrtc/mediastream.h"
33 #include "talk/app/webrtc/mediastreamsignaling.h"
34 #include "talk/app/webrtc/sctputils.h"
35 #include "talk/app/webrtc/streamcollection.h"
36 #include "talk/app/webrtc/test/fakeconstraints.h"
37 #include "talk/app/webrtc/test/fakedatachannelprovider.h"
38 #include "talk/app/webrtc/videotrack.h"
39 #include "talk/media/base/fakemediaengine.h"
40 #include "talk/media/devices/fakedevicemanager.h"
41 #include "webrtc/p2p/base/constants.h"
42 #include "webrtc/p2p/base/sessiondescription.h"
43 #include "talk/session/media/channelmanager.h"
44 #include "webrtc/base/gunit.h"
45 #include "webrtc/base/scoped_ptr.h"
46 #include "webrtc/base/stringutils.h"
47 #include "webrtc/base/thread.h"
49 static const char kStreams[][8] = {"stream1", "stream2"};
50 static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"};
51 static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"};
53 using webrtc::AudioTrack;
54 using webrtc::AudioTrackInterface;
55 using webrtc::AudioTrackVector;
56 using webrtc::VideoTrack;
57 using webrtc::VideoTrackInterface;
58 using webrtc::VideoTrackVector;
59 using webrtc::DataChannelInterface;
60 using webrtc::FakeConstraints;
61 using webrtc::IceCandidateInterface;
62 using webrtc::MediaConstraintsInterface;
63 using webrtc::MediaStreamInterface;
64 using webrtc::MediaStreamTrackInterface;
65 using webrtc::PeerConnectionInterface;
66 using webrtc::SdpParseError;
67 using webrtc::SessionDescriptionInterface;
68 using webrtc::StreamCollection;
69 using webrtc::StreamCollectionInterface;
71 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
73 // Reference SDP with a MediaStream with label "stream1" and audio track with
74 // id "audio_1" and a video track with id "video_1;
75 static const char kSdpStringWithStream1[] =
77 "o=- 0 0 IN IP4 127.0.0.1\r\n"
80 "m=audio 1 RTP/AVPF 103\r\n"
82 "a=rtpmap:103 ISAC/16000\r\n"
83 "a=ssrc:1 cname:stream1\r\n"
84 "a=ssrc:1 mslabel:stream1\r\n"
85 "a=ssrc:1 label:audiotrack0\r\n"
86 "m=video 1 RTP/AVPF 120\r\n"
88 "a=rtpmap:120 VP8/90000\r\n"
89 "a=ssrc:2 cname:stream1\r\n"
90 "a=ssrc:2 mslabel:stream1\r\n"
91 "a=ssrc:2 label:videotrack0\r\n";
93 // Reference SDP with two MediaStreams with label "stream1" and "stream2. Each
94 // MediaStreams have one audio track and one video track.
96 static const char kSdpStringWith2Stream[] =
98 "o=- 0 0 IN IP4 127.0.0.1\r\n"
101 "a=msid-semantic: WMS stream1 stream2\r\n"
102 "m=audio 1 RTP/AVPF 103\r\n"
104 "a=rtpmap:103 ISAC/16000\r\n"
105 "a=ssrc:1 cname:stream1\r\n"
106 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
107 "a=ssrc:3 cname:stream2\r\n"
108 "a=ssrc:3 msid:stream2 audiotrack1\r\n"
109 "m=video 1 RTP/AVPF 120\r\n"
111 "a=rtpmap:120 VP8/0\r\n"
112 "a=ssrc:2 cname:stream1\r\n"
113 "a=ssrc:2 msid:stream1 videotrack0\r\n"
114 "a=ssrc:4 cname:stream2\r\n"
115 "a=ssrc:4 msid:stream2 videotrack1\r\n";
117 // Reference SDP without MediaStreams. Msid is not supported.
118 static const char kSdpStringWithoutStreams[] =
120 "o=- 0 0 IN IP4 127.0.0.1\r\n"
123 "m=audio 1 RTP/AVPF 103\r\n"
125 "a=rtpmap:103 ISAC/16000\r\n"
126 "m=video 1 RTP/AVPF 120\r\n"
128 "a=rtpmap:120 VP8/90000\r\n";
130 // Reference SDP without MediaStreams. Msid is supported.
131 static const char kSdpStringWithMsidWithoutStreams[] =
133 "o=- 0 0 IN IP4 127.0.0.1\r\n"
136 "a=msid-semantic: WMS\r\n"
137 "m=audio 1 RTP/AVPF 103\r\n"
139 "a=rtpmap:103 ISAC/16000\r\n"
140 "m=video 1 RTP/AVPF 120\r\n"
142 "a=rtpmap:120 VP8/90000\r\n";
144 // Reference SDP without MediaStreams and audio only.
145 static const char kSdpStringWithoutStreamsAudioOnly[] =
147 "o=- 0 0 IN IP4 127.0.0.1\r\n"
150 "m=audio 1 RTP/AVPF 103\r\n"
152 "a=rtpmap:103 ISAC/16000\r\n";
154 // Reference SENDONLY SDP without MediaStreams. Msid is not supported.
155 static const char kSdpStringSendOnlyWithWithoutStreams[] =
157 "o=- 0 0 IN IP4 127.0.0.1\r\n"
160 "m=audio 1 RTP/AVPF 103\r\n"
163 "a=rtpmap:103 ISAC/16000\r\n"
164 "m=video 1 RTP/AVPF 120\r\n"
167 "a=rtpmap:120 VP8/90000\r\n";
169 static const char kSdpStringInit[] =
171 "o=- 0 0 IN IP4 127.0.0.1\r\n"
174 "a=msid-semantic: WMS\r\n";
176 static const char kSdpStringAudio[] =
177 "m=audio 1 RTP/AVPF 103\r\n"
179 "a=rtpmap:103 ISAC/16000\r\n";
181 static const char kSdpStringVideo[] =
182 "m=video 1 RTP/AVPF 120\r\n"
184 "a=rtpmap:120 VP8/90000\r\n";
186 static const char kSdpStringMs1Audio0[] =
187 "a=ssrc:1 cname:stream1\r\n"
188 "a=ssrc:1 msid:stream1 audiotrack0\r\n";
190 static const char kSdpStringMs1Video0[] =
191 "a=ssrc:2 cname:stream1\r\n"
192 "a=ssrc:2 msid:stream1 videotrack0\r\n";
194 static const char kSdpStringMs1Audio1[] =
195 "a=ssrc:3 cname:stream1\r\n"
196 "a=ssrc:3 msid:stream1 audiotrack1\r\n";
198 static const char kSdpStringMs1Video1[] =
199 "a=ssrc:4 cname:stream1\r\n"
200 "a=ssrc:4 msid:stream1 videotrack1\r\n";
202 // Verifies that |options| contain all tracks in |collection| and that
203 // the |options| has set the the has_audio and has_video flags correct.
204 static void VerifyMediaOptions(StreamCollectionInterface* collection,
205 const cricket::MediaSessionOptions& options) {
210 size_t stream_index = 0;
211 for (size_t i = 0; i < collection->count(); ++i) {
212 MediaStreamInterface* stream = collection->at(i);
213 AudioTrackVector audio_tracks = stream->GetAudioTracks();
214 ASSERT_GE(options.streams.size(), stream_index + audio_tracks.size());
215 for (size_t j = 0; j < audio_tracks.size(); ++j) {
216 webrtc::AudioTrackInterface* audio = audio_tracks[j];
217 EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
218 EXPECT_EQ(options.streams[stream_index++].id, audio->id());
219 EXPECT_TRUE(options.has_audio());
221 VideoTrackVector video_tracks = stream->GetVideoTracks();
222 ASSERT_GE(options.streams.size(), stream_index + video_tracks.size());
223 for (size_t j = 0; j < video_tracks.size(); ++j) {
224 webrtc::VideoTrackInterface* video = video_tracks[j];
225 EXPECT_EQ(options.streams[stream_index].sync_label, stream->label());
226 EXPECT_EQ(options.streams[stream_index++].id, video->id());
227 EXPECT_TRUE(options.has_video());
232 static bool CompareStreamCollections(StreamCollectionInterface* s1,
233 StreamCollectionInterface* s2) {
234 if (s1 == NULL || s2 == NULL || s1->count() != s2->count())
237 for (size_t i = 0; i != s1->count(); ++i) {
238 if (s1->at(i)->label() != s2->at(i)->label())
240 webrtc::AudioTrackVector audio_tracks1 = s1->at(i)->GetAudioTracks();
241 webrtc::AudioTrackVector audio_tracks2 = s2->at(i)->GetAudioTracks();
242 webrtc::VideoTrackVector video_tracks1 = s1->at(i)->GetVideoTracks();
243 webrtc::VideoTrackVector video_tracks2 = s2->at(i)->GetVideoTracks();
245 if (audio_tracks1.size() != audio_tracks2.size())
247 for (size_t j = 0; j != audio_tracks1.size(); ++j) {
248 if (audio_tracks1[j]->id() != audio_tracks2[j]->id())
251 if (video_tracks1.size() != video_tracks2.size())
253 for (size_t j = 0; j != video_tracks1.size(); ++j) {
254 if (video_tracks1[j]->id() != video_tracks2[j]->id())
261 class FakeDataChannelFactory : public webrtc::DataChannelFactory {
263 FakeDataChannelFactory(FakeDataChannelProvider* provider,
264 cricket::DataChannelType dct,
265 webrtc::MediaStreamSignaling* media_stream_signaling)
266 : provider_(provider),
268 media_stream_signaling_(media_stream_signaling) {}
270 virtual rtc::scoped_refptr<webrtc::DataChannel> CreateDataChannel(
271 const std::string& label,
272 const webrtc::InternalDataChannelInit* config) {
273 last_init_ = *config;
274 rtc::scoped_refptr<webrtc::DataChannel> data_channel =
275 webrtc::DataChannel::Create(provider_, type_, label, *config);
276 media_stream_signaling_->AddDataChannel(data_channel);
280 const webrtc::InternalDataChannelInit& last_init() const {
285 FakeDataChannelProvider* provider_;
286 cricket::DataChannelType type_;
287 webrtc::MediaStreamSignaling* media_stream_signaling_;
288 webrtc::InternalDataChannelInit last_init_;
291 class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
293 MockSignalingObserver()
294 : remote_media_streams_(StreamCollection::Create()) {
297 virtual ~MockSignalingObserver() {
300 // New remote stream have been discovered.
301 virtual void OnAddRemoteStream(MediaStreamInterface* remote_stream) {
302 remote_media_streams_->AddStream(remote_stream);
305 // Remote stream is no longer available.
306 virtual void OnRemoveRemoteStream(MediaStreamInterface* remote_stream) {
307 remote_media_streams_->RemoveStream(remote_stream);
310 virtual void OnAddDataChannel(DataChannelInterface* data_channel) {
313 virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream,
314 AudioTrackInterface* audio_track,
316 AddTrack(&local_audio_tracks_, stream, audio_track, ssrc);
319 virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream,
320 VideoTrackInterface* video_track,
322 AddTrack(&local_video_tracks_, stream, video_track, ssrc);
325 virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
326 AudioTrackInterface* audio_track,
328 RemoveTrack(&local_audio_tracks_, stream, audio_track);
331 virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
332 VideoTrackInterface* video_track) {
333 RemoveTrack(&local_video_tracks_, stream, video_track);
336 virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream,
337 AudioTrackInterface* audio_track,
339 AddTrack(&remote_audio_tracks_, stream, audio_track, ssrc);
342 virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
343 VideoTrackInterface* video_track,
345 AddTrack(&remote_video_tracks_, stream, video_track, ssrc);
348 virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
349 AudioTrackInterface* audio_track) {
350 RemoveTrack(&remote_audio_tracks_, stream, audio_track);
353 virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream,
354 VideoTrackInterface* video_track) {
355 RemoveTrack(&remote_video_tracks_, stream, video_track);
358 virtual void OnRemoveLocalStream(MediaStreamInterface* stream) {
361 MediaStreamInterface* RemoteStream(const std::string& label) {
362 return remote_media_streams_->find(label);
365 StreamCollectionInterface* remote_streams() const {
366 return remote_media_streams_;
369 size_t NumberOfRemoteAudioTracks() { return remote_audio_tracks_.size(); }
371 void VerifyRemoteAudioTrack(const std::string& stream_label,
372 const std::string& track_id,
374 VerifyTrack(remote_audio_tracks_, stream_label, track_id, ssrc);
377 size_t NumberOfRemoteVideoTracks() { return remote_video_tracks_.size(); }
379 void VerifyRemoteVideoTrack(const std::string& stream_label,
380 const std::string& track_id,
382 VerifyTrack(remote_video_tracks_, stream_label, track_id, ssrc);
385 size_t NumberOfLocalAudioTracks() { return local_audio_tracks_.size(); }
386 void VerifyLocalAudioTrack(const std::string& stream_label,
387 const std::string& track_id,
389 VerifyTrack(local_audio_tracks_, stream_label, track_id, ssrc);
392 size_t NumberOfLocalVideoTracks() { return local_video_tracks_.size(); }
394 void VerifyLocalVideoTrack(const std::string& stream_label,
395 const std::string& track_id,
397 VerifyTrack(local_video_tracks_, stream_label, track_id, ssrc);
403 TrackInfo(const std::string& stream_label, const std::string track_id,
405 : stream_label(stream_label),
409 std::string stream_label;
410 std::string track_id;
413 typedef std::vector<TrackInfo> TrackInfos;
415 void AddTrack(TrackInfos* track_infos, MediaStreamInterface* stream,
416 MediaStreamTrackInterface* track,
418 (*track_infos).push_back(TrackInfo(stream->label(), track->id(),
422 void RemoveTrack(TrackInfos* track_infos, MediaStreamInterface* stream,
423 MediaStreamTrackInterface* track) {
424 for (TrackInfos::iterator it = track_infos->begin();
425 it != track_infos->end(); ++it) {
426 if (it->stream_label == stream->label() && it->track_id == track->id()) {
427 track_infos->erase(it);
434 const TrackInfo* FindTrackInfo(const TrackInfos& infos,
435 const std::string& stream_label,
436 const std::string track_id) const {
437 for (TrackInfos::const_iterator it = infos.begin();
438 it != infos.end(); ++it) {
439 if (it->stream_label == stream_label && it->track_id == track_id)
446 void VerifyTrack(const TrackInfos& track_infos,
447 const std::string& stream_label,
448 const std::string& track_id,
450 const TrackInfo* track_info = FindTrackInfo(track_infos,
453 ASSERT_TRUE(track_info != NULL);
454 EXPECT_EQ(ssrc, track_info->ssrc);
457 TrackInfos remote_audio_tracks_;
458 TrackInfos remote_video_tracks_;
459 TrackInfos local_audio_tracks_;
460 TrackInfos local_video_tracks_;
462 rtc::scoped_refptr<StreamCollection> remote_media_streams_;
465 class MediaStreamSignalingForTest : public webrtc::MediaStreamSignaling {
467 MediaStreamSignalingForTest(MockSignalingObserver* observer,
468 cricket::ChannelManager* channel_manager)
469 : webrtc::MediaStreamSignaling(rtc::Thread::Current(), observer,
473 using webrtc::MediaStreamSignaling::GetOptionsForOffer;
474 using webrtc::MediaStreamSignaling::GetOptionsForAnswer;
475 using webrtc::MediaStreamSignaling::OnRemoteDescriptionChanged;
476 using webrtc::MediaStreamSignaling::remote_streams;
479 class MediaStreamSignalingTest: public testing::Test {
481 virtual void SetUp() {
482 observer_.reset(new MockSignalingObserver());
483 channel_manager_.reset(
484 new cricket::ChannelManager(new cricket::FakeMediaEngine(),
485 new cricket::FakeDeviceManager(),
486 rtc::Thread::Current()));
487 signaling_.reset(new MediaStreamSignalingForTest(observer_.get(),
488 channel_manager_.get()));
489 data_channel_provider_.reset(new FakeDataChannelProvider());
492 // Create a collection of streams.
493 // CreateStreamCollection(1) creates a collection that
494 // correspond to kSdpString1.
495 // CreateStreamCollection(2) correspond to kSdpString2.
496 rtc::scoped_refptr<StreamCollection>
497 CreateStreamCollection(int number_of_streams) {
498 rtc::scoped_refptr<StreamCollection> local_collection(
499 StreamCollection::Create());
501 for (int i = 0; i < number_of_streams; ++i) {
502 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
503 webrtc::MediaStream::Create(kStreams[i]));
505 // Add a local audio track.
506 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
507 webrtc::AudioTrack::Create(kAudioTracks[i], NULL));
508 stream->AddTrack(audio_track);
510 // Add a local video track.
511 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
512 webrtc::VideoTrack::Create(kVideoTracks[i], NULL));
513 stream->AddTrack(video_track);
515 local_collection->AddStream(stream);
517 return local_collection;
520 // This functions Creates a MediaStream with label kStreams[0] and
521 // |number_of_audio_tracks| and |number_of_video_tracks| tracks and the
522 // corresponding SessionDescriptionInterface. The SessionDescriptionInterface
523 // is returned in |desc| and the MediaStream is stored in
524 // |reference_collection_|
525 void CreateSessionDescriptionAndReference(
526 size_t number_of_audio_tracks,
527 size_t number_of_video_tracks,
528 SessionDescriptionInterface** desc) {
529 ASSERT_TRUE(desc != NULL);
530 ASSERT_LE(number_of_audio_tracks, 2u);
531 ASSERT_LE(number_of_video_tracks, 2u);
533 reference_collection_ = StreamCollection::Create();
534 std::string sdp_ms1 = std::string(kSdpStringInit);
536 std::string mediastream_label = kStreams[0];
538 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
539 webrtc::MediaStream::Create(mediastream_label));
540 reference_collection_->AddStream(stream);
542 if (number_of_audio_tracks > 0) {
543 sdp_ms1 += std::string(kSdpStringAudio);
544 sdp_ms1 += std::string(kSdpStringMs1Audio0);
545 AddAudioTrack(kAudioTracks[0], stream);
547 if (number_of_audio_tracks > 1) {
548 sdp_ms1 += kSdpStringMs1Audio1;
549 AddAudioTrack(kAudioTracks[1], stream);
552 if (number_of_video_tracks > 0) {
553 sdp_ms1 += std::string(kSdpStringVideo);
554 sdp_ms1 += std::string(kSdpStringMs1Video0);
555 AddVideoTrack(kVideoTracks[0], stream);
557 if (number_of_video_tracks > 1) {
558 sdp_ms1 += kSdpStringMs1Video1;
559 AddVideoTrack(kVideoTracks[1], stream);
562 *desc = webrtc::CreateSessionDescription(
563 SessionDescriptionInterface::kOffer, sdp_ms1, NULL);
566 void AddAudioTrack(const std::string& track_id,
567 MediaStreamInterface* stream) {
568 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
569 webrtc::AudioTrack::Create(track_id, NULL));
570 ASSERT_TRUE(stream->AddTrack(audio_track));
573 void AddVideoTrack(const std::string& track_id,
574 MediaStreamInterface* stream) {
575 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
576 webrtc::VideoTrack::Create(track_id, NULL));
577 ASSERT_TRUE(stream->AddTrack(video_track));
580 rtc::scoped_refptr<webrtc::DataChannel> AddDataChannel(
581 cricket::DataChannelType type, const std::string& label, int id) {
582 webrtc::InternalDataChannelInit config;
584 rtc::scoped_refptr<webrtc::DataChannel> data_channel(
585 webrtc::DataChannel::Create(
586 data_channel_provider_.get(), type, label, config));
587 EXPECT_TRUE(data_channel.get() != NULL);
588 EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
592 // ChannelManager is used by VideoSource, so it should be released after all
593 // the video tracks. Put it as the first private variable should ensure that.
594 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
595 rtc::scoped_refptr<StreamCollection> reference_collection_;
596 rtc::scoped_ptr<MockSignalingObserver> observer_;
597 rtc::scoped_ptr<MediaStreamSignalingForTest> signaling_;
598 rtc::scoped_ptr<FakeDataChannelProvider> data_channel_provider_;
601 TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidAudioOption) {
602 RTCOfferAnswerOptions rtc_options;
603 rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
605 cricket::MediaSessionOptions options;
606 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
608 rtc_options.offer_to_receive_audio =
609 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
610 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
614 TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidVideoOption) {
615 RTCOfferAnswerOptions rtc_options;
616 rtc_options.offer_to_receive_video =
617 RTCOfferAnswerOptions::kUndefined - 1;
619 cricket::MediaSessionOptions options;
620 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
622 rtc_options.offer_to_receive_video =
623 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
624 EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
627 // Test that a MediaSessionOptions is created for an offer if
628 // OfferToReceiveAudio and OfferToReceiveVideo options are set but no
629 // MediaStreams are sent.
630 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
631 RTCOfferAnswerOptions rtc_options;
632 rtc_options.offer_to_receive_audio = 1;
633 rtc_options.offer_to_receive_video = 1;
635 cricket::MediaSessionOptions options;
636 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
637 EXPECT_TRUE(options.has_audio());
638 EXPECT_TRUE(options.has_video());
639 EXPECT_TRUE(options.bundle_enabled);
642 // Test that a correct MediaSessionOptions is created for an offer if
643 // OfferToReceiveAudio is set but no MediaStreams are sent.
644 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudio) {
645 RTCOfferAnswerOptions rtc_options;
646 rtc_options.offer_to_receive_audio = 1;
648 cricket::MediaSessionOptions options;
649 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
650 EXPECT_TRUE(options.has_audio());
651 EXPECT_FALSE(options.has_video());
652 EXPECT_TRUE(options.bundle_enabled);
655 // Test that a correct MediaSessionOptions is created for an offer if
656 // the default OfferOptons is used or MediaStreams are sent.
657 TEST_F(MediaStreamSignalingTest, GetDefaultMediaSessionOptionsForOffer) {
658 RTCOfferAnswerOptions rtc_options;
660 cricket::MediaSessionOptions options;
661 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
662 EXPECT_FALSE(options.has_audio());
663 EXPECT_FALSE(options.has_video());
664 EXPECT_FALSE(options.bundle_enabled);
665 EXPECT_TRUE(options.vad_enabled);
666 EXPECT_FALSE(options.transport_options.ice_restart);
669 // Test that a correct MediaSessionOptions is created for an offer if
670 // OfferToReceiveVideo is set but no MediaStreams are sent.
671 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithVideo) {
672 RTCOfferAnswerOptions rtc_options;
673 rtc_options.offer_to_receive_audio = 0;
674 rtc_options.offer_to_receive_video = 1;
676 cricket::MediaSessionOptions options;
677 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
678 EXPECT_FALSE(options.has_audio());
679 EXPECT_TRUE(options.has_video());
680 EXPECT_TRUE(options.bundle_enabled);
683 // Test that a correct MediaSessionOptions is created for an offer if
684 // UseRtpMux is set to false.
685 TEST_F(MediaStreamSignalingTest,
686 GetMediaSessionOptionsForOfferWithBundleDisabled) {
687 RTCOfferAnswerOptions rtc_options;
688 rtc_options.offer_to_receive_audio = 1;
689 rtc_options.offer_to_receive_video = 1;
690 rtc_options.use_rtp_mux = false;
692 cricket::MediaSessionOptions options;
693 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
694 EXPECT_TRUE(options.has_audio());
695 EXPECT_TRUE(options.has_video());
696 EXPECT_FALSE(options.bundle_enabled);
699 // Test that a correct MediaSessionOptions is created to restart ice if
700 // IceRestart is set. It also tests that subsequent MediaSessionOptions don't
701 // have |transport_options.ice_restart| set.
702 TEST_F(MediaStreamSignalingTest,
703 GetMediaSessionOptionsForOfferWithIceRestart) {
704 RTCOfferAnswerOptions rtc_options;
705 rtc_options.ice_restart = true;
707 cricket::MediaSessionOptions options;
708 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
709 EXPECT_TRUE(options.transport_options.ice_restart);
711 rtc_options = RTCOfferAnswerOptions();
712 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
713 EXPECT_FALSE(options.transport_options.ice_restart);
716 // Test that a correct MediaSessionOptions are created for an offer if
717 // a MediaStream is sent and later updated with a new track.
718 // MediaConstraints are not used.
719 TEST_F(MediaStreamSignalingTest, AddTrackToLocalMediaStream) {
720 RTCOfferAnswerOptions rtc_options;
721 rtc::scoped_refptr<StreamCollection> local_streams(
722 CreateStreamCollection(1));
723 MediaStreamInterface* local_stream = local_streams->at(0);
724 EXPECT_TRUE(signaling_->AddLocalStream(local_stream));
725 cricket::MediaSessionOptions options;
726 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
727 VerifyMediaOptions(local_streams, options);
729 cricket::MediaSessionOptions updated_options;
730 local_stream->AddTrack(AudioTrack::Create(kAudioTracks[1], NULL));
731 EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
732 VerifyMediaOptions(local_streams, options);
735 // Test that the MediaConstraints in an answer don't affect if audio and video
736 // is offered in an offer but that if kOfferToReceiveAudio or
737 // kOfferToReceiveVideo constraints are true in an offer, the media type will be
738 // included in subsequent answers.
739 TEST_F(MediaStreamSignalingTest, MediaConstraintsInAnswer) {
740 FakeConstraints answer_c;
741 answer_c.SetMandatoryReceiveAudio(true);
742 answer_c.SetMandatoryReceiveVideo(true);
744 cricket::MediaSessionOptions answer_options;
745 EXPECT_TRUE(signaling_->GetOptionsForAnswer(&answer_c, &answer_options));
746 EXPECT_TRUE(answer_options.has_audio());
747 EXPECT_TRUE(answer_options.has_video());
749 RTCOfferAnswerOptions rtc_offer_optoins;
751 cricket::MediaSessionOptions offer_options;
753 signaling_->GetOptionsForOffer(rtc_offer_optoins, &offer_options));
754 EXPECT_FALSE(offer_options.has_audio());
755 EXPECT_FALSE(offer_options.has_video());
757 RTCOfferAnswerOptions updated_rtc_offer_optoins;
758 updated_rtc_offer_optoins.offer_to_receive_audio = 1;
759 updated_rtc_offer_optoins.offer_to_receive_video = 1;
761 cricket::MediaSessionOptions updated_offer_options;
762 EXPECT_TRUE(signaling_->GetOptionsForOffer(updated_rtc_offer_optoins,
763 &updated_offer_options));
764 EXPECT_TRUE(updated_offer_options.has_audio());
765 EXPECT_TRUE(updated_offer_options.has_video());
767 // Since an offer has been created with both audio and video, subsequent
768 // offers and answers should contain both audio and video.
769 // Answers will only contain the media types that exist in the offer
770 // regardless of the value of |updated_answer_options.has_audio| and
771 // |updated_answer_options.has_video|.
772 FakeConstraints updated_answer_c;
773 answer_c.SetMandatoryReceiveAudio(false);
774 answer_c.SetMandatoryReceiveVideo(false);
776 cricket::MediaSessionOptions updated_answer_options;
777 EXPECT_TRUE(signaling_->GetOptionsForAnswer(&updated_answer_c,
778 &updated_answer_options));
779 EXPECT_TRUE(updated_answer_options.has_audio());
780 EXPECT_TRUE(updated_answer_options.has_video());
782 RTCOfferAnswerOptions default_rtc_options;
783 EXPECT_TRUE(signaling_->GetOptionsForOffer(default_rtc_options,
784 &updated_offer_options));
785 // By default, |has_audio| or |has_video| are false if there is no media
787 EXPECT_FALSE(updated_offer_options.has_audio());
788 EXPECT_FALSE(updated_offer_options.has_video());
791 // This test verifies that the remote MediaStreams corresponding to a received
792 // SDP string is created. In this test the two separate MediaStreams are
794 TEST_F(MediaStreamSignalingTest, UpdateRemoteStreams) {
795 rtc::scoped_ptr<SessionDescriptionInterface> desc(
796 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
797 kSdpStringWithStream1, NULL));
798 EXPECT_TRUE(desc != NULL);
799 signaling_->OnRemoteDescriptionChanged(desc.get());
801 rtc::scoped_refptr<StreamCollection> reference(
802 CreateStreamCollection(1));
803 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
805 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
807 EXPECT_EQ(1u, observer_->NumberOfRemoteAudioTracks());
808 observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1);
809 EXPECT_EQ(1u, observer_->NumberOfRemoteVideoTracks());
810 observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2);
811 ASSERT_EQ(1u, observer_->remote_streams()->count());
812 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
813 EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != NULL);
815 // Create a session description based on another SDP with another
817 rtc::scoped_ptr<SessionDescriptionInterface> update_desc(
818 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
819 kSdpStringWith2Stream, NULL));
820 EXPECT_TRUE(update_desc != NULL);
821 signaling_->OnRemoteDescriptionChanged(update_desc.get());
823 rtc::scoped_refptr<StreamCollection> reference2(
824 CreateStreamCollection(2));
825 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
827 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
830 EXPECT_EQ(2u, observer_->NumberOfRemoteAudioTracks());
831 observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1);
832 observer_->VerifyRemoteAudioTrack(kStreams[1], kAudioTracks[1], 3);
833 EXPECT_EQ(2u, observer_->NumberOfRemoteVideoTracks());
834 observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2);
835 observer_->VerifyRemoteVideoTrack(kStreams[1], kVideoTracks[1], 4);
838 // This test verifies that the remote MediaStreams corresponding to a received
839 // SDP string is created. In this test the same remote MediaStream is signaled
840 // but MediaStream tracks are added and removed.
841 TEST_F(MediaStreamSignalingTest, AddRemoveTrackFromExistingRemoteMediaStream) {
842 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1;
843 CreateSessionDescriptionAndReference(1, 1, desc_ms1.use());
844 signaling_->OnRemoteDescriptionChanged(desc_ms1.get());
845 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
846 reference_collection_));
848 // Add extra audio and video tracks to the same MediaStream.
849 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks;
850 CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.use());
851 signaling_->OnRemoteDescriptionChanged(desc_ms1_two_tracks.get());
852 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
853 reference_collection_));
854 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
855 reference_collection_));
857 // Remove the extra audio and video tracks again.
858 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2;
859 CreateSessionDescriptionAndReference(1, 1, desc_ms2.use());
860 signaling_->OnRemoteDescriptionChanged(desc_ms2.get());
861 EXPECT_TRUE(CompareStreamCollections(signaling_->remote_streams(),
862 reference_collection_));
863 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
864 reference_collection_));
867 // This test that remote tracks are ended if a
868 // local session description is set that rejects the media content type.
869 TEST_F(MediaStreamSignalingTest, RejectMediaContent) {
870 rtc::scoped_ptr<SessionDescriptionInterface> desc(
871 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
872 kSdpStringWithStream1, NULL));
873 EXPECT_TRUE(desc != NULL);
874 signaling_->OnRemoteDescriptionChanged(desc.get());
876 ASSERT_EQ(1u, observer_->remote_streams()->count());
877 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
878 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
879 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
881 rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video =
882 remote_stream->GetVideoTracks()[0];
883 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state());
884 rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio =
885 remote_stream->GetAudioTracks()[0];
886 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
888 cricket::ContentInfo* video_info =
889 desc->description()->GetContentByName("video");
890 ASSERT_TRUE(video_info != NULL);
891 video_info->rejected = true;
892 signaling_->OnLocalDescriptionChanged(desc.get());
893 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
894 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
896 cricket::ContentInfo* audio_info =
897 desc->description()->GetContentByName("audio");
898 ASSERT_TRUE(audio_info != NULL);
899 audio_info->rejected = true;
900 signaling_->OnLocalDescriptionChanged(desc.get());
901 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state());
904 // This test that it won't crash if the remote track as been removed outside
905 // of MediaStreamSignaling and then MediaStreamSignaling tries to reject
907 TEST_F(MediaStreamSignalingTest, RemoveTrackThenRejectMediaContent) {
908 rtc::scoped_ptr<SessionDescriptionInterface> desc(
909 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
910 kSdpStringWithStream1, NULL));
911 EXPECT_TRUE(desc != NULL);
912 signaling_->OnRemoteDescriptionChanged(desc.get());
914 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
915 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
916 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
918 cricket::ContentInfo* video_info =
919 desc->description()->GetContentByName("video");
920 video_info->rejected = true;
921 signaling_->OnLocalDescriptionChanged(desc.get());
923 cricket::ContentInfo* audio_info =
924 desc->description()->GetContentByName("audio");
925 audio_info->rejected = true;
926 signaling_->OnLocalDescriptionChanged(desc.get());
928 // No crash is a pass.
931 // This tests that a default MediaStream is created if a remote session
932 // description doesn't contain any streams and no MSID support.
933 // It also tests that the default stream is updated if a video m-line is added
934 // in a subsequent session description.
935 TEST_F(MediaStreamSignalingTest, SdpWithoutMsidCreatesDefaultStream) {
936 rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only(
937 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
938 kSdpStringWithoutStreamsAudioOnly,
940 ASSERT_TRUE(desc_audio_only != NULL);
941 signaling_->OnRemoteDescriptionChanged(desc_audio_only.get());
943 EXPECT_EQ(1u, signaling_->remote_streams()->count());
944 ASSERT_EQ(1u, observer_->remote_streams()->count());
945 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
947 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
948 EXPECT_EQ(0u, remote_stream->GetVideoTracks().size());
949 EXPECT_EQ("default", remote_stream->label());
951 rtc::scoped_ptr<SessionDescriptionInterface> desc(
952 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
953 kSdpStringWithoutStreams, NULL));
954 ASSERT_TRUE(desc != NULL);
955 signaling_->OnRemoteDescriptionChanged(desc.get());
956 EXPECT_EQ(1u, signaling_->remote_streams()->count());
957 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
958 EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
959 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
960 EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
961 observer_->VerifyRemoteAudioTrack("default", "defaulta0", 0);
962 observer_->VerifyRemoteVideoTrack("default", "defaultv0", 0);
965 // This tests that a default MediaStream is created if a remote session
966 // description doesn't contain any streams and media direction is send only.
967 TEST_F(MediaStreamSignalingTest, RecvOnlySdpWithoutMsidCreatesDefaultStream) {
968 rtc::scoped_ptr<SessionDescriptionInterface> desc(
969 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
970 kSdpStringSendOnlyWithWithoutStreams,
972 ASSERT_TRUE(desc != NULL);
973 signaling_->OnRemoteDescriptionChanged(desc.get());
975 EXPECT_EQ(1u, signaling_->remote_streams()->count());
976 ASSERT_EQ(1u, observer_->remote_streams()->count());
977 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
979 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
980 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
981 EXPECT_EQ("default", remote_stream->label());
984 // This tests that it won't crash when MediaStreamSignaling tries to remove
985 // a remote track that as already been removed from the mediastream.
986 TEST_F(MediaStreamSignalingTest, RemoveAlreadyGoneRemoteStream) {
987 rtc::scoped_ptr<SessionDescriptionInterface> desc_audio_only(
988 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
989 kSdpStringWithoutStreams,
991 ASSERT_TRUE(desc_audio_only != NULL);
992 signaling_->OnRemoteDescriptionChanged(desc_audio_only.get());
993 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
994 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
995 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
997 rtc::scoped_ptr<SessionDescriptionInterface> desc(
998 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
999 kSdpStringWithoutStreams, NULL));
1000 ASSERT_TRUE(desc != NULL);
1001 signaling_->OnRemoteDescriptionChanged(desc.get());
1003 // No crash is a pass.
1006 // This tests that a default MediaStream is created if the remote session
1007 // description doesn't contain any streams and don't contain an indication if
1008 // MSID is supported.
1009 TEST_F(MediaStreamSignalingTest,
1010 SdpWithoutMsidAndStreamsCreatesDefaultStream) {
1011 rtc::scoped_ptr<SessionDescriptionInterface> desc(
1012 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1013 kSdpStringWithoutStreams,
1015 ASSERT_TRUE(desc != NULL);
1016 signaling_->OnRemoteDescriptionChanged(desc.get());
1018 ASSERT_EQ(1u, observer_->remote_streams()->count());
1019 MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
1020 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
1021 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
1024 // This tests that a default MediaStream is not created if the remote session
1025 // description doesn't contain any streams but does support MSID.
1026 TEST_F(MediaStreamSignalingTest, SdpWitMsidDontCreatesDefaultStream) {
1027 rtc::scoped_ptr<SessionDescriptionInterface> desc_msid_without_streams(
1028 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1029 kSdpStringWithMsidWithoutStreams,
1031 signaling_->OnRemoteDescriptionChanged(desc_msid_without_streams.get());
1032 EXPECT_EQ(0u, observer_->remote_streams()->count());
1035 // This test that a default MediaStream is not created if a remote session
1036 // description is updated to not have any MediaStreams.
1037 TEST_F(MediaStreamSignalingTest, VerifyDefaultStreamIsNotCreated) {
1038 rtc::scoped_ptr<SessionDescriptionInterface> desc(
1039 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1040 kSdpStringWithStream1,
1042 ASSERT_TRUE(desc != NULL);
1043 signaling_->OnRemoteDescriptionChanged(desc.get());
1044 rtc::scoped_refptr<StreamCollection> reference(
1045 CreateStreamCollection(1));
1046 EXPECT_TRUE(CompareStreamCollections(observer_->remote_streams(),
1049 rtc::scoped_ptr<SessionDescriptionInterface> desc_without_streams(
1050 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1051 kSdpStringWithoutStreams,
1053 signaling_->OnRemoteDescriptionChanged(desc_without_streams.get());
1054 EXPECT_EQ(0u, observer_->remote_streams()->count());
1057 // This test that the correct MediaStreamSignalingObserver methods are called
1058 // when MediaStreamSignaling::OnLocalDescriptionChanged is called with an
1059 // updated local session description.
1060 TEST_F(MediaStreamSignalingTest, LocalDescriptionChanged) {
1061 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
1062 CreateSessionDescriptionAndReference(2, 2, desc_1.use());
1064 signaling_->AddLocalStream(reference_collection_->at(0));
1065 signaling_->OnLocalDescriptionChanged(desc_1.get());
1066 EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks());
1067 EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks());
1068 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
1069 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
1070 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3);
1071 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4);
1073 // Remove an audio and video track.
1074 rtc::scoped_ptr<SessionDescriptionInterface> desc_2;
1075 CreateSessionDescriptionAndReference(1, 1, desc_2.use());
1076 signaling_->OnLocalDescriptionChanged(desc_2.get());
1077 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
1078 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
1079 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
1080 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
1083 // This test that the correct MediaStreamSignalingObserver methods are called
1084 // when MediaStreamSignaling::AddLocalStream is called after
1085 // MediaStreamSignaling::OnLocalDescriptionChanged is called.
1086 TEST_F(MediaStreamSignalingTest, AddLocalStreamAfterLocalDescriptionChanged) {
1087 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
1088 CreateSessionDescriptionAndReference(2, 2, desc_1.use());
1090 signaling_->OnLocalDescriptionChanged(desc_1.get());
1091 EXPECT_EQ(0u, observer_->NumberOfLocalAudioTracks());
1092 EXPECT_EQ(0u, observer_->NumberOfLocalVideoTracks());
1094 signaling_->AddLocalStream(reference_collection_->at(0));
1095 EXPECT_EQ(2u, observer_->NumberOfLocalAudioTracks());
1096 EXPECT_EQ(2u, observer_->NumberOfLocalVideoTracks());
1097 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
1098 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
1099 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[1], 3);
1100 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[1], 4);
1103 // This test that the correct MediaStreamSignalingObserver methods are called
1104 // if the ssrc on a local track is changed when
1105 // MediaStreamSignaling::OnLocalDescriptionChanged is called.
1106 TEST_F(MediaStreamSignalingTest, ChangeSsrcOnTrackInLocalSessionDescription) {
1107 rtc::scoped_ptr<SessionDescriptionInterface> desc;
1108 CreateSessionDescriptionAndReference(1, 1, desc.use());
1110 signaling_->AddLocalStream(reference_collection_->at(0));
1111 signaling_->OnLocalDescriptionChanged(desc.get());
1112 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
1113 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
1114 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 1);
1115 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 2);
1117 // Change the ssrc of the audio and video track.
1119 desc->ToString(&sdp);
1120 std::string ssrc_org = "a=ssrc:1";
1121 std::string ssrc_to = "a=ssrc:97";
1122 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(),
1123 ssrc_to.c_str(), ssrc_to.length(),
1125 ssrc_org = "a=ssrc:2";
1126 ssrc_to = "a=ssrc:98";
1127 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(),
1128 ssrc_to.c_str(), ssrc_to.length(),
1130 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
1131 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1134 signaling_->OnLocalDescriptionChanged(updated_desc.get());
1135 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
1136 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
1137 observer_->VerifyLocalAudioTrack(kStreams[0], kAudioTracks[0], 97);
1138 observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 98);
1141 // This test that the correct MediaStreamSignalingObserver methods are called
1142 // if a new session description is set with the same tracks but they are now
1143 // sent on a another MediaStream.
1144 TEST_F(MediaStreamSignalingTest, SignalSameTracksInSeparateMediaStream) {
1145 rtc::scoped_ptr<SessionDescriptionInterface> desc;
1146 CreateSessionDescriptionAndReference(1, 1, desc.use());
1148 signaling_->AddLocalStream(reference_collection_->at(0));
1149 signaling_->OnLocalDescriptionChanged(desc.get());
1150 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
1151 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
1153 std::string stream_label_0 = kStreams[0];
1154 observer_->VerifyLocalAudioTrack(stream_label_0, kAudioTracks[0], 1);
1155 observer_->VerifyLocalVideoTrack(stream_label_0, kVideoTracks[0], 2);
1157 // Add a new MediaStream but with the same tracks as in the first stream.
1158 std::string stream_label_1 = kStreams[1];
1159 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
1160 webrtc::MediaStream::Create(kStreams[1]));
1161 stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]);
1162 stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]);
1163 signaling_->AddLocalStream(stream_1);
1165 // Replace msid in the original SDP.
1167 desc->ToString(&sdp);
1168 rtc::replace_substrs(
1169 kStreams[0], strlen(kStreams[0]), kStreams[1], strlen(kStreams[1]), &sdp);
1171 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
1172 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1175 signaling_->OnLocalDescriptionChanged(updated_desc.get());
1176 observer_->VerifyLocalAudioTrack(kStreams[1], kAudioTracks[0], 1);
1177 observer_->VerifyLocalVideoTrack(kStreams[1], kVideoTracks[0], 2);
1178 EXPECT_EQ(1u, observer_->NumberOfLocalAudioTracks());
1179 EXPECT_EQ(1u, observer_->NumberOfLocalVideoTracks());
1182 // Verifies that an even SCTP id is allocated for SSL_CLIENT and an odd id for
1184 TEST_F(MediaStreamSignalingTest, SctpIdAllocationBasedOnRole) {
1186 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id));
1188 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id));
1190 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &id));
1192 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &id));
1196 // Verifies that SCTP ids of existing DataChannels are not reused.
1197 TEST_F(MediaStreamSignalingTest, SctpIdAllocationNoReuse) {
1199 AddDataChannel(cricket::DCT_SCTP, "a", old_id);
1202 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER, &new_id));
1203 EXPECT_NE(old_id, new_id);
1205 // Creates a DataChannel with id 0.
1207 AddDataChannel(cricket::DCT_SCTP, "a", old_id);
1208 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT, &new_id));
1209 EXPECT_NE(old_id, new_id);
1212 // Verifies that SCTP ids of removed DataChannels can be reused.
1213 TEST_F(MediaStreamSignalingTest, SctpIdReusedForRemovedDataChannel) {
1216 AddDataChannel(cricket::DCT_SCTP, "a", odd_id);
1217 AddDataChannel(cricket::DCT_SCTP, "a", even_id);
1219 int allocated_id = -1;
1220 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
1222 EXPECT_EQ(odd_id + 2, allocated_id);
1223 AddDataChannel(cricket::DCT_SCTP, "a", allocated_id);
1225 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
1227 EXPECT_EQ(even_id + 2, allocated_id);
1228 AddDataChannel(cricket::DCT_SCTP, "a", allocated_id);
1230 signaling_->RemoveSctpDataChannel(odd_id);
1231 signaling_->RemoveSctpDataChannel(even_id);
1233 // Verifies that removed DataChannel ids are reused.
1234 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
1236 EXPECT_EQ(odd_id, allocated_id);
1238 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
1240 EXPECT_EQ(even_id, allocated_id);
1242 // Verifies that used higher DataChannel ids are not reused.
1243 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_SERVER,
1245 EXPECT_NE(odd_id + 2, allocated_id);
1247 ASSERT_TRUE(signaling_->AllocateSctpSid(rtc::SSL_CLIENT,
1249 EXPECT_NE(even_id + 2, allocated_id);
1253 // Verifies that duplicated label is not allowed for RTP data channel.
1254 TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) {
1255 AddDataChannel(cricket::DCT_RTP, "a", -1);
1257 webrtc::InternalDataChannelInit config;
1258 rtc::scoped_refptr<webrtc::DataChannel> data_channel =
1259 webrtc::DataChannel::Create(
1260 data_channel_provider_.get(), cricket::DCT_RTP, "a", config);
1261 ASSERT_TRUE(data_channel.get() != NULL);
1262 EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get()));
1265 // Verifies that duplicated label is allowed for SCTP data channel.
1266 TEST_F(MediaStreamSignalingTest, SctpDuplicatedLabelAllowed) {
1267 AddDataChannel(cricket::DCT_SCTP, "a", -1);
1268 AddDataChannel(cricket::DCT_SCTP, "a", -1);
1271 // Verifies the correct configuration is used to create DataChannel from an OPEN
1273 TEST_F(MediaStreamSignalingTest, CreateDataChannelFromOpenMessage) {
1274 FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
1277 signaling_->SetDataChannelFactory(&fake_factory);
1278 webrtc::DataChannelInit config;
1280 rtc::Buffer payload;
1281 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
1282 cricket::ReceiveDataParams params;
1283 params.ssrc = config.id;
1284 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
1285 EXPECT_EQ(config.id, fake_factory.last_init().id);
1286 EXPECT_FALSE(fake_factory.last_init().negotiated);
1287 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
1288 fake_factory.last_init().open_handshake_role);
1291 // Verifies that duplicated label from OPEN message is allowed.
1292 TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) {
1293 AddDataChannel(cricket::DCT_SCTP, "a", -1);
1295 FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
1298 signaling_->SetDataChannelFactory(&fake_factory);
1299 webrtc::DataChannelInit config;
1301 rtc::Buffer payload;
1302 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
1303 cricket::ReceiveDataParams params;
1304 params.ssrc = config.id;
1305 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
1308 // Verifies that a DataChannel closed remotely is closed locally.
1309 TEST_F(MediaStreamSignalingTest,
1310 SctpDataChannelClosedLocallyWhenClosedRemotely) {
1311 webrtc::InternalDataChannelInit config;
1314 rtc::scoped_refptr<webrtc::DataChannel> data_channel =
1315 webrtc::DataChannel::Create(
1316 data_channel_provider_.get(), cricket::DCT_SCTP, "a", config);
1317 ASSERT_TRUE(data_channel.get() != NULL);
1318 EXPECT_EQ(webrtc::DataChannelInterface::kConnecting,
1319 data_channel->state());
1321 EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
1323 signaling_->OnRemoteSctpDataChannelClosed(config.id);
1324 EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state());
1327 // Verifies that DataChannel added from OPEN message is added to
1328 // MediaStreamSignaling only once (webrtc issue 3778).
1329 TEST_F(MediaStreamSignalingTest, DataChannelFromOpenMessageAddedOnce) {
1330 FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
1333 signaling_->SetDataChannelFactory(&fake_factory);
1334 webrtc::DataChannelInit config;
1336 rtc::Buffer payload;
1337 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
1338 cricket::ReceiveDataParams params;
1339 params.ssrc = config.id;
1340 EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
1341 EXPECT_TRUE(signaling_->HasDataChannels());
1343 // Removes the DataChannel and verifies that no DataChannel is left.
1344 signaling_->RemoveSctpDataChannel(config.id);
1345 EXPECT_FALSE(signaling_->HasDataChannels());