Index: webrtc/ortc/rtpparametersconversion_unittest.cc |
diff --git a/webrtc/ortc/rtpparametersconversion_unittest.cc b/webrtc/ortc/rtpparametersconversion_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6bb335c78dd8758c43c51181ee8114de93c227a1 |
--- /dev/null |
+++ b/webrtc/ortc/rtpparametersconversion_unittest.cc |
@@ -0,0 +1,535 @@ |
+/* |
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include <algorithm> |
+ |
+#include "webrtc/base/gunit.h" |
+#include "webrtc/ortc/rtpparametersconversion.h" |
+#include "webrtc/ortc/testrtpparameters.h" |
+ |
+namespace webrtc { |
+ |
+TEST(RtpParametersConversionTest, ToCricketFeedbackParam) { |
+ auto result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR}); |
+ EXPECT_EQ(cricket::FeedbackParam("ccm", "fir"), result.value()); |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK}); |
+ EXPECT_EQ(cricket::FeedbackParam("nack"), result.value()); |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI}); |
+ EXPECT_EQ(cricket::FeedbackParam("nack", "pli"), result.value()); |
+ result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::REMB)); |
+ EXPECT_EQ(cricket::FeedbackParam("goog-remb"), result.value()); |
+ result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC)); |
+ EXPECT_EQ(cricket::FeedbackParam("transport-cc"), result.value()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketFeedbackParamErrors) { |
+ // CCM with missing or invalid message type. |
+ auto result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::CCM)); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::PLI}); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ // NACK with missing or invalid message type. |
+ result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::NACK)); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::FIR}); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ // REMB with message type (should be left empty). |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::REMB, RtcpFeedbackMessageType::GENERIC_NACK}); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ // TRANSPORT_CC with message type (should be left empty). |
+ result = ToCricketFeedbackParam( |
+ {RtcpFeedbackType::TRANSPORT_CC, RtcpFeedbackMessageType::FIR}); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToAudioCodec) { |
+ RtpCodecParameters codec; |
+ codec.name = "AuDiO"; |
+ codec.kind = cricket::MEDIA_TYPE_AUDIO; |
+ codec.payload_type = 120; |
+ codec.clock_rate.emplace(36000); |
+ codec.num_channels.emplace(6); |
+ codec.parameters["foo"] = "bar"; |
+ codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC); |
+ auto result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ ASSERT_TRUE(result.ok()); |
+ |
+ EXPECT_EQ("AuDiO", result.value().name); |
+ EXPECT_EQ(120, result.value().id); |
+ EXPECT_EQ(36000, result.value().clockrate); |
+ EXPECT_EQ(6u, result.value().channels); |
+ ASSERT_EQ(1u, result.value().params.size()); |
+ EXPECT_EQ("bar", result.value().params["foo"]); |
+ EXPECT_EQ(1u, result.value().feedback_params.params().size()); |
+ EXPECT_TRUE(result.value().feedback_params.Has( |
+ cricket::FeedbackParam("transport-cc"))); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToVideoCodec) { |
+ RtpCodecParameters codec; |
+ codec.name = "coolcodec"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.payload_type = 101; |
+ codec.clock_rate.emplace(90000); |
+ codec.parameters["foo"] = "bar"; |
+ codec.parameters["PING"] = "PONG"; |
+ codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC); |
+ codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK, |
+ RtcpFeedbackMessageType::PLI); |
+ auto result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ ASSERT_TRUE(result.ok()); |
+ |
+ EXPECT_EQ("coolcodec", result.value().name); |
+ EXPECT_EQ(101, result.value().id); |
+ EXPECT_EQ(90000, result.value().clockrate); |
+ ASSERT_EQ(2u, result.value().params.size()); |
+ EXPECT_EQ("bar", result.value().params["foo"]); |
+ EXPECT_EQ("PONG", result.value().params["PING"]); |
+ EXPECT_EQ(2u, result.value().feedback_params.params().size()); |
+ EXPECT_TRUE(result.value().feedback_params.Has( |
+ cricket::FeedbackParam("transport-cc"))); |
+ EXPECT_TRUE(result.value().feedback_params.Has( |
+ cricket::FeedbackParam("nack", "pli"))); |
+} |
+ |
+// Trying to convert to an AudioCodec if the kind is "video" should fail. |
+TEST(RtpParametersConversionTest, ToCricketCodecInvalidKind) { |
+ RtpCodecParameters audio_codec; |
+ audio_codec.name = "opus"; |
+ audio_codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ audio_codec.payload_type = 111; |
+ audio_codec.clock_rate.emplace(48000); |
+ audio_codec.num_channels.emplace(2); |
+ |
+ RtpCodecParameters video_codec; |
+ video_codec.name = "VP8"; |
+ video_codec.kind = cricket::MEDIA_TYPE_AUDIO; |
+ video_codec.payload_type = 102; |
+ video_codec.clock_rate.emplace(90000); |
+ |
+ auto audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, audio_result.error().type()); |
+ |
+ auto video_result = ToCricketCodec<cricket::VideoCodec>(video_codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_result.error().type()); |
+ |
+ // Sanity check that if the kind is correct, the conversion succeeds. |
+ audio_codec.kind = cricket::MEDIA_TYPE_AUDIO; |
+ video_codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec); |
+ EXPECT_TRUE(audio_result.ok()); |
+ video_result = ToCricketCodec<cricket::VideoCodec>(video_codec); |
+ EXPECT_TRUE(video_result.ok()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToAudioCodecInvalidParameters) { |
+ // Missing channels. |
+ RtpCodecParameters codec; |
+ codec.name = "opus"; |
+ codec.kind = cricket::MEDIA_TYPE_AUDIO; |
+ codec.payload_type = 111; |
+ codec.clock_rate.emplace(48000); |
+ auto result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Negative number of channels. |
+ codec.num_channels.emplace(-1); |
+ result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ // Missing clock rate. |
+ codec.num_channels.emplace(2); |
+ codec.clock_rate.reset(); |
+ result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Negative clock rate. |
+ codec.clock_rate.emplace(-48000); |
+ result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ // Sanity check that conversion succeeds if these errors are fixed. |
+ codec.clock_rate.emplace(48000); |
+ result = ToCricketCodec<cricket::AudioCodec>(codec); |
+ EXPECT_TRUE(result.ok()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToVideoCodecInvalidParameters) { |
+ // Missing clock rate. |
+ RtpCodecParameters codec; |
+ codec.name = "VP8"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.payload_type = 102; |
+ auto result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Invalid clock rate. |
+ codec.clock_rate.emplace(48000); |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Channels set (should be unset). |
+ codec.clock_rate.emplace(90000); |
+ codec.num_channels.emplace(2); |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Sanity check that conversion succeeds if these errors are fixed. |
+ codec.num_channels.reset(); |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_TRUE(result.ok()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketCodecInvalidPayloadType) { |
+ RtpCodecParameters codec; |
+ codec.name = "VP8"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.clock_rate.emplace(90000); |
+ |
+ codec.payload_type = -1000; |
+ auto result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ // Max payload type is 127. |
+ codec.payload_type = 128; |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ // Sanity check that conversion succeeds with a valid payload type. |
+ codec.payload_type = 127; |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_TRUE(result.ok()); |
+} |
+ |
+// There are already tests for ToCricketFeedbackParam, but ensure that those |
+// errors are propagated from ToCricketCodec. |
+TEST(RtpParametersConversionTest, ToCricketCodecInvalidRtcpFeedback) { |
+ RtpCodecParameters codec; |
+ codec.name = "VP8"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.clock_rate.emplace(90000); |
+ codec.payload_type = 99; |
+ codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM, |
+ RtcpFeedbackMessageType::PLI); |
+ |
+ auto result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Sanity check that conversion succeeds without invalid feedback. |
+ codec.rtcp_feedback.clear(); |
+ result = ToCricketCodec<cricket::VideoCodec>(codec); |
+ EXPECT_TRUE(result.ok()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketCodecs) { |
+ std::vector<RtpCodecParameters> codecs; |
+ RtpCodecParameters codec; |
+ codec.name = "VP8"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.clock_rate.emplace(90000); |
+ codec.payload_type = 99; |
+ codecs.push_back(codec); |
+ |
+ codec.name = "VP9"; |
+ codec.payload_type = 100; |
+ codecs.push_back(codec); |
+ |
+ auto result = ToCricketCodecs<cricket::VideoCodec>(codecs); |
+ ASSERT_TRUE(result.ok()); |
+ ASSERT_EQ(2u, result.value().size()); |
+ EXPECT_EQ("VP8", result.value()[0].name); |
+ EXPECT_EQ(99, result.value()[0].id); |
+ EXPECT_EQ("VP9", result.value()[1].name); |
+ EXPECT_EQ(100, result.value()[1].id); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketCodecsDuplicatePayloadType) { |
+ std::vector<RtpCodecParameters> codecs; |
+ RtpCodecParameters codec; |
+ codec.name = "VP8"; |
+ codec.kind = cricket::MEDIA_TYPE_VIDEO; |
+ codec.clock_rate.emplace(90000); |
+ codec.payload_type = 99; |
+ codecs.push_back(codec); |
+ |
+ codec.name = "VP9"; |
+ codec.payload_type = 99; |
+ codecs.push_back(codec); |
+ |
+ auto result = ToCricketCodecs<cricket::VideoCodec>(codecs); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+ |
+ // Sanity check that this succeeds without the duplicate payload type. |
+ codecs[1].payload_type = 120; |
+ result = ToCricketCodecs<cricket::VideoCodec>(codecs); |
+ EXPECT_TRUE(result.ok()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensions) { |
+ std::vector<RtpHeaderExtensionParameters> extensions = { |
+ {"http://example.com", 1}, {"urn:foo:bar", 14}}; |
+ auto result = ToCricketRtpHeaderExtensions(extensions); |
+ ASSERT_TRUE(result.ok()); |
+ ASSERT_EQ(2u, result.value().size()); |
+ EXPECT_EQ("http://example.com", result.value()[0].uri); |
+ EXPECT_EQ(1, result.value()[0].id); |
+ EXPECT_EQ("urn:foo:bar", result.value()[1].uri); |
+ EXPECT_EQ(14, result.value()[1].id); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensionsErrors) { |
+ // First, IDs outside the range 1-14. |
+ std::vector<RtpHeaderExtensionParameters> extensions = { |
+ {"http://example.com", 0}}; |
+ auto result = ToCricketRtpHeaderExtensions(extensions); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ extensions[0].id = 15; |
+ result = ToCricketRtpHeaderExtensions(extensions); |
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); |
+ |
+ // Duplicate IDs. |
+ extensions = {{"http://example.com", 1}, {"urn:foo:bar", 1}}; |
+ result = ToCricketRtpHeaderExtensions(extensions); |
+ EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketStreamParamsVecSimple) { |
+ std::vector<RtpEncodingParameters> encodings; |
+ RtpEncodingParameters encoding; |
+ encoding.ssrc.emplace(0xbaadf00d); |
+ encodings.push_back(encoding); |
+ auto result = ToCricketStreamParamsVec(encodings); |
+ ASSERT_TRUE(result.ok()); |
+ ASSERT_EQ(1u, result.value().size()); |
+ EXPECT_EQ(1u, result.value()[0].ssrcs.size()); |
+ EXPECT_EQ(0xbaadf00d, result.value()[0].first_ssrc()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToCricketStreamParamsVecWithRtx) { |
+ std::vector<RtpEncodingParameters> encodings; |
+ RtpEncodingParameters encoding; |
+ // Test a corner case SSRC of 0. |
+ encoding.ssrc.emplace(0u); |
+ encoding.rtx.emplace(0xdeadbeef); |
+ encodings.push_back(encoding); |
+ auto result = ToCricketStreamParamsVec(encodings); |
+ ASSERT_TRUE(result.ok()); |
+ ASSERT_EQ(1u, result.value().size()); |
+ EXPECT_EQ(2u, result.value()[0].ssrcs.size()); |
+ EXPECT_EQ(0u, result.value()[0].first_ssrc()); |
+ uint32_t rtx_ssrc = 0; |
+ EXPECT_TRUE(result.value()[0].GetFidSsrc(0u, &rtx_ssrc)); |
+ EXPECT_EQ(0xdeadbeef, rtx_ssrc); |
+} |
+ |
+// No encodings should be accepted; an endpoint may want to prepare a |
+// decoder/encoder without having something to receive/send yet. |
+TEST(RtpParametersConversionTest, ToCricketStreamParamsVecNoEncodings) { |
+ std::vector<RtpEncodingParameters> encodings; |
+ auto result = ToCricketStreamParamsVec(encodings); |
+ ASSERT_TRUE(result.ok()); |
+ EXPECT_EQ(0u, result.value().size()); |
+} |
+ |
+// An encoding without SSRCs should be accepted. This could be the case when |
+// SSRCs aren't signaled and payload-type based demuxing is used. |
+TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMissingSsrcs) { |
+ std::vector<RtpEncodingParameters> encodings = {{}}; |
+ // Creates RtxParameters with empty SSRC. |
+ encodings[0].rtx.emplace(); |
+ auto result = ToCricketStreamParamsVec(encodings); |
+ ASSERT_TRUE(result.ok()); |
+ EXPECT_EQ(0u, result.value().size()); |
+} |
+ |
+// The media engine doesn't have a way of receiving an RTX SSRC that's known |
+// with a primary SSRC that's unknown, so this should produce an error. |
+TEST(RtpParametersConversionTest, ToStreamParamsWithPrimarySsrcSetAndRtxUnset) { |
+ std::vector<RtpEncodingParameters> encodings = {{}}; |
+ encodings[0].rtx.emplace(0xdeadbeef); |
+ EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, |
+ ToCricketStreamParamsVec(encodings).error().type()); |
+} |
+ |
+// TODO(deadbeef): Update this test when we support multiple encodings. |
+TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMultipleEncodings) { |
+ std::vector<RtpEncodingParameters> encodings = {{}, {}}; |
+ auto result = ToCricketStreamParamsVec(encodings); |
+ EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, result.error().type()); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToRtcpFeedback) { |
+ rtc::Optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "fir"}); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR), |
+ *result); |
+ result = ToRtcpFeedback(cricket::FeedbackParam("nack")); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, |
+ RtcpFeedbackMessageType::GENERIC_NACK), |
+ *result); |
+ result = ToRtcpFeedback({"nack", "pli"}); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI), |
+ *result); |
+ result = ToRtcpFeedback(cricket::FeedbackParam("goog-remb")); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::REMB), *result); |
+ result = ToRtcpFeedback(cricket::FeedbackParam("transport-cc")); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), *result); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToRtcpFeedbackErrors) { |
+ // CCM with missing or invalid message type. |
+ rtc::Optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "pli"}); |
+ EXPECT_FALSE(result); |
+ result = ToRtcpFeedback(cricket::FeedbackParam("ccm")); |
+ EXPECT_FALSE(result); |
+ // NACK with missing or invalid message type. |
+ result = ToRtcpFeedback({"nack", "fir"}); |
+ EXPECT_FALSE(result); |
+ // REMB with message type (should be left empty). |
+ result = ToRtcpFeedback({"goog-remb", "pli"}); |
+ EXPECT_FALSE(result); |
+ // TRANSPORT_CC with message type (should be left empty). |
+ result = ToRtcpFeedback({"transport-cc", "fir"}); |
+ EXPECT_FALSE(result); |
+ // Unknown message type. |
+ result = ToRtcpFeedback(cricket::FeedbackParam("foo")); |
+ EXPECT_FALSE(result); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToAudioRtpCodecCapability) { |
+ cricket::AudioCodec cricket_codec; |
+ cricket_codec.name = "foo"; |
+ cricket_codec.id = 50; |
+ cricket_codec.clockrate = 22222; |
+ cricket_codec.channels = 4; |
+ cricket_codec.params["foo"] = "bar"; |
+ cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc")); |
+ RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec); |
+ |
+ EXPECT_EQ("foo", codec.name); |
+ EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind); |
+ EXPECT_EQ(rtc::Optional<int>(50), codec.preferred_payload_type); |
+ EXPECT_EQ(rtc::Optional<int>(22222), codec.clock_rate); |
+ EXPECT_EQ(rtc::Optional<int>(4), codec.num_channels); |
+ ASSERT_EQ(1u, codec.parameters.size()); |
+ EXPECT_EQ("bar", codec.parameters["foo"]); |
+ EXPECT_EQ(1u, codec.rtcp_feedback.size()); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), |
+ codec.rtcp_feedback[0]); |
+} |
+ |
+TEST(RtpParametersConversionTest, ToVideoRtpCodecCapability) { |
+ cricket::VideoCodec cricket_codec; |
+ cricket_codec.name = "VID"; |
+ cricket_codec.id = 101; |
+ cricket_codec.clockrate = 80000; |
+ cricket_codec.params["foo"] = "bar"; |
+ cricket_codec.params["ANOTHER"] = "param"; |
+ cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc")); |
+ cricket_codec.feedback_params.Add({"nack", "pli"}); |
+ RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec); |
+ |
+ EXPECT_EQ("VID", codec.name); |
+ EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind); |
+ EXPECT_EQ(rtc::Optional<int>(101), codec.preferred_payload_type); |
+ EXPECT_EQ(rtc::Optional<int>(80000), codec.clock_rate); |
+ ASSERT_EQ(2u, codec.parameters.size()); |
+ EXPECT_EQ("bar", codec.parameters["foo"]); |
+ EXPECT_EQ("param", codec.parameters["ANOTHER"]); |
+ EXPECT_EQ(2u, codec.rtcp_feedback.size()); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), |
+ codec.rtcp_feedback[0]); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI), |
+ codec.rtcp_feedback[1]); |
+} |
+ |
+// An unknown feedback param should just be ignored. |
+TEST(RtpParametersConversionTest, ToRtpCodecCapabilityUnknownFeedbackParam) { |
+ cricket::AudioCodec cricket_codec; |
+ cricket_codec.name = "foo"; |
+ cricket_codec.id = 50; |
+ cricket_codec.clockrate = 22222; |
+ cricket_codec.channels = 4; |
+ cricket_codec.params["foo"] = "bar"; |
+ cricket_codec.feedback_params.Add({"unknown", "param"}); |
+ cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc")); |
+ RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec); |
+ |
+ ASSERT_EQ(1u, codec.rtcp_feedback.size()); |
+ EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), |
+ codec.rtcp_feedback[0]); |
+} |
+ |
+// Most of ToRtpCapabilities is tested by ToRtpCodecCapability, but we need to |
+// test that the result of ToRtpCodecCapability ends up in the result, and that |
+// the "fec" list is assembled correctly. |
+TEST(RtpParametersConversionTest, ToRtpCapabilities) { |
+ cricket::VideoCodec vp8; |
+ vp8.name = "VP8"; |
+ vp8.id = 101; |
+ vp8.clockrate = 90000; |
+ |
+ cricket::VideoCodec red; |
+ red.name = "red"; |
+ red.id = 102; |
+ red.clockrate = 90000; |
+ |
+ cricket::VideoCodec ulpfec; |
+ ulpfec.name = "ulpfec"; |
+ ulpfec.id = 103; |
+ ulpfec.clockrate = 90000; |
+ |
+ cricket::VideoCodec flexfec; |
+ flexfec.name = "flexfec-03"; |
+ flexfec.id = 102; |
+ flexfec.clockrate = 90000; |
+ |
+ RtpCapabilities capabilities = ToRtpCapabilities<cricket::VideoCodec>( |
+ {vp8, ulpfec}, {{"uri", 1}, {"uri2", 3}}); |
+ ASSERT_EQ(2u, capabilities.codecs.size()); |
+ EXPECT_EQ("VP8", capabilities.codecs[0].name); |
+ EXPECT_EQ("ulpfec", capabilities.codecs[1].name); |
+ ASSERT_EQ(2u, capabilities.header_extensions.size()); |
+ EXPECT_EQ("uri", capabilities.header_extensions[0].uri); |
+ EXPECT_EQ(1, capabilities.header_extensions[0].preferred_id); |
+ EXPECT_EQ("uri2", capabilities.header_extensions[1].uri); |
+ EXPECT_EQ(3, capabilities.header_extensions[1].preferred_id); |
+ EXPECT_EQ(0u, capabilities.fec.size()); |
+ |
+ capabilities = ToRtpCapabilities<cricket::VideoCodec>( |
+ {vp8, red, ulpfec}, cricket::RtpHeaderExtensions()); |
+ EXPECT_EQ(3u, capabilities.codecs.size()); |
+ EXPECT_EQ(2u, capabilities.fec.size()); |
+ EXPECT_NE(capabilities.fec.end(), |
+ std::find(capabilities.fec.begin(), capabilities.fec.end(), |
+ FecMechanism::RED)); |
+ EXPECT_NE(capabilities.fec.end(), |
+ std::find(capabilities.fec.begin(), capabilities.fec.end(), |
+ FecMechanism::RED_AND_ULPFEC)); |
+ |
+ capabilities = ToRtpCapabilities<cricket::VideoCodec>( |
+ {vp8, red, flexfec}, cricket::RtpHeaderExtensions()); |
+ EXPECT_EQ(3u, capabilities.codecs.size()); |
+ EXPECT_EQ(2u, capabilities.fec.size()); |
+ EXPECT_NE(capabilities.fec.end(), |
+ std::find(capabilities.fec.begin(), capabilities.fec.end(), |
+ FecMechanism::RED)); |
+ EXPECT_NE(capabilities.fec.end(), |
+ std::find(capabilities.fec.begin(), capabilities.fec.end(), |
+ FecMechanism::FLEXFEC)); |
+} |
+ |
+} // namespace webrtc |