diff --git a/webrtc/modules/rtp_rtcp/include/rtp_receiver.h b/webrtc/modules/rtp_rtcp/include/rtp_receiver.h index f393e41eab..0640d5cc19 100644 --- a/webrtc/modules/rtp_rtcp/include/rtp_receiver.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_receiver.h @@ -45,6 +45,7 @@ class RtpReceiver { // Creates an audio-enabled RTP receiver. static RtpReceiver* CreateAudioReceiver( Clock* clock, + RtpAudioFeedback* incoming_audio_feedback, RtpData* incoming_payload_callback, RtpFeedback* incoming_messages_callback, RTPPayloadRegistry* rtp_payload_registry); diff --git a/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 9acef79f38..2367a68d89 100644 --- a/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -217,6 +217,16 @@ class RtpFeedback { virtual void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) = 0; }; +class RtpAudioFeedback { + public: + virtual void OnPlayTelephoneEvent(const uint8_t event, + const uint16_t lengthMs, + const uint8_t volume) = 0; + + protected: + virtual ~RtpAudioFeedback() {} +}; + class RtcpIntraFrameObserver { public: virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) = 0; @@ -347,6 +357,16 @@ class NullRtpData : public RtpData { } }; +// Null object version of RtpAudioFeedback. +class NullRtpAudioFeedback : public RtpAudioFeedback { + public: + virtual ~NullRtpAudioFeedback() {} + + void OnPlayTelephoneEvent(const uint8_t event, + const uint16_t lengthMs, + const uint8_t volume) override {} +}; + // Statistics about packet loss for a single directional connection. All values // are totals since the connection initiated. struct RtpPacketLossStats { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc index 7a3b6fd829..c4c7dbb4cd 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc @@ -20,11 +20,13 @@ namespace webrtc { RTPReceiverStrategy* RTPReceiverStrategy::CreateAudioStrategy( - RtpData* data_callback) { - return new RTPReceiverAudio(data_callback); + RtpData* data_callback, + RtpAudioFeedback* incoming_messages_callback) { + return new RTPReceiverAudio(data_callback, incoming_messages_callback); } -RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) +RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback, + RtpAudioFeedback* incoming_messages_callback) : RTPReceiverStrategy(data_callback), TelephoneEventHandler(), last_received_frequency_(8000), @@ -38,7 +40,8 @@ RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) g722_payload_type_(-1), last_received_g722_(false), num_energy_(0), - current_remote_energy_() { + current_remote_energy_(), + cb_audio_feedback_(incoming_messages_callback) { last_payload_.Audio.channels = 1; memset(current_remote_energy_, 0, sizeof(current_remote_energy_)); } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h index b68febbb82..1dd07d1cc9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h @@ -28,7 +28,8 @@ class CriticalSectionWrapper; class RTPReceiverAudio : public RTPReceiverStrategy, public TelephoneEventHandler { public: - explicit RTPReceiverAudio(RtpData* data_callback); + RTPReceiverAudio(RtpData* data_callback, + RtpAudioFeedback* incoming_messages_callback); virtual ~RTPReceiverAudio() {} // The following three methods implement the TelephoneEventHandler interface. @@ -118,6 +119,8 @@ class RTPReceiverAudio : public RTPReceiverStrategy, uint8_t num_energy_; uint8_t current_remote_energy_[kRtpCsrcSize]; + + RtpAudioFeedback* cb_audio_feedback_; }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc index 6f2efe783a..5950dc7554 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc @@ -34,26 +34,33 @@ RtpReceiver* RtpReceiver::CreateVideoReceiver( if (!incoming_messages_callback) incoming_messages_callback = NullObjectRtpFeedback(); return new RtpReceiverImpl( - clock, incoming_messages_callback, rtp_payload_registry, + clock, NullObjectRtpAudioFeedback(), incoming_messages_callback, + rtp_payload_registry, RTPReceiverStrategy::CreateVideoStrategy(incoming_payload_callback)); } RtpReceiver* RtpReceiver::CreateAudioReceiver( Clock* clock, + RtpAudioFeedback* incoming_audio_feedback, RtpData* incoming_payload_callback, RtpFeedback* incoming_messages_callback, RTPPayloadRegistry* rtp_payload_registry) { + if (!incoming_audio_feedback) + incoming_audio_feedback = NullObjectRtpAudioFeedback(); if (!incoming_payload_callback) incoming_payload_callback = NullObjectRtpData(); if (!incoming_messages_callback) incoming_messages_callback = NullObjectRtpFeedback(); return new RtpReceiverImpl( - clock, incoming_messages_callback, rtp_payload_registry, - RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback)); + clock, incoming_audio_feedback, incoming_messages_callback, + rtp_payload_registry, + RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback, + incoming_audio_feedback)); } RtpReceiverImpl::RtpReceiverImpl( Clock* clock, + RtpAudioFeedback* incoming_audio_messages_callback, RtpFeedback* incoming_messages_callback, RTPPayloadRegistry* rtp_payload_registry, RTPReceiverStrategy* rtp_media_receiver) @@ -72,6 +79,7 @@ RtpReceiverImpl::RtpReceiverImpl( last_received_frame_time_ms_(-1), last_received_sequence_number_(0), nack_method_(kNackOff) { + assert(incoming_audio_messages_callback); assert(incoming_messages_callback); memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_)); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h index 63b65fefd8..5cf94c2859 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h @@ -26,6 +26,7 @@ class RtpReceiverImpl : public RtpReceiver { // want callbacks to do nothing). This class takes ownership of the media // receiver but nothing else. RtpReceiverImpl(Clock* clock, + RtpAudioFeedback* incoming_audio_messages_callback, RtpFeedback* incoming_messages_callback, RTPPayloadRegistry* rtp_payload_registry, RTPReceiverStrategy* rtp_media_receiver); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h index f2a60ff855..0f7ad30e87 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h @@ -27,7 +27,9 @@ class TelephoneEventHandler; class RTPReceiverStrategy { public: static RTPReceiverStrategy* CreateVideoStrategy(RtpData* data_callback); - static RTPReceiverStrategy* CreateAudioStrategy(RtpData* data_callback); + static RTPReceiverStrategy* CreateAudioStrategy( + RtpData* data_callback, + RtpAudioFeedback* incoming_messages_callback); virtual ~RTPReceiverStrategy() {} diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc index bdae3c4806..0f0ad835b1 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc @@ -27,6 +27,11 @@ RtpFeedback* NullObjectRtpFeedback() { return &null_rtp_feedback; } +RtpAudioFeedback* NullObjectRtpAudioFeedback() { + static NullRtpAudioFeedback null_rtp_audio_feedback; + return &null_rtp_audio_feedback; +} + ReceiveStatistics* NullObjectReceiveStatistics() { static NullReceiveStatistics null_receive_statistics; return &null_receive_statistics; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/webrtc/modules/rtp_rtcp/source/rtp_utility.h index 1a24285395..23c175356a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h @@ -26,6 +26,7 @@ const uint8_t kRtpMarkerBitMask = 0x80; RtpData* NullObjectRtpData(); RtpFeedback* NullObjectRtpFeedback(); +RtpAudioFeedback* NullObjectRtpAudioFeedback(); ReceiveStatistics* NullObjectReceiveStatistics(); namespace RtpUtility { diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc index 67e8a65c4d..1d4d6d04a5 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc @@ -97,7 +97,7 @@ class RtpRtcpAPITest : public ::testing::Test { rtp_payload_registry_.reset(new RTPPayloadRegistry( RTPPayloadStrategy::CreateStrategy(true))); rtp_receiver_.reset(RtpReceiver::CreateAudioReceiver( - &fake_clock_, NULL, NULL, rtp_payload_registry_.get())); + &fake_clock_, NULL, NULL, NULL, rtp_payload_registry_.get())); } rtc::scoped_ptr rtp_payload_registry_; diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc index 9b44c4f40d..11b592afcc 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc @@ -86,6 +86,7 @@ class RtpRtcpAudioTest : public ::testing::Test { ~RtpRtcpAudioTest() {} void SetUp() override { + audioFeedback = new NullRtpAudioFeedback(); data_receiver1 = new VerifyingAudioReceiver(); data_receiver2 = new VerifyingAudioReceiver(); rtp_callback = new RTPCallback(); @@ -108,14 +109,16 @@ class RtpRtcpAudioTest : public ::testing::Test { module1 = RtpRtcp::CreateRtpRtcp(configuration); rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver( - &fake_clock, data_receiver1, NULL, rtp_payload_registry1_.get())); + &fake_clock, audioFeedback, data_receiver1, NULL, + rtp_payload_registry1_.get())); configuration.receive_statistics = receive_statistics2_.get(); configuration.outgoing_transport = transport2; module2 = RtpRtcp::CreateRtpRtcp(configuration); rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver( - &fake_clock, data_receiver2, NULL, rtp_payload_registry2_.get())); + &fake_clock, audioFeedback, data_receiver2, NULL, + rtp_payload_registry2_.get())); transport1->SetSendModule(module2, rtp_payload_registry2_.get(), rtp_receiver2_.get(), receive_statistics2_.get()); @@ -128,6 +131,7 @@ class RtpRtcpAudioTest : public ::testing::Test { delete module2; delete transport1; delete transport2; + delete audioFeedback; delete data_receiver1; delete data_receiver2; delete rtp_callback; @@ -145,6 +149,7 @@ class RtpRtcpAudioTest : public ::testing::Test { VerifyingAudioReceiver* data_receiver2; LoopBackTransport* transport1; LoopBackTransport* transport2; + NullRtpAudioFeedback* audioFeedback; RTPCallback* rtp_callback; uint32_t test_ssrc; uint32_t test_timestamp; diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc index d4b3641273..6c60bf1f6d 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc @@ -101,7 +101,7 @@ class RtpRtcpRtcpTest : public ::testing::Test { rtp_feedback1_.reset(new TestRtpFeedback(module1)); rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver( - &fake_clock, receiver, rtp_feedback1_.get(), + &fake_clock, NULL, receiver, rtp_feedback1_.get(), rtp_payload_registry1_.get())); configuration.receive_statistics = receive_statistics2_.get(); @@ -113,7 +113,7 @@ class RtpRtcpRtcpTest : public ::testing::Test { rtp_feedback2_.reset(new TestRtpFeedback(module2)); rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver( - &fake_clock, receiver, rtp_feedback2_.get(), + &fake_clock, NULL, receiver, rtp_feedback2_.get(), rtp_payload_registry2_.get())); transport1->SetSendModule(module2, rtp_payload_registry2_.get(), diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc index 82f16ea733..5bbbce3c40 100644 --- a/webrtc/voice_engine/channel.cc +++ b/webrtc/voice_engine/channel.cc @@ -722,6 +722,7 @@ Channel::Channel(int32_t channelId, ReceiveStatistics::Create(Clock::GetRealTimeClock())), rtp_receiver_( RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(), + nullptr, this, this, rtp_payload_registry_.get())),