1 /*
2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 *
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.
9 */
10
11 #include "modules/rtp_rtcp/source/rtp_sender_audio.h"
12
13 #include <memory>
14 #include <vector>
15
16 #include "api/transport/field_trial_based_config.h"
17 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
18 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
19 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
20 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
21 #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
22 #include "rtc_base/thread.h"
23 #include "test/field_trial.h"
24 #include "test/gmock.h"
25 #include "test/gtest.h"
26
27 namespace webrtc {
28
29 namespace {
30 enum : int { // The first valid value is 1.
31 kAudioLevelExtensionId = 1,
32 kAbsoluteCaptureTimeExtensionId = 2,
33 };
34
35 const uint16_t kSeqNum = 33;
36 const uint32_t kSsrc = 725242;
37 const uint8_t kAudioLevel = 0x5a;
38 const uint64_t kStartTime = 123456789;
39
40 using ::testing::ElementsAreArray;
41
42 class LoopbackTransportTest : public webrtc::Transport {
43 public:
LoopbackTransportTest()44 LoopbackTransportTest() {
45 receivers_extensions_.Register<AudioLevel>(kAudioLevelExtensionId);
46 receivers_extensions_.Register<AbsoluteCaptureTimeExtension>(
47 kAbsoluteCaptureTimeExtensionId);
48 }
49
SendRtp(const uint8_t * data,size_t len,const PacketOptions &)50 bool SendRtp(const uint8_t* data,
51 size_t len,
52 const PacketOptions& /*options*/) override {
53 sent_packets_.push_back(RtpPacketReceived(&receivers_extensions_));
54 EXPECT_TRUE(sent_packets_.back().Parse(data, len));
55 return true;
56 }
SendRtcp(const uint8_t * data,size_t len)57 bool SendRtcp(const uint8_t* data, size_t len) override { return false; }
last_sent_packet()58 const RtpPacketReceived& last_sent_packet() { return sent_packets_.back(); }
packets_sent()59 int packets_sent() { return sent_packets_.size(); }
60
61 private:
62 RtpHeaderExtensionMap receivers_extensions_;
63 std::vector<RtpPacketReceived> sent_packets_;
64 };
65
66 } // namespace
67
68 class RtpSenderAudioTest : public ::testing::Test {
69 public:
RtpSenderAudioTest()70 RtpSenderAudioTest()
71 : fake_clock_(kStartTime),
72 rtp_module_(ModuleRtpRtcpImpl2::Create([&] {
73 RtpRtcpInterface::Configuration config;
74 config.audio = true;
75 config.clock = &fake_clock_;
76 config.outgoing_transport = &transport_;
77 config.local_media_ssrc = kSsrc;
78 return config;
79 }())),
80 rtp_sender_audio_(
81 std::make_unique<RTPSenderAudio>(&fake_clock_,
82 rtp_module_->RtpSender())) {
83 rtp_module_->SetSequenceNumber(kSeqNum);
84 }
85
86 rtc::AutoThread main_thread_;
87 SimulatedClock fake_clock_;
88 LoopbackTransportTest transport_;
89 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_module_;
90 std::unique_ptr<RTPSenderAudio> rtp_sender_audio_;
91 };
92
TEST_F(RtpSenderAudioTest,SendAudio)93 TEST_F(RtpSenderAudioTest, SendAudio) {
94 const char payload_name[] = "PAYLOAD_NAME";
95 const uint8_t payload_type = 127;
96 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
97 payload_name, payload_type, 48000, 0, 1500));
98 uint8_t payload[] = {47, 11, 32, 93, 89};
99
100 ASSERT_TRUE(
101 rtp_sender_audio_->SendAudio(AudioFrameType::kAudioFrameCN, payload_type,
102 4321, payload, sizeof(payload),
103 /*absolute_capture_timestamp_ms=*/0));
104
105 auto sent_payload = transport_.last_sent_packet().payload();
106 EXPECT_THAT(sent_payload, ElementsAreArray(payload));
107 }
108
TEST_F(RtpSenderAudioTest,SendAudioWithAudioLevelExtension)109 TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
110 EXPECT_EQ(0, rtp_sender_audio_->SetAudioLevel(kAudioLevel));
111 rtp_module_->RegisterRtpHeaderExtension(AudioLevel::Uri(),
112 kAudioLevelExtensionId);
113
114 const char payload_name[] = "PAYLOAD_NAME";
115 const uint8_t payload_type = 127;
116 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
117 payload_name, payload_type, 48000, 0, 1500));
118
119 uint8_t payload[] = {47, 11, 32, 93, 89};
120
121 ASSERT_TRUE(
122 rtp_sender_audio_->SendAudio(AudioFrameType::kAudioFrameCN, payload_type,
123 4321, payload, sizeof(payload),
124 /*absolute_capture_timestamp_ms=*/0));
125
126 auto sent_payload = transport_.last_sent_packet().payload();
127 EXPECT_THAT(sent_payload, ElementsAreArray(payload));
128 // Verify AudioLevel extension.
129 bool voice_activity;
130 uint8_t audio_level;
131 EXPECT_TRUE(transport_.last_sent_packet().GetExtension<AudioLevel>(
132 &voice_activity, &audio_level));
133 EXPECT_EQ(kAudioLevel, audio_level);
134 EXPECT_FALSE(voice_activity);
135 }
136
TEST_F(RtpSenderAudioTest,SendAudioWithoutAbsoluteCaptureTime)137 TEST_F(RtpSenderAudioTest, SendAudioWithoutAbsoluteCaptureTime) {
138 constexpr uint32_t kAbsoluteCaptureTimestampMs = 521;
139 const char payload_name[] = "audio";
140 const uint8_t payload_type = 127;
141 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
142 payload_name, payload_type, 48000, 0, 1500));
143 uint8_t payload[] = {47, 11, 32, 93, 89};
144
145 ASSERT_TRUE(rtp_sender_audio_->SendAudio(
146 AudioFrameType::kAudioFrameCN, payload_type, 4321, payload,
147 sizeof(payload), kAbsoluteCaptureTimestampMs));
148
149 EXPECT_FALSE(transport_.last_sent_packet()
150 .HasExtension<AbsoluteCaptureTimeExtension>());
151 }
152
153 // Essentially the same test as
154 // SendAudioWithAbsoluteCaptureTimeWithCaptureClockOffset but with a field
155 // trial. We will remove this test eventually.
TEST_F(RtpSenderAudioTest,SendAudioWithAbsoluteCaptureTime)156 TEST_F(RtpSenderAudioTest, SendAudioWithAbsoluteCaptureTime) {
157 // Recreate rtp_sender_audio_ with new field trial.
158 test::ScopedFieldTrials field_trial(
159 "WebRTC-IncludeCaptureClockOffset/Disabled/");
160 rtp_sender_audio_ =
161 std::make_unique<RTPSenderAudio>(&fake_clock_, rtp_module_->RtpSender());
162
163 rtp_module_->RegisterRtpHeaderExtension(AbsoluteCaptureTimeExtension::Uri(),
164 kAbsoluteCaptureTimeExtensionId);
165 constexpr uint32_t kAbsoluteCaptureTimestampMs = 521;
166 const char payload_name[] = "audio";
167 const uint8_t payload_type = 127;
168 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
169 payload_name, payload_type, 48000, 0, 1500));
170 uint8_t payload[] = {47, 11, 32, 93, 89};
171
172 ASSERT_TRUE(rtp_sender_audio_->SendAudio(
173 AudioFrameType::kAudioFrameCN, payload_type, 4321, payload,
174 sizeof(payload), kAbsoluteCaptureTimestampMs));
175
176 auto absolute_capture_time =
177 transport_.last_sent_packet()
178 .GetExtension<AbsoluteCaptureTimeExtension>();
179 EXPECT_TRUE(absolute_capture_time);
180 EXPECT_EQ(
181 absolute_capture_time->absolute_capture_timestamp,
182 Int64MsToUQ32x32(fake_clock_.ConvertTimestampToNtpTimeInMilliseconds(
183 kAbsoluteCaptureTimestampMs)));
184 EXPECT_FALSE(
185 absolute_capture_time->estimated_capture_clock_offset.has_value());
186 }
187
TEST_F(RtpSenderAudioTest,SendAudioWithAbsoluteCaptureTimeWithCaptureClockOffset)188 TEST_F(RtpSenderAudioTest,
189 SendAudioWithAbsoluteCaptureTimeWithCaptureClockOffset) {
190 rtp_module_->RegisterRtpHeaderExtension(AbsoluteCaptureTimeExtension::Uri(),
191 kAbsoluteCaptureTimeExtensionId);
192 constexpr uint32_t kAbsoluteCaptureTimestampMs = 521;
193 const char payload_name[] = "audio";
194 const uint8_t payload_type = 127;
195 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
196 payload_name, payload_type, 48000, 0, 1500));
197 uint8_t payload[] = {47, 11, 32, 93, 89};
198
199 ASSERT_TRUE(rtp_sender_audio_->SendAudio(
200 AudioFrameType::kAudioFrameCN, payload_type, 4321, payload,
201 sizeof(payload), kAbsoluteCaptureTimestampMs));
202
203 auto absolute_capture_time =
204 transport_.last_sent_packet()
205 .GetExtension<AbsoluteCaptureTimeExtension>();
206 EXPECT_TRUE(absolute_capture_time);
207 EXPECT_EQ(
208 absolute_capture_time->absolute_capture_timestamp,
209 Int64MsToUQ32x32(fake_clock_.ConvertTimestampToNtpTimeInMilliseconds(
210 kAbsoluteCaptureTimestampMs)));
211 EXPECT_TRUE(
212 absolute_capture_time->estimated_capture_clock_offset.has_value());
213 EXPECT_EQ(0, *absolute_capture_time->estimated_capture_clock_offset);
214 }
215
216 // As RFC4733, named telephone events are carried as part of the audio stream
217 // and must use the same sequence number and timestamp base as the regular
218 // audio channel.
219 // This test checks the marker bit for the first packet and the consequent
220 // packets of the same telephone event. Since it is specifically for DTMF
221 // events, ignoring audio packets and sending kEmptyFrame instead of those.
TEST_F(RtpSenderAudioTest,CheckMarkerBitForTelephoneEvents)222 TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) {
223 const char* kDtmfPayloadName = "telephone-event";
224 const uint32_t kPayloadFrequency = 8000;
225 const uint8_t kPayloadType = 126;
226 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
227 kDtmfPayloadName, kPayloadType, kPayloadFrequency, 0, 0));
228 // For Telephone events, payload is not added to the registered payload list,
229 // it will register only the payload used for audio stream.
230 // Registering the payload again for audio stream with different payload name.
231 const char* kPayloadName = "payload_name";
232 ASSERT_EQ(0, rtp_sender_audio_->RegisterAudioPayload(
233 kPayloadName, kPayloadType, kPayloadFrequency, 1, 0));
234 // Start time is arbitrary.
235 uint32_t capture_timestamp = fake_clock_.TimeInMilliseconds();
236 // DTMF event key=9, duration=500 and attenuationdB=10
237 rtp_sender_audio_->SendTelephoneEvent(9, 500, 10);
238 // During start, it takes the starting timestamp as last sent timestamp.
239 // The duration is calculated as the difference of current and last sent
240 // timestamp. So for first call it will skip since the duration is zero.
241 ASSERT_TRUE(rtp_sender_audio_->SendAudio(
242 AudioFrameType::kEmptyFrame, kPayloadType, capture_timestamp, nullptr, 0,
243 /*absolute_capture_time_ms=0*/ 0));
244
245 // DTMF Sample Length is (Frequency/1000) * Duration.
246 // So in this case, it is (8000/1000) * 500 = 4000.
247 // Sending it as two packets.
248 ASSERT_TRUE(rtp_sender_audio_->SendAudio(AudioFrameType::kEmptyFrame,
249 kPayloadType,
250 capture_timestamp + 2000, nullptr, 0,
251 /*absolute_capture_time_ms=0*/ 0));
252
253 // Marker Bit should be set to 1 for first packet.
254 EXPECT_TRUE(transport_.last_sent_packet().Marker());
255
256 ASSERT_TRUE(rtp_sender_audio_->SendAudio(AudioFrameType::kEmptyFrame,
257 kPayloadType,
258 capture_timestamp + 4000, nullptr, 0,
259 /*absolute_capture_time_ms=0*/ 0));
260 // Marker Bit should be set to 0 for rest of the packets.
261 EXPECT_FALSE(transport_.last_sent_packet().Marker());
262 }
263
264 } // namespace webrtc
265