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
This commit is contained in:
pbos@webrtc.org 2014-09-03 15:25:49 +00:00
parent 9730d3aae9
commit c4175b9fdf
4 changed files with 50 additions and 18 deletions

View File

@ -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());

View File

@ -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<int>(frame->GetWidth()),
static_cast<int>(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);

View File

@ -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_;

View File

@ -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.