summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpbos@webrtc.org <pbos@webrtc.org>2014-11-07 10:54:43 +0000
committerpbos@webrtc.org <pbos@webrtc.org>2014-11-07 10:54:43 +0000
commitefe932275823d38966a45310eff7a60763f06ec1 (patch)
tree8fc4572c3fa2436b7a72fb28c355ae424d14f399
parent2cc4257b28bcc0ab6bdd6f6f67ce4b79fb6c60e1 (diff)
downloadtalk-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.cc129
-rw-r--r--media/webrtc/webrtcvideoengine2.h19
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_);