diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 2d9879c2e..19f2b8d1a 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -778,6 +778,7 @@ void WebRtcVideoChannel2::SetDefaultOptions() { options_.video_noise_reduction.Set(true); options_.video_start_bitrate.Set( webrtc::Call::Config::kDefaultStartBitrateBps / 1000); + options_.screencast_min_bitrate.Set(0); } WebRtcVideoChannel2::~WebRtcVideoChannel2() { @@ -1672,30 +1673,47 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( int width, int height, - bool override_max) { + bool is_screencast) { + if (last_dimensions_.width == width && last_dimensions_.height == height && + last_dimensions_.is_screencast == is_screencast) { + // Configured using the same parameters, do not reconfigure. + return; + } + + 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 (!override_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; } - if (parameters_.encoder_config.streams.back().width == width && - parameters_.encoder_config.streams.back().height == height) { - return; - } - webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config; 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; diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index 2b2e10734..e87c25871 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -346,6 +346,13 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, bool external; }; + struct LastDimensions { + LastDimensions() : width(-1), height(-1), is_screencast(false) {} + int width; + int height; + bool is_screencast; + }; + AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec) EXCLUSIVE_LOCKS_REQUIRED(lock_); void DestroyVideoEncoder(AllocatedEncoder* encoder); @@ -353,8 +360,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, const VideoOptions& options) EXCLUSIVE_LOCKS_REQUIRED(lock_); void RecreateWebRtcStream() EXCLUSIVE_LOCKS_REQUIRED(lock_); - // When |override_max| is false constrain width/height to codec dimensions. - void SetDimensions(int width, int height, bool override_max) + void SetDimensions(int width, int height, bool is_screencast) EXCLUSIVE_LOCKS_REQUIRED(lock_); webrtc::Call* const call_; @@ -365,6 +371,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, webrtc::VideoSendStream* stream_ GUARDED_BY(lock_); VideoSendStreamParameters parameters_ GUARDED_BY(lock_); AllocatedEncoder allocated_encoder_ GUARDED_BY(lock_); + LastDimensions last_dimensions_ GUARDED_BY(lock_); VideoCapturer* capturer_ GUARDED_BY(lock_); bool sending_ GUARDED_BY(lock_); diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 1556732cc..29c7dd57f 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -79,10 +79,14 @@ FakeVideoSendStream::FakeVideoSendStream( ReconfigureVideoEncoder(encoder_config); } -webrtc::VideoSendStream::Config FakeVideoSendStream::GetConfig() { +webrtc::VideoSendStream::Config FakeVideoSendStream::GetConfig() const { return config_; } +webrtc::VideoEncoderConfig FakeVideoSendStream::GetEncoderConfig() const { + return encoder_config_; +} + std::vector FakeVideoSendStream::GetVideoStreams() { return encoder_config_.streams; } @@ -725,7 +729,7 @@ TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_SendVp8HdAndReceiveAdaptedVp8Vga) { EXPECT_TRUE(channel_->SetCapturer(kSsrc, video_capturer_.get())); // Capture format HD -> adapt (OnOutputFormatRequest VGA) -> VGA. - cricket::VideoCodec codec(100, "VP8", 1280, 720, 30, 0); + cricket::VideoCodec codec = kVp8Codec720p; EXPECT_TRUE(SetOneCodec(codec)); codec.width /= 2; codec.height /= 2; @@ -1189,8 +1193,60 @@ TEST_F(WebRtcVideoChannel2Test, DISABLED_SetBandwidthInConference) { FAIL() << "Not implemented."; // TODO(pbos): Implement. } -TEST_F(WebRtcVideoChannel2Test, DISABLED_SetBandwidthScreencast) { - FAIL() << "Not implemented."; // TODO(pbos): Implement. +TEST_F(WebRtcVideoChannel2Test, UsesCorrectSettingsForScreencast) { + static const int kScreenshareMinBitrateKbps = 800; + cricket::VideoCodec codec = kVp8Codec360p; + std::vector codecs; + codecs.push_back(codec); + EXPECT_TRUE(channel_->SetSendCodecs(codecs)); + VideoOptions options; + options.screencast_min_bitrate.Set(kScreenshareMinBitrateKbps); + channel_->SetOptions(options); + + AddSendStream(); + + cricket::FakeVideoCapturer capturer; + capturer.SetScreencast(false); + EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); + cricket::VideoFormat capture_format_hd = + capturer.GetSupportedFormats()->front(); + EXPECT_EQ(1280, capture_format_hd.width); + EXPECT_EQ(720, capture_format_hd.height); + EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd)); + + EXPECT_TRUE(channel_->SetSend(true)); + + EXPECT_TRUE(capturer.CaptureFrame()); + ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); + FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front(); + + EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames()); + + // Verify non-screencast settings. + webrtc::VideoEncoderConfig encoder_config = send_stream->GetEncoderConfig(); + EXPECT_EQ(webrtc::VideoEncoderConfig::kRealtimeVideo, + encoder_config.content_type); + EXPECT_EQ(codec.width, encoder_config.streams.front().width); + EXPECT_EQ(codec.height, encoder_config.streams.front().height); + EXPECT_EQ(0, encoder_config.min_transmit_bitrate_bps) + << "Non-screenshare shouldn't use min-transmit bitrate."; + + capturer.SetScreencast(true); + EXPECT_TRUE(capturer.CaptureFrame()); + + EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames()); + + // Verify screencast settings. + encoder_config = send_stream->GetEncoderConfig(); + EXPECT_EQ(webrtc::VideoEncoderConfig::kScreenshare, + encoder_config.content_type); + EXPECT_EQ(kScreenshareMinBitrateKbps * 1000, + encoder_config.min_transmit_bitrate_bps); + + EXPECT_EQ(capture_format_hd.width, encoder_config.streams.front().width); + EXPECT_EQ(capture_format_hd.height, encoder_config.streams.front().height); + + EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); } TEST_F(WebRtcVideoChannel2Test, DISABLED_SetSendSsrcAndCname) { @@ -1290,7 +1346,7 @@ TEST_F(WebRtcVideoChannel2Test, DoesNotAdaptOnOveruseWhenDisabled) { } void WebRtcVideoChannel2Test::TestCpuAdaptation(bool enable_overuse) { - cricket::VideoCodec codec(100, "VP8", 1280, 720, 30, 0); + cricket::VideoCodec codec = kVp8Codec720p; std::vector codecs; codecs.push_back(codec); EXPECT_TRUE(channel_->SetSendCodecs(codecs)); diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.h b/talk/media/webrtc/webrtcvideoengine2_unittest.h index b3014ad86..de151a2c5 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.h +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.h @@ -41,7 +41,8 @@ class FakeVideoSendStream : public webrtc::VideoSendStream, public: FakeVideoSendStream(const webrtc::VideoSendStream::Config& config, const webrtc::VideoEncoderConfig& encoder_config); - webrtc::VideoSendStream::Config GetConfig(); + webrtc::VideoSendStream::Config GetConfig() const; + webrtc::VideoEncoderConfig GetEncoderConfig() const; std::vector GetVideoStreams(); bool IsSending() const;