generic_decoder_unittest.cc (9156B)
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 <optional> 15 #include <utility> 16 #include <vector> 17 18 #include "api/array_view.h" 19 #include "api/field_trials.h" 20 #include "api/rtp_packet_infos.h" 21 #include "api/scoped_refptr.h" 22 #include "api/units/time_delta.h" 23 #include "api/units/timestamp.h" 24 #include "api/video/corruption_detection/frame_instrumentation_data.h" 25 #include "api/video/encoded_frame.h" 26 #include "api/video/i420_buffer.h" 27 #include "api/video/video_codec_type.h" 28 #include "api/video/video_content_type.h" 29 #include "api/video/video_frame.h" 30 #include "api/video/video_frame_type.h" 31 #include "api/video/video_timing.h" 32 #include "api/video_codecs/video_decoder.h" 33 #include "common_video/include/corruption_score_calculator.h" 34 #include "common_video/test/utilities.h" 35 #include "modules/video_coding/include/video_coding_defines.h" 36 #include "modules/video_coding/timing/timing.h" 37 #include "system_wrappers/include/clock.h" 38 #include "test/create_test_field_trials.h" 39 #include "test/fake_decoder.h" 40 #include "test/gmock.h" 41 #include "test/gtest.h" 42 #include "test/time_controller/simulated_time_controller.h" 43 44 using ::testing::Eq; 45 using ::testing::Field; 46 using ::testing::Property; 47 using ::testing::Return; 48 49 namespace webrtc { 50 namespace video_coding { 51 52 class MockCorruptionScoreCalculator : public CorruptionScoreCalculator { 53 public: 54 MOCK_METHOD(void, 55 CalculateCorruptionScore, 56 (const VideoFrame& frame, 57 const FrameInstrumentationData& frame_instrumentation_data, 58 VideoContentType content_type), 59 (override)); 60 }; 61 62 class ReceiveCallback : public VCMReceiveCallback { 63 public: 64 int32_t OnFrameToRender(const FrameToRender& arguments) override { 65 frames_.push_back(arguments.video_frame); 66 return 0; 67 } 68 69 std::optional<VideoFrame> PopLastFrame() { 70 if (frames_.empty()) 71 return std::nullopt; 72 auto ret = frames_.front(); 73 frames_.pop_back(); 74 return ret; 75 } 76 77 ArrayView<const VideoFrame> GetAllFrames() const { return frames_; } 78 79 void OnDroppedFrames(uint32_t frames_dropped) override { 80 frames_dropped_ += frames_dropped; 81 } 82 83 uint32_t frames_dropped() const { return frames_dropped_; } 84 85 private: 86 std::vector<VideoFrame> frames_; 87 uint32_t frames_dropped_ = 0; 88 }; 89 90 class GenericDecoderTest : public ::testing::Test { 91 protected: 92 GenericDecoderTest() 93 : time_controller_(Timestamp::Zero()), 94 clock_(time_controller_.GetClock()), 95 field_trials_(CreateTestFieldTrials()), 96 timing_(time_controller_.GetClock(), field_trials_), 97 decoder_(time_controller_.GetTaskQueueFactory()), 98 vcm_callback_(&timing_, 99 time_controller_.GetClock(), 100 field_trials_, 101 &corruption_score_calculator_), 102 generic_decoder_(&decoder_) {} 103 104 void SetUp() override { 105 generic_decoder_.RegisterDecodeCompleteCallback(&vcm_callback_); 106 vcm_callback_.SetUserReceiveCallback(&user_callback_); 107 VideoDecoder::Settings settings; 108 settings.set_codec_type(kVideoCodecVP8); 109 settings.set_max_render_resolution({10, 10}); 110 settings.set_number_of_cores(4); 111 generic_decoder_.Configure(settings); 112 } 113 114 GlobalSimulatedTimeController time_controller_; 115 Clock* const clock_; 116 FieldTrials field_trials_; 117 VCMTiming timing_; 118 test::FakeDecoder decoder_; 119 VCMDecodedFrameCallback vcm_callback_; 120 VCMGenericDecoder generic_decoder_; 121 ReceiveCallback user_callback_; 122 MockCorruptionScoreCalculator corruption_score_calculator_; 123 }; 124 125 TEST_F(GenericDecoderTest, PassesPacketInfos) { 126 RtpPacketInfos packet_infos = CreatePacketInfos(3); 127 EncodedFrame encoded_frame; 128 encoded_frame.SetPacketInfos(packet_infos); 129 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 130 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 131 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 132 ASSERT_TRUE(decoded_frame.has_value()); 133 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U); 134 } 135 136 TEST_F(GenericDecoderTest, FrameDroppedIfTooManyFramesInFlight) { 137 constexpr int kMaxFramesInFlight = 10; 138 decoder_.SetDelayedDecoding(10); 139 for (int i = 0; i < kMaxFramesInFlight + 1; ++i) { 140 EncodedFrame encoded_frame; 141 encoded_frame.SetRtpTimestamp(90000 * i); 142 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 143 } 144 145 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 146 147 auto frames = user_callback_.GetAllFrames(); 148 ASSERT_EQ(10U, frames.size()); 149 // Expect that the first frame was dropped since all decodes released at the 150 // same time and the oldest frame info is the first one dropped. 151 EXPECT_EQ(frames[0].rtp_timestamp(), 90000u); 152 EXPECT_EQ(1u, user_callback_.frames_dropped()); 153 } 154 155 TEST_F(GenericDecoderTest, PassesPacketInfosForDelayedDecoders) { 156 RtpPacketInfos packet_infos = CreatePacketInfos(3); 157 decoder_.SetDelayedDecoding(100); 158 159 { 160 // Ensure the original frame is destroyed before the decoding is completed. 161 EncodedFrame encoded_frame; 162 encoded_frame.SetPacketInfos(packet_infos); 163 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 164 } 165 166 time_controller_.AdvanceTime(TimeDelta::Millis(200)); 167 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 168 ASSERT_TRUE(decoded_frame.has_value()); 169 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U); 170 } 171 172 TEST_F(GenericDecoderTest, MaxCompositionDelayNotSetByDefault) { 173 EncodedFrame encoded_frame; 174 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 175 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 176 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 177 ASSERT_TRUE(decoded_frame.has_value()); 178 EXPECT_THAT( 179 decoded_frame->render_parameters().max_composition_delay_in_frames, 180 testing::Eq(std::nullopt)); 181 } 182 183 TEST_F(GenericDecoderTest, MaxCompositionDelayActivatedByPlayoutDelay) { 184 EncodedFrame encoded_frame; 185 // VideoReceiveStream2 would set MaxCompositionDelayInFrames if playout delay 186 // is specified as X,Y, where X=0, Y>0. 187 constexpr int kMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps. 188 timing_.SetMaxCompositionDelayInFrames( 189 std::make_optional(kMaxCompositionDelayInFrames)); 190 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 191 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 192 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 193 ASSERT_TRUE(decoded_frame.has_value()); 194 EXPECT_THAT( 195 decoded_frame->render_parameters().max_composition_delay_in_frames, 196 testing::Optional(kMaxCompositionDelayInFrames)); 197 } 198 199 TEST_F(GenericDecoderTest, IsLowLatencyStreamFalseByDefault) { 200 EncodedFrame encoded_frame; 201 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 202 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 203 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 204 ASSERT_TRUE(decoded_frame.has_value()); 205 EXPECT_FALSE(decoded_frame->render_parameters().use_low_latency_rendering); 206 } 207 208 TEST_F(GenericDecoderTest, IsLowLatencyStreamActivatedByPlayoutDelay) { 209 EncodedFrame encoded_frame; 210 const VideoPlayoutDelay kPlayoutDelay(TimeDelta::Zero(), 211 TimeDelta::Millis(50)); 212 timing_.set_playout_delay(kPlayoutDelay); 213 generic_decoder_.Decode(encoded_frame, clock_->CurrentTime()); 214 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 215 std::optional<VideoFrame> decoded_frame = user_callback_.PopLastFrame(); 216 ASSERT_TRUE(decoded_frame.has_value()); 217 EXPECT_TRUE(decoded_frame->render_parameters().use_low_latency_rendering); 218 } 219 220 TEST_F(GenericDecoderTest, CallCalculateCorruptionScoreInDecoded) { 221 constexpr uint32_t kRtpTimestamp = 1; 222 FrameInfo frame_info; 223 frame_info.frame_instrumentation_data.emplace(); 224 frame_info.frame_instrumentation_data->SetSequenceIndex(1); 225 frame_info.rtp_timestamp = kRtpTimestamp; 226 frame_info.decode_start = Timestamp::Zero(); 227 frame_info.content_type = VideoContentType::SCREENSHARE; 228 frame_info.frame_type = VideoFrameType::kVideoFrameDelta; 229 VideoFrame video_frame = VideoFrame::Builder() 230 .set_video_frame_buffer(I420Buffer::Create(5, 5)) 231 .set_rtp_timestamp(kRtpTimestamp) 232 .build(); 233 vcm_callback_.Map(std::move(frame_info)); 234 235 EXPECT_CALL(corruption_score_calculator_, 236 CalculateCorruptionScore( 237 Property(&VideoFrame::rtp_timestamp, Eq(kRtpTimestamp)), 238 Property(&FrameInstrumentationData::sequence_index, Eq(1)), 239 VideoContentType::SCREENSHARE)); 240 vcm_callback_.Decoded(video_frame); 241 } 242 243 } // namespace video_coding 244 } // namespace webrtc