- 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:
Fredrik Solenberg
2015-12-04 15:22:19 +01:00
parent fcdcf4a927
commit b572768efb
15 changed files with 141 additions and 106 deletions

View File

@ -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 {

View File

@ -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_;
};

View File

@ -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_;
};

View File

@ -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_;

View File

@ -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(

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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;