Index: talk/media/webrtc/webrtcvideoengine2.cc |
diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc |
index a3f8b8e7acc75fa6d76b7398595ffdfc6673c827..05cd6bbcf1a582380d1c35b5aeb3dbdfb98f2b31 100644 |
--- a/talk/media/webrtc/webrtcvideoengine2.cc |
+++ b/talk/media/webrtc/webrtcvideoengine2.cc |
@@ -856,6 +856,39 @@ WebRtcVideoChannel2::FilterSupportedCodecs( |
return supported_codecs; |
} |
+bool WebRtcVideoChannel2::ReceiveCodecsHaveChanged( |
+ std::vector<VideoCodecSettings> before, |
+ std::vector<VideoCodecSettings> after) { |
+ if (before.size() != after.size()) { |
+ return true; |
+ } |
+ // The receive codec order doesn't matter, so we sort the codecs before |
+ // comparing. This is necessary because currently the |
+ // only way to change the send codec is to munge SDP, which causes |
+ // the receive codec list to change order, which causes the streams |
+ // to be recreates which causes a "blink" of black video. In order |
+ // to support munging the SDP in this way without recreating receive |
+ // streams, we ignore the order of the received codecs so that |
+ // changing the order doesn't cause this "blink". |
+ auto comparison = |
+ [](const VideoCodecSettings& codec1, const VideoCodecSettings& codec2) { |
+ return codec1.codec.id > codec2.codec.id; |
+ }; |
+ std::sort(before.begin(), before.end(), comparison); |
+ std::sort(after.begin(), after.end(), comparison); |
+ for (size_t i = 0; i < before.size(); ++i) { |
+ // For the same reason that we sort the codecs, we also ignore the |
+ // preference. We don't want a preference change on the receive |
+ // side to cause recreation of the stream. |
+ before[i].codec.preference = 0; |
+ after[i].codec.preference = 0; |
+ if (before[i] != after[i]) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { |
// TODO(pbos): Refactor this to only recreate the send streams once |
// instead of 4 times. |
@@ -872,6 +905,20 @@ bool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) { |
SetRecvRtpHeaderExtensions(params.extensions)); |
} |
+std::string WebRtcVideoChannel2::CodecSettingsVectorToString( |
+ const std::vector<VideoCodecSettings>& codecs) { |
+ std::stringstream out; |
+ out << '{'; |
+ for (size_t i = 0; i < codecs.size(); ++i) { |
+ out << codecs[i].codec.ToString(); |
+ if (i != codecs.size() - 1) { |
+ out << ", "; |
+ } |
+ } |
+ out << '}'; |
+ return out.str(); |
+} |
+ |
bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { |
TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvCodecs"); |
LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs); |
@@ -885,7 +932,7 @@ bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { |
return false; |
} |
- const std::vector<VideoCodecSettings> supported_codecs = |
+ std::vector<VideoCodecSettings> supported_codecs = |
FilterSupportedCodecs(mapped_codecs); |
if (mapped_codecs.size() != supported_codecs.size()) { |
@@ -894,18 +941,15 @@ bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { |
} |
// Prevent reconfiguration when setting identical receive codecs. |
- if (recv_codecs_.size() == supported_codecs.size()) { |
- bool reconfigured = false; |
- for (size_t i = 0; i < supported_codecs.size(); ++i) { |
- if (recv_codecs_[i] != supported_codecs[i]) { |
- reconfigured = true; |
- break; |
- } |
- } |
- if (!reconfigured) |
- return true; |
+ if (!ReceiveCodecsHaveChanged(recv_codecs_, supported_codecs)) { |
+ LOG(LS_INFO) |
+ << "Ignoring call to SetRecvCodecs because codecs haven't changed."; |
+ return true; |
} |
+ LOG(LS_INFO) << "Changing recv codecs from " |
+ << CodecSettingsVectorToString(recv_codecs_) << " to " |
+ << CodecSettingsVectorToString(supported_codecs); |
recv_codecs_ = supported_codecs; |
tommi
2015/08/24 17:05:37
nit: swap()? :)
|
rtc::CritScope stream_lock(&stream_crit_); |
@@ -938,6 +982,8 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { |
VideoCodecSettings old_codec; |
if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) { |
+ LOG(LS_INFO) << "Ignore call to SetSendCodecs because first supported " |
+ "codec hasn't changed."; |
// Using same codec, avoid reconfiguring. |
return true; |
} |
@@ -945,10 +991,14 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { |
send_codec_.Set(supported_codecs.front()); |
rtc::CritScope stream_lock(&stream_crit_); |
+ LOG(LS_INFO) << "Change the send codec because SetSendCodecs has a different " |
+ "first supported codec."; |
for (auto& kv : send_streams_) { |
DCHECK(kv.second != nullptr); |
kv.second->SetCodec(supported_codecs.front()); |
} |
+ LOG(LS_INFO) << "SetNackAndRemb on all the receive streams because the send " |
+ "codec has changed."; |
for (auto& kv : receive_streams_) { |
DCHECK(kv.second != nullptr); |
kv.second->SetNackAndRemb(HasNack(supported_codecs.front().codec), |
@@ -1076,6 +1126,8 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { |
if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) { |
rtcp_receiver_report_ssrc_ = ssrc; |
+ LOG(LS_INFO) << "SetLocalSsrc on all the receive streams because we added " |
+ "a send stream."; |
for (auto& kv : receive_streams_) |
kv.second->SetLocalSsrc(ssrc); |
} |
@@ -1465,8 +1517,11 @@ bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( |
std::vector<webrtc::RtpExtension> filtered_extensions = |
FilterRtpExtensions(extensions); |
- if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) |
+ if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) { |
+ LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because " |
+ "header extensions haven't changed."; |
return true; |
+ } |
recv_rtp_extensions_ = filtered_extensions; |
@@ -1490,8 +1545,11 @@ bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( |
std::vector<webrtc::RtpExtension> filtered_extensions = |
FilterRtpExtensions(extensions); |
- if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) |
+ if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) { |
+ LOG(LS_INFO) << "Ignoring call to SetSendRtpHeaderExtensions because " |
+ "header extensions haven't changed."; |
return true; |
+ } |
send_rtp_extensions_ = filtered_extensions; |
@@ -1880,6 +1938,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions( |
rtc::CritScope cs(&lock_); |
VideoCodecSettings codec_settings; |
if (parameters_.codec_settings.Get(&codec_settings)) { |
+ LOG(LS_INFO) << "SetCodecAndOptions because of SetOptions; options=" |
+ << options.ToString(); |
SetCodecAndOptions(codec_settings, options); |
} else { |
parameters_.options = options; |
@@ -1889,6 +1949,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions( |
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( |
const VideoCodecSettings& codec_settings) { |
rtc::CritScope cs(&lock_); |
+ LOG(LS_INFO) << "SetCodecAndOptions because of SetCodec."; |
SetCodecAndOptions(codec_settings, parameters_.options); |
} |
@@ -1985,6 +2046,9 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions( |
parameters_.codec_settings.Set(codec_settings); |
parameters_.options = options; |
+ LOG(LS_INFO) |
+ << "RecreateWebRtcStream (send) because of SetCodecAndOptions; options=" |
+ << options.ToString(); |
RecreateWebRtcStream(); |
if (allocated_encoder_.encoder != new_encoder.encoder) { |
DestroyVideoEncoder(&allocated_encoder_); |
@@ -1996,8 +2060,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( |
const std::vector<webrtc::RtpExtension>& rtp_extensions) { |
rtc::CritScope cs(&lock_); |
parameters_.config.rtp.extensions = rtp_extensions; |
- if (stream_ != nullptr) |
+ if (stream_ != nullptr) { |
+ LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetRtpExtensions"; |
RecreateWebRtcStream(); |
+ } |
} |
webrtc::VideoEncoderConfig |
@@ -2277,6 +2343,9 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
estimated_remote_start_ntp_time_ms_(0) { |
config_.renderer = this; |
// SetRecvCodecs will also reset (start) the VideoReceiveStream. |
+ LOG(LS_INFO) << "SetRecvCodecs (recv) because we are creating the receive " |
+ "stream for the first time: " |
+ << CodecSettingsVectorToString(recv_codecs); |
SetRecvCodecs(recv_codecs); |
} |
@@ -2372,6 +2441,8 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs( |
HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; |
ClearDecoders(&old_decoders); |
+ LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvCodecs: " |
+ << CodecSettingsVectorToString(recv_codecs); |
RecreateWebRtcStream(); |
} |
@@ -2381,10 +2452,16 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc( |
// not be able to create a sender with the same SSRC as a receiver, but right |
// now this can't be done due to unittests depending on receiving what they |
// are sending from the same MediaChannel. |
- if (local_ssrc == config_.rtp.remote_ssrc) |
+ if (local_ssrc == config_.rtp.remote_ssrc) { |
+ LOG(LS_INFO) << "Ignoring call to SetLocalSsrc because parameters are " |
+ "unchanged; local_ssrc=" << local_ssrc; |
return; |
+ } |
config_.rtp.local_ssrc = local_ssrc; |
+ LOG(LS_INFO) |
+ << "RecreateWebRtcStream (recv) because of SetLocalSsrc; local_ssrc=" |
+ << local_ssrc; |
RecreateWebRtcStream(); |
} |
@@ -2393,16 +2470,22 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetNackAndRemb( |
int nack_history_ms = nack_enabled ? kNackHistoryMs : 0; |
if (config_.rtp.nack.rtp_history_ms == nack_history_ms && |
config_.rtp.remb == remb_enabled) { |
+ LOG(LS_INFO) << "Ignoring call to SetNackAndRemb because parameters are " |
+ "unchanged; nack=" << nack_enabled |
+ << ", remb=" << remb_enabled; |
return; |
} |
config_.rtp.remb = remb_enabled; |
config_.rtp.nack.rtp_history_ms = nack_history_ms; |
+ LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetNackAndRemb; nack=" |
+ << nack_enabled << ", remb=" << remb_enabled; |
RecreateWebRtcStream(); |
} |
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions( |
const std::vector<webrtc::RtpExtension>& extensions) { |
config_.rtp.extensions = extensions; |
+ LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRtpExtensions"; |
RecreateWebRtcStream(); |
} |