blob: 4cb434463bd25051a2e7225e51d4be1a29cf7b98 [file] [log] [blame]
philipel539f9b32020-01-09 16:12:25 +01001/*
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"
Danil Chapovalovd08930d2021-08-12 13:26:55 +020016#include "api/video_codecs/video_decoder.h"
philipel539f9b32020-01-09 16:12:25 +010017#include "test/gmock.h"
18#include "test/gtest.h"
19#include "test/time_controller/simulated_time_controller.h"
20
21namespace webrtc {
22namespace {
23using ::testing::_;
24using ::testing::ByMove;
25using ::testing::NiceMock;
26using ::testing::Return;
27
28class MockVideoStreamDecoderCallbacks
29 : public VideoStreamDecoderInterface::Callbacks {
30 public:
Danil Chapovalov91fdc602020-05-14 19:17:51 +020031 MOCK_METHOD(void, OnNonDecodableState, (), (override));
philipel9aa9b8d2021-02-15 13:31:29 +010032 MOCK_METHOD(void, OnContinuousUntil, (int64_t frame_id), (override));
philipela028a1a2020-09-11 16:05:56 +020033 MOCK_METHOD(
34 void,
35 OnDecodedFrame,
36 (VideoFrame frame,
37 const VideoStreamDecoderInterface::Callbacks::FrameInfo& frame_info),
38 (override));
philipel539f9b32020-01-09 16:12:25 +010039};
40
41class StubVideoDecoder : public VideoDecoder {
42 public:
Danil Chapovalovd08930d2021-08-12 13:26:55 +020043 StubVideoDecoder() { ON_CALL(*this, Configure).WillByDefault(Return(true)); }
44
45 MOCK_METHOD(bool, Configure, (const Settings&), (override));
philipel539f9b32020-01-09 16:12:25 +010046
47 int32_t Decode(const EncodedImage& input_image,
48 bool missing_frames,
49 int64_t render_time_ms) override {
50 int32_t ret_code = DecodeCall(input_image, missing_frames, render_time_ms);
51 if (ret_code == WEBRTC_VIDEO_CODEC_OK ||
52 ret_code == WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME) {
53 VideoFrame frame = VideoFrame::Builder()
54 .set_video_frame_buffer(I420Buffer::Create(1, 1))
55 .build();
56 callback_->Decoded(frame);
57 }
58 return ret_code;
59 }
60
Danil Chapovalov91fdc602020-05-14 19:17:51 +020061 MOCK_METHOD(int32_t,
62 DecodeCall,
63 (const EncodedImage& input_image,
64 bool missing_frames,
65 int64_t render_time_ms),
66 ());
philipel539f9b32020-01-09 16:12:25 +010067
68 int32_t Release() override { return 0; }
69
70 int32_t RegisterDecodeCompleteCallback(
71 DecodedImageCallback* callback) override {
72 callback_ = callback;
73 return 0;
74 }
75
76 private:
77 DecodedImageCallback* callback_;
78};
79
80class WrappedVideoDecoder : public VideoDecoder {
81 public:
82 explicit WrappedVideoDecoder(StubVideoDecoder* decoder) : decoder_(decoder) {}
83
Danil Chapovalovd08930d2021-08-12 13:26:55 +020084 bool Configure(const Settings& settings) override {
85 return decoder_->Configure(settings);
philipel539f9b32020-01-09 16:12:25 +010086 }
87 int32_t Decode(const EncodedImage& input_image,
88 bool missing_frames,
89 int64_t render_time_ms) override {
90 return decoder_->Decode(input_image, missing_frames, render_time_ms);
91 }
92 int32_t Release() override { return decoder_->Release(); }
93
94 int32_t RegisterDecodeCompleteCallback(
95 DecodedImageCallback* callback) override {
96 return decoder_->RegisterDecodeCompleteCallback(callback);
97 }
98
99 private:
100 StubVideoDecoder* decoder_;
101};
102
103class FakeVideoDecoderFactory : public VideoDecoderFactory {
104 public:
105 std::vector<SdpVideoFormat> GetSupportedFormats() const override {
106 return {};
107 }
108 std::unique_ptr<VideoDecoder> CreateVideoDecoder(
109 const SdpVideoFormat& format) override {
110 if (format.name == "VP8") {
111 return std::make_unique<WrappedVideoDecoder>(&vp8_decoder_);
112 }
113
114 if (format.name == "AV1") {
115 return std::make_unique<WrappedVideoDecoder>(&av1_decoder_);
116 }
117
118 return {};
119 }
120
121 StubVideoDecoder& Vp8Decoder() { return vp8_decoder_; }
122 StubVideoDecoder& Av1Decoder() { return av1_decoder_; }
123
124 private:
125 NiceMock<StubVideoDecoder> vp8_decoder_;
126 NiceMock<StubVideoDecoder> av1_decoder_;
127};
128
philipelca188092021-03-23 12:00:49 +0100129class FakeEncodedFrame : public EncodedFrame {
philipel539f9b32020-01-09 16:12:25 +0100130 public:
131 int64_t ReceivedTime() const override { return 0; }
132 int64_t RenderTime() const override { return 0; }
133
134 // Setters for protected variables.
135 void SetPayloadType(int payload_type) { _payloadType = payload_type; }
136};
137
138class FrameBuilder {
139 public:
140 FrameBuilder() : frame_(std::make_unique<FakeEncodedFrame>()) {}
141
142 FrameBuilder& WithPayloadType(int payload_type) {
143 frame_->SetPayloadType(payload_type);
144 return *this;
145 }
146
147 FrameBuilder& WithPictureId(int picture_id) {
philipel9aa9b8d2021-02-15 13:31:29 +0100148 frame_->SetId(picture_id);
philipel539f9b32020-01-09 16:12:25 +0100149 return *this;
150 }
151
152 std::unique_ptr<FakeEncodedFrame> Build() { return std::move(frame_); }
153
154 private:
155 std::unique_ptr<FakeEncodedFrame> frame_;
156};
157
158class VideoStreamDecoderImplTest : public ::testing::Test {
159 public:
160 VideoStreamDecoderImplTest()
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100161 : time_controller_(Timestamp::Seconds(0)),
philipel539f9b32020-01-09 16:12:25 +0100162 video_stream_decoder_(&callbacks_,
163 &decoder_factory_,
164 time_controller_.GetTaskQueueFactory(),
165 {{1, std::make_pair(SdpVideoFormat("VP8"), 1)},
166 {2, std::make_pair(SdpVideoFormat("AV1"), 1)}}) {
Johannes Kron23bfff32021-09-28 21:31:46 +0200167 // Set the min playout delay to a value greater than zero to not activate
168 // the low-latency renderer.
169 video_stream_decoder_.SetMinPlayoutDelay(TimeDelta::Millis(10));
philipel539f9b32020-01-09 16:12:25 +0100170 }
171
172 NiceMock<MockVideoStreamDecoderCallbacks> callbacks_;
173 FakeVideoDecoderFactory decoder_factory_;
174 GlobalSimulatedTimeController time_controller_;
175 VideoStreamDecoderImpl video_stream_decoder_;
176};
177
178TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrame) {
179 video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build());
180 EXPECT_CALL(callbacks_, OnDecodedFrame);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100181 time_controller_.AdvanceTime(TimeDelta::Millis(1));
philipel539f9b32020-01-09 16:12:25 +0100182}
183
184TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForKeyframe) {
185 EXPECT_CALL(callbacks_, OnNonDecodableState);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100186 time_controller_.AdvanceTime(TimeDelta::Millis(200));
philipel539f9b32020-01-09 16:12:25 +0100187}
188
189TEST_F(VideoStreamDecoderImplTest, NonDecodableStateWaitingForDeltaFrame) {
190 video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build());
191 EXPECT_CALL(callbacks_, OnDecodedFrame);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100192 time_controller_.AdvanceTime(TimeDelta::Millis(1));
philipel539f9b32020-01-09 16:12:25 +0100193 EXPECT_CALL(callbacks_, OnNonDecodableState);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100194 time_controller_.AdvanceTime(TimeDelta::Millis(3000));
philipel539f9b32020-01-09 16:12:25 +0100195}
196
197TEST_F(VideoStreamDecoderImplTest, InsertAndDecodeFrameWithKeyframeRequest) {
198 video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build());
199 EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
200 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK_REQUEST_KEYFRAME));
201 EXPECT_CALL(callbacks_, OnDecodedFrame);
202 EXPECT_CALL(callbacks_, OnNonDecodableState);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100203 time_controller_.AdvanceTime(TimeDelta::Millis(1));
philipel539f9b32020-01-09 16:12:25 +0100204}
205
206TEST_F(VideoStreamDecoderImplTest, FailToInitDecoder) {
207 video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build());
Danil Chapovalovd08930d2021-08-12 13:26:55 +0200208 ON_CALL(decoder_factory_.Vp8Decoder(), Configure)
209 .WillByDefault(Return(false));
philipel539f9b32020-01-09 16:12:25 +0100210 EXPECT_CALL(callbacks_, OnNonDecodableState);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100211 time_controller_.AdvanceTime(TimeDelta::Millis(1));
philipel539f9b32020-01-09 16:12:25 +0100212}
213
214TEST_F(VideoStreamDecoderImplTest, FailToDecodeFrame) {
215 video_stream_decoder_.OnFrame(FrameBuilder().WithPayloadType(1).Build());
216 ON_CALL(decoder_factory_.Vp8Decoder(), DecodeCall)
217 .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ERROR));
218 EXPECT_CALL(callbacks_, OnNonDecodableState);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100219 time_controller_.AdvanceTime(TimeDelta::Millis(1));
philipel539f9b32020-01-09 16:12:25 +0100220}
221
222TEST_F(VideoStreamDecoderImplTest, ChangeFramePayloadType) {
Johannes Kron23bfff32021-09-28 21:31:46 +0200223 constexpr TimeDelta kFrameInterval = TimeDelta::Millis(1000 / 60);
philipel539f9b32020-01-09 16:12:25 +0100224 video_stream_decoder_.OnFrame(
225 FrameBuilder().WithPayloadType(1).WithPictureId(0).Build());
226 EXPECT_CALL(decoder_factory_.Vp8Decoder(), DecodeCall);
227 EXPECT_CALL(callbacks_, OnDecodedFrame);
Johannes Kron23bfff32021-09-28 21:31:46 +0200228 time_controller_.AdvanceTime(kFrameInterval);
philipel539f9b32020-01-09 16:12:25 +0100229
230 video_stream_decoder_.OnFrame(
231 FrameBuilder().WithPayloadType(2).WithPictureId(1).Build());
232 EXPECT_CALL(decoder_factory_.Av1Decoder(), DecodeCall);
233 EXPECT_CALL(callbacks_, OnDecodedFrame);
Johannes Kron23bfff32021-09-28 21:31:46 +0200234 time_controller_.AdvanceTime(kFrameInterval);
philipel539f9b32020-01-09 16:12:25 +0100235}
236
237} // namespace
238} // namespace webrtc