Using Rent-A-Codec for static Codec access in WVoE/MC.
Mostly moved code around in WebRtcVoiceEngine: - Added new internal class WebRtcVoiceCodecs for static codec functions and the CodecPrefs. - ConstructCodecs() -> WebRtcVoiceCodecs::SupportedCodecs(). - FindWebRtcCodec -> WebRtcVoiceCodecs::ToCodecInst(). - WebRtcVoiceMediaChannel::SetRecvCodecsInternal() folded into WebRtcVoiceMediaChannel::SetRecvCodecs() (slight logic change). - Change to how SetRecPayloadType() is implemented in fakewebrtcvoiceengine.h (lines 460-470). BUG=webrtc:4690 Review URL: https://codereview.webrtc.org/1461333002 Cr-Commit-Position: refs/heads/master@{#10819}
This commit is contained in:
parent
8779a777f8
commit
26c8c91de2
@ -41,6 +41,7 @@
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/stringutils.h"
|
||||
#include "webrtc/config.h"
|
||||
#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
|
||||
namespace cricket {
|
||||
@ -63,18 +64,6 @@ static const int kOpusBandwidthFb = 20000;
|
||||
#define WEBRTC_CHECK_CHANNEL(channel) \
|
||||
if (channels_.find(channel) == channels_.end()) return -1;
|
||||
|
||||
#define WEBRTC_ASSERT_CHANNEL(channel) \
|
||||
RTC_DCHECK(channels_.find(channel) != channels_.end());
|
||||
|
||||
// Verify the header extension ID, if enabled, is within the bounds specified in
|
||||
// [RFC5285]: 1-14 inclusive.
|
||||
#define WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id) \
|
||||
do { \
|
||||
if (enable && (id < 1 || id > 14)) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
class FakeAudioProcessing : public webrtc::AudioProcessing {
|
||||
public:
|
||||
FakeAudioProcessing() : experimental_ns_enabled_(false) {}
|
||||
@ -189,6 +178,7 @@ class FakeWebRtcVoiceEngine
|
||||
nack_max_packets(0),
|
||||
send_ssrc(0),
|
||||
associate_send_channel(-1),
|
||||
recv_codecs(),
|
||||
neteq_capacity(-1),
|
||||
neteq_fast_accelerate(false) {
|
||||
memset(&send_codec, 0, sizeof(send_codec));
|
||||
@ -219,13 +209,10 @@ class FakeWebRtcVoiceEngine
|
||||
bool neteq_fast_accelerate;
|
||||
};
|
||||
|
||||
FakeWebRtcVoiceEngine(const cricket::AudioCodec* const* codecs,
|
||||
int num_codecs)
|
||||
FakeWebRtcVoiceEngine()
|
||||
: inited_(false),
|
||||
last_channel_(-1),
|
||||
fail_create_channel_(false),
|
||||
codecs_(codecs),
|
||||
num_codecs_(num_codecs),
|
||||
num_set_send_codecs_(0),
|
||||
ec_enabled_(false),
|
||||
ec_metrics_enabled_(false),
|
||||
@ -247,12 +234,7 @@ class FakeWebRtcVoiceEngine
|
||||
memset(&agc_config_, 0, sizeof(agc_config_));
|
||||
}
|
||||
~FakeWebRtcVoiceEngine() {
|
||||
// Ought to have all been deleted by the WebRtcVoiceMediaChannel
|
||||
// destructors, but just in case ...
|
||||
for (std::map<int, Channel*>::const_iterator i = channels_.begin();
|
||||
i != channels_.end(); ++i) {
|
||||
delete i->second;
|
||||
}
|
||||
RTC_CHECK(channels_.empty());
|
||||
}
|
||||
|
||||
bool ec_metrics_enabled() const { return ec_metrics_enabled_; }
|
||||
@ -291,7 +273,7 @@ class FakeWebRtcVoiceEngine
|
||||
return channels_[channel]->nack_max_packets;
|
||||
}
|
||||
const webrtc::PacketTime& GetLastRtpPacketTime(int channel) {
|
||||
WEBRTC_ASSERT_CHANNEL(channel);
|
||||
RTC_DCHECK(channels_.find(channel) != channels_.end());
|
||||
return channels_[channel]->last_rtp_packet_time;
|
||||
}
|
||||
int GetSendCNPayloadType(int channel, bool wideband) {
|
||||
@ -335,11 +317,8 @@ class FakeWebRtcVoiceEngine
|
||||
return -1;
|
||||
}
|
||||
Channel* ch = new Channel();
|
||||
for (int i = 0; i < NumOfCodecs(); ++i) {
|
||||
webrtc::CodecInst codec;
|
||||
GetCodec(i, codec);
|
||||
ch->recv_codecs.push_back(codec);
|
||||
}
|
||||
auto db = webrtc::acm2::RentACodec::Database();
|
||||
ch->recv_codecs.assign(db.begin(), db.end());
|
||||
if (config.Get<webrtc::NetEqCapacityConfig>().enabled) {
|
||||
ch->neteq_capacity = config.Get<webrtc::NetEqCapacityConfig>().capacity;
|
||||
}
|
||||
@ -439,22 +418,8 @@ class FakeWebRtcVoiceEngine
|
||||
webrtc::RtcEventLog* GetEventLog() { return nullptr; }
|
||||
|
||||
// webrtc::VoECodec
|
||||
WEBRTC_FUNC(NumOfCodecs, ()) {
|
||||
return num_codecs_;
|
||||
}
|
||||
WEBRTC_FUNC(GetCodec, (int index, webrtc::CodecInst& codec)) {
|
||||
if (index < 0 || index >= NumOfCodecs()) {
|
||||
return -1;
|
||||
}
|
||||
const cricket::AudioCodec& c(*codecs_[index]);
|
||||
codec.pltype = c.id;
|
||||
rtc::strcpyn(codec.plname, sizeof(codec.plname), c.name.c_str());
|
||||
codec.plfreq = c.clockrate;
|
||||
codec.pacsize = 0;
|
||||
codec.channels = c.channels;
|
||||
codec.rate = c.bitrate;
|
||||
return 0;
|
||||
}
|
||||
WEBRTC_STUB(NumOfCodecs, ());
|
||||
WEBRTC_STUB(GetCodec, (int index, webrtc::CodecInst& codec));
|
||||
WEBRTC_FUNC(SetSendCodec, (int channel, const webrtc::CodecInst& codec)) {
|
||||
WEBRTC_CHECK_CHANNEL(channel);
|
||||
// To match the behavior of the real implementation.
|
||||
@ -492,16 +457,17 @@ class FakeWebRtcVoiceEngine
|
||||
}
|
||||
}
|
||||
// Otherwise try to find this codec and update its payload type.
|
||||
int result = -1; // not found
|
||||
for (std::vector<webrtc::CodecInst>::iterator it = ch->recv_codecs.begin();
|
||||
it != ch->recv_codecs.end(); ++it) {
|
||||
if (strcmp(it->plname, codec.plname) == 0 &&
|
||||
it->plfreq == codec.plfreq) {
|
||||
it->plfreq == codec.plfreq &&
|
||||
it->channels == codec.channels) {
|
||||
it->pltype = codec.pltype;
|
||||
it->channels = codec.channels;
|
||||
return 0;
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
return -1; // not found
|
||||
return result;
|
||||
}
|
||||
WEBRTC_FUNC(SetSendCNPayloadType, (int channel, int type,
|
||||
webrtc::PayloadFrequencies frequency)) {
|
||||
@ -932,8 +898,6 @@ class FakeWebRtcVoiceEngine
|
||||
int last_channel_;
|
||||
std::map<int, Channel*> channels_;
|
||||
bool fail_create_channel_;
|
||||
const cricket::AudioCodec* const* codecs_;
|
||||
int num_codecs_;
|
||||
int num_set_send_codecs_; // how many times we call SetSendCodec().
|
||||
bool ec_enabled_;
|
||||
bool ec_metrics_enabled_;
|
||||
@ -957,8 +921,6 @@ class FakeWebRtcVoiceEngine
|
||||
FakeAudioProcessing audio_processing_;
|
||||
};
|
||||
|
||||
#undef WEBRTC_CHECK_HEADER_EXTENSION_ID
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // TALK_SESSION_PHONE_FAKEWEBRTCVOICEENGINE_H_
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
#include "webrtc/base/stringutils.h"
|
||||
#include "webrtc/call/rtc_event_log.h"
|
||||
#include "webrtc/common.h"
|
||||
#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/system_wrappers/include/field_trial.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
@ -66,32 +67,6 @@ const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
|
||||
const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
|
||||
webrtc::kTraceInfo;
|
||||
|
||||
const int kMaxNumPacketSize = 6;
|
||||
struct CodecPref {
|
||||
const char* name;
|
||||
int clockrate;
|
||||
int channels;
|
||||
int payload_type;
|
||||
bool is_multi_rate;
|
||||
int packet_sizes_ms[kMaxNumPacketSize];
|
||||
};
|
||||
// Note: keep the supported packet sizes in ascending order.
|
||||
const CodecPref kCodecPrefs[] = {
|
||||
{ kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } },
|
||||
{ kIsacCodecName, 16000, 1, 103, true, { 30, 60 } },
|
||||
{ kIsacCodecName, 32000, 1, 104, true, { 30 } },
|
||||
// G722 should be advertised as 8000 Hz because of the RFC "bug".
|
||||
{ kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
|
||||
{ kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kCnCodecName, 32000, 1, 106, false, { } },
|
||||
{ kCnCodecName, 16000, 1, 105, false, { } },
|
||||
{ kCnCodecName, 8000, 1, 13, false, { } },
|
||||
{ kRedCodecName, 8000, 1, 127, false, { } },
|
||||
{ kDtmfCodecName, 8000, 1, 126, false, { } },
|
||||
};
|
||||
|
||||
// For Linux/Mac, using the default device is done by specifying index 0 for
|
||||
// VoE 4.0 and not -1 (which was the case for VoE 3.5).
|
||||
//
|
||||
@ -185,13 +160,6 @@ std::string ToString(const webrtc::CodecInst& codec) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void LogMultiline(rtc::LoggingSeverity sev, char* text) {
|
||||
const char* delim = "\r\n";
|
||||
for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
|
||||
LOG_V(sev) << tok;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCodec(const AudioCodec& codec, const char* ref_name) {
|
||||
return (_stricmp(codec.name.c_str(), ref_name) == 0);
|
||||
}
|
||||
@ -200,19 +168,9 @@ bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) {
|
||||
return (_stricmp(codec.plname, ref_name) == 0);
|
||||
}
|
||||
|
||||
bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
|
||||
for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
|
||||
if (IsCodec(codec, kCodecPrefs[i].name) &&
|
||||
kCodecPrefs[i].clockrate == codec.plfreq) {
|
||||
return kCodecPrefs[i].is_multi_rate;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindCodec(const std::vector<AudioCodec>& codecs,
|
||||
const AudioCodec& codec,
|
||||
AudioCodec* found_codec) {
|
||||
const AudioCodec& codec,
|
||||
AudioCodec* found_codec) {
|
||||
for (const AudioCodec& c : codecs) {
|
||||
if (c.Matches(codec)) {
|
||||
if (found_codec != NULL) {
|
||||
@ -242,38 +200,8 @@ bool IsNackEnabled(const AudioCodec& codec) {
|
||||
kParamValueEmpty));
|
||||
}
|
||||
|
||||
int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
|
||||
int selected_packet_size_ms = codec_pref.packet_sizes_ms[0];
|
||||
for (int packet_size_ms : codec_pref.packet_sizes_ms) {
|
||||
if (packet_size_ms && packet_size_ms <= ptime_ms) {
|
||||
selected_packet_size_ms = packet_size_ms;
|
||||
}
|
||||
}
|
||||
return selected_packet_size_ms;
|
||||
}
|
||||
|
||||
// If the AudioCodec param kCodecParamPTime is set, then we will set it to codec
|
||||
// pacsize if it's valid, or we will pick the next smallest value we support.
|
||||
// TODO(Brave): Query supported packet sizes from ACM when the API is ready.
|
||||
bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
|
||||
for (const CodecPref& codec_pref : kCodecPrefs) {
|
||||
if ((IsCodec(*codec, codec_pref.name) &&
|
||||
codec_pref.clockrate == codec->plfreq) ||
|
||||
IsCodec(*codec, kG722CodecName)) {
|
||||
int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
|
||||
if (packet_size_ms) {
|
||||
// Convert unit from milli-seconds to samples.
|
||||
codec->pacsize = (codec->plfreq / 1000) * packet_size_ms;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if codec.params[feature] == "1", false otherwise.
|
||||
bool IsCodecFeatureEnabled(const AudioCodec& codec,
|
||||
const char* feature) {
|
||||
bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) {
|
||||
int value;
|
||||
return codec.GetParam(feature, &value) && value == 1;
|
||||
}
|
||||
@ -340,18 +268,6 @@ void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
|
||||
voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
|
||||
}
|
||||
|
||||
// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
|
||||
// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
|
||||
// codec.
|
||||
void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
|
||||
if (IsCodec(*voe_codec, kG722CodecName)) {
|
||||
// If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
|
||||
// has changed, and this special case is no longer needed.
|
||||
RTC_DCHECK(voe_codec->plfreq != new_plfreq);
|
||||
voe_codec->plfreq = new_plfreq;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the default set of options applied to the engine. Historically, these
|
||||
// were supplied as a combination of flags from the channel manager (ec, agc,
|
||||
// ns, and highpass) and the rest hardcoded in InitInternal.
|
||||
@ -393,54 +309,17 @@ std::vector<webrtc::RtpExtension> FindAudioRtpHeaderExtensions(
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace {
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine()
|
||||
: voe_wrapper_(new VoEWrapper()),
|
||||
audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper)
|
||||
: voe_wrapper_(voe_wrapper) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::Construct() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
|
||||
|
||||
signal_thread_checker_.DetachFromThread();
|
||||
std::memset(&default_agc_config_, 0, sizeof(default_agc_config_));
|
||||
|
||||
webrtc::Trace::set_level_filter(kDefaultTraceFilter);
|
||||
webrtc::Trace::SetTraceCallback(this);
|
||||
|
||||
// Load our audio codec list.
|
||||
ConstructCodecs();
|
||||
|
||||
// Load our RTP Header extensions.
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
|
||||
kRtpAudioLevelHeaderExtensionDefaultId));
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
|
||||
kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
|
||||
if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
|
||||
rtp_header_extensions_.push_back(RtpHeaderExtension(
|
||||
kRtpTransportSequenceNumberHeaderExtension,
|
||||
kRtpTransportSequenceNumberHeaderExtensionDefaultId));
|
||||
}
|
||||
options_ = GetDefaultEngineOptions();
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
|
||||
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
|
||||
for (int i = 0; i < ncodecs; ++i) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (GetVoeCodec(i, &voe_codec)) {
|
||||
class WebRtcVoiceCodecs final {
|
||||
public:
|
||||
// TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec
|
||||
// list and add a test which verifies VoE supports the listed codecs.
|
||||
static std::vector<AudioCodec> SupportedCodecs() {
|
||||
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
|
||||
std::vector<AudioCodec> result;
|
||||
for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
|
||||
// Change the sample rate of G722 to 8000 to match SDP.
|
||||
MaybeFixupG722(&voe_codec, 8000);
|
||||
// Skip uncompressed formats.
|
||||
if (IsCodec(voe_codec, kL16CodecName)) {
|
||||
continue;
|
||||
@ -483,24 +362,181 @@ void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
// TODO(hellner): Add ptime, sprop-stereo, and stereo
|
||||
// when they can be set to values other than the default.
|
||||
}
|
||||
codecs_.push_back(codec);
|
||||
result.push_back(codec);
|
||||
} else {
|
||||
LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec);
|
||||
}
|
||||
}
|
||||
// Make sure they are in local preference order.
|
||||
std::sort(result.begin(), result.end(), &AudioCodec::Preferable);
|
||||
return result;
|
||||
}
|
||||
// Make sure they are in local preference order.
|
||||
std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable);
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) {
|
||||
static bool ToCodecInst(const AudioCodec& in,
|
||||
webrtc::CodecInst* out) {
|
||||
for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
|
||||
// Change the sample rate of G722 to 8000 to match SDP.
|
||||
MaybeFixupG722(&voe_codec, 8000);
|
||||
AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
|
||||
voe_codec.rate, voe_codec.channels, 0);
|
||||
bool multi_rate = IsCodecMultiRate(voe_codec);
|
||||
// Allow arbitrary rates for ISAC to be specified.
|
||||
if (multi_rate) {
|
||||
// Set codec.bitrate to 0 so the check for codec.Matches() passes.
|
||||
codec.bitrate = 0;
|
||||
}
|
||||
if (codec.Matches(in)) {
|
||||
if (out) {
|
||||
// Fixup the payload type.
|
||||
voe_codec.pltype = in.id;
|
||||
|
||||
// Set bitrate if specified.
|
||||
if (multi_rate && in.bitrate != 0) {
|
||||
voe_codec.rate = in.bitrate;
|
||||
}
|
||||
|
||||
// Reset G722 sample rate to 16000 to match WebRTC.
|
||||
MaybeFixupG722(&voe_codec, 16000);
|
||||
|
||||
// Apply codec-specific settings.
|
||||
if (IsCodec(codec, kIsacCodecName)) {
|
||||
// If ISAC and an explicit bitrate is not specified,
|
||||
// enable auto bitrate adjustment.
|
||||
voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
|
||||
}
|
||||
*out = voe_codec;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Change the sample rate of G722 to 8000 to match SDP.
|
||||
MaybeFixupG722(codec, 8000);
|
||||
return true;
|
||||
|
||||
static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
|
||||
for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
|
||||
if (IsCodec(codec, kCodecPrefs[i].name) &&
|
||||
kCodecPrefs[i].clockrate == codec.plfreq) {
|
||||
return kCodecPrefs[i].is_multi_rate;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the AudioCodec param kCodecParamPTime is set, then we will set it to
|
||||
// codec pacsize if it's valid, or we will pick the next smallest value we
|
||||
// support.
|
||||
// TODO(Brave): Query supported packet sizes from ACM when the API is ready.
|
||||
static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
|
||||
for (const CodecPref& codec_pref : kCodecPrefs) {
|
||||
if ((IsCodec(*codec, codec_pref.name) &&
|
||||
codec_pref.clockrate == codec->plfreq) ||
|
||||
IsCodec(*codec, kG722CodecName)) {
|
||||
int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
|
||||
if (packet_size_ms) {
|
||||
// Convert unit from milli-seconds to samples.
|
||||
codec->pacsize = (codec->plfreq / 1000) * packet_size_ms;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kMaxNumPacketSize = 6;
|
||||
struct CodecPref {
|
||||
const char* name;
|
||||
int clockrate;
|
||||
int channels;
|
||||
int payload_type;
|
||||
bool is_multi_rate;
|
||||
int packet_sizes_ms[kMaxNumPacketSize];
|
||||
};
|
||||
// Note: keep the supported packet sizes in ascending order.
|
||||
static const CodecPref kCodecPrefs[12];
|
||||
|
||||
static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
|
||||
int selected_packet_size_ms = codec_pref.packet_sizes_ms[0];
|
||||
for (int packet_size_ms : codec_pref.packet_sizes_ms) {
|
||||
if (packet_size_ms && packet_size_ms <= ptime_ms) {
|
||||
selected_packet_size_ms = packet_size_ms;
|
||||
}
|
||||
}
|
||||
return selected_packet_size_ms;
|
||||
}
|
||||
|
||||
// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
|
||||
// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
|
||||
// codec.
|
||||
static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
|
||||
if (IsCodec(*voe_codec, kG722CodecName)) {
|
||||
// If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
|
||||
// has changed, and this special case is no longer needed.
|
||||
RTC_DCHECK(voe_codec->plfreq != new_plfreq);
|
||||
voe_codec->plfreq = new_plfreq;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[12] = {
|
||||
{ kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } },
|
||||
{ kIsacCodecName, 16000, 1, 103, true, { 30, 60 } },
|
||||
{ kIsacCodecName, 32000, 1, 104, true, { 30 } },
|
||||
// G722 should be advertised as 8000 Hz because of the RFC "bug".
|
||||
{ kG722CodecName, 8000, 1, 9, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
|
||||
{ kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kCnCodecName, 32000, 1, 106, false, { } },
|
||||
{ kCnCodecName, 16000, 1, 105, false, { } },
|
||||
{ kCnCodecName, 8000, 1, 13, false, { } },
|
||||
{ kRedCodecName, 8000, 1, 127, false, { } },
|
||||
{ kDtmfCodecName, 8000, 1, 126, false, { } },
|
||||
};
|
||||
} // namespace {
|
||||
|
||||
bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in,
|
||||
webrtc::CodecInst* out) {
|
||||
return WebRtcVoiceCodecs::ToCodecInst(in, out);
|
||||
}
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine()
|
||||
: voe_wrapper_(new VoEWrapper()),
|
||||
audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper)
|
||||
: voe_wrapper_(voe_wrapper) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::Construct() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
|
||||
|
||||
signal_thread_checker_.DetachFromThread();
|
||||
std::memset(&default_agc_config_, 0, sizeof(default_agc_config_));
|
||||
|
||||
webrtc::Trace::set_level_filter(kDefaultTraceFilter);
|
||||
webrtc::Trace::SetTraceCallback(this);
|
||||
|
||||
// Load our audio codec list.
|
||||
codecs_ = WebRtcVoiceCodecs::SupportedCodecs();
|
||||
|
||||
// Load our RTP Header extensions.
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
|
||||
kRtpAudioLevelHeaderExtensionDefaultId));
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
|
||||
kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
|
||||
if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
|
||||
rtp_header_extensions_.push_back(RtpHeaderExtension(
|
||||
kRtpTransportSequenceNumberHeaderExtension,
|
||||
kRtpTransportSequenceNumberHeaderExtensionDefaultId));
|
||||
}
|
||||
options_ = GetDefaultEngineOptions();
|
||||
}
|
||||
|
||||
WebRtcVoiceEngine::~WebRtcVoiceEngine() {
|
||||
@ -539,10 +575,15 @@ bool WebRtcVoiceEngine::InitInternal() {
|
||||
webrtc::Trace::set_level_filter(kDefaultTraceFilter);
|
||||
|
||||
// Log the VoiceEngine version info
|
||||
char buffer[1024] = "";
|
||||
voe_wrapper_->base()->GetVersion(buffer);
|
||||
LOG(LS_INFO) << "WebRtc VoiceEngine Version:";
|
||||
LogMultiline(rtc::LS_INFO, buffer);
|
||||
{
|
||||
char buffer[1024] = "";
|
||||
voe_wrapper_->base()->GetVersion(buffer);
|
||||
LOG(LS_INFO) << "WebRtc VoiceEngine Version:";
|
||||
const char* delim = "\r\n";
|
||||
for (char* tok = strtok(buffer, delim); tok; tok = strtok(NULL, delim)) {
|
||||
LOG(LS_INFO) << tok;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the default AGC configuration settings. This must happen before
|
||||
// calling SetOptions or the default will be overwritten.
|
||||
@ -1056,55 +1097,6 @@ const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
|
||||
return codecs_;
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return FindWebRtcCodec(in, NULL);
|
||||
}
|
||||
|
||||
// Get the VoiceEngine codec that matches |in|, with the supplied settings.
|
||||
bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
|
||||
webrtc::CodecInst* out) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
|
||||
for (int i = 0; i < ncodecs; ++i) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (GetVoeCodec(i, &voe_codec)) {
|
||||
AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
|
||||
voe_codec.rate, voe_codec.channels, 0);
|
||||
bool multi_rate = IsCodecMultiRate(voe_codec);
|
||||
// Allow arbitrary rates for ISAC to be specified.
|
||||
if (multi_rate) {
|
||||
// Set codec.bitrate to 0 so the check for codec.Matches() passes.
|
||||
codec.bitrate = 0;
|
||||
}
|
||||
if (codec.Matches(in)) {
|
||||
if (out) {
|
||||
// Fixup the payload type.
|
||||
voe_codec.pltype = in.id;
|
||||
|
||||
// Set bitrate if specified.
|
||||
if (multi_rate && in.bitrate != 0) {
|
||||
voe_codec.rate = in.bitrate;
|
||||
}
|
||||
|
||||
// Reset G722 sample rate to 16000 to match WebRTC.
|
||||
MaybeFixupG722(&voe_codec, 16000);
|
||||
|
||||
// Apply codec-specific settings.
|
||||
if (IsCodec(codec, kIsacCodecName)) {
|
||||
// If ISAC and an explicit bitrate is not specified,
|
||||
// enable auto bitrate adjustment.
|
||||
voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
|
||||
}
|
||||
*out = voe_codec;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<RtpHeaderExtension>&
|
||||
WebRtcVoiceEngine::rtp_header_extensions() const {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
@ -1592,7 +1584,26 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs(
|
||||
PausePlayout();
|
||||
}
|
||||
|
||||
bool result = SetRecvCodecsInternal(new_codecs);
|
||||
bool result = true;
|
||||
for (const AudioCodec& codec : new_codecs) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
|
||||
LOG(LS_INFO) << ToString(codec);
|
||||
voe_codec.pltype = codec.id;
|
||||
for (const auto& ch : recv_streams_) {
|
||||
if (engine()->voe()->codec()->SetRecPayloadType(
|
||||
ch.second->channel(), voe_codec) == -1) {
|
||||
LOG_RTCERR2(SetRecPayloadType, ch.second->channel(),
|
||||
ToString(voe_codec));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result) {
|
||||
recv_codecs_ = codecs;
|
||||
}
|
||||
@ -1627,7 +1638,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
// Ignore codecs we don't know about. The negotiation step should prevent
|
||||
// this, but double-check to be sure.
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (!engine()->FindWebRtcCodec(codec, &voe_codec)) {
|
||||
if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
|
||||
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
|
||||
continue;
|
||||
}
|
||||
@ -1668,7 +1679,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
// Set packet size if the AudioCodec param kCodecParamPTime is set.
|
||||
int ptime_ms = 0;
|
||||
if (codec.GetParam(kCodecParamPTime, &ptime_ms)) {
|
||||
if (!SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
|
||||
if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
|
||||
LOG(LS_WARNING) << "Failed to set packet size for codec "
|
||||
<< send_codec.plname;
|
||||
return false;
|
||||
@ -1746,7 +1757,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
// Ignore codecs we don't know about. The negotiation step should prevent
|
||||
// this, but double-check to be sure.
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (!engine()->FindWebRtcCodec(codec, &voe_codec)) {
|
||||
if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
|
||||
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
|
||||
continue;
|
||||
}
|
||||
@ -2116,24 +2127,20 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
|
||||
}
|
||||
|
||||
// Turn off all supported codecs.
|
||||
const int ncodecs = engine()->voe()->codec()->NumOfCodecs();
|
||||
for (int i = 0; i < ncodecs; ++i) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) {
|
||||
voe_codec.pltype = -1;
|
||||
if (engine()->voe()->codec()->SetRecPayloadType(
|
||||
channel, voe_codec) == -1) {
|
||||
LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
|
||||
DeleteVoEChannel(channel);
|
||||
return false;
|
||||
}
|
||||
// TODO(solenberg): Remove once "no codecs" is the default state of a stream.
|
||||
for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
|
||||
voe_codec.pltype = -1;
|
||||
if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) {
|
||||
LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
|
||||
DeleteVoEChannel(channel);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Only enable those configured for this channel.
|
||||
for (const auto& codec : recv_codecs_) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (engine()->FindWebRtcCodec(codec, &voe_codec)) {
|
||||
if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
|
||||
voe_codec.pltype = codec.id;
|
||||
if (engine()->voe()->codec()->SetRecPayloadType(
|
||||
channel, voe_codec) == -1) {
|
||||
@ -2486,7 +2493,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
|
||||
return true;
|
||||
|
||||
webrtc::CodecInst codec = *send_codec_;
|
||||
bool is_multi_rate = IsCodecMultiRate(codec);
|
||||
bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec);
|
||||
|
||||
if (is_multi_rate) {
|
||||
// If codec is multi-rate then just set the bitrate.
|
||||
@ -2635,7 +2642,7 @@ bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec,
|
||||
if (codec.id == red_pt) {
|
||||
// If we find the right codec, that will be the codec we pass to
|
||||
// SetSendCodec, with the desired payload type.
|
||||
if (engine()->FindWebRtcCodec(codec, send_codec)) {
|
||||
if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) {
|
||||
return true;
|
||||
} else {
|
||||
break;
|
||||
@ -2659,30 +2666,6 @@ bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal(
|
||||
const std::vector<AudioCodec>& new_codecs) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
for (const AudioCodec& codec : new_codecs) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (engine()->FindWebRtcCodec(codec, &voe_codec)) {
|
||||
LOG(LS_INFO) << ToString(codec);
|
||||
voe_codec.pltype = codec.id;
|
||||
for (const auto& ch : recv_streams_) {
|
||||
if (engine()->voe()->codec()->SetRecPayloadType(
|
||||
ch.second->channel(), voe_codec) == -1) {
|
||||
LOG_RTCERR2(SetRecPayloadType, ch.second->channel(),
|
||||
ToString(voe_codec));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace cricket
|
||||
|
||||
#endif // HAVE_WEBRTC_VOICE
|
||||
|
||||
@ -57,8 +57,10 @@ class WebRtcVoiceMediaChannel;
|
||||
// It uses the WebRtc VoiceEngine library for audio handling.
|
||||
class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
friend class WebRtcVoiceMediaChannel;
|
||||
|
||||
public:
|
||||
// Exposed for the WVoE/MC unit test.
|
||||
static bool ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out);
|
||||
|
||||
WebRtcVoiceEngine();
|
||||
// Dependency injection for testing.
|
||||
explicit WebRtcVoiceEngine(VoEWrapper* voe_wrapper);
|
||||
@ -78,9 +80,6 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
int GetInputLevel();
|
||||
|
||||
const std::vector<AudioCodec>& codecs();
|
||||
bool FindCodec(const AudioCodec& codec);
|
||||
bool FindWebRtcCodec(const AudioCodec& codec, webrtc::CodecInst* gcodec);
|
||||
|
||||
const std::vector<RtpHeaderExtension>& rtp_header_extensions() const;
|
||||
|
||||
// For tracking WebRtc channels. Needed because we have to pause them
|
||||
@ -114,8 +113,6 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
|
||||
private:
|
||||
void Construct();
|
||||
void ConstructCodecs();
|
||||
bool GetVoeCodec(int index, webrtc::CodecInst* codec);
|
||||
bool InitInternal();
|
||||
// Every option that is "set" will be applied. Every option not "set" will be
|
||||
// ignored. This allows us to selectively turn on and off different options
|
||||
@ -258,7 +255,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
|
||||
}
|
||||
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
|
||||
bool SetSendBitrateInternal(int bps);
|
||||
bool SetRecvCodecsInternal(const std::vector<AudioCodec>& new_codecs);
|
||||
|
||||
rtc::ThreadChecker worker_thread_checker_;
|
||||
|
||||
|
||||
@ -54,10 +54,6 @@ const cricket::AudioCodec kCn8000Codec(13, "CN", 8000, 0, 1, 0);
|
||||
const cricket::AudioCodec kCn16000Codec(105, "CN", 16000, 0, 1, 0);
|
||||
const cricket::AudioCodec kTelephoneEventCodec(106, "telephone-event", 8000, 0,
|
||||
1, 0);
|
||||
const cricket::AudioCodec* const kAudioCodecs[] = {
|
||||
&kPcmuCodec, &kIsacCodec, &kOpusCodec, &kG722CodecVoE, &kRedCodec,
|
||||
&kCn8000Codec, &kCn16000Codec, &kTelephoneEventCodec,
|
||||
};
|
||||
const uint32_t kSsrc1 = 0x99;
|
||||
const uint32_t kSsrc2 = 0x98;
|
||||
const uint32_t kSsrcs4[] = { 1, 2, 3, 4 };
|
||||
@ -81,7 +77,6 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
public:
|
||||
WebRtcVoiceEngineTestFake()
|
||||
: call_(webrtc::Call::Config()),
|
||||
voe_(kAudioCodecs, arraysize(kAudioCodecs)),
|
||||
engine_(new FakeVoEWrapper(&voe_)),
|
||||
channel_(nullptr) {
|
||||
send_parameters_.codecs.push_back(kPcmuCodec);
|
||||
@ -451,32 +446,33 @@ TEST_F(WebRtcVoiceEngineTestFake, FindCodec) {
|
||||
cricket::AudioCodec codec;
|
||||
webrtc::CodecInst codec_inst;
|
||||
// Find PCMU with explicit clockrate and bitrate.
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(kPcmuCodec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kPcmuCodec, &codec_inst));
|
||||
// Find ISAC with explicit clockrate and 0 bitrate.
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(kIsacCodec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kIsacCodec, &codec_inst));
|
||||
// Find telephone-event with explicit clockrate and 0 bitrate.
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(kTelephoneEventCodec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kTelephoneEventCodec,
|
||||
&codec_inst));
|
||||
// Find ISAC with a different payload id.
|
||||
codec = kIsacCodec;
|
||||
codec.id = 127;
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
|
||||
EXPECT_EQ(codec.id, codec_inst.pltype);
|
||||
// Find PCMU with a 0 clockrate.
|
||||
codec = kPcmuCodec;
|
||||
codec.clockrate = 0;
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
|
||||
EXPECT_EQ(codec.id, codec_inst.pltype);
|
||||
EXPECT_EQ(8000, codec_inst.plfreq);
|
||||
// Find PCMU with a 0 bitrate.
|
||||
codec = kPcmuCodec;
|
||||
codec.bitrate = 0;
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
|
||||
EXPECT_EQ(codec.id, codec_inst.pltype);
|
||||
EXPECT_EQ(64000, codec_inst.rate);
|
||||
// Find ISAC with an explicit bitrate.
|
||||
codec = kIsacCodec;
|
||||
codec.bitrate = 32000;
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(codec, &codec_inst));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(codec, &codec_inst));
|
||||
EXPECT_EQ(codec.id, codec_inst.pltype);
|
||||
EXPECT_EQ(32000, codec_inst.rate);
|
||||
}
|
||||
@ -539,7 +535,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpusNoStereo) {
|
||||
cricket::StreamParams::CreateLegacy(kSsrc1)));
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
webrtc::CodecInst opus;
|
||||
engine_.FindWebRtcCodec(kOpusCodec, &opus);
|
||||
cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
|
||||
// Even without stereo parameters, recv codecs still specify channels = 2.
|
||||
EXPECT_EQ(2, opus.channels);
|
||||
EXPECT_EQ(111, opus.pltype);
|
||||
@ -562,7 +558,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus0Stereo) {
|
||||
cricket::StreamParams::CreateLegacy(kSsrc1)));
|
||||
int channel_num2 = voe_.GetLastChannel();
|
||||
webrtc::CodecInst opus;
|
||||
engine_.FindWebRtcCodec(kOpusCodec, &opus);
|
||||
cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
|
||||
// Even when stereo is off, recv codecs still specify channels = 2.
|
||||
EXPECT_EQ(2, opus.channels);
|
||||
EXPECT_EQ(111, opus.pltype);
|
||||
@ -585,7 +581,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsWithOpus1Stereo) {
|
||||
cricket::StreamParams::CreateLegacy(kSsrc1)));
|
||||
int channel_num2 = voe_.GetLastChannel();
|
||||
webrtc::CodecInst opus;
|
||||
engine_.FindWebRtcCodec(kOpusCodec, &opus);
|
||||
cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
|
||||
EXPECT_EQ(2, opus.channels);
|
||||
EXPECT_EQ(111, opus.pltype);
|
||||
EXPECT_STREQ("opus", opus.plname);
|
||||
@ -670,7 +666,7 @@ TEST_F(WebRtcVoiceEngineTestFake, AddRecvCodecsWhilePlaying) {
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
EXPECT_TRUE(voe_.GetPlayout(channel_num));
|
||||
webrtc::CodecInst gcodec;
|
||||
EXPECT_TRUE(engine_.FindWebRtcCodec(kOpusCodec, &gcodec));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &gcodec));
|
||||
EXPECT_EQ(kOpusCodec.id, gcodec.pltype);
|
||||
}
|
||||
|
||||
@ -3246,54 +3242,60 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) {
|
||||
|
||||
// Tests that the library is configured with the codecs we want.
|
||||
TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
|
||||
cricket::WebRtcVoiceEngine engine;
|
||||
// Check codecs by name.
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0)));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "OPUS", 48000, 0, 2, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "ISAC", 16000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "ISAC", 32000, 0, 1, 0), nullptr));
|
||||
// Check that name matching is case-insensitive.
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "G722", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "red", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "CN", 32000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "CN", 16000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "CN", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0)));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "ILBC", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "iLBC", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "PCMU", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "PCMA", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "G722", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "red", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "CN", 32000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "CN", 16000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "CN", 8000, 0, 1, 0), nullptr));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(96, "telephone-event", 8000, 0, 1, 0), nullptr));
|
||||
// Check codecs with an id by id.
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(0, "", 8000, 0, 1, 0))); // PCMU
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(8, "", 8000, 0, 1, 0))); // PCMA
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(9, "", 8000, 0, 1, 0))); // G722
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(13, "", 8000, 0, 1, 0))); // CN
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(0, "", 8000, 0, 1, 0), nullptr)); // PCMU
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(8, "", 8000, 0, 1, 0), nullptr)); // PCMA
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(9, "", 8000, 0, 1, 0), nullptr)); // G722
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(13, "", 8000, 0, 1, 0), nullptr)); // CN
|
||||
// Check sample/bitrate matching.
|
||||
EXPECT_TRUE(engine.FindCodec(
|
||||
cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0)));
|
||||
EXPECT_TRUE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 0), nullptr));
|
||||
// Check that bad codecs fail.
|
||||
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0)));
|
||||
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(88, "", 0, 0, 1, 0)));
|
||||
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 0, 2, 0)));
|
||||
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 5000, 0, 1, 0)));
|
||||
EXPECT_FALSE(engine.FindCodec(cricket::AudioCodec(0, "", 0, 5000, 1, 0)));
|
||||
EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(99, "ABCD", 0, 0, 1, 0), nullptr));
|
||||
EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(88, "", 0, 0, 1, 0), nullptr));
|
||||
EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(0, "", 0, 0, 2, 0), nullptr));
|
||||
EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(0, "", 5000, 0, 1, 0), nullptr));
|
||||
EXPECT_FALSE(cricket::WebRtcVoiceEngine::ToCodecInst(
|
||||
cricket::AudioCodec(0, "", 0, 5000, 1, 0), nullptr));
|
||||
|
||||
// Verify the payload id of common audio codecs, including CN, ISAC, and G722.
|
||||
cricket::WebRtcVoiceEngine engine;
|
||||
for (std::vector<cricket::AudioCodec>::const_iterator it =
|
||||
engine.codecs().begin(); it != engine.codecs().end(); ++it) {
|
||||
if (it->name == "CN" && it->clockrate == 16000) {
|
||||
@ -3320,7 +3322,6 @@ TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
|
||||
EXPECT_EQ("1", it->params.find("useinbandfec")->second);
|
||||
}
|
||||
}
|
||||
|
||||
engine.Terminate();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user