1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "modules/video_coding/svc/scalability_structure_full_svc.h"
11
12 #include <vector>
13
14 #include "modules/video_coding/svc/scalability_structure_test_helpers.h"
15 #include "test/gmock.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19 namespace {
20
21 using ::testing::IsEmpty;
22 using ::testing::SizeIs;
23
TEST(ScalabilityStructureL3T3Test,SkipT0FrameByEncoderKeepsReferencesValid)24 TEST(ScalabilityStructureL3T3Test, SkipT0FrameByEncoderKeepsReferencesValid) {
25 std::vector<GenericFrameInfo> frames;
26 ScalabilityStructureL3T3 structure;
27 ScalabilityStructureWrapper wrapper(structure);
28
29 // Only S0T0 decode target is enabled.
30 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/1, /*s1=*/0));
31 // Encoder generates S0T0 key frame.
32 wrapper.GenerateFrames(/*num_temporal_units=*/1, frames);
33 EXPECT_THAT(frames, SizeIs(1));
34 // Spatial layers 1 is enabled.
35 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/1, /*s1=*/1));
36 // Encoder tries to generate S0T0 and S1T0 delta frames but they are dropped.
37 structure.NextFrameConfig(/*restart=*/false);
38 // Encoder successfully generates S0T0 and S1T0 delta frames.
39 wrapper.GenerateFrames(/*num_temporal_units=*/1, frames);
40 EXPECT_THAT(frames, SizeIs(3));
41
42 EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
43 }
44
TEST(ScalabilityStructureL3T3Test,SkipS1T1FrameKeepsStructureValid)45 TEST(ScalabilityStructureL3T3Test, SkipS1T1FrameKeepsStructureValid) {
46 ScalabilityStructureL3T3 structure;
47 ScalabilityStructureWrapper wrapper(structure);
48
49 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/3, /*s1=*/3));
50 auto frames = wrapper.GenerateFrames(/*num_temporal_units=*/1);
51 EXPECT_THAT(frames, SizeIs(2));
52 EXPECT_EQ(frames[0].temporal_id, 0);
53
54 frames = wrapper.GenerateFrames(/*num_temporal_units=*/1);
55 EXPECT_THAT(frames, SizeIs(2));
56 EXPECT_EQ(frames[0].temporal_id, 2);
57
58 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/3, /*s1=*/0));
59 frames = wrapper.GenerateFrames(/*num_temporal_units=*/1);
60 EXPECT_THAT(frames, SizeIs(1));
61 EXPECT_EQ(frames[0].temporal_id, 1);
62
63 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/3, /*s1=*/3));
64 // Rely on checks inside GenerateFrames frame references are valid.
65 frames = wrapper.GenerateFrames(/*num_temporal_units=*/1);
66 EXPECT_THAT(frames, SizeIs(2));
67 EXPECT_EQ(frames[0].temporal_id, 2);
68 }
69
TEST(ScalabilityStructureL3T3Test,SkipT1FrameByEncoderKeepsReferencesValid)70 TEST(ScalabilityStructureL3T3Test, SkipT1FrameByEncoderKeepsReferencesValid) {
71 std::vector<GenericFrameInfo> frames;
72 ScalabilityStructureL3T3 structure;
73 ScalabilityStructureWrapper wrapper(structure);
74
75 // 1st 2 temporal units (T0 and T2)
76 wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
77 // Simulate T1 frame dropped by the encoder,
78 // i.e. retrieve config, but skip calling OnEncodeDone.
79 structure.NextFrameConfig(/*restart=*/false);
80 // one more temporal units (T2)
81 wrapper.GenerateFrames(/*num_temporal_units=*/1, frames);
82
83 EXPECT_TRUE(wrapper.FrameReferencesAreValid(frames));
84 }
85
TEST(ScalabilityStructureL3T3Test,SkippingFrameReusePreviousFrameConfiguration)86 TEST(ScalabilityStructureL3T3Test,
87 SkippingFrameReusePreviousFrameConfiguration) {
88 std::vector<GenericFrameInfo> frames;
89 ScalabilityStructureL3T3 structure;
90 ScalabilityStructureWrapper wrapper(structure);
91
92 // 1st 2 temporal units (T0 and T2)
93 wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
94 ASSERT_THAT(frames, SizeIs(6));
95 ASSERT_EQ(frames[0].temporal_id, 0);
96 ASSERT_EQ(frames[3].temporal_id, 2);
97
98 // Simulate a frame dropped by the encoder,
99 // i.e. retrieve config, but skip calling OnEncodeDone.
100 structure.NextFrameConfig(/*restart=*/false);
101 // two more temporal unit, expect temporal pattern continues
102 wrapper.GenerateFrames(/*num_temporal_units=*/2, frames);
103 ASSERT_THAT(frames, SizeIs(12));
104 // Expect temporal pattern continues as if there were no dropped frames.
105 EXPECT_EQ(frames[6].temporal_id, 1);
106 EXPECT_EQ(frames[9].temporal_id, 2);
107 }
108
TEST(ScalabilityStructureL3T3Test,SwitchSpatialLayerBeforeT1Frame)109 TEST(ScalabilityStructureL3T3Test, SwitchSpatialLayerBeforeT1Frame) {
110 ScalabilityStructureL3T3 structure;
111 ScalabilityStructureWrapper wrapper(structure);
112
113 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/2, /*s1=*/0));
114 EXPECT_THAT(wrapper.GenerateFrames(1), SizeIs(1));
115 structure.OnRatesUpdated(EnableTemporalLayers(/*s0=*/0, /*s1=*/2));
116 auto frames = wrapper.GenerateFrames(1);
117 ASSERT_THAT(frames, SizeIs(1));
118 EXPECT_THAT(frames[0].frame_diffs, IsEmpty());
119 EXPECT_EQ(frames[0].temporal_id, 0);
120 }
121
122 } // namespace
123 } // namespace webrtc
124