WebRtcVoiceMediaChannel::AddRecvStream: Don't call SetRecPayloadType
This removes one more place where we were unable to handle codecs not
in the built-in set.
BUG=webrtc:5805
Review-Url: https://codereview.webrtc.org/2686043006
Cr-Commit-Position: refs/heads/master@{#17370}
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index 8c073d9..f64d305 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -94,10 +94,7 @@
channel_proxy_->GetAudioDecoderFactory());
channel_proxy_->RegisterExternalTransport(config.rtcp_send_transport);
-
- for (const auto& kv : config.decoder_map) {
- channel_proxy_->SetRecPayloadType(kv.first, kv.second);
- }
+ channel_proxy_->SetReceiveCodecs(config.decoder_map);
for (const auto& extension : config.rtp.extensions) {
if (extension.uri == RtpExtension::kAudioLevelUri) {
diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc
index e6b81a8..9025550 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include <map>
#include <string>
#include <vector>
@@ -111,6 +112,11 @@
.Times(1)
.After(expect_set);
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
+ EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
+ .WillRepeatedly(
+ Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
+ EXPECT_THAT(codecs, testing::IsEmpty());
+ }));
return channel_proxy_;
}));
stream_config_.voe_channel_id = kChannelId;
diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
index 99d6812..a45b91c 100644
--- a/webrtc/call/call_unittest.cc
+++ b/webrtc/call/call_unittest.cc
@@ -9,6 +9,7 @@
*/
#include <list>
+#include <map>
#include <memory>
#include "webrtc/call/audio_state.h"
@@ -141,6 +142,11 @@
new testing::NiceMock<test::MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory));
+ EXPECT_CALL(*channel_proxy, SetReceiveCodecs(testing::_))
+ .WillRepeatedly(testing::Invoke(
+ [](const std::map<int, SdpAudioFormat>& codecs) {
+ EXPECT_THAT(codecs, testing::IsEmpty());
+ }));
// If being called for the send channel, save a pointer to the channel
// proxy for later.
if (channel_id == kRecvChannelId) {
@@ -188,6 +194,11 @@
new testing::NiceMock<test::MockVoEChannelProxy>();
EXPECT_CALL(*channel_proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory));
+ EXPECT_CALL(*channel_proxy, SetReceiveCodecs(testing::_))
+ .WillRepeatedly(testing::Invoke(
+ [](const std::map<int, SdpAudioFormat>& codecs) {
+ EXPECT_THAT(codecs, testing::IsEmpty());
+ }));
// If being called for the send channel, save a pointer to the channel
// proxy for later.
if (channel_id == kRecvChannelId) {
diff --git a/webrtc/media/engine/fakewebrtcvoiceengine.h b/webrtc/media/engine/fakewebrtcvoiceengine.h
index e7d95d0..180d06b 100644
--- a/webrtc/media/engine/fakewebrtcvoiceengine.h
+++ b/webrtc/media/engine/fakewebrtcvoiceengine.h
@@ -117,8 +117,6 @@
return -1;
}
Channel* ch = new Channel();
- auto db = webrtc::acm2::RentACodec::Database();
- ch->recv_codecs.assign(db.begin(), db.end());
ch->neteq_capacity = config.acm_config.neteq_config.max_packets_in_buffer;
ch->neteq_fast_accelerate =
config.acm_config.neteq_config.enable_fast_accelerate;
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 7c6d794..31a9d27 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -132,13 +132,6 @@
return ss.str();
}
-std::string ToString(const webrtc::CodecInst& codec) {
- std::stringstream ss;
- ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels
- << " (" << codec.pltype << ")";
- return ss.str();
-}
-
bool IsCodec(const AudioCodec& codec, const char* ref_name) {
return (_stricmp(codec.name.c_str(), ref_name) == 0);
}
@@ -1466,7 +1459,8 @@
const std::vector<webrtc::RtpExtension>& extensions,
webrtc::Call* call,
webrtc::Transport* rtcp_send_transport,
- const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory)
+ const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
+ const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
: call_(call), config_() {
RTC_DCHECK_GE(ch, 0);
RTC_DCHECK(call);
@@ -1479,6 +1473,7 @@
config_.voe_channel_id = ch;
config_.sync_group = sync_group;
config_.decoder_factory = decoder_factory;
+ config_.decoder_map = decoder_map;
RecreateAudioReceiveStream();
}
@@ -1867,8 +1862,9 @@
ChangePlayout(false);
}
+ decoder_map_ = std::move(decoder_map);
for (auto& kv : recv_streams_) {
- kv.second->RecreateAudioReceiveStream(decoder_map);
+ kv.second->RecreateAudioReceiveStream(decoder_map_);
}
recv_codecs_ = codecs;
@@ -2225,38 +2221,12 @@
return false;
}
- // Turn off all supported codecs.
- // 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 = {0};
- if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
- voe_codec.pltype = codec.id;
- if (engine()->voe()->codec()->SetRecPayloadType(
- channel, voe_codec) == -1) {
- LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
- DeleteVoEChannel(channel);
- return false;
- }
- }
- }
-
recv_streams_.insert(std::make_pair(
- ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
- recv_transport_cc_enabled_,
- recv_nack_enabled_,
- sp.sync_label, recv_rtp_extensions_,
- call_, this,
- engine()->decoder_factory_)));
+ ssrc,
+ new WebRtcAudioReceiveStream(
+ channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
+ recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
+ engine()->decoder_factory_, decoder_map_)));
recv_streams_[ssrc]->SetPlayout(playout_);
return true;
diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h
index c777c6c..64f7afa 100644
--- a/webrtc/media/engine/webrtcvoiceengine.h
+++ b/webrtc/media/engine/webrtcvoiceengine.h
@@ -251,7 +251,12 @@
WebRtcVoiceEngine* const engine_ = nullptr;
std::vector<AudioCodec> send_codecs_;
+
+ // TODO(kwiberg): decoder_map_ and recv_codecs_ store the exact same
+ // information, in slightly different formats. Eliminate recv_codecs_.
+ std::map<int, webrtc::SdpAudioFormat> decoder_map_;
std::vector<AudioCodec> recv_codecs_;
+
int max_send_bitrate_bps_ = 0;
AudioOptions options_;
rtc::Optional<int> dtmf_payload_type_;
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index 2d41ecd..3777b3d 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -31,6 +31,7 @@
#include "webrtc/test/gtest.h"
#include "webrtc/voice_engine/transmit_mixer.h"
+using testing::ContainerEq;
using testing::Return;
using testing::StrictMock;
@@ -795,26 +796,12 @@
parameters.codecs[2].id = 126;
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num = voe_.GetLastChannel();
-
- webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
- gcodec.plfreq = 16000;
- gcodec.channels = 1;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
- EXPECT_EQ(106, gcodec.pltype);
- EXPECT_STREQ("ISAC", gcodec.plname);
-
- rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "telephone-event");
- gcodec.plfreq = 8000;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
- EXPECT_EQ(126, gcodec.pltype);
- EXPECT_STREQ("telephone-event", gcodec.plname);
-
- gcodec.plfreq = 32000;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, gcodec));
- EXPECT_EQ(107, gcodec.pltype);
- EXPECT_STREQ("telephone-event", gcodec.plname);
+ EXPECT_THAT(GetRecvStreamConfig(kSsrcX).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}},
+ {106, {"ISAC", 16000, 1}},
+ {126, {"telephone-event", 8000, 1}},
+ {107, {"telephone-event", 32000, 1}}})));
}
// Test that we fail to set an unknown inbound codec.
@@ -845,16 +832,11 @@
parameters.codecs.push_back(kOpusCodec);
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num = voe_.GetLastChannel();
- webrtc::CodecInst 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);
- EXPECT_STREQ("opus", opus.plname);
- opus.pltype = 0;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num, opus));
- EXPECT_EQ(111, opus.pltype);
+ EXPECT_THAT(GetRecvStreamConfig(kSsrcX).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}},
+ {103, {"ISAC", 16000, 1}},
+ {111, {"opus", 48000, 2}}})));
}
// Test that we can decode OPUS with stereo = 0.
@@ -867,16 +849,11 @@
parameters.codecs[2].params["stereo"] = "0";
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num2 = voe_.GetLastChannel();
- webrtc::CodecInst 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);
- EXPECT_STREQ("opus", opus.plname);
- opus.pltype = 0;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, opus));
- EXPECT_EQ(111, opus.pltype);
+ EXPECT_THAT(GetRecvStreamConfig(kSsrcX).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}},
+ {103, {"ISAC", 16000, 1}},
+ {111, {"opus", 48000, 2, {{"stereo", "0"}}}}})));
}
// Test that we can decode OPUS with stereo = 1.
@@ -889,15 +866,11 @@
parameters.codecs[2].params["stereo"] = "1";
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num2 = voe_.GetLastChannel();
- webrtc::CodecInst opus;
- cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
- EXPECT_EQ(2, opus.channels);
- EXPECT_EQ(111, opus.pltype);
- EXPECT_STREQ("opus", opus.plname);
- opus.pltype = 0;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, opus));
- EXPECT_EQ(111, opus.pltype);
+ EXPECT_THAT(GetRecvStreamConfig(kSsrcX).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}},
+ {103, {"ISAC", 16000, 1}},
+ {111, {"opus", 48000, 2, {{"stereo", "1"}}}}})));
}
// Test that changes to recv codecs are applied to all streams.
@@ -911,28 +884,15 @@
parameters.codecs[0].id = 106; // collide with existing CN 32k
parameters.codecs[2].id = 126;
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
- EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num2 = voe_.GetLastChannel();
-
- webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
- gcodec.plfreq = 16000;
- gcodec.channels = 1;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
- EXPECT_EQ(106, gcodec.pltype);
- EXPECT_STREQ("ISAC", gcodec.plname);
-
- rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "telephone-event");
- gcodec.plfreq = 8000;
- gcodec.channels = 1;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
- EXPECT_EQ(126, gcodec.pltype);
- EXPECT_STREQ("telephone-event", gcodec.plname);
-
- gcodec.plfreq = 32000;
- EXPECT_EQ(0, voe_.GetRecPayloadType(channel_num2, gcodec));
- EXPECT_EQ(107, gcodec.pltype);
- EXPECT_STREQ("telephone-event", gcodec.plname);
+ for (const auto& ssrc : {kSsrcX, kSsrcY}) {
+ EXPECT_TRUE(AddRecvStream(ssrc));
+ EXPECT_THAT(GetRecvStreamConfig(ssrc).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}},
+ {106, {"ISAC", 16000, 1}},
+ {126, {"telephone-event", 8000, 1}},
+ {107, {"telephone-event", 32000, 1}}})));
+ }
}
TEST_F(WebRtcVoiceEngineTestFake, SetRecvCodecsAfterAddingStreams) {
@@ -2961,12 +2921,9 @@
parameters.codecs.push_back(kPcmuCodec);
EXPECT_TRUE(channel_->SetRecvParameters(parameters));
EXPECT_TRUE(AddRecvStream(kSsrcX));
- int channel_num2 = voe_.GetLastChannel();
- webrtc::CodecInst gcodec;
- rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "opus");
- gcodec.plfreq = 48000;
- gcodec.channels = 2;
- EXPECT_EQ(-1, voe_.GetRecPayloadType(channel_num2, gcodec));
+ EXPECT_THAT(GetRecvStreamConfig(kSsrcX).decoder_map,
+ (ContainerEq<std::map<int, webrtc::SdpAudioFormat>>(
+ {{0, {"PCMU", 8000, 1}}, {103, {"ISAC", 16000, 1}}})));
}
// Test that we properly clean up any streams that were added, even if
diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
index 21dbc74..4980d27 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc
@@ -179,6 +179,10 @@
return 0;
}
+void AcmReceiver::SetCodecs(const std::map<int, SdpAudioFormat>& codecs) {
+ neteq_->SetCodecs(codecs);
+}
+
int32_t AcmReceiver::AddCodec(int acm_codec_id,
uint8_t payload_type,
size_t channels,
diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.h b/webrtc/modules/audio_coding/acm2/acm_receiver.h
index 63ed43d..8f0963f 100644
--- a/webrtc/modules/audio_coding/acm2/acm_receiver.h
+++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h
@@ -79,6 +79,9 @@
//
int GetAudio(int desired_freq_hz, AudioFrame* audio_frame, bool* muted);
+ // Replace the current set of decoders with the specified set.
+ void SetCodecs(const std::map<int, SdpAudioFormat>& codecs);
+
//
// Adds a new codec to the NetEq codec database.
//
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
index daeea35..bc814f6 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
@@ -121,6 +121,8 @@
// Get current playout frequency.
int PlayoutFrequency() const override;
+ void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
+
bool RegisterReceiveCodec(int rtp_payload_type,
const SdpAudioFormat& audio_format) override;
@@ -318,16 +320,6 @@
webrtc::AudioEncoder::CodecType::kMaxLoggedAudioCodecTypes));
}
-// TODO(turajs): the same functionality is used in NetEq. If both classes
-// need them, make it a static function in ACMCodecDB.
-bool IsCodecRED(const CodecInst& codec) {
- return (STR_CASE_CMP(codec.plname, "RED") == 0);
-}
-
-bool IsCodecCN(const CodecInst& codec) {
- return (STR_CASE_CMP(codec.plname, "CN") == 0);
-}
-
// Stereo-to-mono can be used as in-place.
int DownMix(const AudioFrame& frame,
size_t length_out_buff,
@@ -956,19 +948,6 @@
receiver_.SetMaximumDelay(0);
receiver_.FlushBuffers();
- // Register RED and CN.
- auto db = acm2::RentACodec::Database();
- for (size_t i = 0; i < db.size(); i++) {
- if (IsCodecRED(db[i]) || IsCodecCN(db[i])) {
- if (receiver_.AddCodec(static_cast<int>(i),
- static_cast<uint8_t>(db[i].pltype), 1,
- db[i].plfreq, nullptr, db[i].plname) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot register master codec.");
- return -1;
- }
- }
- }
receiver_initialized_ = true;
return 0;
}
@@ -987,6 +966,12 @@
return receiver_.last_output_sample_rate_hz();
}
+void AudioCodingModuleImpl::SetReceiveCodecs(
+ const std::map<int, SdpAudioFormat>& codecs) {
+ rtc::CritScope lock(&acm_crit_sect_);
+ receiver_.SetCodecs(codecs);
+}
+
bool AudioCodingModuleImpl::RegisterReceiveCodec(
int rtp_payload_type,
const SdpAudioFormat& audio_format) {
diff --git a/webrtc/modules/audio_coding/include/audio_coding_module.h b/webrtc/modules/audio_coding/include/audio_coding_module.h
index 1893b62..b5cbff2 100644
--- a/webrtc/modules/audio_coding/include/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/include/audio_coding_module.h
@@ -485,6 +485,10 @@
//
virtual int32_t PlayoutFrequency() const = 0;
+ // Replace any existing decoders with the given payload type -> decoder map.
+ virtual void SetReceiveCodecs(
+ const std::map<int, SdpAudioFormat>& codecs) = 0;
+
// Registers a decoder for the given payload type. Returns true iff
// successful.
virtual bool RegisterReceiveCodec(int rtp_payload_type,
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc
index d147d67..8cd4386 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.cc
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc
@@ -123,6 +123,38 @@
active_cng_decoder_type_ = -1;
}
+std::vector<int> DecoderDatabase::SetCodecs(
+ const std::map<int, SdpAudioFormat>& codecs) {
+ // First collect all payload types that we'll remove or reassign, then remove
+ // them from the database.
+ std::vector<int> changed_payload_types;
+ for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
+ auto i = codecs.find(kv.first);
+ if (i == codecs.end() || i->second != kv.second.GetFormat()) {
+ changed_payload_types.push_back(kv.first);
+ }
+ }
+ for (int pl_type : changed_payload_types) {
+ Remove(pl_type);
+ }
+
+ // Enter the new and changed payload type mappings into the database.
+ for (const auto& kv : codecs) {
+ const int& rtp_payload_type = kv.first;
+ const SdpAudioFormat& audio_format = kv.second;
+ RTC_DCHECK_GE(rtp_payload_type, 0);
+ RTC_DCHECK_LE(rtp_payload_type, 0x7f);
+ if (decoders_.count(rtp_payload_type) == 0) {
+ decoders_.insert(std::make_pair(
+ rtp_payload_type, DecoderInfo(audio_format, decoder_factory_.get())));
+ } else {
+ // The mapping for this payload type hasn't changed.
+ }
+ }
+
+ return changed_payload_types;
+}
+
int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
NetEqDecoder codec_type,
const std::string& name) {
diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h
index ec470f8..35d1d0d 100644
--- a/webrtc/modules/audio_coding/neteq/decoder_database.h
+++ b/webrtc/modules/audio_coding/neteq/decoder_database.h
@@ -149,6 +149,11 @@
// using InsertExternal().
virtual void Reset();
+ // Replaces the existing set of decoders with the given set. Returns the
+ // payload types that were reassigned or removed while doing so.
+ virtual std::vector<int> SetCodecs(
+ const std::map<int, SdpAudioFormat>& codecs);
+
// Registers |rtp_payload_type| as a decoder of type |codec_type|. The |name|
// is only used to populate the name field in the DecoderInfo struct in the
// database, and can be arbitrary (including empty). Returns kOK on success;
diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h
index ea05940..450318e 100644
--- a/webrtc/modules/audio_coding/neteq/include/neteq.h
+++ b/webrtc/modules/audio_coding/neteq/include/neteq.h
@@ -157,6 +157,9 @@
// Returns kOK on success, or kFail in case of an error.
virtual int GetAudio(AudioFrame* audio_frame, bool* muted) = 0;
+ // Replaces the current set of decoders with the given one.
+ virtual void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) = 0;
+
// Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the
// information in the codec database. Returns 0 on success, -1 on failure.
// The name is only used to provide information back to the caller about the
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
index 5015b7e..501e567 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -212,6 +212,15 @@
return kOK;
}
+void NetEqImpl::SetCodecs(const std::map<int, SdpAudioFormat>& codecs) {
+ rtc::CritScope lock(&crit_sect_);
+ const std::vector<int> changed_payload_types =
+ decoder_database_->SetCodecs(codecs);
+ for (const int pt : changed_payload_types) {
+ packet_buffer_->DiscardPacketsWithPayloadType(pt);
+ }
+}
+
int NetEqImpl::RegisterPayloadType(NetEqDecoder codec,
const std::string& name,
uint8_t rtp_payload_type) {
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h
index a8c3462..88c0308 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.h
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h
@@ -111,6 +111,8 @@
int GetAudio(AudioFrame* audio_frame, bool* muted) override;
+ void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
+
int RegisterPayloadType(NetEqDecoder codec,
const std::string& codec_name,
uint8_t rtp_payload_type) override;
diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn
index 541edd9..c1d69e0 100644
--- a/webrtc/modules/rtp_rtcp/BUILD.gn
+++ b/webrtc/modules/rtp_rtcp/BUILD.gn
@@ -168,6 +168,7 @@
deps = [
"../..:webrtc_common",
"../../api:transport_api",
+ "../../api/audio_codecs:audio_codecs_api",
"../../base:gtest_prod",
"../../base:rtc_base_approved",
"../../base:rtc_task_queue",
@@ -175,6 +176,7 @@
"../../common_video",
"../../logging:rtc_event_log_api",
"../../system_wrappers",
+ "../audio_coding:audio_format_conversion",
"../remote_bitrate_estimator",
]
diff --git a/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h b/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h
index 767bd07..029de5d 100644
--- a/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h
+++ b/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h
@@ -15,6 +15,7 @@
#include <memory>
#include <set>
+#include "webrtc/api/audio_codecs/audio_format.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/deprecation.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
@@ -43,6 +44,10 @@
// TODO(magjed): Split RTPPayloadRegistry into separate Audio and Video class
// and simplify the code. http://crbug/webrtc/6743.
+
+ // Replace all audio receive payload types with the given map.
+ void SetAudioReceivePayloads(std::map<int, SdpAudioFormat> codecs);
+
int32_t RegisterReceivePayload(const CodecInst& audio_codec,
bool* created_new_payload_type);
int32_t RegisterReceivePayload(const VideoCodec& video_codec);
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
index 1023bf8..234fd7f 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -16,6 +16,7 @@
#include "webrtc/base/logging.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/codecs/audio_format_conversion.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
namespace webrtc {
@@ -119,6 +120,31 @@
RTPPayloadRegistry::~RTPPayloadRegistry() = default;
+void RTPPayloadRegistry::SetAudioReceivePayloads(
+ std::map<int, SdpAudioFormat> codecs) {
+ rtc::CritScope cs(&crit_sect_);
+
+#if RTC_DCHECK_IS_ON
+ RTC_DCHECK(!used_for_video_);
+ used_for_audio_ = true;
+#endif
+
+ payload_type_map_.clear();
+ for (const auto& kv : codecs) {
+ const int& rtp_payload_type = kv.first;
+ const SdpAudioFormat& audio_format = kv.second;
+ const CodecInst ci = SdpToCodecInst(rtp_payload_type, audio_format);
+ RTC_DCHECK(IsPayloadTypeValid(rtp_payload_type));
+ payload_type_map_.insert(
+ std::make_pair(rtp_payload_type, CreatePayloadType(ci)));
+ }
+
+ // Clear the value of last received payload type since it might mean
+ // something else now.
+ last_received_payload_type_ = -1;
+ last_received_media_payload_type_ = -1;
+}
+
int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
bool* created_new_payload) {
rtc::CritScope cs(&crit_sect_);
diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h
index d704e19..450dd7b 100644
--- a/webrtc/test/mock_voe_channel_proxy.h
+++ b/webrtc/test/mock_voe_channel_proxy.h
@@ -87,6 +87,8 @@
MOCK_METHOD1(SetSendCodec, bool(const CodecInst& codec_inst));
MOCK_METHOD2(SetSendCNPayloadType,
bool(int type, PayloadFrequencies frequency));
+ MOCK_METHOD1(SetReceiveCodecs,
+ void(const std::map<int, SdpAudioFormat>& codecs));
MOCK_METHOD1(OnTwccBasedUplinkPacketLossRate, void(float packet_loss_rate));
MOCK_METHOD1(OnRecoverableUplinkPacketLossRate,
void(float recoverable_packet_loss_rate));
diff --git a/webrtc/test/mock_voice_engine.h b/webrtc/test/mock_voice_engine.h
index ca3fe4f..6b1f9cf 100644
--- a/webrtc/test/mock_voice_engine.h
+++ b/webrtc/test/mock_voice_engine.h
@@ -52,6 +52,11 @@
new testing::NiceMock<webrtc::test::MockVoEChannelProxy>();
EXPECT_CALL(*proxy, GetAudioDecoderFactory())
.WillRepeatedly(testing::ReturnRef(decoder_factory_));
+ EXPECT_CALL(*proxy, SetReceiveCodecs(testing::_))
+ .WillRepeatedly(testing::Invoke(
+ [](const std::map<int, SdpAudioFormat>& codecs) {
+ EXPECT_THAT(codecs, testing::IsEmpty());
+ }));
return proxy;
}));
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index d2b30ca..3b562f9 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -987,9 +987,10 @@
return -1;
}
- // --- Register all supported codecs to the receiving side of the
- // RTP/RTCP module
+ return 0;
+}
+void Channel::RegisterLegacyCodecs() {
CodecInst codec;
const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
@@ -1041,8 +1042,6 @@
}
}
}
-
- return 0;
}
void Channel::Terminate() {
@@ -1360,6 +1359,11 @@
return 0;
}
+void Channel::SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) {
+ rtp_payload_registry_->SetAudioReceivePayloads(codecs);
+ audio_coding_->SetReceiveCodecs(codecs);
+}
+
int32_t Channel::SetRecPayloadType(const CodecInst& codec) {
return SetRecPayloadType(codec.pltype, CodecInstToSdp(codec));
}
diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h
index 0a12f21..1365ae8 100644
--- a/webrtc/voice_engine/channel.h
+++ b/webrtc/voice_engine/channel.h
@@ -151,6 +151,7 @@
uint32_t instanceId,
const VoEBase::ChannelConfig& config);
int32_t Init();
+ void RegisterLegacyCodecs();
void Terminate();
int32_t SetEngineInformation(Statistics& engineStatistics,
OutputMixer& outputMixer,
@@ -168,6 +169,8 @@
// go.
const rtc::scoped_refptr<AudioDecoderFactory>& GetAudioDecoderFactory() const;
+ void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
+
// API methods
// VoEBase
diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc
index 45cbf10..d67011e 100644
--- a/webrtc/voice_engine/channel_proxy.cc
+++ b/webrtc/voice_engine/channel_proxy.cc
@@ -173,6 +173,12 @@
RTC_DCHECK_EQ(0, result);
}
+void ChannelProxy::SetReceiveCodecs(
+ const std::map<int, SdpAudioFormat>& codecs) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ channel()->SetReceiveCodecs(codecs);
+}
+
void ChannelProxy::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
channel()->SetSink(std::move(sink));
@@ -379,6 +385,11 @@
channel()->OnRecoverableUplinkPacketLossRate(recoverable_packet_loss_rate);
}
+void ChannelProxy::RegisterLegacyCodecs() {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ channel()->RegisterLegacyCodecs();
+}
+
Channel* ChannelProxy::channel() const {
RTC_DCHECK(channel_owner_.channel());
return channel_owner_.channel();
diff --git a/webrtc/voice_engine/channel_proxy.h b/webrtc/voice_engine/channel_proxy.h
index 685a168..b808096 100644
--- a/webrtc/voice_engine/channel_proxy.h
+++ b/webrtc/voice_engine/channel_proxy.h
@@ -82,6 +82,7 @@
virtual void SetBitrate(int bitrate_bps, int64_t probing_interval_ms);
virtual void SetRecPayloadType(int payload_type,
const SdpAudioFormat& format);
+ virtual void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
virtual void SetSink(std::unique_ptr<AudioSinkInterface> sink);
virtual void SetInputMute(bool muted);
virtual void RegisterExternalTransport(Transport* transport);
@@ -119,6 +120,7 @@
virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate);
virtual void OnRecoverableUplinkPacketLossRate(
float recoverable_packet_loss_rate);
+ virtual void RegisterLegacyCodecs();
private:
Channel* channel() const;
diff --git a/webrtc/voice_engine/test/auto_test/fakes/conference_transport.cc b/webrtc/voice_engine/test/auto_test/fakes/conference_transport.cc
index b15d72f..f1eee9c 100644
--- a/webrtc/voice_engine/test/auto_test/fakes/conference_transport.cc
+++ b/webrtc/voice_engine/test/auto_test/fakes/conference_transport.cc
@@ -15,6 +15,8 @@
#include "webrtc/base/byteorder.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/system_wrappers/include/sleep.h"
+#include "webrtc/voice_engine/channel_proxy.h"
+#include "webrtc/voice_engine/voice_engine_impl.h"
namespace {
static const unsigned int kReflectorSsrc = 0x0000;
@@ -62,6 +64,9 @@
EXPECT_EQ(0, local_base_->Init());
local_sender_ = local_base_->CreateChannel();
+ static_cast<webrtc::VoiceEngineImpl*>(local_voe_)
+ ->GetChannelProxy(local_sender_)
+ ->RegisterLegacyCodecs();
EXPECT_EQ(0, local_network_->RegisterExternalTransport(local_sender_, *this));
EXPECT_EQ(0, local_rtp_rtcp_->SetLocalSSRC(local_sender_, kLocalSsrc));
EXPECT_EQ(0, local_rtp_rtcp_->
@@ -72,6 +77,9 @@
EXPECT_EQ(0, remote_base_->Init());
reflector_ = remote_base_->CreateChannel();
+ static_cast<webrtc::VoiceEngineImpl*>(remote_voe_)
+ ->GetChannelProxy(reflector_)
+ ->RegisterLegacyCodecs();
EXPECT_EQ(0, remote_network_->RegisterExternalTransport(reflector_, *this));
EXPECT_EQ(0, remote_rtp_rtcp_->SetLocalSSRC(reflector_, kReflectorSsrc));
@@ -222,6 +230,9 @@
unsigned int ConferenceTransport::AddStream(std::string file_name,
webrtc::FileFormats format) {
const int new_sender = remote_base_->CreateChannel();
+ static_cast<webrtc::VoiceEngineImpl*>(remote_voe_)
+ ->GetChannelProxy(new_sender)
+ ->RegisterLegacyCodecs();
EXPECT_EQ(0, remote_network_->RegisterExternalTransport(new_sender, *this));
const unsigned int remote_ssrc = kFirstRemoteSsrc + stream_count_++;
@@ -235,6 +246,9 @@
new_sender, file_name.c_str(), true, false, format, 1.0));
const int new_receiver = local_base_->CreateChannel();
+ static_cast<webrtc::VoiceEngineImpl*>(local_voe_)
+ ->GetChannelProxy(new_receiver)
+ ->RegisterLegacyCodecs();
EXPECT_EQ(0, local_base_->AssociateSendChannel(new_receiver, local_sender_));
EXPECT_EQ(0, local_network_->RegisterExternalTransport(new_receiver, *this));
diff --git a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc
index 0fbe635..5582124 100644
--- a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc
+++ b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc
@@ -16,5 +16,6 @@
webrtc::VoiceEngineImpl* voe_impl =
static_cast<webrtc::VoiceEngineImpl*>(voice_engine_);
channel_proxy_ = voe_impl->GetChannelProxy(channel_);
+ channel_proxy_->RegisterLegacyCodecs();
ResumePlaying();
}
diff --git a/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc b/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc
index a733b12..d9a5e2b 100644
--- a/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc
+++ b/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc
@@ -8,7 +8,9 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include "webrtc/voice_engine/channel_proxy.h"
#include "webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h"
+#include "webrtc/voice_engine/voice_engine_impl.h"
class CodecBeforeStreamingTest : public AfterInitializationFixture {
protected:
@@ -19,6 +21,9 @@
codec_instance_.pacsize = 480;
channel_ = voe_base_->CreateChannel();
+ static_cast<webrtc::VoiceEngineImpl*>(voice_engine_)
+ ->GetChannelProxy(channel_)
+ ->RegisterLegacyCodecs();
}
void TearDown() {