- Remove calls to VoEDtmf from WVoE/MC.
- Flatten logic and make the relevant calls on VoE::Channel from AudioSendStream::SendTelephoneEvent(). - Store current payload type for telephone events in WVoMC, instead of setting it on the Channel. This should be refactored to be an AudioSendStream::Config parameter when we redo WVoMC::SetSendCodecs(). BUG=webrtc:4690 R=pthatcher@webrtc.org, tina.legrand@webrtc.org Review URL: https://codereview.webrtc.org/1491743004 . Cr-Commit-Position: refs/heads/master@{#10895}
This commit is contained in:
@ -39,14 +39,27 @@ FakeAudioSendStream::FakeAudioSendStream(
|
||||
RTC_DCHECK(config.voe_channel_id != -1);
|
||||
}
|
||||
|
||||
const webrtc::AudioSendStream::Config&
|
||||
FakeAudioSendStream::GetConfig() const {
|
||||
return config_;
|
||||
}
|
||||
|
||||
void FakeAudioSendStream::SetStats(
|
||||
const webrtc::AudioSendStream::Stats& stats) {
|
||||
stats_ = stats;
|
||||
}
|
||||
|
||||
const webrtc::AudioSendStream::Config&
|
||||
FakeAudioSendStream::GetConfig() const {
|
||||
return config_;
|
||||
FakeAudioSendStream::TelephoneEvent
|
||||
FakeAudioSendStream::GetLatestTelephoneEvent() const {
|
||||
return latest_telephone_event_;
|
||||
}
|
||||
|
||||
bool FakeAudioSendStream::SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) {
|
||||
latest_telephone_event_.payload_type = payload_type;
|
||||
latest_telephone_event_.event_code = event;
|
||||
latest_telephone_event_.duration_ms = duration_ms;
|
||||
return true;
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
|
||||
|
||||
@ -49,10 +49,17 @@
|
||||
namespace cricket {
|
||||
class FakeAudioSendStream final : public webrtc::AudioSendStream {
|
||||
public:
|
||||
struct TelephoneEvent {
|
||||
int payload_type = -1;
|
||||
uint8_t event_code = 0;
|
||||
uint32_t duration_ms = 0;
|
||||
};
|
||||
|
||||
explicit FakeAudioSendStream(const webrtc::AudioSendStream::Config& config);
|
||||
|
||||
const webrtc::AudioSendStream::Config& GetConfig() const;
|
||||
void SetStats(const webrtc::AudioSendStream::Stats& stats);
|
||||
TelephoneEvent GetLatestTelephoneEvent() const;
|
||||
|
||||
private:
|
||||
// webrtc::SendStream implementation.
|
||||
@ -64,8 +71,11 @@ class FakeAudioSendStream final : public webrtc::AudioSendStream {
|
||||
}
|
||||
|
||||
// webrtc::AudioSendStream implementation.
|
||||
bool SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) override;
|
||||
webrtc::AudioSendStream::Stats GetStats() const override;
|
||||
|
||||
TelephoneEvent latest_telephone_event_;
|
||||
webrtc::AudioSendStream::Config config_;
|
||||
webrtc::AudioSendStream::Stats stats_;
|
||||
};
|
||||
|
||||
@ -145,20 +145,11 @@ class FakeAudioProcessing : public webrtc::AudioProcessing {
|
||||
|
||||
class FakeWebRtcVoiceEngine
|
||||
: public webrtc::VoEAudioProcessing,
|
||||
public webrtc::VoEBase, public webrtc::VoECodec, public webrtc::VoEDtmf,
|
||||
public webrtc::VoEBase, public webrtc::VoECodec,
|
||||
public webrtc::VoEHardware,
|
||||
public webrtc::VoENetwork, public webrtc::VoERTP_RTCP,
|
||||
public webrtc::VoEVolumeControl {
|
||||
public:
|
||||
struct DtmfInfo {
|
||||
DtmfInfo()
|
||||
: dtmf_event_code(-1),
|
||||
dtmf_out_of_band(false),
|
||||
dtmf_length_ms(-1) {}
|
||||
int dtmf_event_code;
|
||||
bool dtmf_out_of_band;
|
||||
int dtmf_length_ms;
|
||||
};
|
||||
struct Channel {
|
||||
explicit Channel()
|
||||
: external_transport(false),
|
||||
@ -173,7 +164,6 @@ class FakeWebRtcVoiceEngine
|
||||
nack(false),
|
||||
cn8_type(13),
|
||||
cn16_type(105),
|
||||
dtmf_type(106),
|
||||
red_type(117),
|
||||
nack_max_packets(0),
|
||||
send_ssrc(0),
|
||||
@ -195,12 +185,10 @@ class FakeWebRtcVoiceEngine
|
||||
bool nack;
|
||||
int cn8_type;
|
||||
int cn16_type;
|
||||
int dtmf_type;
|
||||
int red_type;
|
||||
int nack_max_packets;
|
||||
uint32_t send_ssrc;
|
||||
int associate_send_channel;
|
||||
DtmfInfo dtmf_info;
|
||||
std::vector<webrtc::CodecInst> recv_codecs;
|
||||
webrtc::CodecInst send_codec;
|
||||
webrtc::PacketTime last_rtp_packet_time;
|
||||
@ -281,9 +269,6 @@ class FakeWebRtcVoiceEngine
|
||||
channels_[channel]->cn16_type :
|
||||
channels_[channel]->cn8_type;
|
||||
}
|
||||
int GetSendTelephoneEventPayloadType(int channel) {
|
||||
return channels_[channel]->dtmf_type;
|
||||
}
|
||||
int GetSendREDPayloadType(int channel) {
|
||||
return channels_[channel]->red_type;
|
||||
}
|
||||
@ -552,26 +537,6 @@ class FakeWebRtcVoiceEngine
|
||||
return 0;
|
||||
}
|
||||
|
||||
// webrtc::VoEDtmf
|
||||
WEBRTC_FUNC(SendTelephoneEvent, (int channel, int event_code,
|
||||
bool out_of_band = true, int length_ms = 160, int attenuation_db = 10)) {
|
||||
channels_[channel]->dtmf_info.dtmf_event_code = event_code;
|
||||
channels_[channel]->dtmf_info.dtmf_out_of_band = out_of_band;
|
||||
channels_[channel]->dtmf_info.dtmf_length_ms = length_ms;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_FUNC(SetSendTelephoneEventPayloadType,
|
||||
(int channel, unsigned char type)) {
|
||||
channels_[channel]->dtmf_type = type;
|
||||
return 0;
|
||||
};
|
||||
WEBRTC_STUB(GetSendTelephoneEventPayloadType,
|
||||
(int channel, unsigned char& type));
|
||||
WEBRTC_STUB(SetDtmfFeedbackStatus, (bool enable, bool directFeedback));
|
||||
WEBRTC_STUB(GetDtmfFeedbackStatus, (bool& enabled, bool& directFeedback));
|
||||
WEBRTC_STUB(PlayDtmfTone,
|
||||
(int event_code, int length_ms = 200, int attenuation_db = 10));
|
||||
|
||||
// webrtc::VoEHardware
|
||||
WEBRTC_FUNC(GetNumOfRecordingDevices, (int& num)) {
|
||||
return GetNumDevices(num);
|
||||
@ -831,15 +796,6 @@ class FakeWebRtcVoiceEngine
|
||||
void EnableStereoChannelSwapping(bool enable) {
|
||||
stereo_swapping_enabled_ = enable;
|
||||
}
|
||||
bool WasSendTelephoneEventCalled(int channel, int event_code, int length_ms) {
|
||||
return (channels_[channel]->dtmf_info.dtmf_event_code == event_code &&
|
||||
channels_[channel]->dtmf_info.dtmf_out_of_band == true &&
|
||||
channels_[channel]->dtmf_info.dtmf_length_ms == length_ms);
|
||||
}
|
||||
bool WasPlayDtmfToneCalled(int event_code, int length_ms) {
|
||||
return (dtmf_info_.dtmf_event_code == event_code &&
|
||||
dtmf_info_.dtmf_length_ms == length_ms);
|
||||
}
|
||||
int GetNetEqCapacity() const {
|
||||
auto ch = channels_.find(last_channel_);
|
||||
ASSERT(ch != channels_.end());
|
||||
@ -910,7 +866,6 @@ class FakeWebRtcVoiceEngine
|
||||
int send_fail_channel_;
|
||||
int recording_sample_rate_;
|
||||
int playout_sample_rate_;
|
||||
DtmfInfo dtmf_info_;
|
||||
FakeAudioProcessing audio_processing_;
|
||||
};
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
#include "webrtc/voice_engine/include/voe_codec.h"
|
||||
#include "webrtc/voice_engine/include/voe_dtmf.h"
|
||||
#include "webrtc/voice_engine/include/voe_errors.h"
|
||||
#include "webrtc/voice_engine/include/voe_hardware.h"
|
||||
#include "webrtc/voice_engine/include/voe_network.h"
|
||||
@ -91,14 +90,13 @@ class VoEWrapper {
|
||||
public:
|
||||
VoEWrapper()
|
||||
: engine_(webrtc::VoiceEngine::Create()), processing_(engine_),
|
||||
base_(engine_), codec_(engine_), dtmf_(engine_),
|
||||
base_(engine_), codec_(engine_),
|
||||
hw_(engine_), network_(engine_),
|
||||
rtp_(engine_), volume_(engine_) {
|
||||
}
|
||||
VoEWrapper(webrtc::VoEAudioProcessing* processing,
|
||||
webrtc::VoEBase* base,
|
||||
webrtc::VoECodec* codec,
|
||||
webrtc::VoEDtmf* dtmf,
|
||||
webrtc::VoEHardware* hw,
|
||||
webrtc::VoENetwork* network,
|
||||
webrtc::VoERTP_RTCP* rtp,
|
||||
@ -107,7 +105,6 @@ class VoEWrapper {
|
||||
processing_(processing),
|
||||
base_(base),
|
||||
codec_(codec),
|
||||
dtmf_(dtmf),
|
||||
hw_(hw),
|
||||
network_(network),
|
||||
rtp_(rtp),
|
||||
@ -118,7 +115,6 @@ class VoEWrapper {
|
||||
webrtc::VoEAudioProcessing* processing() const { return processing_.get(); }
|
||||
webrtc::VoEBase* base() const { return base_.get(); }
|
||||
webrtc::VoECodec* codec() const { return codec_.get(); }
|
||||
webrtc::VoEDtmf* dtmf() const { return dtmf_.get(); }
|
||||
webrtc::VoEHardware* hw() const { return hw_.get(); }
|
||||
webrtc::VoENetwork* network() const { return network_.get(); }
|
||||
webrtc::VoERTP_RTCP* rtp() const { return rtp_.get(); }
|
||||
@ -130,7 +126,6 @@ class VoEWrapper {
|
||||
scoped_voe_ptr<webrtc::VoEAudioProcessing> processing_;
|
||||
scoped_voe_ptr<webrtc::VoEBase> base_;
|
||||
scoped_voe_ptr<webrtc::VoECodec> codec_;
|
||||
scoped_voe_ptr<webrtc::VoEDtmf> dtmf_;
|
||||
scoped_voe_ptr<webrtc::VoEHardware> hw_;
|
||||
scoped_voe_ptr<webrtc::VoENetwork> network_;
|
||||
scoped_voe_ptr<webrtc::VoERTP_RTCP> rtp_;
|
||||
|
||||
@ -134,6 +134,12 @@ const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
|
||||
const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
|
||||
#endif
|
||||
|
||||
// Constants from voice_engine_defines.h.
|
||||
const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
|
||||
const int kMaxTelephoneEventCode = 255;
|
||||
const int kMinTelephoneEventDuration = 100;
|
||||
const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16
|
||||
|
||||
bool ValidateStreamParams(const StreamParams& sp) {
|
||||
if (sp.ssrcs.empty()) {
|
||||
LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
|
||||
@ -582,12 +588,6 @@ bool WebRtcVoiceEngine::InitInternal() {
|
||||
LOG(LS_INFO) << ToString(codec);
|
||||
}
|
||||
|
||||
// Disable the DTMF playout when a tone is sent.
|
||||
// PlayDtmfTone will be used if local playout is needed.
|
||||
if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
|
||||
LOG_RTCERR1(SetDtmfFeedbackStatus, false);
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
@ -1258,6 +1258,13 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
RTC_CHECK(stream_);
|
||||
}
|
||||
|
||||
bool SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(stream_);
|
||||
return stream_->SendTelephoneEvent(payload_type, event, duration_ms);
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats GetStats() const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(stream_);
|
||||
@ -1612,7 +1619,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
engine()->voe()->codec()->SetFECStatus(channel, false);
|
||||
|
||||
// Scan through the list to figure out the codec to use for sending, along
|
||||
// with the proper configuration for VAD and DTMF.
|
||||
// with the proper configuration for VAD.
|
||||
bool found_send_codec = false;
|
||||
webrtc::CodecInst send_codec;
|
||||
memset(&send_codec, 0, sizeof(send_codec));
|
||||
@ -1741,7 +1748,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
SetSendBitrateInternal(send_bitrate_bps_);
|
||||
}
|
||||
|
||||
// Loop through the codecs list again to config the telephone-event/CN codec.
|
||||
// Loop through the codecs list again to config the CN codec.
|
||||
for (const AudioCodec& codec : codecs) {
|
||||
// Ignore codecs we don't know about. The negotiation step should prevent
|
||||
// this, but double-check to be sure.
|
||||
@ -1751,15 +1758,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the DTMF telephone event "codec" and tell VoiceEngine channels
|
||||
// about it.
|
||||
if (IsCodec(codec, kDtmfCodecName)) {
|
||||
if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
|
||||
channel, codec.id) == -1) {
|
||||
LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, codec.id);
|
||||
return false;
|
||||
}
|
||||
} else if (IsCodec(codec, kCnCodecName)) {
|
||||
if (IsCodec(codec, kCnCodecName)) {
|
||||
// Turn voice activity detection/comfort noise on if supported.
|
||||
// Set the wideband CN payload type appropriately.
|
||||
// (narrowband always uses the static payload type 13).
|
||||
@ -1814,12 +1813,16 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
const std::vector<AudioCodec>& codecs) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// TODO(solenberg): Validate input - that payload types don't overlap, are
|
||||
// within range, filter out codecs we don't support,
|
||||
// redundant codecs etc.
|
||||
|
||||
dtmf_allowed_ = false;
|
||||
// Find the DTMF telephone event "codec" payload type.
|
||||
dtmf_payload_type_ = rtc::Optional<int>();
|
||||
for (const AudioCodec& codec : codecs) {
|
||||
// Find the DTMF telephone event "codec".
|
||||
if (IsCodec(codec, kDtmfCodecName)) {
|
||||
dtmf_allowed_ = true;
|
||||
dtmf_payload_type_ = rtc::Optional<int>(codec.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2282,38 +2285,34 @@ bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
|
||||
return dtmf_allowed_;
|
||||
return dtmf_payload_type_ ? true : false;
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
|
||||
int duration) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (!dtmf_allowed_) {
|
||||
LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
|
||||
if (!dtmf_payload_type_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send the event.
|
||||
int channel = -1;
|
||||
if (ssrc == 0) {
|
||||
if (send_streams_.size() > 0) {
|
||||
channel = send_streams_.begin()->second->channel();
|
||||
}
|
||||
} else {
|
||||
channel = GetSendChannelId(ssrc);
|
||||
}
|
||||
if (channel == -1) {
|
||||
LOG(LS_WARNING) << "InsertDtmf - The specified ssrc "
|
||||
<< ssrc << " is not in use.";
|
||||
// Figure out which WebRtcAudioSendStream to send the event on.
|
||||
auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
|
||||
if (it == send_streams_.end()) {
|
||||
LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
|
||||
return false;
|
||||
}
|
||||
// Send DTMF using out-of-band DTMF. ("true", as 3rd arg)
|
||||
if (engine()->voe()->dtmf()->SendTelephoneEvent(
|
||||
channel, event, true, duration) == -1) {
|
||||
LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
|
||||
if (event < kMinTelephoneEventCode ||
|
||||
event > kMaxTelephoneEventCode) {
|
||||
LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (duration < kMinTelephoneEventDuration ||
|
||||
duration > kMaxTelephoneEventDuration) {
|
||||
LOG(LS_WARNING) << "DTMF event duration " << duration << " out of range.";
|
||||
return false;
|
||||
}
|
||||
return it->second->SendTelephoneEvent(*dtmf_payload_type_, event, duration);
|
||||
}
|
||||
|
||||
void WebRtcVoiceMediaChannel::OnPacketReceived(
|
||||
|
||||
@ -265,7 +265,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
|
||||
bool send_bitrate_setting_ = false;
|
||||
int send_bitrate_bps_ = 0;
|
||||
AudioOptions options_;
|
||||
bool dtmf_allowed_ = false;
|
||||
rtc::Optional<int> dtmf_payload_type_;
|
||||
bool desired_playout_ = false;
|
||||
bool nack_enabled_ = false;
|
||||
bool playout_ = false;
|
||||
|
||||
@ -64,7 +64,6 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
|
||||
: cricket::VoEWrapper(engine, // processing
|
||||
engine, // base
|
||||
engine, // codec
|
||||
engine, // dtmf
|
||||
engine, // hw
|
||||
engine, // network
|
||||
engine, // rtp
|
||||
@ -121,6 +120,12 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
engine_.Terminate();
|
||||
}
|
||||
|
||||
const cricket::FakeAudioSendStream& GetSendStream(uint32_t ssrc) {
|
||||
const auto* send_stream = call_.GetAudioSendStream(ssrc);
|
||||
EXPECT_TRUE(send_stream);
|
||||
return *send_stream;
|
||||
}
|
||||
|
||||
const webrtc::AudioSendStream::Config& GetSendStreamConfig(uint32_t ssrc) {
|
||||
const auto* send_stream = call_.GetAudioSendStream(ssrc);
|
||||
EXPECT_TRUE(send_stream);
|
||||
@ -163,11 +168,15 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
// Check we fail if the ssrc is invalid.
|
||||
EXPECT_FALSE(channel_->InsertDtmf(-1, 1, 111));
|
||||
|
||||
// Test send
|
||||
int channel_id = voe_.GetLastChannel();
|
||||
EXPECT_FALSE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123));
|
||||
// Test send.
|
||||
cricket::FakeAudioSendStream::TelephoneEvent telephone_event =
|
||||
GetSendStream(kSsrc1).GetLatestTelephoneEvent();
|
||||
EXPECT_EQ(-1, telephone_event.payload_type);
|
||||
EXPECT_TRUE(channel_->InsertDtmf(ssrc, 2, 123));
|
||||
EXPECT_TRUE(voe_.WasSendTelephoneEventCalled(channel_id, 2, 123));
|
||||
telephone_event = GetSendStream(kSsrc1).GetLatestTelephoneEvent();
|
||||
EXPECT_EQ(kTelephoneEventCodec.id, telephone_event.payload_type);
|
||||
EXPECT_EQ(2, telephone_event.event_code);
|
||||
EXPECT_EQ(123, telephone_event.duration_ms);
|
||||
}
|
||||
|
||||
// Test that send bandwidth is set correctly.
|
||||
@ -766,7 +775,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) {
|
||||
EXPECT_FALSE(voe_.GetRED(channel_num));
|
||||
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
|
||||
EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
|
||||
EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
|
||||
EXPECT_FALSE(channel_->CanInsertDtmf());
|
||||
}
|
||||
|
||||
// Test that VoE Channel doesn't call SetSendCodec again if same codec is tried
|
||||
@ -1607,7 +1616,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsDTMFOnTop) {
|
||||
EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
|
||||
EXPECT_EQ(96, gcodec.pltype);
|
||||
EXPECT_STREQ("ISAC", gcodec.plname);
|
||||
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
|
||||
EXPECT_TRUE(channel_->CanInsertDtmf());
|
||||
}
|
||||
|
||||
// Test that we can set send codecs even with CN codec as the first
|
||||
@ -1653,7 +1662,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCaller) {
|
||||
EXPECT_FALSE(voe_.GetRED(channel_num));
|
||||
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
|
||||
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
|
||||
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
|
||||
EXPECT_TRUE(channel_->CanInsertDtmf());
|
||||
}
|
||||
|
||||
// Test that we set VAD and DTMF types correctly as callee.
|
||||
@ -1686,7 +1695,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCallee) {
|
||||
EXPECT_FALSE(voe_.GetRED(channel_num));
|
||||
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
|
||||
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
|
||||
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
|
||||
EXPECT_TRUE(channel_->CanInsertDtmf());
|
||||
}
|
||||
|
||||
// Test that we only apply VAD if we have a CN codec that matches the
|
||||
@ -1750,7 +1759,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) {
|
||||
EXPECT_FALSE(voe_.GetRED(channel_num));
|
||||
EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
|
||||
EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
|
||||
EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
|
||||
EXPECT_TRUE(channel_->CanInsertDtmf());
|
||||
}
|
||||
|
||||
// Test that we set up RED correctly as caller.
|
||||
|
||||
@ -102,6 +102,13 @@ bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioSendStream::SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return channel_proxy_->SetSendTelephoneEventPayloadType(payload_type) &&
|
||||
channel_proxy_->SendTelephoneEventOutband(event, duration_ms);
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
webrtc::AudioSendStream::Stats stats;
|
||||
|
||||
@ -37,6 +37,8 @@ class AudioSendStream final : public webrtc::AudioSendStream {
|
||||
bool DeliverRtcp(const uint8_t* packet, size_t length) override;
|
||||
|
||||
// webrtc::AudioSendStream implementation.
|
||||
bool SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) override;
|
||||
webrtc::AudioSendStream::Stats GetStats() const override;
|
||||
|
||||
const webrtc::AudioSendStream::Config& config() const;
|
||||
|
||||
@ -40,6 +40,9 @@ const CallStatistics kCallStats = {
|
||||
1345, 1678, 1901, 1234, 112, 13456, 17890, 1567, -1890, -1123};
|
||||
const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, -451, -671};
|
||||
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
|
||||
const int kTelephoneEventPayloadType = 123;
|
||||
const uint8_t kTelephoneEventCode = 45;
|
||||
const uint32_t kTelephoneEventDuration = 6789;
|
||||
|
||||
struct ConfigHelper {
|
||||
ConfigHelper() : stream_config_(nullptr) {
|
||||
@ -79,6 +82,16 @@ struct ConfigHelper {
|
||||
AudioSendStream::Config& config() { return stream_config_; }
|
||||
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
|
||||
|
||||
void SetupMockForSendTelephoneEvent() {
|
||||
EXPECT_TRUE(channel_proxy_);
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
SetSendTelephoneEventPayloadType(kTelephoneEventPayloadType))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*channel_proxy_,
|
||||
SendTelephoneEventOutband(kTelephoneEventCode, kTelephoneEventDuration))
|
||||
.WillOnce(Return(true));
|
||||
}
|
||||
|
||||
void SetupMockForGetStats() {
|
||||
using testing::DoAll;
|
||||
using testing::SetArgReferee;
|
||||
@ -142,6 +155,14 @@ TEST(AudioSendStreamTest, ConstructDestruct) {
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, SendTelephoneEvent) {
|
||||
ConfigHelper helper;
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
helper.SetupMockForSendTelephoneEvent();
|
||||
EXPECT_TRUE(send_stream.SendTelephoneEvent(kTelephoneEventPayloadType,
|
||||
kTelephoneEventCode, kTelephoneEventDuration));
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStats) {
|
||||
ConfigHelper helper;
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
|
||||
@ -89,6 +89,9 @@ class AudioSendStream : public SendStream {
|
||||
int red_payload_type = -1; // pt, or -1 to disable REDundant coding.
|
||||
};
|
||||
|
||||
// TODO(solenberg): Make payload_type a config property instead.
|
||||
virtual bool SendTelephoneEvent(int payload_type, uint8_t event,
|
||||
uint32_t duration_ms) = 0;
|
||||
virtual Stats GetStats() const = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
@ -33,6 +33,9 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
|
||||
MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
|
||||
MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int32_t());
|
||||
MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t());
|
||||
MOCK_METHOD1(SetSendTelephoneEventPayloadType, bool(int payload_type));
|
||||
MOCK_METHOD2(SendTelephoneEventOutband, bool(uint8_t event,
|
||||
uint32_t duration_ms));
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -2372,6 +2372,9 @@ int Channel::SendTelephoneEventOutband(unsigned char eventCode,
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
|
||||
"Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
|
||||
playDtmfEvent);
|
||||
if (!Sending()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_playOutbandDtmfEvent = playDtmfEvent;
|
||||
|
||||
|
||||
@ -108,6 +108,18 @@ uint32_t ChannelProxy::GetDelayEstimate() const {
|
||||
return channel()->GetDelayEstimate();
|
||||
}
|
||||
|
||||
bool ChannelProxy::SetSendTelephoneEventPayloadType(int payload_type) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return channel()->SetSendTelephoneEventPayloadType(payload_type) == 0;
|
||||
}
|
||||
|
||||
bool ChannelProxy::SendTelephoneEventOutband(uint8_t event,
|
||||
uint32_t duration_ms) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return
|
||||
channel()->SendTelephoneEventOutband(event, duration_ms, 10, false) == 0;
|
||||
}
|
||||
|
||||
Channel* ChannelProxy::channel() const {
|
||||
RTC_DCHECK(channel_owner_.channel());
|
||||
return channel_owner_.channel();
|
||||
|
||||
@ -51,6 +51,9 @@ class ChannelProxy {
|
||||
virtual int32_t GetSpeechOutputLevelFullRange() const;
|
||||
virtual uint32_t GetDelayEstimate() const;
|
||||
|
||||
virtual bool SetSendTelephoneEventPayloadType(int payload_type);
|
||||
virtual bool SendTelephoneEventOutband(uint8_t event, uint32_t duration_ms);
|
||||
|
||||
private:
|
||||
Channel* channel() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user