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
diff --git a/talk/media/base/videoengine_unittest.h b/talk/media/base/videoengine_unittest.h
index 0f03c7b..aa5eff0 100644
--- a/talk/media/base/videoengine_unittest.h
+++ b/talk/media/base/videoengine_unittest.h
@@ -1593,6 +1593,24 @@
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 efd3df4..97d274d 100644
--- a/talk/media/webrtc/webrtcvideoengine2.cc
+++ b/talk/media/webrtc/webrtcvideoengine2.cc
@@ -1364,15 +1364,15 @@
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<int>(frame->GetWidth()),
+ static_cast<int>(frame->GetHeight()));
}
rtc::CritScope cs(&lock_);
if (stream_ == NULL) {
@@ -1386,9 +1386,9 @@
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 @@
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 @@
// 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 @@
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 @@
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 dbd3990..d77afb9 100644
--- a/talk/media/webrtc/webrtcvideoengine2.h
+++ b/talk/media/webrtc/webrtcvideoengine2.h
@@ -322,7 +322,8 @@
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 6aaa7bd..4f69f6d 100644
--- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -536,15 +536,17 @@
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.