1 /*
2 * Copyright (c) 2022 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/video_receiver2.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "api/test/mock_video_decoder.h"
17 #include "api/units/timestamp.h"
18 #include "api/video/encoded_frame.h"
19 #include "common_video/test/utilities.h"
20 #include "modules/video_coding/decoder_database.h"
21 #include "modules/video_coding/timing/timing.h"
22 #include "system_wrappers/include/clock.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25 #include "test/scoped_key_value_config.h"
26
27 namespace webrtc {
28 namespace {
29
30 using ::testing::_;
31 using ::testing::NiceMock;
32 using ::testing::Return;
33
34 class MockVCMReceiveCallback : public VCMReceiveCallback {
35 public:
36 MockVCMReceiveCallback() = default;
37
38 MOCK_METHOD(
39 int32_t,
40 FrameToRender,
41 (VideoFrame&, absl::optional<uint8_t>, TimeDelta, VideoContentType),
42 (override));
43 MOCK_METHOD(void, OnIncomingPayloadType, (int), (override));
44 MOCK_METHOD(void,
45 OnDecoderInfoChanged,
46 (const VideoDecoder::DecoderInfo&),
47 (override));
48 };
49
50 class TestEncodedFrame : public EncodedFrame {
51 public:
TestEncodedFrame(int payload_type)52 explicit TestEncodedFrame(int payload_type) {
53 _payloadType = payload_type;
54 SetPacketInfos(CreatePacketInfos(3));
55 }
56
SetReceivedTime(webrtc::Timestamp received_time)57 void SetReceivedTime(webrtc::Timestamp received_time) {
58 received_time_ = received_time;
59 }
60
ReceivedTime() const61 int64_t ReceivedTime() const override { return received_time_.ms(); }
62
RenderTime() const63 int64_t RenderTime() const override { return _renderTimeMs; }
64
65 private:
66 webrtc::Timestamp received_time_ = webrtc::Timestamp::Millis(0);
67 };
68
69 class VideoReceiver2Test : public ::testing::Test {
70 protected:
VideoReceiver2Test()71 VideoReceiver2Test() {
72 receiver_.RegisterReceiveCallback(&receive_callback_);
73 }
74
RegisterReceiveCodecSettings(int payload_type,VideoCodecType codec_type=kVideoCodecVP8)75 void RegisterReceiveCodecSettings(
76 int payload_type,
77 VideoCodecType codec_type = kVideoCodecVP8) {
78 VideoDecoder::Settings settings;
79 settings.set_codec_type(codec_type);
80 settings.set_max_render_resolution({10, 10});
81 settings.set_number_of_cores(4);
82 receiver_.RegisterReceiveCodec(payload_type, settings);
83 }
84
85 test::ScopedKeyValueConfig field_trials_;
86 SimulatedClock clock_{Timestamp::Millis(1337)};
87 VCMTiming timing_{&clock_, field_trials_};
88 NiceMock<MockVCMReceiveCallback> receive_callback_;
89 VideoReceiver2 receiver_{&clock_, &timing_, field_trials_};
90 };
91
TEST_F(VideoReceiver2Test,RegisterExternalDecoder)92 TEST_F(VideoReceiver2Test, RegisterExternalDecoder) {
93 constexpr int kPayloadType = 1;
94 ASSERT_FALSE(receiver_.IsExternalDecoderRegistered(kPayloadType));
95
96 // Register a decoder, check for correctness, then unregister and check again.
97 auto decoder = std::make_unique<NiceMock<MockVideoDecoder>>();
98 bool decoder_deleted = false;
99 EXPECT_CALL(*decoder, Destruct).WillOnce([&decoder_deleted] {
100 decoder_deleted = true;
101 });
102 receiver_.RegisterExternalDecoder(std::move(decoder), kPayloadType);
103 EXPECT_TRUE(receiver_.IsExternalDecoderRegistered(kPayloadType));
104 receiver_.RegisterExternalDecoder(nullptr, kPayloadType);
105 EXPECT_TRUE(decoder_deleted);
106 EXPECT_FALSE(receiver_.IsExternalDecoderRegistered(kPayloadType));
107 }
108
TEST_F(VideoReceiver2Test,RegisterReceiveCodecs)109 TEST_F(VideoReceiver2Test, RegisterReceiveCodecs) {
110 constexpr int kPayloadType = 1;
111
112 RegisterReceiveCodecSettings(kPayloadType);
113
114 TestEncodedFrame frame(kPayloadType);
115
116 // A decoder has not been registered yet, so an attempt to decode should fail.
117 EXPECT_EQ(receiver_.Decode(&frame), VCM_NO_CODEC_REGISTERED);
118
119 // Register a decoder that will accept the Decode operation.
120 auto decoder = std::make_unique<NiceMock<MockVideoDecoder>>();
121 EXPECT_CALL(*decoder, RegisterDecodeCompleteCallback)
122 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
123 EXPECT_CALL(*decoder, Decode).WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
124 EXPECT_CALL(*decoder, Release).WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
125
126 // Register the decoder. Note that this moves ownership of the mock object
127 // to the `receiver_`.
128 receiver_.RegisterExternalDecoder(std::move(decoder), kPayloadType);
129 EXPECT_TRUE(receiver_.IsExternalDecoderRegistered(kPayloadType));
130
131 EXPECT_CALL(receive_callback_, OnIncomingPayloadType(kPayloadType));
132 EXPECT_CALL(receive_callback_, OnDecoderInfoChanged);
133
134 // Call `Decode`. This triggers the above call expectations.
135 EXPECT_EQ(receiver_.Decode(&frame), VCM_OK);
136
137 // Unregister the decoder and verify.
138 receiver_.RegisterExternalDecoder(nullptr, kPayloadType);
139 EXPECT_FALSE(receiver_.IsExternalDecoderRegistered(kPayloadType));
140
141 receiver_.DeregisterReceiveCodec(kPayloadType);
142 }
143
144 } // namespace
145 } // namespace webrtc
146