Add layer skipping to L2T2_KEY_SHIFT structure

Bug: None
Change-Id: Iba019a999cb1812eee12bfe54c2f9ec9ebfa248f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/189965
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32487}
This commit is contained in:
Danil Chapovalov
2020-10-23 19:04:11 +02:00
committed by Commit Bot
parent f01bd6c266
commit 71002a226a
5 changed files with 454 additions and 55 deletions

View File

@ -73,6 +73,7 @@ if (rtc_include_tests) {
testonly = true
sources = [
"scalability_structure_key_svc_unittest.cc",
"scalability_structure_l2t2_key_shift_unittest.cc",
"scalability_structure_l3t3_unittest.cc",
"scalability_structure_test_helpers.cc",
"scalability_structure_test_helpers.h",

View File

@ -20,21 +20,28 @@
namespace webrtc {
namespace {
constexpr auto kNotPresent = DecodeTargetIndication::kNotPresent;
constexpr auto kDiscardable = DecodeTargetIndication::kDiscardable;
constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
DecodeTargetIndication
Dti(int sid, int tid, const ScalableVideoController::LayerFrameConfig& config) {
if (config.IsKeyframe()) {
RTC_DCHECK_EQ(config.TemporalId(), 0);
return sid < config.SpatialId() ? DecodeTargetIndication::kNotPresent
: DecodeTargetIndication::kSwitch;
}
constexpr DecodeTargetIndication kDtis[6][4] = {
{kSwitch, kSwitch, kSwitch, kSwitch}, // kKey, S0T0
{kNotPresent, kNotPresent, kSwitch, kSwitch}, // kKey, S1T0
{kSwitch, kSwitch, kNotPresent, kNotPresent}, // kDelta0, S0T0
{kNotPresent, kNotPresent, kNotPresent, kDiscardable}, // kDelta0, S1T1
{kNotPresent, kDiscardable, kNotPresent, kNotPresent}, // kDelta1, S0T1
{kNotPresent, kNotPresent, kSwitch, kSwitch}, // kDelta1, S1T0
};
if (sid != config.SpatialId() || tid < config.TemporalId()) {
return DecodeTargetIndication::kNotPresent;
}
if (tid == config.TemporalId() && tid > 0) {
return DecodeTargetIndication::kDiscardable;
}
return DecodeTargetIndication::kSwitch;
}
} // namespace
constexpr int ScalabilityStructureL2T2KeyShift::kNumSpatialLayers;
constexpr int ScalabilityStructureL2T2KeyShift::kNumTemporalLayers;
ScalabilityStructureL2T2KeyShift::~ScalabilityStructureL2T2KeyShift() = default;
ScalableVideoController::StreamLayersConfig
@ -65,52 +72,80 @@ FrameDependencyStructure ScalabilityStructureL2T2KeyShift::DependencyStructure()
return structure;
}
ScalableVideoController::LayerFrameConfig
ScalabilityStructureL2T2KeyShift::KeyFrameConfig() const {
return LayerFrameConfig().Id(0).Keyframe().S(0).T(0).Update(0);
}
std::vector<ScalableVideoController::LayerFrameConfig>
ScalabilityStructureL2T2KeyShift::NextFrameConfig(bool restart) {
std::vector<LayerFrameConfig> configs;
configs.reserve(2);
if (restart) {
next_pattern_ = kKey;
}
std::vector<LayerFrameConfig> result(2);
// Buffer0 keeps latest S0T0 frame,
// Buffer1 keeps latest S1T0 frame.
switch (next_pattern_) {
case kKey:
result[0] = KeyFrameConfig();
result[1].Id(1).S(1).T(0).Reference(0).Update(1);
if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(0).T(0).Update(0).Keyframe();
}
if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(1).T(0).Update(1);
if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
configs.back().Reference(0);
} else {
configs.back().Keyframe();
}
}
next_pattern_ = kDelta0;
break;
case kDelta0:
result[0].Id(2).S(0).T(0).ReferenceAndUpdate(0);
result[1].Id(3).S(1).T(1).Reference(1);
if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(0).T(0).ReferenceAndUpdate(0);
}
if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/1)) {
configs.emplace_back();
configs.back().S(1).T(1).Reference(1);
}
if (configs.empty() && DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(1).T(0).ReferenceAndUpdate(1);
}
next_pattern_ = kDelta1;
break;
case kDelta1:
result[0].Id(4).S(0).T(1).Reference(0);
result[1].Id(5).S(1).T(0).ReferenceAndUpdate(1);
if (DecodeTargetIsActive(/*sid=*/0, /*tid=*/1)) {
configs.emplace_back();
configs.back().S(0).T(1).Reference(0);
}
if (DecodeTargetIsActive(/*sid=*/1, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(1).T(0).ReferenceAndUpdate(1);
}
if (configs.empty() && DecodeTargetIsActive(/*sid=*/0, /*tid=*/0)) {
configs.emplace_back();
configs.back().S(0).T(0).ReferenceAndUpdate(0);
}
next_pattern_ = kDelta0;
break;
}
return result;
RTC_DCHECK(!configs.empty() || active_decode_targets_.none());
return configs;
}
GenericFrameInfo ScalabilityStructureL2T2KeyShift::OnEncodeDone(
const LayerFrameConfig& config) {
RTC_CHECK_GE(config.Id(), 0);
RTC_CHECK_LT(config.Id(), ABSL_ARRAYSIZE(kDtis));
GenericFrameInfo frame_info;
frame_info.spatial_id = config.SpatialId();
frame_info.temporal_id = config.TemporalId();
frame_info.encoder_buffers = config.Buffers();
int config_id = config.IsKeyframe() ? 0 : config.Id();
frame_info.decode_target_indications.assign(std::begin(kDtis[config_id]),
std::end(kDtis[config_id]));
for (int sid = 0; sid < kNumSpatialLayers; ++sid) {
for (int tid = 0; tid < kNumTemporalLayers; ++tid) {
frame_info.decode_target_indications.push_back(Dti(sid, tid, config));
}
}
if (config.IsKeyframe()) {
frame_info.part_of_chain = {true, true};
} else if (config.TemporalId() == 0) {
@ -122,4 +157,20 @@ GenericFrameInfo ScalabilityStructureL2T2KeyShift::OnEncodeDone(
return frame_info;
}
void ScalabilityStructureL2T2KeyShift::OnRatesUpdated(
const VideoBitrateAllocation& bitrates) {
for (int sid = 0; sid < kNumSpatialLayers; ++sid) {
// Enable/disable spatial layers independetely.
bool active = bitrates.GetBitrate(sid, /*tid=*/0) > 0;
if (!DecodeTargetIsActive(sid, /*tid=*/0) && active) {
// Key frame is required to reenable any spatial layer.
next_pattern_ = kKey;
}
SetDecodeTargetIsActive(sid, /*tid=*/0, active);
SetDecodeTargetIsActive(sid, /*tid=*/1,
active && bitrates.GetBitrate(sid, /*tid=*/1) > 0);
}
}
} // namespace webrtc

View File

@ -13,6 +13,7 @@
#include <vector>
#include "api/transport/rtp/dependency_descriptor.h"
#include "api/video/video_bitrate_allocation.h"
#include "common_video/generic_frame_descriptor/generic_frame_info.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
@ -35,6 +36,7 @@ class ScalabilityStructureL2T2KeyShift : public ScalableVideoController {
std::vector<LayerFrameConfig> NextFrameConfig(bool restart) override;
GenericFrameInfo OnEncodeDone(const LayerFrameConfig& config) override;
void OnRatesUpdated(const VideoBitrateAllocation& bitrates) override;
private:
enum FramePattern {
@ -42,9 +44,19 @@ class ScalabilityStructureL2T2KeyShift : public ScalableVideoController {
kDelta0,
kDelta1,
};
LayerFrameConfig KeyFrameConfig() const;
static constexpr int kNumSpatialLayers = 2;
static constexpr int kNumTemporalLayers = 2;
bool DecodeTargetIsActive(int sid, int tid) const {
return active_decode_targets_[sid * kNumTemporalLayers + tid];
}
void SetDecodeTargetIsActive(int sid, int tid, bool value) {
active_decode_targets_.set(sid * kNumTemporalLayers + tid, value);
}
FramePattern next_pattern_ = kKey;
std::bitset<32> active_decode_targets_ = 0b1111;
};
} // namespace webrtc

View File

@ -0,0 +1,358 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/video_coding/svc/scalability_structure_l2t2_key_shift.h"
#include <vector>
#include "api/array_view.h"
#include "api/transport/rtp/dependency_descriptor.h"
#include "common_video/generic_frame_descriptor/generic_frame_info.h"
#include "modules/video_coding/svc/scalability_structure_test_helpers.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::SizeIs;
// S1T1 3 7
// / /
// S1T0 1---5---9
// |
// S0T1 | 4 8
// | / /
// S0T0 0-2---6
// Time-> 0 1 2 3 4
TEST(ScalabilityStructureL2T2KeyShiftTest, DecodeTargetsAreEnabledByDefault) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/5, frames);
ASSERT_THAT(frames, SizeIs(10));
EXPECT_EQ(frames[0].spatial_id, 0);
EXPECT_EQ(frames[1].spatial_id, 1);
EXPECT_EQ(frames[2].spatial_id, 0);
EXPECT_EQ(frames[3].spatial_id, 1);
EXPECT_EQ(frames[4].spatial_id, 0);
EXPECT_EQ(frames[5].spatial_id, 1);
EXPECT_EQ(frames[6].spatial_id, 0);
EXPECT_EQ(frames[7].spatial_id, 1);
EXPECT_EQ(frames[8].spatial_id, 0);
EXPECT_EQ(frames[9].spatial_id, 1);
// spatial_id = 0 has the temporal shift.
EXPECT_EQ(frames[0].temporal_id, 0);
EXPECT_EQ(frames[2].temporal_id, 0);
EXPECT_EQ(frames[4].temporal_id, 1);
EXPECT_EQ(frames[6].temporal_id, 0);
EXPECT_EQ(frames[8].temporal_id, 1);
// spatial_id = 1 hasn't temporal shift.
EXPECT_EQ(frames[1].temporal_id, 0);
EXPECT_EQ(frames[3].temporal_id, 1);
EXPECT_EQ(frames[5].temporal_id, 0);
EXPECT_EQ(frames[7].temporal_id, 1);
EXPECT_EQ(frames[9].temporal_id, 0);
// Key frame diff.
EXPECT_THAT(frames[0].frame_diffs, IsEmpty());
EXPECT_THAT(frames[1].frame_diffs, ElementsAre(1));
// S0T0 frame diffs
EXPECT_THAT(frames[2].frame_diffs, ElementsAre(2));
EXPECT_THAT(frames[6].frame_diffs, ElementsAre(4));
// S1T0 frame diffs
EXPECT_THAT(frames[5].frame_diffs, ElementsAre(4));
EXPECT_THAT(frames[9].frame_diffs, ElementsAre(4));
// T1 frames refer T0 frame of same spatial layer which is 2 frame ids away.
EXPECT_THAT(frames[3].frame_diffs, ElementsAre(2));
EXPECT_THAT(frames[4].frame_diffs, ElementsAre(2));
EXPECT_THAT(frames[7].frame_diffs, ElementsAre(2));
EXPECT_THAT(frames[8].frame_diffs, ElementsAre(2));
}
// S1T0 1---4---7
// |
// S0T1 | 3 6
// | / /
// S0T0 0-2---5--
// Time-> 0 1 2 3 4
TEST(ScalabilityStructureL2T2KeyShiftTest, DisableS1T1Layer) {
ScalabilityStructureL2T2KeyShift structure;
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/2, /*s1=*/1));
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/5, frames);
ASSERT_THAT(frames, SizeIs(8));
EXPECT_EQ(frames[0].spatial_id, 0);
EXPECT_EQ(frames[1].spatial_id, 1);
EXPECT_EQ(frames[2].spatial_id, 0);
EXPECT_EQ(frames[3].spatial_id, 0);
EXPECT_EQ(frames[4].spatial_id, 1);
EXPECT_EQ(frames[5].spatial_id, 0);
EXPECT_EQ(frames[6].spatial_id, 0);
EXPECT_EQ(frames[7].spatial_id, 1);
// spatial_id = 0 has the temporal shift.
EXPECT_EQ(frames[0].temporal_id, 0);
EXPECT_EQ(frames[2].temporal_id, 0);
EXPECT_EQ(frames[3].temporal_id, 1);
EXPECT_EQ(frames[5].temporal_id, 0);
EXPECT_EQ(frames[6].temporal_id, 1);
// spatial_id = 1 has single temporal layer.
EXPECT_EQ(frames[1].temporal_id, 0);
EXPECT_EQ(frames[4].temporal_id, 0);
EXPECT_EQ(frames[5].temporal_id, 0);
}
// S1T1 3 |
// / |
// S1T0 1---5+--7
// | |
// S0T1 | 4|
// | / |
// S0T0 0-2--+6---8
// Time-> 0 1 2 3 4 5
TEST(ScalabilityStructureL2T2KeyShiftTest, DisableT1LayersAfterFewFrames) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
EXPECT_THAT(frames, SizeIs(6));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/1, /*s1=*/1));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(9));
// Skip validation before T1 was disabled as that is covered by the test
// where no layers are disabled.
EXPECT_EQ(frames[6].spatial_id, 0);
EXPECT_EQ(frames[7].spatial_id, 1);
EXPECT_EQ(frames[8].spatial_id, 0);
EXPECT_EQ(frames[6].temporal_id, 0);
EXPECT_EQ(frames[7].temporal_id, 0);
EXPECT_EQ(frames[8].temporal_id, 0);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
// S1T1 1 3
// / /
// S1T0 0---2
// Time-> 0 1 2 3 4 5
TEST(ScalabilityStructureL2T2KeyShiftTest, DisableS0FromTheStart) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/0, /*s1=*/2));
wrapper.GenerateFrames(/*num_temporal_units=*/4, frames);
EXPECT_THAT(frames, SizeIs(4));
EXPECT_EQ(frames[0].spatial_id, 1);
EXPECT_EQ(frames[1].spatial_id, 1);
EXPECT_EQ(frames[2].spatial_id, 1);
EXPECT_EQ(frames[3].spatial_id, 1);
EXPECT_EQ(frames[0].temporal_id, 0);
EXPECT_EQ(frames[1].temporal_id, 1);
EXPECT_EQ(frames[2].temporal_id, 0);
EXPECT_EQ(frames[3].temporal_id, 1);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
// S1T1 3 |6 8
// / / /
// S1T0 1---5+--7
// | |
// S0T1 | 4|
// | / |
// S0T0 0-2 |
// Time-> 0 1 2 3 4 5
TEST(ScalabilityStructureL2T2KeyShiftTest, DisableS0AfterFewFrames) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
EXPECT_THAT(frames, SizeIs(6));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/0, /*s1=*/2));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(9));
// Expect frame[6] is delta frame.
EXPECT_THAT(frames[6].frame_diffs, ElementsAre(1));
// Skip validation before S0 was disabled as that should be covered by
// test where no layers are disabled.
EXPECT_EQ(frames[6].spatial_id, 1);
EXPECT_EQ(frames[7].spatial_id, 1);
EXPECT_EQ(frames[8].spatial_id, 1);
EXPECT_EQ(frames[6].temporal_id, 1);
EXPECT_EQ(frames[7].temporal_id, 0);
EXPECT_EQ(frames[8].temporal_id, 1);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
// S1T1 3| | 8
// / | | /
// S1T0 1 | |6
// | | ||
// S0T1 | |4||
// | / ||
// S0T0 0-2| |5-7
// Time-> 0 1 2 3 4 5
TEST(ScalabilityStructureL2T2KeyShiftTest, ReenableS1TriggersKeyFrame) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
EXPECT_THAT(frames, SizeIs(4));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/2, /*s1=*/0));
wrapper.GenerateFrames(/*num_temporal_units=*/1, frames);
EXPECT_THAT(frames, SizeIs(5));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/2, /*s1=*/2));
wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
ASSERT_THAT(frames, SizeIs(9));
EXPECT_THAT(frames[4].spatial_id, 0);
EXPECT_THAT(frames[4].temporal_id, 1);
// Expect frame[5] to be a key frame.
EXPECT_TRUE(wrapper.FrameReferencesAreValid(
rtc::MakeArrayView(frames.data() + 5, 4)));
EXPECT_THAT(frames[5].spatial_id, 0);
EXPECT_THAT(frames[6].spatial_id, 1);
EXPECT_THAT(frames[7].spatial_id, 0);
EXPECT_THAT(frames[8].spatial_id, 1);
// S0 should do temporal shift after the key frame.
EXPECT_THAT(frames[5].temporal_id, 0);
EXPECT_THAT(frames[7].temporal_id, 0);
// No temporal shift for the top spatial layer.
EXPECT_THAT(frames[6].temporal_id, 0);
EXPECT_THAT(frames[8].temporal_id, 1);
}
TEST(ScalabilityStructureL2T2KeyShiftTest, EnableOnlyS0T0FromTheStart) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/1, /*s1=*/0));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(3));
EXPECT_EQ(frames[0].spatial_id, 0);
EXPECT_EQ(frames[1].spatial_id, 0);
EXPECT_EQ(frames[2].spatial_id, 0);
EXPECT_EQ(frames[0].temporal_id, 0);
EXPECT_EQ(frames[1].temporal_id, 0);
EXPECT_EQ(frames[2].temporal_id, 0);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
// S1T1 3|
// / |
// S1T0 1 |
// | |
// S0T1 | |
// | |
// S0T0 0-2+4-5-6
// Time-> 0 1 2 3 4
TEST(ScalabilityStructureL2T2KeyShiftTest, EnableOnlyS0T0AfterFewFrames) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
EXPECT_THAT(frames, SizeIs(4));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/1, /*s1=*/0));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(7));
EXPECT_EQ(frames[4].spatial_id, 0);
EXPECT_EQ(frames[5].spatial_id, 0);
EXPECT_EQ(frames[6].spatial_id, 0);
EXPECT_EQ(frames[4].temporal_id, 0);
EXPECT_EQ(frames[5].temporal_id, 0);
EXPECT_EQ(frames[6].temporal_id, 0);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
TEST(ScalabilityStructureL2T2KeyShiftTest, EnableOnlyS1T0FromTheStart) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/0, /*s1=*/1));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(3));
EXPECT_EQ(frames[0].spatial_id, 1);
EXPECT_EQ(frames[1].spatial_id, 1);
EXPECT_EQ(frames[2].spatial_id, 1);
EXPECT_EQ(frames[0].temporal_id, 0);
EXPECT_EQ(frames[1].temporal_id, 0);
EXPECT_EQ(frames[2].temporal_id, 0);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
// S1T1 3|
// / |
// S1T0 1--+4-5-6
// | |
// S0T1 | |
// | |
// S0T0 0-2|
// Time-> 0 1 2 3 4
TEST(ScalabilityStructureL2T2KeyShiftTest, EnableOnlyS1T0AfterFewFrames) {
ScalabilityStructureL2T2KeyShift structure;
ScalabilityStructureWrapper wrapper(structure);
std::vector<GenericFrameInfo> frames;
wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
EXPECT_THAT(frames, SizeIs(4));
structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/0, /*s1=*/1));
wrapper.GenerateFrames(/*num_temporal_units=*/3, frames);
ASSERT_THAT(frames, SizeIs(7));
EXPECT_EQ(frames[4].spatial_id, 1);
EXPECT_EQ(frames[5].spatial_id, 1);
EXPECT_EQ(frames[6].spatial_id, 1);
EXPECT_EQ(frames[4].temporal_id, 0);
EXPECT_EQ(frames[5].temporal_id, 0);
EXPECT_EQ(frames[6].temporal_id, 0);
EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
}
} // namespace
} // namespace webrtc

View File

@ -250,11 +250,7 @@ TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) {
}
}
// TODO(danilchap): Merge with ScalabilityStructureTest when SetRates
// implemented for all tested structures.
class ScalabilityStructureSetRatesTest : public ScalabilityStructureTest {};
TEST_P(ScalabilityStructureSetRatesTest, ProduceNoFrameForDisabledLayers) {
TEST_P(ScalabilityStructureTest, ProduceNoFrameForDisabledLayers) {
std::unique_ptr<ScalableVideoController> svc_controller =
CreateScalabilityStructure(GetParam().name);
ScalableVideoController::StreamLayersConfig structure =
@ -311,24 +307,5 @@ INSTANTIATE_TEST_SUITE_P(
return info.param.name;
});
// TODO(danilchap): Merge with ScalabilityStructureTest when the functionality
// is implemented for all tested structures.
INSTANTIATE_TEST_SUITE_P(
Svc,
ScalabilityStructureSetRatesTest,
Values(SvcTestParam{"L1T2", /*num_temporal_units=*/4},
SvcTestParam{"L1T3", /*num_temporal_units=*/8},
SvcTestParam{"L2T1", /*num_temporal_units=*/3},
SvcTestParam{"L2T1_KEY", /*num_temporal_units=*/3},
SvcTestParam{"L2T2", /*num_temporal_units=*/4},
SvcTestParam{"L2T2_KEY", /*num_temporal_units=*/4},
SvcTestParam{"L3T1", /*num_temporal_units=*/3},
SvcTestParam{"L3T3", /*num_temporal_units=*/8},
SvcTestParam{"L3T3_KEY", /*num_temporal_units=*/8},
SvcTestParam{"S2T1", /*num_temporal_units=*/3}),
[](const testing::TestParamInfo<SvcTestParam>& info) {
return info.param.name;
});
} // namespace
} // namespace webrtc