diff options
author | pbos@webrtc.org <pbos@webrtc.org> | 2014-11-07 10:54:43 +0000 |
---|---|---|
committer | pbos@webrtc.org <pbos@webrtc.org> | 2014-11-07 10:54:43 +0000 |
commit | efe932275823d38966a45310eff7a60763f06ec1 (patch) | |
tree | 8fc4572c3fa2436b7a72fb28c355ae424d14f399 | |
parent | 2cc4257b28bcc0ab6bdd6f6f67ce4b79fb6c60e1 (diff) | |
download | talk-efe932275823d38966a45310eff7a60763f06ec1.tar.gz |
Prevent a lot of VideoSendStream reconfigures.
Checking whether we're setting the same configuration or not.
Experimentally this brings down underlying reconfigures from ~20 to
about 4-5.
R=stefan@webrtc.org
BUG=1788
Review URL: https://webrtc-codereview.appspot.com/30909004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/talk@7659 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r-- | media/webrtc/webrtcvideoengine2.cc | 129 | ||||
-rw-r--r-- | media/webrtc/webrtcvideoengine2.h | 19 |
2 files changed, 98 insertions, 50 deletions
diff --git a/media/webrtc/webrtcvideoengine2.cc b/media/webrtc/webrtcvideoengine2.cc index 8d53f17..5b5f12e 100644 --- a/media/webrtc/webrtcvideoengine2.cc +++ b/media/webrtc/webrtcvideoengine2.cc @@ -836,9 +836,16 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { return false; } - send_codec_.Set(supported_codecs.front()); LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString(); + VideoCodecSettings old_codec; + if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) { + // Using same codec, avoid reconfiguring. + return true; + } + + send_codec_.Set(supported_codecs.front()); + rtc::CritScope stream_lock(&stream_crit_); for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = send_streams_.begin(); @@ -1272,6 +1279,7 @@ bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( return false; send_rtp_extensions_ = FilterRtpExtensions(extensions); + rtc::CritScope stream_lock(&stream_crit_); for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = send_streams_.begin(); @@ -1289,8 +1297,13 @@ bool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) { } bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) { - LOG(LS_VERBOSE) << "SetOptions: " << options.ToString(); + LOG(LS_INFO) << "SetOptions: " << options.ToString(); + VideoOptions old_options = options_; options_.SetAll(options); + if (options_ == old_options) { + // No new options to set. + return true; + } rtc::CritScope stream_lock(&stream_crit_); for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = send_streams_.begin(); @@ -1502,13 +1515,16 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer( LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; webrtc::I420VideoFrame black_frame; + // TODO(pbos): Base width/height on last_dimensions_. This will however + // fail the test AddRemoveCapturer which needs to be fixed to permit + // sending black frames in the same size that was previously sent. int width = format_.width; int height = format_.height; int half_width = (width + 1) / 2; black_frame.CreateEmptyFrame( width, height, width, half_width, half_width); SetWebRtcFrameToBlack(&black_frame); - SetDimensions(width, height, false); + SetDimensions(width, height, last_dimensions_.is_screencast); stream_->Input()->SwapFrame(&black_frame); } @@ -1635,13 +1651,17 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions( const VideoCodecSettings& codec_settings, const VideoOptions& options) { - std::vector<webrtc::VideoStream> video_streams = - encoder_factory_->CreateVideoStreams( - codec_settings.codec, options, parameters_.config.rtp.ssrcs.size()); - if (video_streams.empty()) { + if (last_dimensions_.width == -1) { + last_dimensions_.width = codec_settings.codec.width; + last_dimensions_.height = codec_settings.codec.height; + last_dimensions_.is_screencast = false; + } + parameters_.encoder_config = + CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); + if (parameters_.encoder_config.streams.empty()) { return; } - parameters_.encoder_config.streams = video_streams; + format_ = VideoFormat(codec_settings.codec.width, codec_settings.codec.height, VideoFormat::FpsToInterval(30), @@ -1685,6 +1705,50 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( RecreateWebRtcStream(); } +webrtc::VideoEncoderConfig +WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( + const Dimensions& dimensions, + const VideoCodec& codec) const { + webrtc::VideoEncoderConfig encoder_config; + if (dimensions.is_screencast) { + int screencast_min_bitrate_kbps; + parameters_.options.screencast_min_bitrate.Get( + &screencast_min_bitrate_kbps); + encoder_config.min_transmit_bitrate_bps = + screencast_min_bitrate_kbps * 1000; + encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare; + } else { + encoder_config.min_transmit_bitrate_bps = 0; + encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo; + } + + // Restrict dimensions according to codec max. + int width = dimensions.width; + int height = dimensions.height; + if (!dimensions.is_screencast) { + if (codec.width < width) + width = codec.width; + if (codec.height < height) + height = codec.height; + } + + VideoCodec clamped_codec = codec; + clamped_codec.width = width; + clamped_codec.height = height; + + encoder_config.streams = encoder_factory_->CreateVideoStreams( + clamped_codec, parameters_.options, parameters_.config.rtp.ssrcs.size()); + + // Conference mode screencast uses 2 temporal layers split at 100kbit. + if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) && + dimensions.is_screencast && encoder_config.streams.size() == 1) { + encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); + encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( + kConferenceModeTemporalLayerBitrateBps); + } + return encoder_config; +} + void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( int width, int height, @@ -1694,56 +1758,25 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( // Configured using the same parameters, do not reconfigure. return; } + LOG(LS_INFO) << "SetDimensions: " << width << "x" << height + << (is_screencast ? " (screencast)" : " (not screencast)"); last_dimensions_.width = width; last_dimensions_.height = height; last_dimensions_.is_screencast = is_screencast; assert(!parameters_.encoder_config.streams.empty()); - LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height; VideoCodecSettings codec_settings; parameters_.codec_settings.Get(&codec_settings); - // Restrict dimensions according to codec max. - if (!is_screencast) { - if (codec_settings.codec.width < width) - width = codec_settings.codec.width; - if (codec_settings.codec.height < height) - height = codec_settings.codec.height; - } - webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config; + webrtc::VideoEncoderConfig encoder_config = + CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); + encoder_config.encoder_specific_settings = encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec, parameters_.options); - if (is_screencast) { - int screencast_min_bitrate_kbps; - parameters_.options.screencast_min_bitrate.Get( - &screencast_min_bitrate_kbps); - encoder_config.min_transmit_bitrate_bps = - screencast_min_bitrate_kbps * 1000; - encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare; - } else { - encoder_config.min_transmit_bitrate_bps = 0; - encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo; - } - - VideoCodec codec = codec_settings.codec; - codec.width = width; - codec.height = height; - - encoder_config.streams = encoder_factory_->CreateVideoStreams( - codec, parameters_.options, parameters_.config.rtp.ssrcs.size()); - - // Conference mode screencast uses 2 temporal layers split at 100kbit. - if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) && - is_screencast && encoder_config.streams.size() == 1) { - encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); - encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( - kConferenceModeTemporalLayerBitrateBps); - } - bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config); encoder_factory_->DestroyVideoEncoderSettings( @@ -2073,6 +2106,14 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() : rtx_payload_type(-1) {} +bool WebRtcVideoChannel2::VideoCodecSettings::operator==( + const WebRtcVideoChannel2::VideoCodecSettings& other) const { + return codec == other.codec && + fec.ulpfec_payload_type == other.fec.ulpfec_payload_type && + fec.red_payload_type == other.fec.red_payload_type && + rtx_payload_type == other.rtx_payload_type; +} + std::vector<WebRtcVideoChannel2::VideoCodecSettings> WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { assert(!codecs.empty()); diff --git a/media/webrtc/webrtcvideoengine2.h b/media/webrtc/webrtcvideoengine2.h index 68cacc0..9a5fe65 100644 --- a/media/webrtc/webrtcvideoengine2.h +++ b/media/webrtc/webrtcvideoengine2.h @@ -280,6 +280,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, struct VideoCodecSettings { VideoCodecSettings(); + bool operator ==(const VideoCodecSettings& other) const; + VideoCodec codec; webrtc::FecConfig fec; int rtx_payload_type; @@ -348,8 +350,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, bool external; }; - struct LastDimensions { - LastDimensions() : width(-1), height(-1), is_screencast(false) {} + struct Dimensions { + Dimensions() : width(-1), height(-1), is_screencast(false) {} int width; int height; bool is_screencast; @@ -357,23 +359,28 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec) EXCLUSIVE_LOCKS_REQUIRED(lock_); - void DestroyVideoEncoder(AllocatedEncoder* encoder); + void DestroyVideoEncoder(AllocatedEncoder* encoder) + EXCLUSIVE_LOCKS_REQUIRED(lock_); void SetCodecAndOptions(const VideoCodecSettings& codec, const VideoOptions& options) EXCLUSIVE_LOCKS_REQUIRED(lock_); void RecreateWebRtcStream() EXCLUSIVE_LOCKS_REQUIRED(lock_); + webrtc::VideoEncoderConfig CreateVideoEncoderConfig( + const Dimensions& dimensions, + const VideoCodec& codec) const EXCLUSIVE_LOCKS_REQUIRED(lock_); void SetDimensions(int width, int height, bool is_screencast) EXCLUSIVE_LOCKS_REQUIRED(lock_); webrtc::Call* const call_; - WebRtcVideoEncoderFactory* const external_encoder_factory_; - WebRtcVideoEncoderFactory2* const encoder_factory_; + WebRtcVideoEncoderFactory* const external_encoder_factory_ + GUARDED_BY(lock_); + WebRtcVideoEncoderFactory2* const encoder_factory_ GUARDED_BY(lock_); rtc::CriticalSection lock_; webrtc::VideoSendStream* stream_ GUARDED_BY(lock_); VideoSendStreamParameters parameters_ GUARDED_BY(lock_); AllocatedEncoder allocated_encoder_ GUARDED_BY(lock_); - LastDimensions last_dimensions_ GUARDED_BY(lock_); + Dimensions last_dimensions_ GUARDED_BY(lock_); VideoCapturer* capturer_ GUARDED_BY(lock_); bool sending_ GUARDED_BY(lock_); |