Set correct encoder-specific settings for vpx in the new API.

Also, make VideoEncoderConfig::ContentType an enum class.

BUG=4569
R=mflodman@webrtc.org, pbos@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/46069004

Cr-Commit-Position: refs/heads/master@{#9093}
This commit is contained in:
Erik Språng 2015-04-28 10:01:41 +02:00
parent e8a197bd07
commit 143cec1cc6
13 changed files with 228 additions and 40 deletions

View File

@ -64,7 +64,17 @@ bool FakeVideoSendStream::GetVp8Settings(
return false;
}
*settings = vp8_settings_;
*settings = vpx_settings_.vp8;
return true;
}
bool FakeVideoSendStream::GetVp9Settings(
webrtc::VideoCodecVP9* settings) const {
if (!codec_settings_set_) {
return false;
}
*settings = vpx_settings_.vp9;
return true;
}
@ -99,9 +109,16 @@ bool FakeVideoSendStream::ReconfigureVideoEncoder(
const webrtc::VideoEncoderConfig& config) {
encoder_config_ = config;
if (config.encoder_specific_settings != NULL) {
assert(config_.encoder_settings.payload_name == "VP8");
vp8_settings_ = *reinterpret_cast<const webrtc::VideoCodecVP8*>(
if (config_.encoder_settings.payload_name == "VP8") {
vpx_settings_.vp8 = *reinterpret_cast<const webrtc::VideoCodecVP8*>(
config.encoder_specific_settings);
} else if (config_.encoder_settings.payload_name == "VP9") {
vpx_settings_.vp9 = *reinterpret_cast<const webrtc::VideoCodecVP9*>(
config.encoder_specific_settings);
} else {
ADD_FAILURE() << "Unsupported encoder payload: "
<< config_.encoder_settings.payload_name;
}
}
codec_settings_set_ = config.encoder_specific_settings != NULL;
return true;

View File

@ -47,6 +47,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
bool IsSending() const;
bool GetVp8Settings(webrtc::VideoCodecVP8* settings) const;
bool GetVp9Settings(webrtc::VideoCodecVP9* settings) const;
int GetNumberOfSwappedFrames() const;
int GetLastWidth() const;
@ -69,7 +70,10 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
webrtc::VideoSendStream::Config config_;
webrtc::VideoEncoderConfig encoder_config_;
bool codec_settings_set_;
webrtc::VideoCodecVP8 vp8_settings_;
union VpxSettings {
webrtc::VideoCodecVP8 vp8;
webrtc::VideoCodecVP9 vp9;
} vpx_settings_;
int num_swapped_frames_;
webrtc::I420VideoFrame last_frame_;
webrtc::VideoSendStream::Stats stats_;

View File

@ -460,6 +460,7 @@ bool ScreenshareLayerConfig::FromFieldTrialGroup(
void ConfigureConferenceModeScreencastCodec(webrtc::VideoCodec* codec) {
codec->codecSpecific.VP8.numberOfTemporalLayers = 2;
codec->codecSpecific.VP8.automaticResizeOn = false;
ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
// For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked

View File

@ -312,15 +312,29 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams(
void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
const VideoCodec& codec,
const VideoOptions& options) {
const VideoOptions& options,
bool is_screencast) {
// No automatic resizing when using simulcast.
bool automatic_resize = !is_screencast && ssrcs_.size() == 1;
bool frame_dropping = !is_screencast;
bool denoising;
if (is_screencast) {
denoising = false;
} else {
options.video_noise_reduction.Get(&denoising);
}
if (CodecNamesEq(codec.name, kVp8CodecName)) {
encoder_settings_.vp8 = webrtc::VideoEncoder::GetDefaultVp8Settings();
options.video_noise_reduction.Get(&encoder_settings_.vp8.denoisingOn);
encoder_settings_.vp8.automaticResizeOn = automatic_resize;
encoder_settings_.vp8.denoisingOn = denoising;
encoder_settings_.vp8.frameDroppingOn = frame_dropping;
return &encoder_settings_.vp8;
}
if (CodecNamesEq(codec.name, kVp9CodecName)) {
encoder_settings_.vp9 = webrtc::VideoEncoder::GetDefaultVp9Settings();
options.video_noise_reduction.Get(&encoder_settings_.vp9.denoisingOn);
encoder_settings_.vp9.denoisingOn = denoising;
encoder_settings_.vp9.frameDroppingOn = frame_dropping;
return &encoder_settings_.vp9;
}
return NULL;
@ -1778,10 +1792,12 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
&screencast_min_bitrate_kbps);
encoder_config.min_transmit_bitrate_bps =
screencast_min_bitrate_kbps * 1000;
encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare;
encoder_config.content_type =
webrtc::VideoEncoderConfig::ContentType::kScreen;
} else {
encoder_config.min_transmit_bitrate_bps = 0;
encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo;
encoder_config.content_type =
webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
}
// Restrict dimensions according to codec max.
@ -1800,7 +1816,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
encoder_config.streams = CreateVideoStreams(
clamped_codec, parameters_.options, parameters_.max_bitrate_bps,
parameters_.config.rtp.ssrcs.size());
dimensions.is_screencast ? 1 : parameters_.config.rtp.ssrcs.size());
// Conference mode screencast uses 2 temporal layers split at 100kbit.
if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) &&
@ -1844,8 +1860,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
webrtc::VideoEncoderConfig encoder_config =
CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
encoder_config.encoder_specific_settings =
ConfigureVideoEncoderSettings(codec_settings.codec, parameters_.options);
encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings(
codec_settings.codec, parameters_.options, is_screencast);
bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
@ -2000,7 +2016,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
VideoCodecSettings codec_settings;
parameters_.codec_settings.Get(&codec_settings);
parameters_.encoder_config.encoder_specific_settings =
ConfigureVideoEncoderSettings(codec_settings.codec, parameters_.options);
ConfigureVideoEncoderSettings(
codec_settings.codec, parameters_.options,
parameters_.encoder_config.content_type ==
webrtc::VideoEncoderConfig::ContentType::kScreen);
webrtc::VideoSendStream::Config config = parameters_.config;
if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) {

View File

@ -353,7 +353,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
size_t num_streams);
void* ConfigureVideoEncoderSettings(const VideoCodec& codec,
const VideoOptions& options)
const VideoOptions& options,
bool is_screencast)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec)

View File

@ -820,7 +820,7 @@ TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_SendVp8HdAndReceiveAdaptedVp8Vga) {
class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test,
public WebRtcCallFactory {
public:
WebRtcVideoChannel2Test() : fake_call_(NULL) {}
WebRtcVideoChannel2Test() : fake_call_(NULL), last_ssrc_(0) {}
void SetUp() override {
engine_.SetCallFactory(this);
engine_.Init(rtc::Thread::Current());
@ -831,6 +831,10 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test,
}
protected:
virtual std::vector<cricket::VideoCodec> GetCodecs() {
return engine_.codecs();
}
webrtc::Call* CreateCall(const webrtc::Call::Config& config) override {
assert(fake_call_ == NULL);
fake_call_ = new FakeCall(config);
@ -971,6 +975,26 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test,
void TestCpuAdaptation(bool enable_overuse);
FakeVideoSendStream* SetDenoisingOption(bool enabled) {
VideoOptions options;
options.video_noise_reduction.Set(enabled);
channel_->SetOptions(options);
return fake_call_->GetVideoSendStreams().back();
}
FakeVideoSendStream* SetUpSimulcast(bool enabled) {
last_ssrc_ += 3;
if (enabled) {
std::vector<uint32_t> ssrcs;
ssrcs.push_back(last_ssrc_);
ssrcs.push_back(last_ssrc_ + 1);
ssrcs.push_back(last_ssrc_ + 2);
return AddSendStream(CreateSimStreamParams("cname", ssrcs));
} else {
return AddSendStream(StreamParams::CreateLegacy(last_ssrc_));
}
}
FakeCall* fake_call_;
rtc::scoped_ptr<VideoMediaChannel> channel_;
uint32 last_ssrc_;
@ -1374,7 +1398,7 @@ TEST_F(WebRtcVideoChannel2Test, UsesCorrectSettingsForScreencast) {
// Verify non-screencast settings.
webrtc::VideoEncoderConfig encoder_config = send_stream->GetEncoderConfig();
EXPECT_EQ(webrtc::VideoEncoderConfig::kRealtimeVideo,
EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
encoder_config.content_type);
EXPECT_EQ(codec.width, encoder_config.streams.front().width);
EXPECT_EQ(codec.height, encoder_config.streams.front().height);
@ -1388,7 +1412,7 @@ TEST_F(WebRtcVideoChannel2Test, UsesCorrectSettingsForScreencast) {
// Verify screencast settings.
encoder_config = send_stream->GetEncoderConfig();
EXPECT_EQ(webrtc::VideoEncoderConfig::kScreenshare,
EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
encoder_config.content_type);
EXPECT_EQ(kScreenshareMinBitrateKbps * 1000,
encoder_config.min_transmit_bitrate_bps);
@ -1426,7 +1450,7 @@ TEST_F(WebRtcVideoChannel2Test,
// Verify screencast settings.
encoder_config = send_stream->GetEncoderConfig();
EXPECT_EQ(webrtc::VideoEncoderConfig::kScreenshare,
EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
encoder_config.content_type);
ASSERT_EQ(1u, encoder_config.streams.size());
ASSERT_EQ(1u, encoder_config.streams[0].temporal_layer_thresholds_bps.size());
@ -1472,22 +1496,143 @@ TEST_F(WebRtcVideoChannel2Test, Vp8DenoisingEnabledByDefault) {
EXPECT_TRUE(vp8_settings.denoisingOn);
}
TEST_F(WebRtcVideoChannel2Test, SetOptionsWithDenoising) {
VideoOptions options;
options.video_noise_reduction.Set(false);
channel_->SetOptions(options);
TEST_F(WebRtcVideoChannel2Test, VerifyVp8SpecificSettings) {
std::vector<cricket::VideoCodec> codecs;
codecs.push_back(kVp8Codec720p);
ASSERT_TRUE(channel_->SetSendCodecs(codecs));
FakeVideoSendStream* stream = SetUpSimulcast(false);
cricket::FakeVideoCapturer capturer;
capturer.SetScreencast(false);
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
stream = SetDenoisingOption(false);
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoCodecVP8 vp8_settings;
ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
EXPECT_FALSE(vp8_settings.denoisingOn);
EXPECT_TRUE(vp8_settings.automaticResizeOn);
EXPECT_TRUE(vp8_settings.frameDroppingOn);
options.video_noise_reduction.Set(true);
channel_->SetOptions(options);
stream = SetDenoisingOption(true);
stream = fake_call_->GetVideoSendStreams()[0];
ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
EXPECT_TRUE(vp8_settings.denoisingOn);
EXPECT_TRUE(vp8_settings.automaticResizeOn);
EXPECT_TRUE(vp8_settings.frameDroppingOn);
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL));
stream = SetUpSimulcast(true);
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
EXPECT_EQ(3, stream->GetVideoStreams().size());
ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
// Autmatic resize off when using simulcast.
EXPECT_FALSE(vp8_settings.automaticResizeOn);
EXPECT_TRUE(vp8_settings.frameDroppingOn);
// In screen-share mode, denoising is forced off and simulcast disabled.
capturer.SetScreencast(true);
EXPECT_TRUE(capturer.CaptureFrame());
stream = SetDenoisingOption(false);
EXPECT_EQ(1, stream->GetVideoStreams().size());
ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
EXPECT_FALSE(vp8_settings.denoisingOn);
// Resizing and frame dropping always off for screen sharing.
EXPECT_FALSE(vp8_settings.automaticResizeOn);
EXPECT_FALSE(vp8_settings.frameDroppingOn);
stream = SetDenoisingOption(true);
ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
EXPECT_FALSE(vp8_settings.denoisingOn);
EXPECT_FALSE(vp8_settings.automaticResizeOn);
EXPECT_FALSE(vp8_settings.frameDroppingOn);
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL));
}
class Vp9SettingsTest : public WebRtcVideoChannel2Test {
public:
Vp9SettingsTest() : WebRtcVideoChannel2Test() {
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP9, "VP9");
}
virtual ~Vp9SettingsTest() {}
protected:
void SetUp() override {
engine_.SetExternalEncoderFactory(&encoder_factory_);
WebRtcVideoChannel2Test::SetUp();
}
void TearDown() override {
// Remove references to encoder_factory_ since this will be destroyed
// before channel_ and engine_.
engine_.Terminate();
engine_.SetExternalEncoderFactory(nullptr);
ASSERT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
}
cricket::FakeWebRtcVideoEncoderFactory encoder_factory_;
};
TEST_F(Vp9SettingsTest, VerifyVp9SpecificSettings) {
std::vector<cricket::VideoCodec> codecs;
codecs.push_back(kVp9Codec);
ASSERT_TRUE(channel_->SetSendCodecs(codecs));
FakeVideoSendStream* stream = SetUpSimulcast(false);
cricket::FakeVideoCapturer capturer;
capturer.SetScreencast(false);
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
stream = SetDenoisingOption(false);
webrtc::VideoCodecVP9 vp9_settings;
ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
EXPECT_FALSE(vp9_settings.denoisingOn);
// Frame dropping always on for real time video.
EXPECT_TRUE(vp9_settings.frameDroppingOn);
stream = SetDenoisingOption(true);
ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
EXPECT_TRUE(vp9_settings.denoisingOn);
EXPECT_TRUE(vp9_settings.frameDroppingOn);
// In screen-share mode, denoising is forced off.
capturer.SetScreencast(true);
EXPECT_TRUE(capturer.CaptureFrame());
stream = SetDenoisingOption(false);
ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
EXPECT_FALSE(vp9_settings.denoisingOn);
// Frame dropping always off for screen sharing.
EXPECT_FALSE(vp9_settings.frameDroppingOn);
stream = SetDenoisingOption(false);
ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
EXPECT_FALSE(vp9_settings.denoisingOn);
EXPECT_FALSE(vp9_settings.frameDroppingOn);
EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL));
}
TEST_F(WebRtcVideoChannel2Test, DISABLED_MultipleSendStreamsWithOneCapturer) {

View File

@ -63,9 +63,10 @@ std::string VideoStream::ToString() const {
}
VideoEncoderConfig::VideoEncoderConfig()
: content_type(kRealtimeVideo),
: content_type(ContentType::kRealtimeVideo),
encoder_specific_settings(NULL),
min_transmit_bitrate_bps(0) {}
min_transmit_bitrate_bps(0) {
}
VideoEncoderConfig::~VideoEncoderConfig() = default;
@ -81,10 +82,10 @@ std::string VideoEncoderConfig::ToString() const {
ss << ']';
ss << ", content_type: ";
switch (content_type) {
case kRealtimeVideo:
case ContentType::kRealtimeVideo:
ss << "kRealtimeVideo";
break;
case kScreenshare:
case ContentType::kScreen:
ss << "kScreenshare";
break;
}

View File

@ -91,9 +91,9 @@ struct VideoStream {
};
struct VideoEncoderConfig {
enum ContentType {
enum class ContentType {
kRealtimeVideo,
kScreenshare,
kScreen,
};
VideoEncoderConfig();

View File

@ -730,7 +730,7 @@ int VP8EncoderImpl::Encode(
}
// Only apply scaling to improve for single-layer streams. The scaling metrics
// use framedrops as a signal and is only applicable when we drop frames.
// use frame drops as a signal and is only applicable when we drop frames.
const bool use_quality_scaler = encoders_.size() == 1 &&
configurations_[0].rc_dropframe_thresh > 0 &&
codec_.codecSpecific.VP8.automaticResizeOn;

View File

@ -460,7 +460,7 @@ void FullStackTest::RunTest(const FullStackTestParams& params) {
stream->max_framerate = params.clip.fps;
if (params.screenshare) {
encoder_config_.content_type = VideoEncoderConfig::kScreenshare;
encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
encoder_config_.min_transmit_bitrate_bps = 400 * 1000;
VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
vp8_settings.denoisingOn = false;

View File

@ -116,7 +116,7 @@ class ScreenshareLoopback : public test::Loopback {
VideoEncoderConfig CreateEncoderConfig() override {
VideoEncoderConfig encoder_config(test::Loopback::CreateEncoderConfig());
VideoStream* stream = &encoder_config.streams[0];
encoder_config.content_type = VideoEncoderConfig::kScreenshare;
encoder_config.content_type = VideoEncoderConfig::ContentType::kScreen;
encoder_config.min_transmit_bitrate_bps = flags::MinTransmitBitrate();
VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
vp8_settings.denoisingOn = false;

View File

@ -315,10 +315,10 @@ bool VideoSendStream::ReconfigureVideoEncoder(
}
switch (config.content_type) {
case VideoEncoderConfig::kRealtimeVideo:
case VideoEncoderConfig::ContentType::kRealtimeVideo:
video_codec.mode = kRealtimeVideo;
break;
case VideoEncoderConfig::kScreenshare:
case VideoEncoderConfig::ContentType::kScreen:
video_codec.mode = kScreensharing;
if (config.streams.size() == 1 &&
config.streams[0].temporal_layer_thresholds_bps.size() == 1) {

View File

@ -1332,7 +1332,7 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
void PerformTest() override {
EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
encoder_config_.content_type = VideoEncoderConfig::kScreenshare;
encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
stream_->ReconfigureVideoEncoder(encoder_config_);
EXPECT_EQ(2u, num_initializations_)
<< "ReconfigureVideoEncoder did not reinitialize the encoder with "
@ -1563,7 +1563,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
kScreencastTargetBitrateKbps * 1000);
encoder_config->content_type = VideoEncoderConfig::kScreenshare;
encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
}
void PerformTest() override {