• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include "modules/rtp_rtcp/source/active_decode_targets_helper.h"
12 
13 #include <vector>
14 
15 #include "absl/types/optional.h"
16 #include "test/gtest.h"
17 
18 namespace webrtc {
19 namespace {
20 constexpr std::bitset<32> kAll = ~uint32_t{0};
21 }  // namespace
22 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptOnKeyFrameWhenAllDecodeTargetsAreActive)23 TEST(ActiveDecodeTargetsHelperTest,
24      ReturnsNulloptOnKeyFrameWhenAllDecodeTargetsAreActive) {
25   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
26   ActiveDecodeTargetsHelper helper;
27   int chain_diffs[] = {0};
28   helper.OnFrame(kDecodeTargetProtectedByChain,
29                  /*active_decode_targets=*/0b11,
30                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs);
31 
32   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
33 }
34 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptOnKeyFrameWhenAllDecodeTargetsAreActiveAfterDeltaFrame)35 TEST(ActiveDecodeTargetsHelperTest,
36      ReturnsNulloptOnKeyFrameWhenAllDecodeTargetsAreActiveAfterDeltaFrame) {
37   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
38   ActiveDecodeTargetsHelper helper;
39   int chain_diffs_key[] = {0};
40   helper.OnFrame(kDecodeTargetProtectedByChain,
41                  /*active_decode_targets=*/0b11,
42                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs_key);
43   int chain_diffs_delta[] = {1};
44   helper.OnFrame(kDecodeTargetProtectedByChain,
45                  /*active_decode_targets=*/0b01,
46                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs_delta);
47 
48   ASSERT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b01u);
49   helper.OnFrame(kDecodeTargetProtectedByChain,
50                  /*active_decode_targets=*/0b11,
51                  /*is_keyframe=*/true, /*frame_id=*/3, chain_diffs_key);
52 
53   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
54 }
55 
TEST(ActiveDecodeTargetsHelperTest,ReturnsBitmaskOnKeyFrameWhenSomeDecodeTargetsAreInactive)56 TEST(ActiveDecodeTargetsHelperTest,
57      ReturnsBitmaskOnKeyFrameWhenSomeDecodeTargetsAreInactive) {
58   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
59   ActiveDecodeTargetsHelper helper;
60   int chain_diffs[] = {0};
61   helper.OnFrame(kDecodeTargetProtectedByChain,
62                  /*active_decode_targets=*/0b01,
63                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs);
64 
65   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b01u);
66 }
67 
TEST(ActiveDecodeTargetsHelperTest,ReturnsBitmaskOnKeyFrameWhenSomeDecodeTargetsAreInactiveAfterDeltaFrame)68 TEST(ActiveDecodeTargetsHelperTest,
69      ReturnsBitmaskOnKeyFrameWhenSomeDecodeTargetsAreInactiveAfterDeltaFrame) {
70   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
71   ActiveDecodeTargetsHelper helper;
72   int chain_diffs_key[] = {0};
73   helper.OnFrame(kDecodeTargetProtectedByChain,
74                  /*active_decode_targets=*/0b01,
75                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs_key);
76   int chain_diffs_delta[] = {1};
77   helper.OnFrame(kDecodeTargetProtectedByChain,
78                  /*active_decode_targets=*/0b01,
79                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs_delta);
80 
81   ASSERT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
82   helper.OnFrame(kDecodeTargetProtectedByChain,
83                  /*active_decode_targets=*/0b01,
84                  /*is_keyframe=*/true, /*frame_id=*/3, chain_diffs_key);
85 
86   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b01u);
87 }
88 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptWhenActiveDecodeTargetsAreUnused)89 TEST(ActiveDecodeTargetsHelperTest,
90      ReturnsNulloptWhenActiveDecodeTargetsAreUnused) {
91   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
92   ActiveDecodeTargetsHelper helper;
93   int chain_diffs[] = {0};
94   helper.OnFrame(kDecodeTargetProtectedByChain,
95                  /*active_decode_targets=*/kAll,
96                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs);
97   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
98 
99   helper.OnFrame(kDecodeTargetProtectedByChain,
100                  /*active_decode_targets=*/kAll,
101                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs);
102   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
103 }
104 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptOnDeltaFrameAfterSentOnKeyFrame)105 TEST(ActiveDecodeTargetsHelperTest,
106      ReturnsNulloptOnDeltaFrameAfterSentOnKeyFrame) {
107   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
108   ActiveDecodeTargetsHelper helper;
109   int chain_diffs_key[] = {0};
110   helper.OnFrame(kDecodeTargetProtectedByChain,
111                  /*active_decode_targets=*/0b01,
112                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs_key);
113   int chain_diffs_delta[] = {1};
114   helper.OnFrame(kDecodeTargetProtectedByChain,
115                  /*active_decode_targets=*/0b01,
116                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs_delta);
117 
118   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
119 }
120 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNewBitmaskOnDeltaFrame)121 TEST(ActiveDecodeTargetsHelperTest, ReturnsNewBitmaskOnDeltaFrame) {
122   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
123   ActiveDecodeTargetsHelper helper;
124   int chain_diffs_key[] = {0};
125   helper.OnFrame(kDecodeTargetProtectedByChain,
126                  /*active_decode_targets=*/0b11,
127                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs_key);
128   ASSERT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
129   int chain_diffs_delta[] = {1};
130   helper.OnFrame(kDecodeTargetProtectedByChain,
131                  /*active_decode_targets=*/0b01,
132                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs_delta);
133 
134   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b01u);
135 }
136 
TEST(ActiveDecodeTargetsHelperTest,ReturnsBitmaskWhenAllDecodeTargetsReactivatedOnDeltaFrame)137 TEST(ActiveDecodeTargetsHelperTest,
138      ReturnsBitmaskWhenAllDecodeTargetsReactivatedOnDeltaFrame) {
139   constexpr int kDecodeTargetProtectedByChain[] = {0, 0};
140   ActiveDecodeTargetsHelper helper;
141   int chain_diffs_key[] = {0};
142   helper.OnFrame(kDecodeTargetProtectedByChain,
143                  /*active_decode_targets=*/0b01,
144                  /*is_keyframe=*/true, /*frame_id=*/1, chain_diffs_key);
145   ASSERT_NE(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
146   int chain_diffs_delta[] = {1};
147   helper.OnFrame(kDecodeTargetProtectedByChain,
148                  /*active_decode_targets=*/0b01,
149                  /*is_keyframe=*/false, /*frame_id=*/2, chain_diffs_delta);
150   ASSERT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
151 
152   // Reactive all the decode targets
153   helper.OnFrame(kDecodeTargetProtectedByChain,
154                  /*active_decode_targets=*/kAll,
155                  /*is_keyframe=*/false, /*frame_id=*/3, chain_diffs_delta);
156   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b11u);
157 }
158 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptAfterSentOnAllActiveChains)159 TEST(ActiveDecodeTargetsHelperTest, ReturnsNulloptAfterSentOnAllActiveChains) {
160   // Active decode targets (0 and 1) are protected by chains 1 and 2.
161   const std::bitset<32> kSome = 0b011;
162   constexpr int kDecodeTargetProtectedByChain[] = {2, 1, 0};
163 
164   ActiveDecodeTargetsHelper helper;
165   int chain_diffs_key[] = {0, 0, 0};
166   helper.OnFrame(kDecodeTargetProtectedByChain,
167                  /*active_decode_targets=*/0b111,
168                  /*is_keyframe=*/true,
169                  /*frame_id=*/0, chain_diffs_key);
170   ASSERT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
171 
172   int chain_diffs_delta1[] = {1, 1, 1};
173   helper.OnFrame(kDecodeTargetProtectedByChain,
174                  /*active_decode_targets=*/kSome,
175                  /*is_keyframe=*/false,
176                  /*frame_id=*/1, chain_diffs_delta1);
177   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b011u);
178 
179   int chain_diffs_delta2[] = {2, 2, 1};  // Previous frame was part of chain#2
180   helper.OnFrame(kDecodeTargetProtectedByChain,
181                  /*active_decode_targets=*/kSome,
182                  /*is_keyframe=*/false,
183                  /*frame_id=*/2, chain_diffs_delta2);
184   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b011u);
185 
186   // active_decode_targets_bitmask was send on chains 1 and 2. It was never sent
187   // on chain 0, but chain 0 only protects inactive decode target#2
188   int chain_diffs_delta3[] = {3, 1, 2};  // Previous frame was part of chain#1
189   helper.OnFrame(kDecodeTargetProtectedByChain,
190                  /*active_decode_targets=*/kSome,
191                  /*is_keyframe=*/false,
192                  /*frame_id=*/3, chain_diffs_delta3);
193   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
194 }
195 
TEST(ActiveDecodeTargetsHelperTest,ReturnsBitmaskWhenChanged)196 TEST(ActiveDecodeTargetsHelperTest, ReturnsBitmaskWhenChanged) {
197   constexpr int kDecodeTargetProtectedByChain[] = {0, 1, 1};
198 
199   ActiveDecodeTargetsHelper helper;
200   int chain_diffs_key[] = {0, 0};
201   helper.OnFrame(kDecodeTargetProtectedByChain, /*active_decode_targets=*/0b111,
202                  /*is_keyframe=*/true,
203                  /*frame_id=*/0, chain_diffs_key);
204   int chain_diffs_delta1[] = {1, 1};
205   helper.OnFrame(kDecodeTargetProtectedByChain,
206                  /*active_decode_targets=*/0b011,
207                  /*is_keyframe=*/false,
208                  /*frame_id=*/1, chain_diffs_delta1);
209   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b011u);
210 
211   int chain_diffs_delta2[] = {1, 2};
212   helper.OnFrame(kDecodeTargetProtectedByChain,
213                  /*active_decode_targets=*/0b101,
214                  /*is_keyframe=*/false,
215                  /*frame_id=*/2, chain_diffs_delta2);
216   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b101u);
217 
218   // active_decode_target_bitmask was send on chain0, but it was an old one.
219   int chain_diffs_delta3[] = {2, 1};
220   helper.OnFrame(kDecodeTargetProtectedByChain,
221                  /*active_decode_targets=*/0b101,
222                  /*is_keyframe=*/false,
223                  /*frame_id=*/3, chain_diffs_delta3);
224   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b101u);
225 }
226 
TEST(ActiveDecodeTargetsHelperTest,ReturnsNulloptWhenChainsAreNotUsed)227 TEST(ActiveDecodeTargetsHelperTest, ReturnsNulloptWhenChainsAreNotUsed) {
228   const rtc::ArrayView<const int> kDecodeTargetProtectedByChain;
229   const rtc::ArrayView<const int> kNoChainDiffs;
230 
231   ActiveDecodeTargetsHelper helper;
232   helper.OnFrame(kDecodeTargetProtectedByChain, /*active_decode_targets=*/kAll,
233                  /*is_keyframe=*/true,
234                  /*frame_id=*/0, kNoChainDiffs);
235   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
236 
237   helper.OnFrame(kDecodeTargetProtectedByChain,
238                  /*active_decode_targets=*/0b101,
239                  /*is_keyframe=*/false,
240                  /*frame_id=*/1, kNoChainDiffs);
241   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
242 }
243 
TEST(ActiveDecodeTargetsHelperTest,Supports32DecodeTargets)244 TEST(ActiveDecodeTargetsHelperTest, Supports32DecodeTargets) {
245   std::bitset<32> some;
246   std::vector<int> decode_target_protected_by_chain(32);
247   for (int i = 0; i < 32; ++i) {
248     decode_target_protected_by_chain[i] = i;
249     some[i] = i % 2 == 0;
250   }
251 
252   ActiveDecodeTargetsHelper helper;
253   std::vector<int> chain_diffs_key(32, 0);
254   helper.OnFrame(decode_target_protected_by_chain,
255                  /*active_decode_targets=*/some,
256                  /*is_keyframe=*/true,
257                  /*frame_id=*/1, chain_diffs_key);
258   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), some.to_ulong());
259   std::vector<int> chain_diffs_delta(32, 1);
260   helper.OnFrame(decode_target_protected_by_chain,
261                  /*active_decode_targets=*/some,
262                  /*is_keyframe=*/false,
263                  /*frame_id=*/2, chain_diffs_delta);
264   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
265   helper.OnFrame(decode_target_protected_by_chain,
266                  /*active_decode_targets=*/kAll,
267                  /*is_keyframe=*/false,
268                  /*frame_id=*/2, chain_diffs_delta);
269   EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), kAll.to_ulong());
270 }
271 
272 }  // namespace webrtc
273