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