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; frame_count += 2;
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); 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. // Tests that we can set the send stream format properly.
void SetSendStreamFormat() { void SetSendStreamFormat() {
cricket::VideoCodec codec(DefaultCodec()); cricket::VideoCodec codec(DefaultCodec());

View File

@@ -1364,15 +1364,15 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
const VideoFrame* frame) { const VideoFrame* frame) {
LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x" LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
<< frame->GetHeight(); << frame->GetHeight();
bool is_screencast = capturer->IsScreencast();
// Lock before copying, can be called concurrently when swapping input source. // Lock before copying, can be called concurrently when swapping input source.
rtc::CritScope frame_cs(&frame_lock_); rtc::CritScope frame_cs(&frame_lock_);
if (!muted_) { if (!muted_) {
ConvertToI420VideoFrame(*frame, &video_frame_); ConvertToI420VideoFrame(*frame, &video_frame_);
} else { } else {
// Create a tiny black frame to transmit instead. // Create a black frame to transmit instead.
CreateBlackFrame(&video_frame_, 1, 1); CreateBlackFrame(&video_frame_,
is_screencast = false; static_cast<int>(frame->GetWidth()),
static_cast<int>(frame->GetHeight()));
} }
rtc::CritScope cs(&lock_); rtc::CritScope cs(&lock_);
if (stream_ == NULL) { if (stream_ == NULL) {
@@ -1386,9 +1386,9 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
return; return;
} }
// Reconfigure codec if necessary. // Reconfigure codec if necessary.
if (is_screencast) { SetDimensions(
SetDimensions(video_frame_.width(), video_frame_.height()); video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
}
LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x" LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
<< video_frame_.height() << " -> (codec) " << video_frame_.height() << " -> (codec) "
<< parameters_.video_streams.back().width << "x" << parameters_.video_streams.back().width << "x"
@@ -1416,7 +1416,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
black_frame.CreateEmptyFrame( black_frame.CreateEmptyFrame(
width, height, width, half_width, half_width); width, height, width, half_width, half_width);
SetWebRtcFrameToBlack(&black_frame); SetWebRtcFrameToBlack(&black_frame);
SetDimensions(width, height); SetDimensions(width, height, false);
stream_->Input()->SwapFrame(&black_frame); stream_->Input()->SwapFrame(&black_frame);
} }
@@ -1450,7 +1450,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
// TODO(pbos): Fix me, this only affects the last stream! // TODO(pbos): Fix me, this only affects the last stream!
parameters_.video_streams.back().max_framerate = parameters_.video_streams.back().max_framerate =
VideoFormat::IntervalToFps(format.interval); VideoFormat::IntervalToFps(format.interval);
SetDimensions(format.width, format.height); SetDimensions(format.width, format.height, false);
} }
format_ = format; format_ = format;
@@ -1539,10 +1539,23 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
RecreateWebRtcStream(); RecreateWebRtcStream();
} }
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width, void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
int height) { int width,
int height,
bool override_max) {
assert(!parameters_.video_streams.empty()); assert(!parameters_.video_streams.empty());
LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height; 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 && if (parameters_.video_streams.back().width == width &&
parameters_.video_streams.back().height == height) { parameters_.video_streams.back().height == height) {
return; return;
@@ -1552,8 +1565,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width,
parameters_.video_streams.back().width = width; parameters_.video_streams.back().width = width;
parameters_.video_streams.back().height = height; parameters_.video_streams.back().height = height;
VideoCodecSettings codec_settings;
parameters_.codec_settings.Get(&codec_settings);
void* encoder_settings = encoder_factory_->CreateVideoEncoderSettings( void* encoder_settings = encoder_factory_->CreateVideoEncoderSettings(
codec_settings.codec, parameters_.options); codec_settings.codec, parameters_.options);

View File

@@ -322,7 +322,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
void SetCodecAndOptions(const VideoCodecSettings& codec, void SetCodecAndOptions(const VideoCodecSettings& codec,
const VideoOptions& options); const VideoOptions& options);
void RecreateWebRtcStream(); 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_; webrtc::Call* const call_;
WebRtcVideoEncoderFactory2* const encoder_factory_; WebRtcVideoEncoderFactory2* const encoder_factory_;

View File

@@ -536,15 +536,17 @@ WEBRTC_BASE_TEST(AdaptResolution16x10);
WEBRTC_BASE_TEST(AdaptResolution4x3); WEBRTC_BASE_TEST(AdaptResolution4x3);
WEBRTC_BASE_TEST(MuteStream);
WEBRTC_BASE_TEST(MultipleSendStreams);
// TODO(juberti): Restore this test once we support sending 0 fps. // TODO(juberti): Restore this test once we support sending 0 fps.
WEBRTC_DISABLED_BASE_TEST(AdaptDropAllFrames); WEBRTC_DISABLED_BASE_TEST(AdaptDropAllFrames);
// TODO(juberti): Understand why we get decode errors on this test. // TODO(juberti): Understand why we get decode errors on this test.
WEBRTC_DISABLED_BASE_TEST(AdaptFramerate); WEBRTC_DISABLED_BASE_TEST(AdaptFramerate);
WEBRTC_BASE_TEST(SendsLowerResolutionOnSmallerFrames);
WEBRTC_BASE_TEST(MuteStream);
WEBRTC_BASE_TEST(MultipleSendStreams);
WEBRTC_BASE_TEST(SetSendStreamFormat0x0); WEBRTC_BASE_TEST(SetSendStreamFormat0x0);
// TODO(zhurunz): Fix the flakey test. // TODO(zhurunz): Fix the flakey test.