From c4175b9fdf7d23eb58a044ff39e2b096f9091995 Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Wed, 3 Sep 2014 15:25:49 +0000 Subject: [PATCH] Set resolution based on incoming VideoFrames. R=pthatcher@webrtc.org BUG=1788 Review URL: https://webrtc-codereview.appspot.com/17269004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7042 4adac7df-926f-26a2-2b94-8c16560cd09d --- talk/media/base/videoengine_unittest.h | 18 +++++++++ talk/media/webrtc/webrtcvideoengine2.cc | 37 ++++++++++++------- talk/media/webrtc/webrtcvideoengine2.h | 3 +- .../webrtc/webrtcvideoengine2_unittest.cc | 10 +++-- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/talk/media/base/videoengine_unittest.h b/talk/media/base/videoengine_unittest.h index 0f03c7b85..aa5eff0e5 100644 --- a/talk/media/base/videoengine_unittest.h +++ b/talk/media/base/videoengine_unittest.h @@ -1593,6 +1593,24 @@ class VideoMediaChannelTest : public testing::Test, frame_count += 2; EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); } + // Tests that adapted frames won't be upscaled to a higher resolution. + void SendsLowerResolutionOnSmallerFrames() { + cricket::VideoCodec codec = DefaultCodec(); + codec.width = 320; + codec.height = 240; + EXPECT_TRUE(SetOneCodec(codec)); + EXPECT_TRUE(SetSend(true)); + EXPECT_TRUE(channel_->SetRender(true)); + EXPECT_TRUE(channel_->SetRenderer(kDefaultReceiveSsrc, &renderer_)); + EXPECT_EQ(0, renderer_.num_rendered_frames()); + EXPECT_TRUE(SendFrame()); + EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); + + // Check that we send smaller frames at the new resolution. + EXPECT_TRUE(video_capturer_->CaptureCustomFrame( + codec.width / 2, codec.height / 2, cricket::FOURCC_I420)); + EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout); + } // Tests that we can set the send stream format properly. void SetSendStreamFormat() { cricket::VideoCodec codec(DefaultCodec()); diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index efd3df414..97d274da2 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -1364,15 +1364,15 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( const VideoFrame* frame) { LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x" << frame->GetHeight(); - bool is_screencast = capturer->IsScreencast(); // Lock before copying, can be called concurrently when swapping input source. rtc::CritScope frame_cs(&frame_lock_); if (!muted_) { ConvertToI420VideoFrame(*frame, &video_frame_); } else { - // Create a tiny black frame to transmit instead. - CreateBlackFrame(&video_frame_, 1, 1); - is_screencast = false; + // Create a black frame to transmit instead. + CreateBlackFrame(&video_frame_, + static_cast(frame->GetWidth()), + static_cast(frame->GetHeight())); } rtc::CritScope cs(&lock_); if (stream_ == NULL) { @@ -1386,9 +1386,9 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( return; } // Reconfigure codec if necessary. - if (is_screencast) { - SetDimensions(video_frame_.width(), video_frame_.height()); - } + SetDimensions( + video_frame_.width(), video_frame_.height(), capturer->IsScreencast()); + LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x" << video_frame_.height() << " -> (codec) " << parameters_.video_streams.back().width << "x" @@ -1416,7 +1416,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer( black_frame.CreateEmptyFrame( width, height, width, half_width, half_width); SetWebRtcFrameToBlack(&black_frame); - SetDimensions(width, height); + SetDimensions(width, height, false); stream_->Input()->SwapFrame(&black_frame); } @@ -1450,7 +1450,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat( // TODO(pbos): Fix me, this only affects the last stream! parameters_.video_streams.back().max_framerate = VideoFormat::IntervalToFps(format.interval); - SetDimensions(format.width, format.height); + SetDimensions(format.width, format.height, false); } format_ = format; @@ -1539,10 +1539,23 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( RecreateWebRtcStream(); } -void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width, - int height) { +void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( + int width, + int height, + bool override_max) { assert(!parameters_.video_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 (codec_settings.codec.width < width) + width = codec_settings.codec.width; + if (codec_settings.codec.height < height) + height = codec_settings.codec.height; + } + if (parameters_.video_streams.back().width == width && parameters_.video_streams.back().height == height) { return; @@ -1552,8 +1565,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width, parameters_.video_streams.back().width = width; parameters_.video_streams.back().height = height; - VideoCodecSettings codec_settings; - parameters_.codec_settings.Get(&codec_settings); void* encoder_settings = encoder_factory_->CreateVideoEncoderSettings( codec_settings.codec, parameters_.options); diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index dbd39907b..d77afb9d2 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -322,7 +322,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, void SetCodecAndOptions(const VideoCodecSettings& codec, const VideoOptions& options); void RecreateWebRtcStream(); - void SetDimensions(int width, int height); + // When |override_max| is false constrain width/height to codec dimensions. + void SetDimensions(int width, int height, bool override_max); webrtc::Call* const call_; WebRtcVideoEncoderFactory2* const encoder_factory_; diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 6aaa7bd3d..4f69f6d3c 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -536,15 +536,17 @@ WEBRTC_BASE_TEST(AdaptResolution16x10); WEBRTC_BASE_TEST(AdaptResolution4x3); -WEBRTC_BASE_TEST(MuteStream); - -WEBRTC_BASE_TEST(MultipleSendStreams); - // TODO(juberti): Restore this test once we support sending 0 fps. WEBRTC_DISABLED_BASE_TEST(AdaptDropAllFrames); // TODO(juberti): Understand why we get decode errors on this test. WEBRTC_DISABLED_BASE_TEST(AdaptFramerate); +WEBRTC_BASE_TEST(SendsLowerResolutionOnSmallerFrames); + +WEBRTC_BASE_TEST(MuteStream); + +WEBRTC_BASE_TEST(MultipleSendStreams); + WEBRTC_BASE_TEST(SetSendStreamFormat0x0); // TODO(zhurunz): Fix the flakey test.