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 ModuleRTPUtility::Payload* ExpectReturnOfTypicalAudioPayload(
40 uint8_t payload_type, uint32_t rate) {
42 ModuleRTPUtility::Payload returned_payload = { "name", audio, {
43 // Initialize the audio struct in this case.
44 { kTypicalFrequency, kTypicalChannels, rate }
47 // Note: we return a new payload since the payload registry takes ownership
48 // of the created object.
49 ModuleRTPUtility::Payload* returned_payload_on_heap =
50 new ModuleRTPUtility::Payload(returned_payload);
51 EXPECT_CALL(*mock_payload_strategy_,
52 CreatePayloadType(kTypicalPayloadName, payload_type,
55 rate)).WillOnce(Return(returned_payload_on_heap));
56 return returned_payload_on_heap;
59 scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_;
60 testing::NiceMock<MockRTPPayloadStrategy>* mock_payload_strategy_;
63 TEST_F(RtpPayloadRegistryTest, RegistersAndRemembersPayloadsUntilDeregistered) {
64 uint8_t payload_type = 97;
65 ModuleRTPUtility::Payload* returned_payload_on_heap =
66 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
68 bool new_payload_created = false;
69 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
70 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
71 kTypicalRate, &new_payload_created));
73 EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
75 ModuleRTPUtility::Payload* retrieved_payload = NULL;
76 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type,
79 // We should get back the exact pointer to the payload returned by the
81 EXPECT_EQ(returned_payload_on_heap, retrieved_payload);
83 // Now forget about it and verify it's gone.
84 EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
85 EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(
86 payload_type, retrieved_payload));
89 TEST_F(RtpPayloadRegistryTest, DoesNotCreateNewPayloadTypeIfRed) {
90 EXPECT_CALL(*mock_payload_strategy_,
91 CreatePayloadType(_, _, _, _, _)).Times(0);
93 bool new_payload_created = false;
94 uint8_t red_type_of_the_day = 104;
95 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
96 "red", red_type_of_the_day, kTypicalFrequency, kTypicalChannels,
97 kTypicalRate, &new_payload_created));
98 ASSERT_FALSE(new_payload_created);
100 ASSERT_EQ(red_type_of_the_day, rtp_payload_registry_->red_payload_type());
102 ModuleRTPUtility::Payload* retrieved_payload = NULL;
103 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(red_type_of_the_day,
105 EXPECT_FALSE(retrieved_payload->audio);
106 EXPECT_STRCASEEQ("red", retrieved_payload->name);
109 TEST_F(RtpPayloadRegistryTest,
110 DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
111 uint8_t payload_type = 97;
113 bool ignored = false;
114 ModuleRTPUtility::Payload* first_payload_on_heap =
115 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
116 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
117 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
118 kTypicalRate, &ignored));
120 EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload(
121 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
122 kTypicalRate, &ignored)) << "Adding same codec twice = bad.";
124 ModuleRTPUtility::Payload* second_payload_on_heap =
125 ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
126 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
127 kTypicalPayloadName, payload_type - 1, kTypicalFrequency,
128 kTypicalChannels, kTypicalRate, &ignored)) <<
129 "With a different payload type is fine though.";
131 // Ensure both payloads are preserved.
132 ModuleRTPUtility::Payload* retrieved_payload = NULL;
133 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type,
135 EXPECT_EQ(first_payload_on_heap, retrieved_payload);
136 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1,
138 EXPECT_EQ(second_payload_on_heap, retrieved_payload);
140 // Ok, update the rate for one of the codecs. If either the incoming rate or
141 // the stored rate is zero it's not really an error to register the same
142 // codec twice, and in that case roughly the following happens.
143 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
144 .WillByDefault(Return(true));
145 EXPECT_CALL(*mock_payload_strategy_,
146 UpdatePayloadRate(first_payload_on_heap, kTypicalRate));
147 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
148 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
149 kTypicalRate, &ignored));
152 TEST_F(RtpPayloadRegistryTest,
153 RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
154 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
155 .WillByDefault(Return(true));
156 ON_CALL(*mock_payload_strategy_, CodecsMustBeUnique())
157 .WillByDefault(Return(true));
159 uint8_t payload_type = 97;
161 bool ignored = false;
162 ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
163 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
164 kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels,
165 kTypicalRate, &ignored));
166 ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
167 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
168 kTypicalPayloadName, payload_type - 1, kTypicalFrequency,
169 kTypicalChannels, kTypicalRate, &ignored));
171 ModuleRTPUtility::Payload* retrieved_payload = NULL;
172 EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(
173 payload_type, retrieved_payload)) << "The first payload should be "
174 "deregistered because the only thing that differs is payload type.";
175 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
176 payload_type - 1, retrieved_payload)) <<
177 "The second payload should still be registered though.";
179 // Now ensure non-compatible codecs aren't removed.
180 ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
181 .WillByDefault(Return(false));
182 ExpectReturnOfTypicalAudioPayload(payload_type + 1, kTypicalRate);
183 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
184 kTypicalPayloadName, payload_type + 1, kTypicalFrequency,
185 kTypicalChannels, kTypicalRate, &ignored));
187 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
188 payload_type - 1, retrieved_payload)) <<
189 "Not compatible; both payloads should be kept.";
190 EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(
191 payload_type + 1, retrieved_payload)) <<
192 "Not compatible; both payloads should be kept.";
195 TEST_F(RtpPayloadRegistryTest,
196 LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
197 rtp_payload_registry_->set_last_received_payload_type(17);
198 EXPECT_EQ(17, rtp_payload_registry_->last_received_payload_type());
200 bool media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
201 EXPECT_FALSE(media_type_unchanged);
202 media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
203 EXPECT_TRUE(media_type_unchanged);
206 ExpectReturnOfTypicalAudioPayload(34, kTypicalRate);
207 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
208 kTypicalPayloadName, 34, kTypicalFrequency, kTypicalChannels,
209 kTypicalRate, &ignored));
211 EXPECT_EQ(-1, rtp_payload_registry_->last_received_payload_type());
212 media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
213 EXPECT_FALSE(media_type_unchanged);
216 class ParameterizedRtpPayloadRegistryTest :
217 public RtpPayloadRegistryTest,
218 public ::testing::WithParamInterface<int> {
221 TEST_P(ParameterizedRtpPayloadRegistryTest,
222 FailsToRegisterKnownPayloadsWeAreNotInterestedIn) {
223 int payload_type = GetParam();
226 EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload(
227 "whatever", static_cast<uint8_t>(payload_type), 19, 1, 17,
231 INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
232 ParameterizedRtpPayloadRegistryTest,
233 testing::Values(64, 72, 73, 74, 75, 76, 77, 78, 79));
235 class RtpPayloadRegistryGenericTest :
236 public RtpPayloadRegistryTest,
237 public ::testing::WithParamInterface<int> {
240 TEST_P(RtpPayloadRegistryGenericTest, RegisterGenericReceivePayloadType) {
241 int payload_type = GetParam();
245 EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload("generic-codec",
246 static_cast<int8_t>(payload_type),
247 19, 1, 17, &ignored)); // dummy values, except for payload_type
250 INSTANTIATE_TEST_CASE_P(TestDynamicRange, RtpPayloadRegistryGenericTest,
251 testing::Range(96, 127+1));
253 } // namespace webrtc