xref: /aosp_15_r20/external/webrtc/modules/video_coding/svc/scalability_structure_full_svc_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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