Move kMinPixelsPerFrame constant in VideoStreamEncoder to VideoEncoder::ScalingSettings.
Make it possible for forced VP8 SW fallback encoder to set min_pixels_per_frame via GetScalingSettings(). Add a min required resolution (in addition to bitrate) before releasing forced SW fallback. BUG=webrtc:6634 Review-Url: https://codereview.webrtc.org/3000693003 Cr-Commit-Position: refs/heads/master@{#19390}
This commit is contained in:
@ -64,6 +64,17 @@ VideoEncoder::ScalingSettings::ScalingSettings(bool on, int low, int high)
|
||||
: enabled(on),
|
||||
thresholds(rtc::Optional<QpThresholds>(QpThresholds(low, high))) {}
|
||||
|
||||
VideoEncoder::ScalingSettings::ScalingSettings(bool on,
|
||||
int low,
|
||||
int high,
|
||||
int min_pixels)
|
||||
: enabled(on),
|
||||
thresholds(rtc::Optional<QpThresholds>(QpThresholds(low, high))),
|
||||
min_pixels_per_frame(min_pixels) {}
|
||||
|
||||
VideoEncoder::ScalingSettings::ScalingSettings(bool on, int min_pixels)
|
||||
: enabled(on), min_pixels_per_frame(min_pixels) {}
|
||||
|
||||
VideoEncoder::ScalingSettings::ScalingSettings(bool on) : enabled(on) {}
|
||||
|
||||
VideoEncoder::ScalingSettings::~ScalingSettings() {}
|
||||
|
||||
@ -75,12 +75,20 @@ class VideoEncoder {
|
||||
};
|
||||
struct ScalingSettings {
|
||||
ScalingSettings(bool on, int low, int high);
|
||||
ScalingSettings(bool on, int low, int high, int min_pixels);
|
||||
ScalingSettings(bool on, int min_pixels);
|
||||
explicit ScalingSettings(bool on);
|
||||
ScalingSettings(const ScalingSettings&);
|
||||
~ScalingSettings();
|
||||
|
||||
const bool enabled;
|
||||
const rtc::Optional<QpThresholds> thresholds;
|
||||
|
||||
// We will never ask for a resolution lower than this.
|
||||
// TODO(kthelgason): Lower this limit when better testing
|
||||
// on MediaCodec and fallback implementations are in place.
|
||||
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206
|
||||
const int min_pixels_per_frame = 320 * 180;
|
||||
};
|
||||
|
||||
static VideoCodecVP8 GetDefaultVp8Settings();
|
||||
|
||||
@ -50,12 +50,14 @@ void GetForcedFallbackParamsFromFieldTrialGroup(uint32_t* param_low_kbps,
|
||||
int low_kbps;
|
||||
int high_kbps;
|
||||
int min_low_ms;
|
||||
if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &low_kbps, &high_kbps,
|
||||
&min_low_ms) != 3) {
|
||||
int min_pixels;
|
||||
if (sscanf(group.c_str(), "Enabled-%d,%d,%d,%d", &low_kbps, &high_kbps,
|
||||
&min_low_ms, &min_pixels) != 4) {
|
||||
LOG(LS_WARNING) << "Invalid number of forced fallback parameters provided.";
|
||||
return;
|
||||
}
|
||||
if (min_low_ms <= 0 || low_kbps <= 0 || high_kbps <= low_kbps) {
|
||||
if (min_low_ms <= 0 || min_pixels <= 0 || low_kbps <= 0 ||
|
||||
high_kbps <= low_kbps) {
|
||||
LOG(LS_WARNING) << "Invalid forced fallback parameter value provided.";
|
||||
return;
|
||||
}
|
||||
@ -245,6 +247,8 @@ bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
|
||||
|
||||
VideoEncoder::ScalingSettings
|
||||
VideoEncoderSoftwareFallbackWrapper::GetScalingSettings() const {
|
||||
if (forced_fallback_possible_ && fallback_encoder_)
|
||||
return fallback_encoder_->GetScalingSettings();
|
||||
return encoder_->GetScalingSettings();
|
||||
}
|
||||
|
||||
@ -272,8 +276,10 @@ bool VideoEncoderSoftwareFallbackWrapper::TryReleaseForcedFallbackEncoder() {
|
||||
if (!IsForcedFallbackActive())
|
||||
return false;
|
||||
|
||||
if (!forced_fallback_.ShouldStop(bitrate_allocation_.get_sum_kbps()))
|
||||
if (!forced_fallback_.ShouldStop(bitrate_allocation_.get_sum_kbps(),
|
||||
codec_settings_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Release the forced fallback encoder.
|
||||
if (encoder_->InitEncode(&codec_settings_, number_of_cores_,
|
||||
@ -343,8 +349,10 @@ bool VideoEncoderSoftwareFallbackWrapper::ForcedFallbackParams::ShouldStart(
|
||||
}
|
||||
|
||||
bool VideoEncoderSoftwareFallbackWrapper::ForcedFallbackParams::ShouldStop(
|
||||
uint32_t bitrate_kbps) const {
|
||||
return bitrate_kbps >= high_kbps;
|
||||
uint32_t bitrate_kbps,
|
||||
const VideoCodec& codec) const {
|
||||
return bitrate_kbps >= high_kbps &&
|
||||
(codec.width * codec.height >= kMinPixelsStop);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -52,22 +52,24 @@ class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder {
|
||||
// If |forced_fallback_possible_| is true:
|
||||
// The forced fallback is requested if the target bitrate is below |low_kbps|
|
||||
// for more than |min_low_ms| and the input video resolution is not larger
|
||||
// than |kMaxPixels|.
|
||||
// If the bitrate is above |high_kbps|, the forced fallback is requested to
|
||||
// immediately be stopped.
|
||||
// than |kMaxPixelsStart|.
|
||||
// If the bitrate is above |high_kbps| and the resolution is not smaller than
|
||||
// |kMinPixelsStop|, the forced fallback is requested to immediately be
|
||||
// stopped.
|
||||
class ForcedFallbackParams {
|
||||
public:
|
||||
bool ShouldStart(uint32_t bitrate_kbps, const VideoCodec& codec);
|
||||
bool ShouldStop(uint32_t bitrate_kbps) const;
|
||||
bool ShouldStop(uint32_t bitrate_kbps, const VideoCodec& codec) const;
|
||||
void Reset() { start_ms.reset(); }
|
||||
bool IsValid(const VideoCodec& codec) const {
|
||||
return codec.width * codec.height <= kMaxPixels;
|
||||
return codec.width * codec.height <= kMaxPixelsStart;
|
||||
}
|
||||
rtc::Optional<int64_t> start_ms; // Set when bitrate is below |low_kbps|.
|
||||
uint32_t low_kbps = 100;
|
||||
uint32_t high_kbps = 150;
|
||||
int64_t min_low_ms = 10000;
|
||||
const int kMaxPixels = 320 * 240;
|
||||
const int kMaxPixelsStart = 320 * 240;
|
||||
const int kMinPixelsStop = 320 * 180;
|
||||
};
|
||||
|
||||
bool RequestForcedFallback();
|
||||
|
||||
@ -29,6 +29,7 @@ const int kHeight = 240;
|
||||
const int kNumCores = 2;
|
||||
const uint32_t kFramerate = 30;
|
||||
const size_t kMaxPayloadSize = 800;
|
||||
const int kDefaultMinPixelsPerFrame = 320 * 180;
|
||||
} // namespace
|
||||
|
||||
class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
|
||||
@ -93,6 +94,10 @@ class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
|
||||
return "fake-encoder";
|
||||
}
|
||||
|
||||
VideoEncoder::ScalingSettings GetScalingSettings() const override {
|
||||
return VideoEncoder::ScalingSettings(true);
|
||||
}
|
||||
|
||||
int init_encode_count_ = 0;
|
||||
int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
|
||||
int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
|
||||
@ -141,7 +146,8 @@ void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
|
||||
}
|
||||
|
||||
void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
|
||||
rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(kWidth, kHeight);
|
||||
rtc::scoped_refptr<I420Buffer> buffer =
|
||||
I420Buffer::Create(codec_.width, codec_.height);
|
||||
I420Buffer::SetBlack(buffer);
|
||||
std::vector<FrameType> types(1, kVideoFrameKey);
|
||||
|
||||
@ -299,9 +305,10 @@ TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
|
||||
}
|
||||
|
||||
TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
|
||||
VideoCodec codec = {};
|
||||
codec_.width = kWidth;
|
||||
codec_.height = kHeight;
|
||||
fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
|
||||
fallback_wrapper_.InitEncode(&codec, kNumCores, kMaxPayloadSize);
|
||||
fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
|
||||
EncodeFrame();
|
||||
CheckLastEncoderName("fake-encoder");
|
||||
}
|
||||
@ -318,6 +325,8 @@ namespace {
|
||||
const int kLowKbps = 220;
|
||||
const int kHighKbps = 300;
|
||||
const int kMinLowDurationMs = 4000;
|
||||
const int kMinPixelsPerFrame = 1;
|
||||
const int kMinPixelsStop = 320 * 180;
|
||||
const std::string kFieldTrial = "WebRTC-VP8-Forced-Fallback-Encoder";
|
||||
} // namespace
|
||||
|
||||
@ -350,6 +359,8 @@ class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
|
||||
codec_.width = kWidth;
|
||||
codec_.height = kHeight;
|
||||
codec_.VP8()->numberOfTemporalLayers = 1;
|
||||
codec_.VP8()->automaticResizeOn = true;
|
||||
codec_.VP8()->frameDroppingOn = true;
|
||||
codec_.VP8()->tl_factory = tl_factory.get();
|
||||
rate_allocator_.reset(
|
||||
new SimulcastRateAllocator(codec_, std::move(tl_factory)));
|
||||
@ -381,7 +392,8 @@ class ForcedFallbackTestEnabled : public ForcedFallbackTest {
|
||||
: ForcedFallbackTest(kFieldTrial + "/Enabled-" +
|
||||
std::to_string(kLowKbps) + "," +
|
||||
std::to_string(kHighKbps) + "," +
|
||||
std::to_string(kMinLowDurationMs) + "/") {}
|
||||
std::to_string(kMinLowDurationMs) + "," +
|
||||
std::to_string(kMinPixelsPerFrame) + "/") {}
|
||||
};
|
||||
|
||||
class ForcedFallbackTestDisabled : public ForcedFallbackTest {
|
||||
@ -575,4 +587,58 @@ TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
|
||||
EncodeFrameAndVerifyLastName("fake-encoder");
|
||||
}
|
||||
|
||||
TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithoutFallback) {
|
||||
// Bitrate at low threshold.
|
||||
SetRateAllocation(kLowKbps);
|
||||
EncodeFrameAndVerifyLastName("fake-encoder");
|
||||
// Default min pixels per frame should be used.
|
||||
const auto settings = fallback_wrapper_.GetScalingSettings();
|
||||
EXPECT_TRUE(settings.enabled);
|
||||
EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
|
||||
}
|
||||
|
||||
TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
|
||||
// Bitrate at low threshold.
|
||||
SetRateAllocation(kLowKbps);
|
||||
EncodeFrameAndVerifyLastName("fake-encoder");
|
||||
// Duration passed, expect fallback.
|
||||
clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
|
||||
EncodeFrameAndVerifyLastName("libvpx");
|
||||
// Configured min pixels per frame should be used.
|
||||
const auto settings = fallback_wrapper_.GetScalingSettings();
|
||||
EXPECT_TRUE(settings.enabled);
|
||||
EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
|
||||
}
|
||||
|
||||
TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptIfResolutionIsTooSmall) {
|
||||
// Bitrate at low threshold.
|
||||
SetRateAllocation(kLowKbps);
|
||||
EncodeFrameAndVerifyLastName("fake-encoder");
|
||||
// Duration passed, expect fallback.
|
||||
clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
|
||||
EncodeFrameAndVerifyLastName("libvpx");
|
||||
|
||||
// Re-initialize encoder with a resolution less than |kMinPixelsStop|.
|
||||
codec_.height = kMinPixelsStop / codec_.width - 1;
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
|
||||
EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change
|
||||
SetRateAllocation(kHighKbps - 1);
|
||||
EncodeFrameAndVerifyLastName("libvpx");
|
||||
// Bitrate at high threshold but resolution too small for fallback to end.
|
||||
SetRateAllocation(kHighKbps);
|
||||
EncodeFrameAndVerifyLastName("libvpx");
|
||||
|
||||
// Re-initialize encoder with a resolution equal to |kMinPixelsStop|.
|
||||
codec_.height++;
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
|
||||
EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change
|
||||
SetRateAllocation(kHighKbps - 1);
|
||||
EncodeFrameAndVerifyLastName("libvpx");
|
||||
// Bitrate at high threshold and resolution large enough for fallback to end.
|
||||
SetRateAllocation(kHighKbps);
|
||||
EncodeFrameAndVerifyLastName("fake-encoder");
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -464,6 +464,7 @@ if (rtc_include_tests) {
|
||||
"../../api:video_frame_api",
|
||||
"../../common_video:common_video",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../test:field_trial",
|
||||
"../../test:test_support",
|
||||
"../../test:video_test_common",
|
||||
"../video_capture",
|
||||
|
||||
@ -20,9 +20,11 @@
|
||||
#include "webrtc/rtc_base/checks.h"
|
||||
#include "webrtc/rtc_base/optional.h"
|
||||
#include "webrtc/rtc_base/timeutils.h"
|
||||
#include "webrtc/test/field_trial.h"
|
||||
#include "webrtc/test/frame_utils.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/test/video_codec_settings.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -39,6 +41,10 @@ enum { kMaxWaitDecTimeMs = 25 };
|
||||
constexpr uint32_t kTestTimestamp = 123;
|
||||
constexpr int64_t kTestNtpTimeMs = 456;
|
||||
constexpr uint32_t kTimestampIncrementPerFrame = 3000;
|
||||
constexpr int kNumCores = 1;
|
||||
constexpr size_t kMaxPayloadSize = 1440;
|
||||
constexpr int kMinPixelsPerFrame = 12345;
|
||||
constexpr int kDefaultMinPixelsPerFrame = 320 * 180;
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -143,6 +149,10 @@ void Vp8UnitTestDecodeCompleteCallback::Decoded(
|
||||
|
||||
class TestVp8Impl : public ::testing::Test {
|
||||
protected:
|
||||
TestVp8Impl() : TestVp8Impl("") {}
|
||||
explicit TestVp8Impl(const std::string& field_trials)
|
||||
: override_field_trials_(field_trials) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
encoder_.reset(VP8Encoder::Create());
|
||||
decoder_.reset(VP8Decoder::Create());
|
||||
@ -190,9 +200,11 @@ class TestVp8Impl : public ::testing::Test {
|
||||
codec_settings_.VP8()->tl_factory = &tl_factory_;
|
||||
codec_settings_.VP8()->numberOfTemporalLayers = 1;
|
||||
|
||||
EXPECT_EQ(
|
||||
WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, 1, 1440));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_settings_, 1));
|
||||
decoder_->InitDecode(&codec_settings_, kNumCores));
|
||||
}
|
||||
|
||||
size_t WaitForEncodedFrame() const {
|
||||
@ -228,6 +240,7 @@ class TestVp8Impl : public ::testing::Test {
|
||||
const int kWidth = 172;
|
||||
const int kHeight = 144;
|
||||
|
||||
test::ScopedFieldTrials override_field_trials_;
|
||||
std::unique_ptr<Vp8UnitTestEncodeCompleteCallback> encode_complete_callback_;
|
||||
std::unique_ptr<Vp8UnitTestDecodeCompleteCallback> decode_complete_callback_;
|
||||
std::unique_ptr<uint8_t[]> source_buffer_;
|
||||
@ -266,12 +279,13 @@ TEST_F(TestVp8Impl, EncoderParameterTest) {
|
||||
codec_settings_.maxFramerate));
|
||||
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, 1, 1440));
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
|
||||
// Decoder parameter tests.
|
||||
// Calls before InitDecode().
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_settings_, 1));
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
decoder_->InitDecode(&codec_settings_, kNumCores));
|
||||
}
|
||||
|
||||
// We only test the encoder here, since the decoded frame rotation is set based
|
||||
@ -374,7 +388,7 @@ TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) {
|
||||
// Override default settings.
|
||||
codec_settings_.VP8()->numberOfTemporalLayers = 2;
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, 1, 1440));
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
|
||||
// Temporal layer 0.
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
@ -410,7 +424,7 @@ TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) {
|
||||
// Reinit.
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, 1, 1440));
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
|
||||
// Temporal layer 0.
|
||||
input_frame_->set_timestamp(input_frame_->timestamp() +
|
||||
@ -445,4 +459,46 @@ TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) {
|
||||
1);
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, ScalingDisabledIfAutomaticResizeOff) {
|
||||
webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_);
|
||||
codec_settings_.VP8()->tl_factory = &tl_factory_;
|
||||
codec_settings_.VP8()->automaticResizeOn = false;
|
||||
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings();
|
||||
EXPECT_FALSE(settings.enabled);
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, ScalingEnabledIfAutomaticResizeOn) {
|
||||
webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_);
|
||||
codec_settings_.VP8()->tl_factory = &tl_factory_;
|
||||
codec_settings_.VP8()->automaticResizeOn = true;
|
||||
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings();
|
||||
EXPECT_TRUE(settings.enabled);
|
||||
EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
|
||||
}
|
||||
|
||||
class TestVp8ImplWithForcedFallbackEnabled : public TestVp8Impl {
|
||||
public:
|
||||
TestVp8ImplWithForcedFallbackEnabled()
|
||||
: TestVp8Impl("WebRTC-VP8-Forced-Fallback-Encoder/Enabled-1,2,3," +
|
||||
std::to_string(kMinPixelsPerFrame) + "/") {}
|
||||
};
|
||||
|
||||
TEST_F(TestVp8ImplWithForcedFallbackEnabled, MinPixelsPerFrameConfigured) {
|
||||
webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_);
|
||||
codec_settings_.VP8()->tl_factory = &tl_factory_;
|
||||
codec_settings_.VP8()->automaticResizeOn = true;
|
||||
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize));
|
||||
VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings();
|
||||
EXPECT_TRUE(settings.enabled);
|
||||
EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -42,6 +42,8 @@ namespace {
|
||||
|
||||
const char kVp8PostProcArmFieldTrial[] = "WebRTC-VP8-Postproc-Arm";
|
||||
const char kVp8GfBoostFieldTrial[] = "WebRTC-VP8-GfBoost";
|
||||
const char kVp8ForceFallbackEncoderFieldTrial[] =
|
||||
"WebRTC-VP8-Forced-Fallback-Encoder";
|
||||
|
||||
const int kTokenPartitions = VP8_ONE_TOKENPARTITION;
|
||||
enum { kVp8ErrorPropagationTh = 30 };
|
||||
@ -110,6 +112,31 @@ int NumStreamsDisabled(const std::vector<bool>& streams) {
|
||||
return num_disabled;
|
||||
}
|
||||
|
||||
rtc::Optional<int> GetForcedFallbackMinPixelsFromFieldTrialGroup() {
|
||||
if (!webrtc::field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial))
|
||||
return rtc::Optional<int>();
|
||||
|
||||
std::string group =
|
||||
webrtc::field_trial::FindFullName(kVp8ForceFallbackEncoderFieldTrial);
|
||||
if (group.empty())
|
||||
return rtc::Optional<int>();
|
||||
|
||||
int low_kbps;
|
||||
int high_kbps;
|
||||
int min_low_ms;
|
||||
int min_pixels;
|
||||
if (sscanf(group.c_str(), "Enabled-%d,%d,%d,%d", &low_kbps, &high_kbps,
|
||||
&min_low_ms, &min_pixels) != 4) {
|
||||
return rtc::Optional<int>();
|
||||
}
|
||||
|
||||
if (min_low_ms <= 0 || min_pixels <= 0 || low_kbps <= 0 ||
|
||||
high_kbps <= low_kbps) {
|
||||
return rtc::Optional<int>();
|
||||
}
|
||||
return rtc::Optional<int>(min_pixels);
|
||||
}
|
||||
|
||||
bool GetGfBoostPercentageFromFieldTrialGroup(int* boost_percentage) {
|
||||
std::string group = webrtc::field_trial::FindFullName(kVp8GfBoostFieldTrial);
|
||||
if (group.empty())
|
||||
@ -181,6 +208,7 @@ vpx_enc_frame_flags_t VP8EncoderImpl::EncodeFlags(
|
||||
|
||||
VP8EncoderImpl::VP8EncoderImpl()
|
||||
: use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)),
|
||||
min_pixels_per_frame_(GetForcedFallbackMinPixelsFromFieldTrialGroup()),
|
||||
encoded_complete_callback_(nullptr),
|
||||
inited_(false),
|
||||
timestamp_(0),
|
||||
@ -935,6 +963,10 @@ VideoEncoder::ScalingSettings VP8EncoderImpl::GetScalingSettings() const {
|
||||
const bool enable_scaling = encoders_.size() == 1 &&
|
||||
configurations_[0].rc_dropframe_thresh > 0 &&
|
||||
codec_.VP8().automaticResizeOn;
|
||||
if (enable_scaling && min_pixels_per_frame_) {
|
||||
return VideoEncoder::ScalingSettings(enable_scaling,
|
||||
*min_pixels_per_frame_);
|
||||
}
|
||||
return VideoEncoder::ScalingSettings(enable_scaling);
|
||||
}
|
||||
|
||||
|
||||
@ -94,6 +94,7 @@ class VP8EncoderImpl : public VP8Encoder {
|
||||
uint32_t MaxIntraTarget(uint32_t optimal_buffer_size);
|
||||
|
||||
const bool use_gf_boost_;
|
||||
const rtc::Optional<int> min_pixels_per_frame_;
|
||||
|
||||
EncodedImageCallback* encoded_complete_callback_;
|
||||
VideoCodec codec_;
|
||||
|
||||
@ -38,12 +38,6 @@ namespace {
|
||||
|
||||
// Time interval for logging frame counts.
|
||||
const int64_t kFrameLogIntervalMs = 60000;
|
||||
|
||||
// We will never ask for a resolution lower than this.
|
||||
// TODO(kthelgason): Lower this limit when better testing
|
||||
// on MediaCodec and fallback implementations are in place.
|
||||
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206
|
||||
const int kMinPixelsPerFrame = 320 * 180;
|
||||
const int kMinFramerateFps = 2;
|
||||
const int kMaxFramerateFps = 120;
|
||||
|
||||
@ -233,7 +227,7 @@ class VideoStreamEncoder::VideoSourceProxy {
|
||||
source_->AddOrUpdateSink(video_stream_encoder_, sink_wants_);
|
||||
}
|
||||
|
||||
bool RequestResolutionLowerThan(int pixel_count) {
|
||||
bool RequestResolutionLowerThan(int pixel_count, int min_pixels_per_frame) {
|
||||
// Called on the encoder task queue.
|
||||
rtc::CritScope lock(&crit_);
|
||||
if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) {
|
||||
@ -244,7 +238,7 @@ class VideoStreamEncoder::VideoSourceProxy {
|
||||
// The input video frame size will have a resolution less than or equal to
|
||||
// |max_pixel_count| depending on how the source can scale the frame size.
|
||||
const int pixels_wanted = (pixel_count * 3) / 5;
|
||||
if (pixels_wanted < kMinPixelsPerFrame ||
|
||||
if (pixels_wanted < min_pixels_per_frame ||
|
||||
pixels_wanted >= sink_wants_.max_pixel_count) {
|
||||
return false;
|
||||
}
|
||||
@ -990,7 +984,8 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) {
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
// Scale down resolution.
|
||||
if (!source_proxy_->RequestResolutionLowerThan(
|
||||
adaptation_request.input_pixel_count_)) {
|
||||
adaptation_request.input_pixel_count_,
|
||||
settings_.encoder->GetScalingSettings().min_pixels_per_frame)) {
|
||||
return;
|
||||
}
|
||||
GetAdaptCounter().IncrementResolution(reason);
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
#include "webrtc/video/video_stream_encoder.h"
|
||||
|
||||
namespace {
|
||||
// TODO(kthelgason): Lower this limit when better testing
|
||||
// on MediaCodec and fallback implementations are in place.
|
||||
const int kMinPixelsPerFrame = 320 * 180;
|
||||
const int kMinFramerateFps = 2;
|
||||
const int64_t kFrameTimeoutMs = 100;
|
||||
@ -482,7 +480,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
|
||||
VideoEncoder::ScalingSettings GetScalingSettings() const override {
|
||||
rtc::CritScope lock(&local_crit_sect_);
|
||||
if (quality_scaling_)
|
||||
return VideoEncoder::ScalingSettings(true, 1, 2);
|
||||
return VideoEncoder::ScalingSettings(true, 1, 2, kMinPixelsPerFrame);
|
||||
return VideoEncoder::ScalingSettings(false);
|
||||
}
|
||||
|
||||
@ -1909,7 +1907,7 @@ TEST_F(VideoStreamEncoderTest, DoesNotScaleBelowSetResolutionLimit) {
|
||||
video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
|
||||
|
||||
// Enable adapter, expected input resolutions when downscaling:
|
||||
// 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (min resolution limit)
|
||||
// 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (kMinPixelsPerFrame)
|
||||
video_source_.set_adaptation_enabled(true);
|
||||
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
|
||||
Reference in New Issue
Block a user