blob: a4cc5b0ded0d9124341702f17a7a1727b3b87da9 [file] [log] [blame]
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +02001/*
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 <vector>
14
15#include "absl/types/optional.h"
16#include "api/task_queue/default_task_queue_factory.h"
17#include "common_video/test/utilities.h"
18#include "modules/video_coding/timing.h"
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020019#include "rtc_base/event.h"
Markus Handell6deec382020-07-07 12:17:12 +020020#include "rtc_base/synchronization/mutex.h"
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020021#include "system_wrappers/include/clock.h"
22#include "test/fake_decoder.h"
23#include "test/gmock.h"
24#include "test/gtest.h"
25
26namespace webrtc {
27namespace video_coding {
28
29class ReceiveCallback : public VCMReceiveCallback {
30 public:
31 int32_t FrameToRender(VideoFrame& videoFrame, // NOLINT
32 absl::optional<uint8_t> qp,
Johannes Kronbfd343b2019-07-01 10:07:50 +020033 int32_t decode_time_ms,
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020034 VideoContentType content_type) override {
35 {
Markus Handell6deec382020-07-07 12:17:12 +020036 MutexLock lock(&lock_);
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020037 last_frame_ = videoFrame;
38 }
39 received_frame_event_.Set();
40 return 0;
41 }
42
43 absl::optional<VideoFrame> GetLastFrame() {
Markus Handell6deec382020-07-07 12:17:12 +020044 MutexLock lock(&lock_);
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020045 return last_frame_;
46 }
47
48 absl::optional<VideoFrame> WaitForFrame(int64_t wait_ms) {
49 if (received_frame_event_.Wait(wait_ms)) {
Markus Handell6deec382020-07-07 12:17:12 +020050 MutexLock lock(&lock_);
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020051 return last_frame_;
52 } else {
53 return absl::nullopt;
54 }
55 }
56
57 private:
Markus Handell6deec382020-07-07 12:17:12 +020058 Mutex lock_;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020059 rtc::Event received_frame_event_;
60 absl::optional<VideoFrame> last_frame_ RTC_GUARDED_BY(lock_);
61};
62
63class GenericDecoderTest : public ::testing::Test {
64 protected:
65 GenericDecoderTest()
66 : clock_(0),
67 timing_(&clock_),
68 task_queue_factory_(CreateDefaultTaskQueueFactory()),
69 decoder_(task_queue_factory_.get()),
70 vcm_callback_(&timing_, &clock_),
71 generic_decoder_(&decoder_, /*isExternal=*/true) {}
72
73 void SetUp() override {
74 generic_decoder_.RegisterDecodeCompleteCallback(&vcm_callback_);
75 vcm_callback_.SetUserReceiveCallback(&user_callback_);
76 VideoCodec settings;
77 settings.codecType = kVideoCodecVP8;
78 settings.width = 10;
79 settings.height = 10;
80 generic_decoder_.InitDecode(&settings, /*numberOfCores=*/4);
81 }
82
83 SimulatedClock clock_;
84 VCMTiming timing_;
85 std::unique_ptr<TaskQueueFactory> task_queue_factory_;
86 webrtc::test::FakeDecoder decoder_;
87 VCMDecodedFrameCallback vcm_callback_;
88 VCMGenericDecoder generic_decoder_;
89 ReceiveCallback user_callback_;
90};
91
Chen Xingf00bf422019-06-20 10:05:55 +020092TEST_F(GenericDecoderTest, PassesPacketInfos) {
93 RtpPacketInfos packet_infos = CreatePacketInfos(3);
94 VCMEncodedFrame encoded_frame;
95 encoded_frame.SetPacketInfos(packet_infos);
Johannes Kron05f84872020-01-16 14:09:33 +010096 generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
Chen Xingf00bf422019-06-20 10:05:55 +020097 absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
98 ASSERT_TRUE(decoded_frame.has_value());
99 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
100}
101
102TEST_F(GenericDecoderTest, PassesPacketInfosForDelayedDecoders) {
103 RtpPacketInfos packet_infos = CreatePacketInfos(3);
104 decoder_.SetDelayedDecoding(100);
105
106 {
107 // Ensure the original frame is destroyed before the decoding is completed.
108 VCMEncodedFrame encoded_frame;
109 encoded_frame.SetPacketInfos(packet_infos);
Johannes Kron05f84872020-01-16 14:09:33 +0100110 generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
Chen Xingf00bf422019-06-20 10:05:55 +0200111 }
112
113 absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(200);
114 ASSERT_TRUE(decoded_frame.has_value());
115 EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
116}
117
Johannes Kron111e9812020-10-26 13:54:40 +0100118TEST_F(GenericDecoderTest, MaxCompositionDelayNotSetByDefault) {
119 VCMEncodedFrame encoded_frame;
120 generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
121 absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
122 ASSERT_TRUE(decoded_frame.has_value());
123 EXPECT_FALSE(decoded_frame->max_composition_delay_in_frames());
124}
125
126TEST_F(GenericDecoderTest, MaxCompositionDelayActivatedByPlayoutDelay) {
127 VCMEncodedFrame encoded_frame;
128 // VideoReceiveStream2 would set MaxCompositionDelayInFrames if playout delay
129 // is specified as X,Y, where X=0, Y>0.
130 const VideoPlayoutDelay kPlayoutDelay = {0, 50};
131 constexpr int kMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
132 encoded_frame.SetPlayoutDelay(kPlayoutDelay);
133 timing_.SetMaxCompositionDelayInFrames(
134 absl::make_optional(kMaxCompositionDelayInFrames));
135 generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
136 absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
137 ASSERT_TRUE(decoded_frame.has_value());
138 EXPECT_EQ(kMaxCompositionDelayInFrames,
139 decoded_frame->max_composition_delay_in_frames());
140}
141
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200142} // namespace video_coding
143} // namespace webrtc