1 /*
2 * Copyright (c) 2016 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/video_coding/generic_decoder.h"
12
13 #include <cstdint>
14 #include <memory>
15 #include <vector>
16
17 #include "absl/types/optional.h"
18 #include "api/array_view.h"
19 #include "api/rtp_packet_infos.h"
20 #include "api/video_codecs/video_decoder.h"
21 #include "common_video/test/utilities.h"
22 #include "modules/video_coding/timing/timing.h"
23 #include "system_wrappers/include/clock.h"
24 #include "test/fake_decoder.h"
25 #include "test/gmock.h"
26 #include "test/gtest.h"
27 #include "test/scoped_key_value_config.h"
28 #include "test/time_controller/simulated_time_controller.h"
29
30 namespace webrtc {
31 namespace video_coding {
32
33 class ReceiveCallback : public VCMReceiveCallback {
34 public:
FrameToRender(VideoFrame & frame,absl::optional<uint8_t> qp,TimeDelta decode_time,VideoContentType content_type)35 int32_t FrameToRender(VideoFrame& frame,
36 absl::optional<uint8_t> qp,
37 TimeDelta decode_time,
38 VideoContentType content_type) override {
39 frames_.push_back(frame);
40 return 0;
41 }
42
PopLastFrame()43 absl::optional<VideoFrame> PopLastFrame() {
44 if (frames_.empty())
45 return absl::nullopt;
46 auto ret = frames_.front();
47 frames_.pop_back();
48 return ret;
49 }
50
GetAllFrames() const51 rtc::ArrayView<const VideoFrame> GetAllFrames() const { return frames_; }
52
OnDroppedFrames(uint32_t frames_dropped)53 void OnDroppedFrames(uint32_t frames_dropped) {
54 frames_dropped_ += frames_dropped;
55 }
56
frames_dropped() const57 uint32_t frames_dropped() const { return frames_dropped_; }
58
59 private:
60 std::vector<VideoFrame> frames_;
61 uint32_t frames_dropped_ = 0;
62 };
63
64 class GenericDecoderTest : public ::testing::Test {
65 protected:
GenericDecoderTest()66 GenericDecoderTest()
67 : time_controller_(Timestamp::Zero()),
68 clock_(time_controller_.GetClock()),
69 timing_(time_controller_.GetClock(), field_trials_),
70 decoder_(time_controller_.GetTaskQueueFactory()),
71 vcm_callback_(&timing_, time_controller_.GetClock(), field_trials_),
72 generic_decoder_(&decoder_) {}
73
SetUp()74 void SetUp() override {
75 generic_decoder_.RegisterDecodeCompleteCallback(&vcm_callback_);
76 vcm_callback_.SetUserReceiveCallback(&user_callback_);
77 VideoDecoder::Settings settings;
78 settings.set_codec_type(kVideoCodecVP8);
79 settings.set_max_render_resolution({10, 10});
80 settings.set_number_of_cores(4);
81 generic_decoder_.Configure(settings);
82 }
83
84 GlobalSimulatedTimeController time_controller_;
85 Clock* const clock_;
86 test::ScopedKeyValueConfig field_trials_;
87 VCMTiming timing_;
88 webrtc::test::FakeDecoder decoder_;
89 VCMDecodedFrameCallback vcm_callback_;
90 VCMGenericDecoder generic_decoder_;
91 ReceiveCallback user_callback_;
92 };
93
TEST_F(GenericDecoderTest,PassesPacketInfos)94 TEST_F(GenericDecoderTest, PassesPacketInfos) {
95 RtpPacketInfos packet_infos = CreatePacketInfos(3);
96 VCMEncodedFrame encoded_frame;
97 encoded_frame.SetPacketInfos(packet_infos);
98 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
99 time_controller_.AdvanceTime(TimeDelta::Millis(10));
100 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
101 ASSERT_TRUE(decoded_frame.has_value());
102 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
103 }
104
TEST_F(GenericDecoderTest,FrameDroppedIfTooManyFramesInFlight)105 TEST_F(GenericDecoderTest, FrameDroppedIfTooManyFramesInFlight) {
106 constexpr int kMaxFramesInFlight = 10;
107 decoder_.SetDelayedDecoding(10);
108 for (int i = 0; i < kMaxFramesInFlight + 1; ++i) {
109 VCMEncodedFrame encoded_frame;
110 encoded_frame.SetTimestamp(90000 * i);
111 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
112 }
113
114 time_controller_.AdvanceTime(TimeDelta::Millis(10));
115
116 auto frames = user_callback_.GetAllFrames();
117 ASSERT_EQ(10U, frames.size());
118 // Expect that the first frame was dropped since all decodes released at the
119 // same time and the oldest frame info is the first one dropped.
120 EXPECT_EQ(frames[0].timestamp(), 90000u);
121 EXPECT_EQ(1u, user_callback_.frames_dropped());
122 }
123
TEST_F(GenericDecoderTest,PassesPacketInfosForDelayedDecoders)124 TEST_F(GenericDecoderTest, PassesPacketInfosForDelayedDecoders) {
125 RtpPacketInfos packet_infos = CreatePacketInfos(3);
126 decoder_.SetDelayedDecoding(100);
127
128 {
129 // Ensure the original frame is destroyed before the decoding is completed.
130 VCMEncodedFrame encoded_frame;
131 encoded_frame.SetPacketInfos(packet_infos);
132 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
133 }
134
135 time_controller_.AdvanceTime(TimeDelta::Millis(200));
136 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
137 ASSERT_TRUE(decoded_frame.has_value());
138 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
139 }
140
TEST_F(GenericDecoderTest,MaxCompositionDelayNotSetByDefault)141 TEST_F(GenericDecoderTest, MaxCompositionDelayNotSetByDefault) {
142 VCMEncodedFrame encoded_frame;
143 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
144 time_controller_.AdvanceTime(TimeDelta::Millis(10));
145 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
146 ASSERT_TRUE(decoded_frame.has_value());
147 EXPECT_THAT(
148 decoded_frame->render_parameters().max_composition_delay_in_frames,
149 testing::Eq(absl::nullopt));
150 }
151
TEST_F(GenericDecoderTest,MaxCompositionDelayActivatedByPlayoutDelay)152 TEST_F(GenericDecoderTest, MaxCompositionDelayActivatedByPlayoutDelay) {
153 VCMEncodedFrame encoded_frame;
154 // VideoReceiveStream2 would set MaxCompositionDelayInFrames if playout delay
155 // is specified as X,Y, where X=0, Y>0.
156 constexpr int kMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
157 timing_.SetMaxCompositionDelayInFrames(
158 absl::make_optional(kMaxCompositionDelayInFrames));
159 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
160 time_controller_.AdvanceTime(TimeDelta::Millis(10));
161 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
162 ASSERT_TRUE(decoded_frame.has_value());
163 EXPECT_THAT(
164 decoded_frame->render_parameters().max_composition_delay_in_frames,
165 testing::Optional(kMaxCompositionDelayInFrames));
166 }
167
TEST_F(GenericDecoderTest,IsLowLatencyStreamFalseByDefault)168 TEST_F(GenericDecoderTest, IsLowLatencyStreamFalseByDefault) {
169 VCMEncodedFrame encoded_frame;
170 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
171 time_controller_.AdvanceTime(TimeDelta::Millis(10));
172 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
173 ASSERT_TRUE(decoded_frame.has_value());
174 EXPECT_FALSE(decoded_frame->render_parameters().use_low_latency_rendering);
175 }
176
TEST_F(GenericDecoderTest,IsLowLatencyStreamActivatedByPlayoutDelay)177 TEST_F(GenericDecoderTest, IsLowLatencyStreamActivatedByPlayoutDelay) {
178 VCMEncodedFrame encoded_frame;
179 const VideoPlayoutDelay kPlayoutDelay = {0, 50};
180 timing_.set_min_playout_delay(TimeDelta::Millis(kPlayoutDelay.min_ms));
181 timing_.set_max_playout_delay(TimeDelta::Millis(kPlayoutDelay.max_ms));
182 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime());
183 time_controller_.AdvanceTime(TimeDelta::Millis(10));
184 absl::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame();
185 ASSERT_TRUE(decoded_frame.has_value());
186 EXPECT_TRUE(decoded_frame->render_parameters().use_low_latency_rendering);
187 }
188
189 } // namespace video_coding
190 } // namespace webrtc
191