xref: /aosp_15_r20/external/webrtc/video/video_stream_decoder_impl_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 
11 #include "video/video_stream_decoder_impl.h"
12 
13 #include <vector>
14 
15 #include "api/video/i420_buffer.h"
16 #include "api/video_codecs/video_decoder.h"
17 #include "test/fake_encoded_frame.h"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20 #include "test/scoped_key_value_config.h"
21 #include "test/time_controller/simulated_time_controller.h"
22 
23 namespace webrtc {
24 namespace {
25 using ::testing::_;
26 using ::testing::NiceMock;
27 using ::testing::Return;
28 
29 class MockVideoStreamDecoderCallbacks
30     : public VideoStreamDecoderInterface::Callbacks {
31  public:
32   MOCK_METHOD(void, OnNonDecodableState, (), (override));
33   MOCK_METHOD(void, OnContinuousUntil, (int64_t frame_id), (override));
34   MOCK_METHOD(
35       void,
36       OnDecodedFrame,
37       (VideoFrame frame,
38        const VideoStreamDecoderInterface::Callbacks::FrameInfo& frame_info),
39       (override));
40 };
41 
42 class StubVideoDecoder : public VideoDecoder {
43  public:
StubVideoDecoder()44   StubVideoDecoder() { ON_CALL(*this, Configure).WillByDefault(Return(true)); }
45 
46   MOCK_METHOD(bool, Configure, (const Settings&), (override));
47 
Decode(const EncodedImage & input_image,bool missing_frames,int64_t render_time_ms)48   int32_t Decode(const EncodedImage& input_image,
49                  bool missing_frames,
50                  int64_t render_time_ms) override {
51     int32_t ret_code = DecodeCall(input_image, missing_frames, render_time_ms);
52     if (ret_code == WEBRTC_VIDEO_CODEC_OK ||
53         ret_code == WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME) {
54       VideoFrame frame = VideoFrame::Builder()
55                              .set_video_frame_buffer(I420Buffer::Create(1, 1))
56                              .build();
57       callback_->Decoded(frame);
58     }
59     return ret_code;
60   }
61 
62   MOCK_METHOD(int32_t,
63               DecodeCall,
64               (const EncodedImage& input_image,
65                bool missing_frames,
66                int64_t render_time_ms),
67               ());
68 
Release()69   int32_t Release() override { return 0; }
70 
RegisterDecodeCompleteCallback(DecodedImageCallback * callback)71   int32_t RegisterDecodeCompleteCallback(
72       DecodedImageCallback* callback) override {
73     callback_ = callback;
74     return 0;
75   }
76 
77  private:
78   DecodedImageCallback* callback_;
79 };
80 
81 class WrappedVideoDecoder : public VideoDecoder {
82  public:
WrappedVideoDecoder(StubVideoDecoder * decoder)83   explicit WrappedVideoDecoder(StubVideoDecoder* decoder) : decoder_(decoder) {}
84 
Configure(const Settings & settings)85   bool Configure(const Settings& settings) override {
86     return decoder_->Configure(settings);
87   }
Decode(const EncodedImage & input_image,bool missing_frames,int64_t render_time_ms)88   int32_t Decode(const EncodedImage& input_image,
89                  bool missing_frames,
90                  int64_t render_time_ms) override {
91     return decoder_->Decode(input_image, missing_frames, render_time_ms);
92   }
Release()93   int32_t Release() override { return decoder_->Release(); }
94 
RegisterDecodeCompleteCallback(DecodedImageCallback * callback)95   int32_t RegisterDecodeCompleteCallback(
96       DecodedImageCallback* callback) override {
97     return decoder_->RegisterDecodeCompleteCallback(callback);
98   }
99 
100  private:
101   StubVideoDecoder* decoder_;
102 };
103 
104 class FakeVideoDecoderFactory : public VideoDecoderFactory {
105  public:
GetSupportedFormats() const106   std::vector<SdpVideoFormat> GetSupportedFormats() const override {
107     return {};
108   }
CreateVideoDecoder(const SdpVideoFormat & format)109   std::unique_ptr<VideoDecoder> CreateVideoDecoder(
110       const SdpVideoFormat& format) override {
111     if (format.name == "VP8") {
112       return std::make_unique<WrappedVideoDecoder>(&vp8_decoder_);
113     }
114 
115     if (format.name == "AV1") {
116       return std::make_unique<WrappedVideoDecoder>(&av1_decoder_);
117     }
118 
119     return {};
120   }
121 
Vp8Decoder()122   StubVideoDecoder& Vp8Decoder() { return vp8_decoder_; }
Av1Decoder()123   StubVideoDecoder& Av1Decoder() { return av1_decoder_; }
124 
125  private:
126   NiceMock<StubVideoDecoder> vp8_decoder_;
127   NiceMock<StubVideoDecoder> av1_decoder_;
128 };
129 
130 class VideoStreamDecoderImplTest : public ::testing::Test {
131  public:
VideoStreamDecoderImplTest()132   VideoStreamDecoderImplTest()
133       : time_controller_(Timestamp::Seconds(0)),
134         video_stream_decoder_(&callbacks_,
135                               &decoder_factory_,
136                               time_controller_.GetTaskQueueFactory(),
137                               {{1, std::make_pair(SdpVideoFormat("VP8"), 1)},
138                                {2, std::make_pair(SdpVideoFormat("AV1"), 1)}},
139                               &field_trials_) {
140     // Set the min playout delay to a value greater than zero to not activate
141     // the low-latency renderer.
142     video_stream_decoder_.SetMinPlayoutDelay(TimeDelta::Millis(10));
143   }
144 
145   test::ScopedKeyValueConfig field_trials_;
146   NiceMock<MockVideoStreamDecoderCallbacks> callbacks_;
147   FakeVideoDecoderFactory decoder_factory_;
148   GlobalSimulatedTimeController time_controller_;
149   VideoStreamDecoderImpl video_stream_decoder_;
150 };
151 
TEST_F(VideoStreamDecoderImplTest,InsertAndDecodeFrame)152 TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrame) {
153   video_stream_decoder_.OnFrame(
154       test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
155   EXPECT_CALL(callbacks_, OnDecodedFrame);
156   time_controller_.AdvanceTime(TimeDelta::Millis(1));
157 }
158 
TEST_F(VideoStreamDecoderImplTest,NonDecodableStateWaitingForKeyframe)159 TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForKeyframe) {
160   EXPECT_CALL(callbacks_, OnNonDecodableState);
161   time_controller_.AdvanceTime(TimeDelta::Millis(200));
162 }
163 
TEST_F(VideoStreamDecoderImplTest,NonDecodableStateWaitingForDeltaFrame)164 TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) {
165   video_stream_decoder_.OnFrame(
166       test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
167   EXPECT_CALL(callbacks_, OnDecodedFrame);
168   time_controller_.AdvanceTime(TimeDelta::Millis(1));
169   EXPECT_CALL(callbacks_, OnNonDecodableState);
170   time_controller_.AdvanceTime(TimeDelta::Millis(3000));
171 }
172 
TEST_F(VideoStreamDecoderImplTest,InsertAndDecodeFrameWithKeyframeRequest)173 TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) {
174   video_stream_decoder_.OnFrame(
175       test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
176   EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
177       .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME));
178   EXPECT_CALL(callbacks_, OnDecodedFrame);
179   EXPECT_CALL(callbacks_, OnNonDecodableState);
180   time_controller_.AdvanceTime(TimeDelta::Millis(1));
181 }
182 
TEST_F(VideoStreamDecoderImplTest,FailToInitDecoder)183 TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) {
184   video_stream_decoder_.OnFrame(
185       test::FakeFrameBuilder()
186           .ReceivedTime(time_controller_.GetClock()->CurrentTime())
187           .PayloadType(1)
188           .AsLast()
189           .Build());
190   ON_CALL(decoder_factory_.Vp8Decoder(), Configure)
191       .WillByDefault(Return(false));
192   EXPECT_CALL(callbacks_, OnNonDecodableState);
193   time_controller_.AdvanceTime(TimeDelta::Millis(1));
194 }
195 
TEST_F(VideoStreamDecoderImplTest,FailToDecodeFrame)196 TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) {
197   video_stream_decoder_.OnFrame(
198       test::FakeFrameBuilder().PayloadType(1).AsLast().Build());
199   ON_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
200       .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ERROR));
201   EXPECT_CALL(callbacks_, OnNonDecodableState);
202   time_controller_.AdvanceTime(TimeDelta::Millis(1));
203 }
204 
TEST_F(VideoStreamDecoderImplTest,ChangeFramePayloadType)205 TEST_F(VideoStreamDecoderImplTest, ChangeFramePayloadType) {
206   constexpr TimeDelta kFrameInterval = TimeDelta::Millis(1000 / 60);
207   video_stream_decoder_.OnFrame(
208       test::FakeFrameBuilder().PayloadType(1).Id(0).AsLast().Build());
209   EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall);
210   EXPECT_CALL(callbacks_, OnDecodedFrame);
211   time_controller_.AdvanceTime(kFrameInterval);
212 
213   video_stream_decoder_.OnFrame(
214       test::FakeFrameBuilder().PayloadType(2).Id(1).AsLast().Build());
215   EXPECT_CALL(decoder_factory_.Av1Decoder(), DecodeCall);
216   EXPECT_CALL(callbacks_, OnDecodedFrame);
217   time_controller_.AdvanceTime(kFrameInterval);
218 }
219 
220 }  // namespace
221 }  // namespace webrtc
222