Don't await adaptation after deg-pref change
Now we only await a previous adaptation if the degradataion preference is the same as our current degradation preference. Without this guard we can get stuck as detailed in the attached bug. Bug: webrtc:11562 Change-Id: I91be48546446ef8d01fe901bc6889201a5b97ba6 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174805 Commit-Queue: Evan Shrubsole <eshr@google.com> Reviewed-by: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31236}
This commit is contained in:

committed by
Commit Bot

parent
1d6e70f33d
commit
84afe46549
@ -315,22 +315,6 @@ class VideoStreamAdapter::VideoSourceRestrictor {
|
|||||||
VideoAdaptationCounters adaptations_;
|
VideoAdaptationCounters adaptations_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// static
|
|
||||||
VideoStreamAdapter::AdaptationRequest::Mode
|
|
||||||
VideoStreamAdapter::AdaptationRequest::GetModeFromAdaptationAction(
|
|
||||||
Adaptation::StepType step_type) {
|
|
||||||
switch (step_type) {
|
|
||||||
case Adaptation::StepType::kIncreaseResolution:
|
|
||||||
return AdaptationRequest::Mode::kAdaptUp;
|
|
||||||
case Adaptation::StepType::kDecreaseResolution:
|
|
||||||
return AdaptationRequest::Mode::kAdaptDown;
|
|
||||||
case Adaptation::StepType::kIncreaseFrameRate:
|
|
||||||
return AdaptationRequest::Mode::kAdaptUp;
|
|
||||||
case Adaptation::StepType::kDecreaseFrameRate:
|
|
||||||
return AdaptationRequest::Mode::kAdaptDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoStreamAdapter::VideoStreamAdapter()
|
VideoStreamAdapter::VideoStreamAdapter()
|
||||||
: source_restrictor_(std::make_unique<VideoSourceRestrictor>()),
|
: source_restrictor_(std::make_unique<VideoSourceRestrictor>()),
|
||||||
balanced_settings_(),
|
balanced_settings_(),
|
||||||
@ -381,10 +365,10 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const {
|
|||||||
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
||||||
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
||||||
// Don't adapt if we're awaiting a previous adaptation to have an effect.
|
// Don't adapt if we're awaiting a previous adaptation to have an effect.
|
||||||
bool last_adaptation_was_up =
|
bool last_request_increased_resolution =
|
||||||
last_adaptation_request_ &&
|
last_adaptation_request_ && last_adaptation_request_->step_type_ ==
|
||||||
last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp;
|
Adaptation::StepType::kIncreaseResolution;
|
||||||
if (last_adaptation_was_up &&
|
if (last_request_increased_resolution &&
|
||||||
degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
|
degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
|
||||||
input_state_.frame_size_pixels().value() <=
|
input_state_.frame_size_pixels().value() <=
|
||||||
last_adaptation_request_->input_pixel_count_) {
|
last_adaptation_request_->input_pixel_count_) {
|
||||||
@ -453,12 +437,12 @@ Adaptation VideoStreamAdapter::GetAdaptationUp() const {
|
|||||||
Adaptation VideoStreamAdapter::GetAdaptationDown() const {
|
Adaptation VideoStreamAdapter::GetAdaptationDown() const {
|
||||||
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
RTC_DCHECK_NE(degradation_preference_, DegradationPreference::DISABLED);
|
||||||
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
RTC_DCHECK(input_state_.HasInputFrameSizeAndFramesPerSecond());
|
||||||
// Don't adapt adaptation is disabled.
|
// Don't adapt if we're awaiting a previous adaptation to have an effect or
|
||||||
bool last_adaptation_was_down =
|
// if we switched degradation preference.
|
||||||
last_adaptation_request_ &&
|
bool last_request_decreased_resolution =
|
||||||
last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown;
|
last_adaptation_request_ && last_adaptation_request_->step_type_ ==
|
||||||
// Don't adapt if we're awaiting a previous adaptation to have an effect.
|
Adaptation::StepType::kDecreaseResolution;
|
||||||
if (last_adaptation_was_down &&
|
if (last_request_decreased_resolution &&
|
||||||
degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
|
degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
|
||||||
input_state_.frame_size_pixels().value() >=
|
input_state_.frame_size_pixels().value() >=
|
||||||
last_adaptation_request_->input_pixel_count_) {
|
last_adaptation_request_->input_pixel_count_) {
|
||||||
@ -536,8 +520,7 @@ void VideoStreamAdapter::ApplyAdaptation(const Adaptation& adaptation) {
|
|||||||
// adapting again before this adaptation has had an effect.
|
// adapting again before this adaptation has had an effect.
|
||||||
last_adaptation_request_.emplace(AdaptationRequest{
|
last_adaptation_request_.emplace(AdaptationRequest{
|
||||||
input_state_.frame_size_pixels().value(),
|
input_state_.frame_size_pixels().value(),
|
||||||
input_state_.frames_per_second(),
|
input_state_.frames_per_second(), adaptation.step().type});
|
||||||
AdaptationRequest::GetModeFromAdaptationAction(adaptation.step().type)});
|
|
||||||
// Adapt!
|
// Adapt!
|
||||||
source_restrictor_->ApplyAdaptationStep(adaptation.step(),
|
source_restrictor_->ApplyAdaptationStep(adaptation.step(),
|
||||||
degradation_preference_);
|
degradation_preference_);
|
||||||
|
@ -147,12 +147,8 @@ class VideoStreamAdapter {
|
|||||||
int input_pixel_count_;
|
int input_pixel_count_;
|
||||||
// Framerate received from the source at the time of the adaptation.
|
// Framerate received from the source at the time of the adaptation.
|
||||||
int framerate_fps_;
|
int framerate_fps_;
|
||||||
// Indicates if request was to adapt up or down.
|
// Degradation preference for the request.
|
||||||
enum class Mode { kAdaptUp, kAdaptDown } mode_;
|
Adaptation::StepType step_type_;
|
||||||
|
|
||||||
// This is a static method rather than an anonymous namespace function due
|
|
||||||
// to namespace visiblity.
|
|
||||||
static Mode GetModeFromAdaptationAction(Adaptation::StepType step_type);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Owner and modifier of the VideoSourceRestriction of this stream adaptor.
|
// Owner and modifier of the VideoSourceRestriction of this stream adaptor.
|
||||||
|
@ -552,6 +552,130 @@ TEST(VideoStreamAdapterTest, MaintainFramerate_AwaitingPreviousAdaptationUp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
MaintainResolution_AdaptsUpAfterSwitchingDegradationPreference) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Adapt down in fps for later.
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationUp());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
|
||||||
|
// We should be able to adapt in framerate one last time after the change of
|
||||||
|
// degradation preference.
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationUp();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationUp());
|
||||||
|
EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
MaintainFramerate_AdaptsUpAfterSwitchingDegradationPreference) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Adapt down in resolution for later.
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationUp());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
EXPECT_EQ(0, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
|
||||||
|
// We should be able to adapt in framerate one last time after the change of
|
||||||
|
// degradation preference.
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationUp();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationUp());
|
||||||
|
EXPECT_EQ(0, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
PendingResolutionIncreaseAllowsAdaptUpAfterSwitchToMaintainResolution) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Adapt fps down so we can adapt up later in the test.
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
// Apply adaptation up but don't update input.
|
||||||
|
adapter.ApplyAdaptation(adapter.GetAdaptationUp());
|
||||||
|
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
||||||
|
adapter.GetAdaptationUp().status());
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationUp();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
MaintainFramerate_AdaptsDownAfterSwitchingDegradationPreference) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Adapt down once, should change FPS.
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
// Adaptation down should apply after the degradation prefs change.
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
fake_stream.ApplyAdaptation(adaptation);
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
MaintainResolution_AdaptsDownAfterSwitchingDegradationPreference) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Adapt down once, should change FPS.
|
||||||
|
fake_stream.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
fake_stream.ApplyAdaptation(adaptation);
|
||||||
|
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().fps_adaptations);
|
||||||
|
EXPECT_EQ(1, adapter.adaptation_counters().resolution_adaptations);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoStreamAdapterTest,
|
||||||
|
PendingResolutionDecreaseAllowsAdaptDownAfterSwitchToMaintainResolution) {
|
||||||
|
VideoStreamAdapter adapter;
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_FRAMERATE);
|
||||||
|
FakeVideoStream fake_stream(&adapter, 1280 * 720, 30,
|
||||||
|
kDefaultMinPixelsPerFrame);
|
||||||
|
// Apply adaptation but don't update the input.
|
||||||
|
adapter.ApplyAdaptation(adapter.GetAdaptationDown());
|
||||||
|
EXPECT_EQ(Adaptation::Status::kAwaitingPreviousAdaptation,
|
||||||
|
adapter.GetAdaptationDown().status());
|
||||||
|
adapter.SetDegradationPreference(DegradationPreference::MAINTAIN_RESOLUTION);
|
||||||
|
Adaptation adaptation = adapter.GetAdaptationDown();
|
||||||
|
EXPECT_EQ(Adaptation::Status::kValid, adaptation.status());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
|
TEST(VideoStreamAdapterTest, PeekNextRestrictions) {
|
||||||
VideoStreamAdapter adapter;
|
VideoStreamAdapter adapter;
|
||||||
// Any non-disabled DegradationPreference will do.
|
// Any non-disabled DegradationPreference will do.
|
||||||
|
Reference in New Issue
Block a user