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