Index: webrtc/pc/mediasession_unittest.cc |
diff --git a/webrtc/pc/mediasession_unittest.cc b/webrtc/pc/mediasession_unittest.cc |
index b1c4044b707699f88125ec2696534e597b952c9a..684e2a70194d4fc147a9d11bbc3aa355b9dde5ae 100644 |
--- a/webrtc/pc/mediasession_unittest.cc |
+++ b/webrtc/pc/mediasession_unittest.cc |
@@ -39,6 +39,7 @@ typedef std::vector<cricket::Candidate> Candidates; |
using cricket::MediaContentDescription; |
using cricket::MediaSessionDescriptionFactory; |
+using cricket::MediaContentDirection; |
using cricket::MediaSessionOptions; |
using cricket::MediaType; |
using cricket::SessionDescription; |
@@ -93,6 +94,11 @@ static const AudioCodec kAudioCodecsAnswer[] = { |
AudioCodec(0, "PCMU", 8000, 64000, 1), |
}; |
+static const AudioCodec kAudioCodecsAnswer2[] = { |
+ AudioCodec(0, "PCMU", 8000, 64000, 1), |
+ AudioCodec(127, "iLBC", 8000, 13300, 1), |
+}; |
+ |
static const VideoCodec kVideoCodecs1[] = { |
VideoCodec(96, "H264-SVC", 320, 200, 30), |
VideoCodec(97, "H264", 320, 200, 30)}; |
@@ -2450,3 +2456,243 @@ INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest, |
INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest, |
MediaProtocolTest, |
::testing::ValuesIn(kMediaProtocolsDtls)); |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecsOld) { |
+ TransportDescriptionFactory tdf; |
+ MediaSessionDescriptionFactory sf(&tdf); |
+ const std::vector<AudioCodec> codecs = MAKE_VECTOR(kAudioCodecs1); |
+ sf.set_audio_codecs(codecs); |
+ |
+ EXPECT_TRUE(sf.audio_codecs() == codecs); |
+ EXPECT_TRUE(sf.audio_send_codecs() == codecs); |
+ EXPECT_TRUE(sf.audio_recv_codecs() == codecs); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) { |
+ TransportDescriptionFactory tdf; |
+ MediaSessionDescriptionFactory sf(&tdf); |
+ std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
+ std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
+ |
+ // The merged list of codecs should contain any send codecs that are also |
+ // nominally in the recieve codecs list. Payload types should be picked from |
+ // the send codecs and a number-of-channels of 0 and 1 should be equivalent |
+ // (set to 1). This equals what happens when the send codecs are used in an |
+ // offer and the receive codecs are used in the following answer. |
+ const std::vector<AudioCodec> sendrecv_codecs = |
+ MAKE_VECTOR(kAudioCodecsAnswer); |
+ const std::vector<AudioCodec> no_codecs; |
+ |
+ RTC_CHECK_EQ(send_codecs[1].name, "iLBC") |
+ << "Please don't change shared test data!"; |
+ RTC_CHECK_EQ(recv_codecs[2].name, "iLBC") |
+ << "Please don't change shared test data!"; |
+ // Alter iLBC send codec to have zero channels, to test that that is handled |
+ // properly. |
+ send_codecs[1].channels = 0; |
+ |
+ // Alther iLBC receive codec to be lowercase, to test that case conversions |
+ // are handled properly. |
+ recv_codecs[2].name = "ilbc"; |
+ |
+ // Test proper merge |
+ sf.set_audio_codecs(send_codecs, recv_codecs); |
+ EXPECT_TRUE(sf.audio_send_codecs() == send_codecs); |
+ EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs); |
+ EXPECT_TRUE(sf.audio_codecs() == sendrecv_codecs); |
+ |
+ // Test empty send codecs list |
+ sf.set_audio_codecs(no_codecs, recv_codecs); |
+ EXPECT_TRUE(sf.audio_send_codecs() == no_codecs); |
+ EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs); |
+ EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
+ |
+ // Test empty recv codecs list |
+ sf.set_audio_codecs(send_codecs, no_codecs); |
+ EXPECT_TRUE(sf.audio_send_codecs() == send_codecs); |
+ EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs); |
+ EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
+ |
+ // Test all empty codec lists |
+ sf.set_audio_codecs(no_codecs, no_codecs); |
+ EXPECT_TRUE(sf.audio_send_codecs() == no_codecs); |
+ EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs); |
+ EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
+} |
+ |
+namespace { |
+void TestAudioCodecsOffer(MediaContentDirection direction) { |
+ TransportDescriptionFactory tdf; |
+ MediaSessionDescriptionFactory sf(&tdf); |
+ const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
+ const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
+ const std::vector<AudioCodec> sendrecv_codecs = |
+ MAKE_VECTOR(kAudioCodecsAnswer); |
+ sf.set_audio_codecs(send_codecs, recv_codecs); |
+ |
+ // Don't add a legacy stream whenever we've not provided a stream ourselves. |
+ sf.set_add_legacy_streams(false); |
+ MediaSessionOptions opts; |
+ opts.recv_audio = (direction == cricket::MD_RECVONLY || |
+ direction == cricket::MD_SENDRECV); |
+ opts.recv_video = false; |
+ if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV) |
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
+ |
+ std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL)); |
+ ASSERT_TRUE(offer.get() != NULL); |
+ const ContentInfo* ac = offer->GetContentByName("audio"); |
+ |
+ // If the factory didn't add any audio content to the offer, we cannot check |
+ // that the codecs put in are right. This happens when we neither want to send |
+ // nor receive audio. The checks are still in place if at some point we'd |
+ // instead create an inactive stream. |
+ if (ac) { |
+ AudioContentDescription* acd = |
+ static_cast<AudioContentDescription*>(ac->description); |
+ // sendrecv and inactive should both present lists as if the channel was to |
+ // be used for sending and receiving. Inactive essentially means it might |
+ // eventually be used anything, but we don't know more at this moment. |
+ if (acd->direction() == cricket::MD_SENDONLY) { |
+ EXPECT_TRUE(acd->codecs() == send_codecs); |
+ } else if (acd->direction() == cricket::MD_RECVONLY) { |
+ EXPECT_TRUE(acd->codecs() == recv_codecs); |
+ } else { |
+ EXPECT_TRUE(acd->codecs() == sendrecv_codecs); |
+ } |
+ } |
+} |
+ |
+void TestAudioCodecsAnswer(MediaContentDirection offer_direction, |
+ MediaContentDirection answer_direction) { |
+ TransportDescriptionFactory offer_tdf; |
+ TransportDescriptionFactory answer_tdf; |
+ MediaSessionDescriptionFactory offer_factory(&offer_tdf); |
+ MediaSessionDescriptionFactory answer_factory(&answer_tdf); |
+ const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
+ const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
+ const std::vector<AudioCodec> answerer_sendrecv_codecs = |
+ MAKE_VECTOR(kAudioCodecsAnswer); |
+ const std::vector<AudioCodec> offerer_sendrecv_codecs = |
+ MAKE_VECTOR(kAudioCodecsAnswer2); |
+ // Send and receive are from the perspective of the answerer (since we're |
+ // testing the answer generation). |
+ offer_factory.set_audio_codecs(recv_codecs, send_codecs); |
+ answer_factory.set_audio_codecs(send_codecs, recv_codecs); |
+ |
+ // Don't add a legacy stream whenever we've not provided a stream ourselves. |
+ offer_factory.set_add_legacy_streams(false); |
+ answer_factory.set_add_legacy_streams(false); |
+ MediaSessionOptions offer_opts; |
+ offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY || |
+ offer_direction == cricket::MD_SENDRECV); |
+ offer_opts.recv_video = false; |
+ if (offer_direction == cricket::MD_SENDONLY || |
+ offer_direction == cricket::MD_SENDRECV) { |
+ offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
+ } |
+ |
+ std::unique_ptr<SessionDescription> offer( |
+ offer_factory.CreateOffer(offer_opts, NULL)); |
+ ASSERT_TRUE(offer.get() != NULL); |
+ |
+ MediaSessionOptions answer_opts; |
+ answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY || |
+ answer_direction == cricket::MD_SENDRECV); |
+ answer_opts.recv_video = false; |
+ if (answer_direction == cricket::MD_SENDONLY || |
+ answer_direction == cricket::MD_SENDRECV) { |
+ answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
+ } |
+ std::unique_ptr<SessionDescription> answer( |
+ answer_factory.CreateAnswer(offer.get(), answer_opts, NULL)); |
+ const ContentInfo* ac = answer->GetContentByName("audio"); |
+ |
+ // If the factory didn't add any audio content to the answer, we cannot check |
+ // that the codecs put in are right. This happens when we neither want to send |
+ // nor receive audio. The checks are still in place if at some point we'd |
+ // instead create an inactive stream. |
+ if (ac) { |
+ const AudioContentDescription* acd = |
+ static_cast<const AudioContentDescription*>(ac->description); |
+ EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); |
+ |
+ // For offers with sendrecv or inactive, we should never reply with more |
+ // codecs than offered, with these codec sets. |
+ if (offer_direction == cricket::MD_SENDRECV || |
+ offer_direction == cricket::MD_INACTIVE) { |
+ EXPECT_TRUE(acd->codecs() == offerer_sendrecv_codecs) |
+ << "Offered: " << MediaContentDirectionToString(offer_direction) |
+ << ", answerer wants: " |
+ << MediaContentDirectionToString(answer_direction) |
+ << "; got: " << MediaContentDirectionToString(acd->direction()); |
+ } else { |
+ // Otherwise, the codecs in the answer should depend only on the direction |
+ // we picked in our answer. |
+ if (acd->direction() == cricket::MD_SENDONLY) { |
+ EXPECT_TRUE(acd->codecs() == send_codecs) |
+ << "Offered: " << MediaContentDirectionToString(offer_direction) |
+ << ", answerer wants: " |
+ << MediaContentDirectionToString(answer_direction) |
+ << "; got: " << MediaContentDirectionToString(acd->direction()); |
+ } else if (acd->direction() == cricket::MD_RECVONLY) { |
+ EXPECT_TRUE(acd->codecs() == recv_codecs) |
+ << "Offered: " << MediaContentDirectionToString(offer_direction) |
+ << ", answerer wants: " |
+ << MediaContentDirectionToString(answer_direction) |
+ << "; got: " << MediaContentDirectionToString(acd->direction()); |
+ } else { |
+ EXPECT_TRUE(acd->codecs() == answerer_sendrecv_codecs) |
+ << "Offered: " << MediaContentDirectionToString(offer_direction) |
+ << ", answerer wants: " |
+ << MediaContentDirectionToString(answer_direction) |
+ << "; got: " << MediaContentDirectionToString(acd->direction()); |
+ } |
+ } |
+ } |
+} |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendOnlyCodecsOffer) { |
+ TestAudioCodecsOffer(cricket::MD_SENDONLY); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioRecvOnlyCodecsOffer) { |
+ TestAudioCodecsOffer(cricket::MD_RECVONLY); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendRecvCodecsOffer) { |
+ TestAudioCodecsOffer(cricket::MD_SENDRECV); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioInactiveCodecsOffer) { |
+ TestAudioCodecsOffer(cricket::MD_INACTIVE); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendOnlyCodecsAnswer) { |
ossu
2016/05/23 14:18:04
I grouped them by the expected resulting direction
|
+ TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY); |
+ TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_SENDRECV); |
+ TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_SENDONLY); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioRecvOnlyCodecsAnswer) { |
+ TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY); |
+ TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_SENDRECV); |
+ TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_RECVONLY); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendRecvCodecsAnswer) { |
+ TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV); |
+} |
+ |
+TEST_F(MediaSessionDescriptionFactoryTest, TestAudioInactiveCodecsAnswer) { |
+ TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE); |
+ TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_SENDONLY); |
+ TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_RECVONLY); |
+ TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_SENDRECV); |
+ TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_RECVONLY); |
+ TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_SENDONLY); |
+ TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_INACTIVE); |
+ TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_INACTIVE); |
+ TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_INACTIVE); |
+} |