blob: e9729170b7284b04071b12a5508eac99bdbf9dc7 [file] [log] [blame]
Markus Handell9c27ed22019-12-04 11:57:581/*
2 * Copyright 2019 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 "pc/video_rtp_receiver.h"
12
Harald Alvestrandc24a2182022-02-23 13:44:5913#include <functional>
Markus Handell9c27ed22019-12-04 11:57:5814#include <memory>
15
Harald Alvestrandc24a2182022-02-23 13:44:5916#include "api/task_queue/task_queue_base.h"
17#include "api/video/recordable_encoded_frame.h"
Markus Handell9c27ed22019-12-04 11:57:5818#include "api/video/test/mock_recordable_encoded_frame.h"
19#include "media/base/fake_media_engine.h"
Florent Castelli1f31c202023-06-26 00:26:0720#include "media/base/media_channel.h"
Danil Chapovalov2aaef452022-08-12 13:55:1121#include "rtc_base/task_queue_for_test.h"
Markus Handell9c27ed22019-12-04 11:57:5822#include "test/gmock.h"
Harald Alvestrandc24a2182022-02-23 13:44:5923#include "test/gtest.h"
Markus Handell9c27ed22019-12-04 11:57:5824
25using ::testing::_;
Tommi4ccdf9322021-05-17 12:50:1026using ::testing::AnyNumber;
Markus Handell9c27ed22019-12-04 11:57:5827using ::testing::InSequence;
28using ::testing::Mock;
Tommi4ccdf9322021-05-17 12:50:1029using ::testing::NiceMock;
Markus Handell9c27ed22019-12-04 11:57:5830using ::testing::SaveArg;
31using ::testing::StrictMock;
32
33namespace webrtc {
34namespace {
35
36class VideoRtpReceiverTest : public testing::Test {
37 protected:
Florent Castelli1f31c202023-06-26 00:26:0738 class MockVideoMediaSendChannel : public cricket::FakeVideoMediaSendChannel {
Markus Handell9c27ed22019-12-04 11:57:5839 public:
Florent Castelli1f31c202023-06-26 00:26:0740 MockVideoMediaSendChannel(
Tommic9625f02021-05-06 20:03:1941 const cricket::VideoOptions& options,
42 TaskQueueBase* network_thread = rtc::Thread::Current())
Florent Castelli1f31c202023-06-26 00:26:0743 : FakeVideoMediaSendChannel(options, network_thread) {}
44 MOCK_METHOD(void,
45 GenerateSendKeyFrame,
46 (uint32_t, const std::vector<std::string>&),
47 (override));
48 };
49
50 class MockVideoMediaReceiveChannel
51 : public cricket::FakeVideoMediaReceiveChannel {
52 public:
53 MockVideoMediaReceiveChannel(
54 const cricket::VideoOptions& options,
55 TaskQueueBase* network_thread = rtc::Thread::Current())
56 : FakeVideoMediaReceiveChannel(options, network_thread) {}
Danil Chapovalov3a353122020-05-15 09:16:5357 MOCK_METHOD(void,
58 SetRecordableEncodedFrameCallback,
59 (uint32_t, std::function<void(const RecordableEncodedFrame&)>),
60 (override));
61 MOCK_METHOD(void,
62 ClearRecordableEncodedFrameCallback,
63 (uint32_t),
64 (override));
Philipp Hancked237c2b2022-10-25 07:54:2865 MOCK_METHOD(void, RequestRecvKeyFrame, (uint32_t), (override));
Markus Handell9c27ed22019-12-04 11:57:5866 };
67
68 class MockVideoSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> {
69 public:
Danil Chapovalov3a353122020-05-15 09:16:5370 MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override));
Markus Handell9c27ed22019-12-04 11:57:5871 };
72
73 VideoRtpReceiverTest()
74 : worker_thread_(rtc::Thread::Create()),
Florent Castelli1f31c202023-06-26 00:26:0775 channel_(cricket::VideoOptions()),
Tommi4ccdf9322021-05-17 12:50:1076 receiver_(rtc::make_ref_counted<VideoRtpReceiver>(
77 worker_thread_.get(),
78 std::string("receiver"),
79 std::vector<std::string>({"stream"}))) {
Markus Handell9c27ed22019-12-04 11:57:5880 worker_thread_->Start();
Tommi6589def2022-02-17 22:36:4781 SetMediaChannel(&channel_);
Markus Handell9c27ed22019-12-04 11:57:5882 }
83
Tommi4ccdf9322021-05-17 12:50:1084 ~VideoRtpReceiverTest() override {
Tommi6589def2022-02-17 22:36:4785 // Clear expectations that tests may have set up before calling
86 // SetMediaChannel(nullptr).
Tommi4ccdf9322021-05-17 12:50:1087 Mock::VerifyAndClearExpectations(&channel_);
88 receiver_->Stop();
Tommi6589def2022-02-17 22:36:4789 SetMediaChannel(nullptr);
90 }
91
Florent Castelli1f31c202023-06-26 00:26:0792 void SetMediaChannel(cricket::MediaReceiveChannelInterface* media_channel) {
Danil Chapovalov2aaef452022-08-12 13:55:1193 SendTask(worker_thread_.get(),
94 [&]() { receiver_->SetMediaChannel(media_channel); });
Tommi4ccdf9322021-05-17 12:50:1095 }
96
Harald Alvestranda6544372023-11-13 09:33:5697 VideoTrackSourceInterface* Source() {
Markus Handell9c27ed22019-12-04 11:57:5898 return receiver_->streams()[0]->FindVideoTrack("receiver")->GetSource();
99 }
100
Niels Möller83830f32022-05-20 07:12:57101 rtc::AutoThread main_thread_;
Markus Handell9c27ed22019-12-04 11:57:58102 std::unique_ptr<rtc::Thread> worker_thread_;
Florent Castelli1f31c202023-06-26 00:26:07103 NiceMock<MockVideoMediaReceiveChannel> channel_;
Markus Handell9c27ed22019-12-04 11:57:58104 rtc::scoped_refptr<VideoRtpReceiver> receiver_;
105};
106
107TEST_F(VideoRtpReceiverTest, SupportsEncodedOutput) {
108 EXPECT_TRUE(Source()->SupportsEncodedOutput());
109}
110
111TEST_F(VideoRtpReceiverTest, GeneratesKeyFrame) {
Philipp Hancked237c2b2022-10-25 07:54:28112 EXPECT_CALL(channel_, RequestRecvKeyFrame(0));
Markus Handell9c27ed22019-12-04 11:57:58113 Source()->GenerateKeyFrame();
114}
115
116TEST_F(VideoRtpReceiverTest,
117 GenerateKeyFrameOnChannelSwitchUnlessGenerateKeyframeCalled) {
118 // A channel switch without previous call to GenerateKeyFrame shouldn't
119 // cause a call to happen on the new channel.
Florent Castelli1f31c202023-06-26 00:26:07120 MockVideoMediaReceiveChannel channel2{cricket::VideoOptions()};
Philipp Hancked237c2b2022-10-25 07:54:28121 EXPECT_CALL(channel_, RequestRecvKeyFrame).Times(0);
122 EXPECT_CALL(channel2, RequestRecvKeyFrame).Times(0);
Tommi6589def2022-02-17 22:36:47123 SetMediaChannel(&channel2);
Markus Handell9c27ed22019-12-04 11:57:58124 Mock::VerifyAndClearExpectations(&channel2);
125
126 // Generate a key frame. When we switch channel next time, we will have to
127 // re-generate it as we don't know if it was eventually received
Philipp Hancked237c2b2022-10-25 07:54:28128 EXPECT_CALL(channel2, RequestRecvKeyFrame).Times(1);
Markus Handell9c27ed22019-12-04 11:57:58129 Source()->GenerateKeyFrame();
Florent Castelli1f31c202023-06-26 00:26:07130 MockVideoMediaReceiveChannel channel3{cricket::VideoOptions()};
Philipp Hancked237c2b2022-10-25 07:54:28131 EXPECT_CALL(channel3, RequestRecvKeyFrame);
Tommi6589def2022-02-17 22:36:47132 SetMediaChannel(&channel3);
Markus Handell9c27ed22019-12-04 11:57:58133
134 // Switching to a new channel should now not cause calls to GenerateKeyFrame.
Florent Castelli1f31c202023-06-26 00:26:07135 StrictMock<MockVideoMediaReceiveChannel> channel4{cricket::VideoOptions()};
Tommi6589def2022-02-17 22:36:47136 SetMediaChannel(&channel4);
Tommi4ccdf9322021-05-17 12:50:10137
Tommi6589def2022-02-17 22:36:47138 // We must call SetMediaChannel(nullptr) here since the mock media channels
139 // live on the stack and `receiver_` still has a pointer to those objects.
140 SetMediaChannel(nullptr);
Markus Handell9c27ed22019-12-04 11:57:58141}
142
143TEST_F(VideoRtpReceiverTest, EnablesEncodedOutput) {
144 EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(/*ssrc=*/0, _));
145 EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback).Times(0);
146 MockVideoSink sink;
147 Source()->AddEncodedSink(&sink);
148}
149
150TEST_F(VideoRtpReceiverTest, DisablesEncodedOutput) {
151 EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback(/*ssrc=*/0));
152 MockVideoSink sink;
153 Source()->AddEncodedSink(&sink);
154 Source()->RemoveEncodedSink(&sink);
155}
156
157TEST_F(VideoRtpReceiverTest, DisablesEnablesEncodedOutputOnChannelSwitch) {
158 InSequence s;
159 EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback);
160 EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback);
161 MockVideoSink sink;
162 Source()->AddEncodedSink(&sink);
Florent Castelli1f31c202023-06-26 00:26:07163 MockVideoMediaReceiveChannel channel2{cricket::VideoOptions()};
Markus Handell9c27ed22019-12-04 11:57:58164 EXPECT_CALL(channel2, SetRecordableEncodedFrameCallback);
Tommi6589def2022-02-17 22:36:47165 SetMediaChannel(&channel2);
Markus Handell9c27ed22019-12-04 11:57:58166 Mock::VerifyAndClearExpectations(&channel2);
167
168 // When clearing encoded frame buffer function, we need channel switches
169 // to NOT set the callback again.
170 EXPECT_CALL(channel2, ClearRecordableEncodedFrameCallback);
171 Source()->RemoveEncodedSink(&sink);
Florent Castelli1f31c202023-06-26 00:26:07172 StrictMock<MockVideoMediaReceiveChannel> channel3{cricket::VideoOptions()};
Tommi6589def2022-02-17 22:36:47173 SetMediaChannel(&channel3);
Tommi4ccdf9322021-05-17 12:50:10174
Tommi6589def2022-02-17 22:36:47175 // We must call SetMediaChannel(nullptr) here since the mock media channels
176 // live on the stack and `receiver_` still has a pointer to those objects.
177 SetMediaChannel(nullptr);
Markus Handell9c27ed22019-12-04 11:57:58178}
179
180TEST_F(VideoRtpReceiverTest, BroadcastsEncodedFramesWhenEnabled) {
181 std::function<void(const RecordableEncodedFrame&)> broadcast;
182 EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(_, _))
183 .WillRepeatedly(SaveArg<1>(&broadcast));
184 MockVideoSink sink;
185 Source()->AddEncodedSink(&sink);
186
187 // Make sure SetEncodedFrameBufferFunction completes.
188 Mock::VerifyAndClearExpectations(&channel_);
189
190 // Pass two frames on different contexts.
191 EXPECT_CALL(sink, OnFrame).Times(2);
192 MockRecordableEncodedFrame frame;
193 broadcast(frame);
Danil Chapovalov2aaef452022-08-12 13:55:11194 SendTask(worker_thread_.get(), [&] { broadcast(frame); });
Markus Handell9c27ed22019-12-04 11:57:58195}
196
197TEST_F(VideoRtpReceiverTest, EnablesEncodedOutputOnChannelRestart) {
198 InSequence s;
Markus Handell9c27ed22019-12-04 11:57:58199 MockVideoSink sink;
200 Source()->AddEncodedSink(&sink);
201 EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(4711, _));
202 receiver_->SetupMediaChannel(4711);
203 EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback(4711));
204 EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(0, _));
205 receiver_->SetupUnsignaledMediaChannel();
206}
207
208} // namespace
209} // namespace webrtc