2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h"
16 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
17 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
22 using ::testing::Return;
25 static const char* kTypicalPayloadName = "name";
26 static const uint8_t kTypicalChannels = 1;
27 static const int kTypicalFrequency = 44000;
28 static const int kTypicalRate = 32 * 1024;
30 class RtpPayloadRegistryTest : public ::testing::Test {
33 // Note: the payload registry takes ownership of the strategy.
34 mock_payload_strategy_ = new testing::NiceMock<MockRTPPayloadStrategy>();
35 rtp_payload_registry_.reset(new RTPPayloadRegistry(mock_payload_strategy_));
39 RtpUtility::Payload* ExpectReturnOfTypicalAudioPayload(uint8_t payload_type,
42 RtpUtility::Payload returned_payload = {
45 {// Initialize the audio struct in this case.
46 {kTypicalFrequency, kTypicalChannels, rate}}};
48 // Note: we return a new payload since the payload registry takes ownership
49 // of the created object.
50 RtpUtility::Payload* returned_payload_on_heap =
51 new RtpUtility::Payload(returned_payload);
52 EXPECT_CALL(*mock_payload_strategy_,
53 CreatePayloadType(kTypicalPayloadName, payload_type,
56 rate)).WillOnce(Return(returned_payload_on_heap));
57 return returned_payload_on_heap;
60 scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_;
61 testing::NiceMock<MockRTPPayloadStrategy>* mock_payload_strategy_;
64 TEST_F(RtpPayloadRegistryTest, RegistersAndRemembersPayloadsUntilDeregistered) {
65 uint8_t payload_type = 97;
66 RtpUtility::Payload* returned_payload_on_heap =
67 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
69 bool new_payload_created = false;
70 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
71 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
72 kTypicalRate, &new_payload_created));
74 EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
76 RtpUtility::Payload* retrieved_payload = NULL;
77 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type,
80 // We should get back the exact pointer to the payload returned by the
82 EXPECT_EQ(returned_payload_on_heap, retrieved_payload);
84 // Now forget about it and verify it's gone.
85 EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
86 EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(
87 payload_type, retrieved_payload));
90 TEST_F(RtpPayloadRegistryTest, DoesNotCreateNewPayloadTypeIfRed) {
91 EXPECT_CALL(*mock_payload_strategy_,
92 CreatePayloadType(_, _, _, _, _)).Times(0);
94 bool new_payload_created = false;
95 uint8_t red_type_of_the_day = 104;
96 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
97 "red", red_type_of_the_day, kTypicalFrequency, kTypicalChannels,
98 kTypicalRate, &new_payload_created));
99 ASSERT_FALSE(new_payload_created);
101 ASSERT_EQ(red_type_of_the_day, rtp_payload_registry_->red_payload_type());
103 RtpUtility::Payload* retrieved_payload = NULL;
104 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(red_type_of_the_day,
106 EXPECT_FALSE(retrieved_payload->audio);
107 EXPECT_STRCASEEQ("red", retrieved_payload->name);
110 TEST_F(RtpPayloadRegistryTest,
111 DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
112 uint8_t payload_type = 97;
114 bool ignored = false;
115 RtpUtility::Payload* first_payload_on_heap =
116 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
117 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
118 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
119 kTypicalRate, &ignored));
121 EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload(
122 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
123 kTypicalRate, &ignored)) << "Adding same codec twice = bad.";
125 RtpUtility::Payload* second_payload_on_heap =
126 ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
127 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
128 kTypicalPayloadName, payload_type - 1, kTypicalFrequency,
129 kTypicalChannels, kTypicalRate, &ignored)) <<
130 "With a different payload type is fine though.";
132 // Ensure both payloads are preserved.
133 RtpUtility::Payload* retrieved_payload = NULL;
134 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type,
136 EXPECT_EQ(first_payload_on_heap, retrieved_payload);
137 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1,
139 EXPECT_EQ(second_payload_on_heap, retrieved_payload);
141 // Ok, update the rate for one of the codecs. If either the incoming rate or
142 // the stored rate is zero it's not really an error to register the same
143 // codec twice, and in that case roughly the following happens.
144 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
145 .WillByDefault(Return(true));
146 EXPECT_CALL(*mock_payload_strategy_,
147 UpdatePayloadRate(first_payload_on_heap, kTypicalRate));
148 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
149 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
150 kTypicalRate, &ignored));
153 TEST_F(RtpPayloadRegistryTest,
154 RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
155 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
156 .WillByDefault(Return(true));
157 ON_CALL(*mock_payload_strategy_, CodecsMustBeUnique())
158 .WillByDefault(Return(true));
160 uint8_t payload_type = 97;
162 bool ignored = false;
163 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
164 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
165 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
166 kTypicalRate, &ignored));
167 ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
168 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
169 kTypicalPayloadName, payload_type - 1, kTypicalFrequency,
170 kTypicalChannels, kTypicalRate, &ignored));
172 RtpUtility::Payload* retrieved_payload = NULL;
173 EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(
174 payload_type, retrieved_payload)) << "The first payload should be "
175 "deregistered because the only thing that differs is payload type.";
176 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
177 payload_type - 1, retrieved_payload)) <<
178 "The second payload should still be registered though.";
180 // Now ensure non-compatible codecs aren't removed.
181 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
182 .WillByDefault(Return(false));
183 ExpectReturnOfTypicalAudioPayload(payload_type + 1, kTypicalRate);
184 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
185 kTypicalPayloadName, payload_type + 1, kTypicalFrequency,
186 kTypicalChannels, kTypicalRate, &ignored));
188 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
189 payload_type - 1, retrieved_payload)) <<
190 "Not compatible; both payloads should be kept.";
191 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
192 payload_type + 1, retrieved_payload)) <<
193 "Not compatible; both payloads should be kept.";
196 TEST_F(RtpPayloadRegistryTest,
197 LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
198 rtp_payload_registry_->set_last_received_payload_type(17);
199 EXPECT_EQ(17, rtp_payload_registry_->last_received_payload_type());
201 bool media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
202 EXPECT_FALSE(media_type_unchanged);
203 media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
204 EXPECT_TRUE(media_type_unchanged);
207 ExpectReturnOfTypicalAudioPayload(34, kTypicalRate);
208 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
209 kTypicalPayloadName, 34, kTypicalFrequency, kTypicalChannels,
210 kTypicalRate, &ignored));
212 EXPECT_EQ(-1, rtp_payload_registry_->last_received_payload_type());
213 media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
214 EXPECT_FALSE(media_type_unchanged);
217 class ParameterizedRtpPayloadRegistryTest :
218 public RtpPayloadRegistryTest,
219 public ::testing::WithParamInterface<int> {
222 TEST_P(ParameterizedRtpPayloadRegistryTest,
223 FailsToRegisterKnownPayloadsWeAreNotInterestedIn) {
224 int payload_type = GetParam();
227 EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload(
228 "whatever", static_cast<uint8_t>(payload_type), 19, 1, 17,
232 INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
233 ParameterizedRtpPayloadRegistryTest,
234 testing::Values(64, 72, 73, 74, 75, 76, 77, 78, 79));
236 class RtpPayloadRegistryGenericTest :
237 public RtpPayloadRegistryTest,
238 public ::testing::WithParamInterface<int> {
241 TEST_P(RtpPayloadRegistryGenericTest, RegisterGenericReceivePayloadType) {
242 int payload_type = GetParam();
246 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload("generic-codec",
247 static_cast<int8_t>(payload_type),
248 19, 1, 17, &ignored)); // dummy values, except for payload_type
251 INSTANTIATE_TEST_CASE_P(TestDynamicRange, RtpPayloadRegistryGenericTest,
252 testing::Range(96, 127+1));
254 } // namespace webrtc