xref: /aosp_15_r20/external/webrtc/video/buffered_frame_decryptor_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2018 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 "video/buffered_frame_decryptor.h"
12 
13 #include <map>
14 #include <memory>
15 #include <vector>
16 
17 #include "api/test/mock_frame_decryptor.h"
18 #include "modules/video_coding/packet_buffer.h"
19 #include "system_wrappers/include/clock.h"
20 #include "test/gmock.h"
21 #include "test/gtest.h"
22 #include "test/scoped_key_value_config.h"
23 
24 using ::testing::Return;
25 
26 namespace webrtc {
27 namespace {
28 
DecryptSuccess()29 FrameDecryptorInterface::Result DecryptSuccess() {
30   return FrameDecryptorInterface::Result(FrameDecryptorInterface::Status::kOk,
31                                          0);
32 }
33 
DecryptFail()34 FrameDecryptorInterface::Result DecryptFail() {
35   return FrameDecryptorInterface::Result(
36       FrameDecryptorInterface::Status::kFailedToDecrypt, 0);
37 }
38 
39 }  // namespace
40 
41 class BufferedFrameDecryptorTest : public ::testing::Test,
42                                    public OnDecryptedFrameCallback,
43                                    public OnDecryptionStatusChangeCallback {
44  public:
45   // Implements the OnDecryptedFrameCallbackInterface
OnDecryptedFrame(std::unique_ptr<RtpFrameObject> frame)46   void OnDecryptedFrame(std::unique_ptr<RtpFrameObject> frame) override {
47     decrypted_frame_call_count_++;
48   }
49 
OnDecryptionStatusChange(FrameDecryptorInterface::Status status)50   void OnDecryptionStatusChange(FrameDecryptorInterface::Status status) {
51     ++decryption_status_change_count_;
52   }
53 
54   // Returns a new fake RtpFrameObject it abstracts the difficult construction
55   // of the RtpFrameObject to simplify testing.
CreateRtpFrameObject(bool key_frame)56   std::unique_ptr<RtpFrameObject> CreateRtpFrameObject(bool key_frame) {
57     seq_num_++;
58     RTPVideoHeader rtp_video_header;
59     rtp_video_header.generic.emplace();
60 
61     // clang-format off
62     return std::make_unique<RtpFrameObject>(
63         seq_num_,
64         seq_num_,
65         /*markerBit=*/true,
66         /*times_nacked=*/0,
67         /*first_packet_received_time=*/0,
68         /*last_packet_received_time=*/0,
69         /*rtp_timestamp=*/0,
70         /*ntp_time_ms=*/0,
71         VideoSendTiming(),
72         /*payload_type=*/0,
73         kVideoCodecGeneric,
74         kVideoRotation_0,
75         VideoContentType::UNSPECIFIED,
76         rtp_video_header,
77         /*color_space=*/absl::nullopt,
78         RtpPacketInfos(),
79         EncodedImageBuffer::Create(/*size=*/0));
80     // clang-format on
81   }
82 
83  protected:
BufferedFrameDecryptorTest()84   BufferedFrameDecryptorTest() {
85     fake_packet_data_ = std::vector<uint8_t>(100);
86     decrypted_frame_call_count_ = 0;
87     decryption_status_change_count_ = 0;
88     seq_num_ = 0;
89     mock_frame_decryptor_ = rtc::make_ref_counted<MockFrameDecryptor>();
90     buffered_frame_decryptor_ =
91         std::make_unique<BufferedFrameDecryptor>(this, this, field_trials_);
92     buffered_frame_decryptor_->SetFrameDecryptor(mock_frame_decryptor_);
93   }
94 
95   static const size_t kMaxStashedFrames;
96 
97   test::ScopedKeyValueConfig field_trials_;
98   std::vector<uint8_t> fake_packet_data_;
99   rtc::scoped_refptr<MockFrameDecryptor> mock_frame_decryptor_;
100   std::unique_ptr<BufferedFrameDecryptor> buffered_frame_decryptor_;
101   size_t decrypted_frame_call_count_;
102   size_t decryption_status_change_count_ = 0;
103   uint16_t seq_num_;
104 };
105 
106 const size_t BufferedFrameDecryptorTest::kMaxStashedFrames = 24;
107 
108 // Callback should always be triggered on a successful decryption.
TEST_F(BufferedFrameDecryptorTest,CallbackCalledOnSuccessfulDecryption)109 TEST_F(BufferedFrameDecryptorTest, CallbackCalledOnSuccessfulDecryption) {
110   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
111       .Times(1)
112       .WillOnce(Return(DecryptSuccess()));
113   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
114       .Times(1)
115       .WillOnce(Return(0));
116   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
117   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(1));
118   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(1));
119 }
120 
121 // An initial fail to decrypt should not trigger the callback.
TEST_F(BufferedFrameDecryptorTest,CallbackNotCalledOnFailedDecryption)122 TEST_F(BufferedFrameDecryptorTest, CallbackNotCalledOnFailedDecryption) {
123   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
124       .Times(1)
125       .WillOnce(Return(DecryptFail()));
126   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
127       .Times(1)
128       .WillOnce(Return(0));
129   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
130   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(0));
131   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(1));
132 }
133 
134 // Initial failures should be stored and retried after the first successful
135 // decryption.
TEST_F(BufferedFrameDecryptorTest,DelayedCallbackOnBufferedFrames)136 TEST_F(BufferedFrameDecryptorTest, DelayedCallbackOnBufferedFrames) {
137   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
138       .Times(3)
139       .WillOnce(Return(DecryptFail()))
140       .WillOnce(Return(DecryptSuccess()))
141       .WillOnce(Return(DecryptSuccess()));
142   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
143       .Times(3)
144       .WillRepeatedly(Return(0));
145 
146   // The first decrypt will fail stashing the first frame.
147   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
148   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(0));
149   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(1));
150   // The second call will succeed playing back both frames.
151   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(false));
152   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(2));
153   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(2));
154 }
155 
156 // Subsequent failure to decrypts after the first successful decryption should
157 // fail to decryptk
TEST_F(BufferedFrameDecryptorTest,FTDDiscardedAfterFirstSuccess)158 TEST_F(BufferedFrameDecryptorTest, FTDDiscardedAfterFirstSuccess) {
159   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
160       .Times(4)
161       .WillOnce(Return(DecryptFail()))
162       .WillOnce(Return(DecryptSuccess()))
163       .WillOnce(Return(DecryptSuccess()))
164       .WillOnce(Return(DecryptFail()));
165   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
166       .Times(4)
167       .WillRepeatedly(Return(0));
168 
169   // The first decrypt will fail stashing the first frame.
170   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
171   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(0));
172   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(1));
173   // The second call will succeed playing back both frames.
174   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(false));
175   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(2));
176   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(2));
177   // A new failure call will not result in an additional decrypted frame
178   // callback.
179   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
180   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(2));
181   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(3));
182 }
183 
184 // Validate that the maximum number of stashed frames cannot be exceeded even if
185 // more than its maximum arrives before the first successful decryption.
TEST_F(BufferedFrameDecryptorTest,MaximumNumberOfFramesStored)186 TEST_F(BufferedFrameDecryptorTest, MaximumNumberOfFramesStored) {
187   const size_t failed_to_decrypt_count = kMaxStashedFrames * 2;
188   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
189       .Times(failed_to_decrypt_count)
190       .WillRepeatedly(Return(DecryptFail()));
191   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
192       .WillRepeatedly(Return(0));
193 
194   for (size_t i = 0; i < failed_to_decrypt_count; ++i) {
195     buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
196   }
197   EXPECT_EQ(decrypted_frame_call_count_, static_cast<size_t>(0));
198   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(1));
199 
200   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
201       .Times(kMaxStashedFrames + 1)
202       .WillRepeatedly(Return(DecryptSuccess()));
203   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
204   EXPECT_EQ(decrypted_frame_call_count_, kMaxStashedFrames + 1);
205   EXPECT_EQ(decryption_status_change_count_, static_cast<size_t>(2));
206 }
207 
208 // Verifies if a BufferedFrameDecryptor is attached but has no FrameDecryptor
209 // attached it will still store frames up to the frame max.
TEST_F(BufferedFrameDecryptorTest,FramesStoredIfDecryptorNull)210 TEST_F(BufferedFrameDecryptorTest, FramesStoredIfDecryptorNull) {
211   buffered_frame_decryptor_->SetFrameDecryptor(nullptr);
212   for (size_t i = 0; i < (2 * kMaxStashedFrames); ++i) {
213     buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
214   }
215 
216   EXPECT_CALL(*mock_frame_decryptor_, Decrypt)
217       .Times(kMaxStashedFrames + 1)
218       .WillRepeatedly(Return(DecryptSuccess()));
219   EXPECT_CALL(*mock_frame_decryptor_, GetMaxPlaintextByteSize)
220       .WillRepeatedly(Return(0));
221 
222   // Attach the frame decryptor at a later point after frames have arrived.
223   buffered_frame_decryptor_->SetFrameDecryptor(mock_frame_decryptor_);
224 
225   // Next frame should trigger kMaxStashedFrame decryptions.
226   buffered_frame_decryptor_->ManageEncryptedFrame(CreateRtpFrameObject(true));
227   EXPECT_EQ(decrypted_frame_call_count_, kMaxStashedFrames + 1);
228 }
229 
230 }  // namespace webrtc
231