Index: webrtc/media/engine/webrtcvoiceengine.cc |
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc |
index e6fa12e45e601280fa657fa44d07fb18907af8aa..c23084eed113a55a1729922fb7e9f20afbde8b38 100644 |
--- a/webrtc/media/engine/webrtcvoiceengine.cc |
+++ b/webrtc/media/engine/webrtcvoiceengine.cc |
@@ -1542,14 +1542,15 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
RTC_DCHECK_GE(ch, 0); |
RTC_DCHECK(call); |
config_.rtp.remote_ssrc = remote_ssrc; |
+ config_.rtp.local_ssrc = local_ssrc; |
+ config_.rtp.transport_cc = use_transport_cc; |
+ config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0; |
+ config_.rtp.extensions = extensions; |
config_.rtcp_send_transport = rtcp_send_transport; |
config_.voe_channel_id = ch; |
config_.sync_group = sync_group; |
config_.decoder_factory = decoder_factory; |
- RecreateAudioReceiveStream(local_ssrc, |
- use_transport_cc, |
- use_nack, |
- extensions); |
+ RecreateAudioReceiveStream(); |
} |
~WebRtcAudioReceiveStream() { |
@@ -1559,27 +1560,40 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
void RecreateAudioReceiveStream(uint32_t local_ssrc) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
- RecreateAudioReceiveStream(local_ssrc, |
- config_.rtp.transport_cc, |
- config_.rtp.nack.rtp_history_ms != 0, |
- config_.rtp.extensions); |
+ config_.rtp.local_ssrc = local_ssrc; |
+ RecreateAudioReceiveStream(); |
} |
void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
- RecreateAudioReceiveStream(config_.rtp.local_ssrc, |
- use_transport_cc, |
- use_nack, |
- config_.rtp.extensions); |
+ config_.rtp.transport_cc = use_transport_cc; |
+ config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0; |
+ RecreateAudioReceiveStream(); |
} |
void RecreateAudioReceiveStream( |
const std::vector<webrtc::RtpExtension>& extensions) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
- RecreateAudioReceiveStream(config_.rtp.local_ssrc, |
- config_.rtp.transport_cc, |
- config_.rtp.nack.rtp_history_ms != 0, |
- extensions); |
+ config_.rtp.extensions = extensions; |
+ RecreateAudioReceiveStream(); |
+ } |
+ |
+ // Set a new payload type -> decoder map. The new map must be a superset of |
+ // the old one. |
+ void RecreateAudioReceiveStream( |
+ const std::map<int, webrtc::SdpAudioFormat>& decoder_map) { |
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
+ RTC_DCHECK([&] { |
+ for (const auto& item : config_.decoder_map) { |
+ auto it = decoder_map.find(item.first); |
+ if (it == decoder_map.end() || *it != item) { |
+ return false; // The old map isn't a subset of the new map. |
+ } |
+ } |
+ return true; |
+ }()); |
+ config_.decoder_map = decoder_map; |
+ RecreateAudioReceiveStream(); |
} |
webrtc::AudioReceiveStream::Stats GetStats() const { |
@@ -1617,21 +1631,11 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
} |
private: |
- void RecreateAudioReceiveStream( |
- uint32_t local_ssrc, |
- bool use_transport_cc, |
- bool use_nack, |
- const std::vector<webrtc::RtpExtension>& extensions) { |
+ void RecreateAudioReceiveStream() { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
if (stream_) { |
call_->DestroyAudioReceiveStream(stream_); |
- stream_ = nullptr; |
} |
- config_.rtp.local_ssrc = local_ssrc; |
- config_.rtp.transport_cc = use_transport_cc; |
- config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0; |
- config_.rtp.extensions = extensions; |
- RTC_DCHECK(!stream_); |
stream_ = call_->CreateAudioReceiveStream(config_); |
RTC_CHECK(stream_); |
SetPlayout(playout_); |
@@ -1901,40 +1905,34 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs( |
return true; |
} |
+ // Create a payload type -> SdpAudioFormat map with all the decoders. Fail |
+ // unless the factory claims to support all decoders. |
+ std::map<int, webrtc::SdpAudioFormat> decoder_map; |
+ for (const AudioCodec& codec : codecs) { |
+ auto format = AudioCodecToSdpAudioFormat(codec); |
+ if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") && |
+ !engine()->decoder_factory_->IsSupportedDecoder(format)) { |
+ LOG(LS_ERROR) << "Unsupported codec: " << format; |
+ return false; |
+ } |
+ decoder_map.insert({codec.id, std::move(format)}); |
+ } |
+ |
if (playout_) { |
// Receive codecs can not be changed while playing. So we temporarily |
// pause playout. |
ChangePlayout(false); |
} |
- bool result = true; |
- for (const AudioCodec& codec : new_codecs) { |
- webrtc::CodecInst voe_codec = {0}; |
- 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; |
+ for (auto& kv : recv_streams_) { |
+ kv.second->RecreateAudioReceiveStream(decoder_map); |
} |
+ recv_codecs_ = codecs; |
if (desired_playout_ && !playout_) { |
ChangePlayout(desired_playout_); |
} |
- return result; |
+ return true; |
} |
// Utility function called from SetSendParameters() to extract current send |