| /* | 
 |  *  Copyright (c) 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 <string> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include "modules/rtp_rtcp/include/rtp_header_extension_map.h" | 
 | #include "modules/rtp_rtcp/source/rtp_header_extensions.h" | 
 | #include "modules/rtp_rtcp/source/rtp_packet.h" | 
 | #include "test/call_test.h" | 
 | #include "test/field_trial.h" | 
 | #include "test/gtest.h" | 
 | #include "test/rtcp_packet_parser.h" | 
 | #include "test/video_test_constants.h" | 
 |  | 
 | namespace webrtc { | 
 | namespace test { | 
 | namespace { | 
 |  | 
 | enum : int {  // The first valid value is 1. | 
 |   kAudioLevelExtensionId = 1, | 
 |   kTransportSequenceNumberExtensionId, | 
 | }; | 
 |  | 
 | class AudioSendTest : public SendTest { | 
 |  public: | 
 |   AudioSendTest() : SendTest(VideoTestConstants::kDefaultTimeout) {} | 
 |  | 
 |   size_t GetNumVideoStreams() const override { return 0; } | 
 |   size_t GetNumAudioStreams() const override { return 1; } | 
 |   size_t GetNumFlexfecStreams() const override { return 0; } | 
 | }; | 
 | }  // namespace | 
 |  | 
 | using AudioSendStreamCallTest = CallTest; | 
 |  | 
 | TEST_F(AudioSendStreamCallTest, SupportsCName) { | 
 |   static std::string kCName = "PjqatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo="; | 
 |   class CNameObserver : public AudioSendTest { | 
 |    public: | 
 |     CNameObserver() = default; | 
 |  | 
 |    private: | 
 |     Action OnSendRtcp(rtc::ArrayView<const uint8_t> packet) override { | 
 |       RtcpPacketParser parser; | 
 |       EXPECT_TRUE(parser.Parse(packet)); | 
 |       if (parser.sdes()->num_packets() > 0) { | 
 |         EXPECT_EQ(1u, parser.sdes()->chunks().size()); | 
 |         EXPECT_EQ(kCName, parser.sdes()->chunks()[0].cname); | 
 |  | 
 |         observation_complete_.Set(); | 
 |       } | 
 |  | 
 |       return SEND_PACKET; | 
 |     } | 
 |  | 
 |     void ModifyAudioConfigs(AudioSendStream::Config* send_config, | 
 |                             std::vector<AudioReceiveStreamInterface::Config>* | 
 |                             /* receive_configs */) override { | 
 |       send_config->rtp.c_name = kCName; | 
 |     } | 
 |  | 
 |     void PerformTest() override { | 
 |       EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME."; | 
 |     } | 
 |   } test; | 
 |  | 
 |   RunBaseTest(&test); | 
 | } | 
 |  | 
 | TEST_F(AudioSendStreamCallTest, NoExtensionsByDefault) { | 
 |   class NoExtensionsObserver : public AudioSendTest { | 
 |    public: | 
 |     NoExtensionsObserver() = default; | 
 |  | 
 |    private: | 
 |     Action OnSendRtp(rtc::ArrayView<const uint8_t> packet) override { | 
 |       RtpPacket rtp_packet; | 
 |       EXPECT_TRUE(rtp_packet.Parse(packet));  // rtp packet is valid. | 
 |       EXPECT_EQ(packet[0] & 0b0001'0000, 0);  // extension bit not set. | 
 |  | 
 |       observation_complete_.Set(); | 
 |       return SEND_PACKET; | 
 |     } | 
 |  | 
 |     void ModifyAudioConfigs(AudioSendStream::Config* send_config, | 
 |                             std::vector<AudioReceiveStreamInterface::Config>* | 
 |                             /* receive_configs */) override { | 
 |       send_config->rtp.extensions.clear(); | 
 |     } | 
 |  | 
 |     void PerformTest() override { | 
 |       EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet."; | 
 |     } | 
 |   } test; | 
 |  | 
 |   RunBaseTest(&test); | 
 | } | 
 |  | 
 | TEST_F(AudioSendStreamCallTest, SupportsAudioLevel) { | 
 |   class AudioLevelObserver : public AudioSendTest { | 
 |    public: | 
 |     AudioLevelObserver() : AudioSendTest() { | 
 |       extensions_.Register<AudioLevelExtension>(kAudioLevelExtensionId); | 
 |     } | 
 |  | 
 |     Action OnSendRtp(rtc::ArrayView<const uint8_t> packet) override { | 
 |       RtpPacket rtp_packet(&extensions_); | 
 |       EXPECT_TRUE(rtp_packet.Parse(packet)); | 
 |  | 
 |       AudioLevel audio_level; | 
 |       EXPECT_TRUE(rtp_packet.GetExtension<AudioLevelExtension>(&audio_level)); | 
 |       if (audio_level.level() != 0) { | 
 |         // Wait for at least one packet with a non-zero level. | 
 |         observation_complete_.Set(); | 
 |       } else { | 
 |         RTC_LOG(LS_WARNING) << "Got a packet with zero audioLevel - waiting" | 
 |                                " for another packet..."; | 
 |       } | 
 |  | 
 |       return SEND_PACKET; | 
 |     } | 
 |  | 
 |     void ModifyAudioConfigs(AudioSendStream::Config* send_config, | 
 |                             std::vector<AudioReceiveStreamInterface::Config>* | 
 |                             /* receive_configs */) override { | 
 |       send_config->rtp.extensions.clear(); | 
 |       send_config->rtp.extensions.push_back( | 
 |           RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelExtensionId)); | 
 |     } | 
 |  | 
 |     void PerformTest() override { | 
 |       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet."; | 
 |     } | 
 |  | 
 |    private: | 
 |     RtpHeaderExtensionMap extensions_; | 
 |   } test; | 
 |  | 
 |   RunBaseTest(&test); | 
 | } | 
 |  | 
 | class TransportWideSequenceNumberObserver : public AudioSendTest { | 
 |  public: | 
 |   explicit TransportWideSequenceNumberObserver(bool expect_sequence_number) | 
 |       : AudioSendTest(), expect_sequence_number_(expect_sequence_number) { | 
 |     extensions_.Register<TransportSequenceNumber>( | 
 |         kTransportSequenceNumberExtensionId); | 
 |   } | 
 |  | 
 |  private: | 
 |   Action OnSendRtp(rtc::ArrayView<const uint8_t> packet) override { | 
 |     RtpPacket rtp_packet(&extensions_); | 
 |     EXPECT_TRUE(rtp_packet.Parse(packet)); | 
 |  | 
 |     EXPECT_EQ(rtp_packet.HasExtension<TransportSequenceNumber>(), | 
 |               expect_sequence_number_); | 
 |     EXPECT_FALSE(rtp_packet.HasExtension<TransmissionOffset>()); | 
 |     EXPECT_FALSE(rtp_packet.HasExtension<AbsoluteSendTime>()); | 
 |  | 
 |     observation_complete_.Set(); | 
 |  | 
 |     return SEND_PACKET; | 
 |   } | 
 |  | 
 |   void ModifyAudioConfigs(AudioSendStream::Config* send_config, | 
 |                           std::vector<AudioReceiveStreamInterface::Config>* | 
 |                           /* receive_configs */) override { | 
 |     send_config->rtp.extensions.clear(); | 
 |     send_config->rtp.extensions.push_back( | 
 |         RtpExtension(RtpExtension::kTransportSequenceNumberUri, | 
 |                      kTransportSequenceNumberExtensionId)); | 
 |   } | 
 |  | 
 |   void PerformTest() override { | 
 |     EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet."; | 
 |   } | 
 |   const bool expect_sequence_number_; | 
 |   RtpHeaderExtensionMap extensions_; | 
 | }; | 
 |  | 
 | TEST_F(AudioSendStreamCallTest, SendsTransportWideSequenceNumbersInFieldTrial) { | 
 |   TransportWideSequenceNumberObserver test(/*expect_sequence_number=*/true); | 
 |   RunBaseTest(&test); | 
 | } | 
 |  | 
 | TEST_F(AudioSendStreamCallTest, SendDtmf) { | 
 |   static const uint8_t kDtmfPayloadType = 120; | 
 |   static const int kDtmfPayloadFrequency = 8000; | 
 |   static const int kDtmfEventFirst = 12; | 
 |   static const int kDtmfEventLast = 31; | 
 |   static const int kDtmfDuration = 50; | 
 |   class DtmfObserver : public AudioSendTest { | 
 |    public: | 
 |     DtmfObserver() = default; | 
 |  | 
 |    private: | 
 |     Action OnSendRtp(rtc::ArrayView<const uint8_t> packet) override { | 
 |       RtpPacket rtp_packet; | 
 |       EXPECT_TRUE(rtp_packet.Parse(packet)); | 
 |  | 
 |       if (rtp_packet.PayloadType() == kDtmfPayloadType) { | 
 |         EXPECT_EQ(rtp_packet.headers_size(), 12u); | 
 |         EXPECT_EQ(rtp_packet.size(), 16u); | 
 |         const int event = rtp_packet.payload()[0]; | 
 |         if (event != expected_dtmf_event_) { | 
 |           ++expected_dtmf_event_; | 
 |           EXPECT_EQ(event, expected_dtmf_event_); | 
 |           if (expected_dtmf_event_ == kDtmfEventLast) { | 
 |             observation_complete_.Set(); | 
 |           } | 
 |         } | 
 |       } | 
 |  | 
 |       return SEND_PACKET; | 
 |     } | 
 |  | 
 |     void OnAudioStreamsCreated(AudioSendStream* send_stream, | 
 |                                const std::vector<AudioReceiveStreamInterface*>& | 
 |                                /* receive_streams */) override { | 
 |       // Need to start stream here, else DTMF events are dropped. | 
 |       send_stream->Start(); | 
 |       for (int event = kDtmfEventFirst; event <= kDtmfEventLast; ++event) { | 
 |         send_stream->SendTelephoneEvent(kDtmfPayloadType, kDtmfPayloadFrequency, | 
 |                                         event, kDtmfDuration); | 
 |       } | 
 |     } | 
 |  | 
 |     void PerformTest() override { | 
 |       EXPECT_TRUE(Wait()) << "Timed out while waiting for DTMF stream."; | 
 |     } | 
 |  | 
 |     int expected_dtmf_event_ = kDtmfEventFirst; | 
 |   } test; | 
 |  | 
 |   RunBaseTest(&test); | 
 | } | 
 |  | 
 | }  // namespace test | 
 | }  // namespace webrtc |