xref: /aosp_15_r20/external/webrtc/pc/video_rtp_receiver_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
13 #include <functional>
14 #include <memory>
15 
16 #include "api/task_queue/task_queue_base.h"
17 #include "api/video/recordable_encoded_frame.h"
18 #include "api/video/test/mock_recordable_encoded_frame.h"
19 #include "media/base/fake_media_engine.h"
20 #include "rtc_base/task_queue_for_test.h"
21 #include "test/gmock.h"
22 #include "test/gtest.h"
23 
24 using ::testing::_;
25 using ::testing::AnyNumber;
26 using ::testing::InSequence;
27 using ::testing::Mock;
28 using ::testing::NiceMock;
29 using ::testing::SaveArg;
30 using ::testing::StrictMock;
31 
32 namespace webrtc {
33 namespace {
34 
35 class VideoRtpReceiverTest : public testing::Test {
36  protected:
37   class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
38    public:
MockVideoMediaChannel(cricket::FakeVideoEngine * engine,const cricket::VideoOptions & options,TaskQueueBase * network_thread=rtc::Thread::Current ())39     MockVideoMediaChannel(
40         cricket::FakeVideoEngine* engine,
41         const cricket::VideoOptions& options,
42         TaskQueueBase* network_thread = rtc::Thread::Current())
43         : FakeVideoMediaChannel(engine, options, network_thread) {}
44     MOCK_METHOD(void,
45                 SetRecordableEncodedFrameCallback,
46                 (uint32_t, std::function<void(const RecordableEncodedFrame&)>),
47                 (override));
48     MOCK_METHOD(void,
49                 ClearRecordableEncodedFrameCallback,
50                 (uint32_t),
51                 (override));
52     MOCK_METHOD(void, RequestRecvKeyFrame, (uint32_t), (override));
53     MOCK_METHOD(void,
54                 GenerateSendKeyFrame,
55                 (uint32_t, const std::vector<std::string>&),
56                 (override));
57   };
58 
59   class MockVideoSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> {
60    public:
61     MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override));
62   };
63 
VideoRtpReceiverTest()64   VideoRtpReceiverTest()
65       : worker_thread_(rtc::Thread::Create()),
66         channel_(nullptr, cricket::VideoOptions()),
67         receiver_(rtc::make_ref_counted<VideoRtpReceiver>(
68             worker_thread_.get(),
69             std::string("receiver"),
70             std::vector<std::string>({"stream"}))) {
71     worker_thread_->Start();
72     SetMediaChannel(&channel_);
73   }
74 
~VideoRtpReceiverTest()75   ~VideoRtpReceiverTest() override {
76     // Clear expectations that tests may have set up before calling
77     // SetMediaChannel(nullptr).
78     Mock::VerifyAndClearExpectations(&channel_);
79     receiver_->Stop();
80     SetMediaChannel(nullptr);
81   }
82 
SetMediaChannel(cricket::MediaChannel * media_channel)83   void SetMediaChannel(cricket::MediaChannel* media_channel) {
84     SendTask(worker_thread_.get(),
85              [&]() { receiver_->SetMediaChannel(media_channel); });
86   }
87 
Source()88   webrtc::VideoTrackSourceInterface* Source() {
89     return receiver_->streams()[0]->FindVideoTrack("receiver")->GetSource();
90   }
91 
92   rtc::AutoThread main_thread_;
93   std::unique_ptr<rtc::Thread> worker_thread_;
94   NiceMock<MockVideoMediaChannel> channel_;
95   rtc::scoped_refptr<VideoRtpReceiver> receiver_;
96 };
97 
TEST_F(VideoRtpReceiverTest,SupportsEncodedOutput)98 TEST_F(VideoRtpReceiverTest, SupportsEncodedOutput) {
99   EXPECT_TRUE(Source()->SupportsEncodedOutput());
100 }
101 
TEST_F(VideoRtpReceiverTest,GeneratesKeyFrame)102 TEST_F(VideoRtpReceiverTest, GeneratesKeyFrame) {
103   EXPECT_CALL(channel_, RequestRecvKeyFrame(0));
104   Source()->GenerateKeyFrame();
105 }
106 
TEST_F(VideoRtpReceiverTest,GenerateKeyFrameOnChannelSwitchUnlessGenerateKeyframeCalled)107 TEST_F(VideoRtpReceiverTest,
108        GenerateKeyFrameOnChannelSwitchUnlessGenerateKeyframeCalled) {
109   // A channel switch without previous call to GenerateKeyFrame shouldn't
110   // cause a call to happen on the new channel.
111   MockVideoMediaChannel channel2(nullptr, cricket::VideoOptions());
112   EXPECT_CALL(channel_, RequestRecvKeyFrame).Times(0);
113   EXPECT_CALL(channel2, RequestRecvKeyFrame).Times(0);
114   SetMediaChannel(&channel2);
115   Mock::VerifyAndClearExpectations(&channel2);
116 
117   // Generate a key frame. When we switch channel next time, we will have to
118   // re-generate it as we don't know if it was eventually received
119   EXPECT_CALL(channel2, RequestRecvKeyFrame).Times(1);
120   Source()->GenerateKeyFrame();
121   MockVideoMediaChannel channel3(nullptr, cricket::VideoOptions());
122   EXPECT_CALL(channel3, RequestRecvKeyFrame);
123   SetMediaChannel(&channel3);
124 
125   // Switching to a new channel should now not cause calls to GenerateKeyFrame.
126   StrictMock<MockVideoMediaChannel> channel4(nullptr, cricket::VideoOptions());
127   SetMediaChannel(&channel4);
128 
129   // We must call SetMediaChannel(nullptr) here since the mock media channels
130   // live on the stack and `receiver_` still has a pointer to those objects.
131   SetMediaChannel(nullptr);
132 }
133 
TEST_F(VideoRtpReceiverTest,EnablesEncodedOutput)134 TEST_F(VideoRtpReceiverTest, EnablesEncodedOutput) {
135   EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(/*ssrc=*/0, _));
136   EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback).Times(0);
137   MockVideoSink sink;
138   Source()->AddEncodedSink(&sink);
139 }
140 
TEST_F(VideoRtpReceiverTest,DisablesEncodedOutput)141 TEST_F(VideoRtpReceiverTest, DisablesEncodedOutput) {
142   EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback(/*ssrc=*/0));
143   MockVideoSink sink;
144   Source()->AddEncodedSink(&sink);
145   Source()->RemoveEncodedSink(&sink);
146 }
147 
TEST_F(VideoRtpReceiverTest,DisablesEnablesEncodedOutputOnChannelSwitch)148 TEST_F(VideoRtpReceiverTest, DisablesEnablesEncodedOutputOnChannelSwitch) {
149   InSequence s;
150   EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback);
151   EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback);
152   MockVideoSink sink;
153   Source()->AddEncodedSink(&sink);
154   MockVideoMediaChannel channel2(nullptr, cricket::VideoOptions());
155   EXPECT_CALL(channel2, SetRecordableEncodedFrameCallback);
156   SetMediaChannel(&channel2);
157   Mock::VerifyAndClearExpectations(&channel2);
158 
159   // When clearing encoded frame buffer function, we need channel switches
160   // to NOT set the callback again.
161   EXPECT_CALL(channel2, ClearRecordableEncodedFrameCallback);
162   Source()->RemoveEncodedSink(&sink);
163   StrictMock<MockVideoMediaChannel> channel3(nullptr, cricket::VideoOptions());
164   SetMediaChannel(&channel3);
165 
166   // We must call SetMediaChannel(nullptr) here since the mock media channels
167   // live on the stack and `receiver_` still has a pointer to those objects.
168   SetMediaChannel(nullptr);
169 }
170 
TEST_F(VideoRtpReceiverTest,BroadcastsEncodedFramesWhenEnabled)171 TEST_F(VideoRtpReceiverTest, BroadcastsEncodedFramesWhenEnabled) {
172   std::function<void(const RecordableEncodedFrame&)> broadcast;
173   EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(_, _))
174       .WillRepeatedly(SaveArg<1>(&broadcast));
175   MockVideoSink sink;
176   Source()->AddEncodedSink(&sink);
177 
178   // Make sure SetEncodedFrameBufferFunction completes.
179   Mock::VerifyAndClearExpectations(&channel_);
180 
181   // Pass two frames on different contexts.
182   EXPECT_CALL(sink, OnFrame).Times(2);
183   MockRecordableEncodedFrame frame;
184   broadcast(frame);
185   SendTask(worker_thread_.get(), [&] { broadcast(frame); });
186 }
187 
TEST_F(VideoRtpReceiverTest,EnablesEncodedOutputOnChannelRestart)188 TEST_F(VideoRtpReceiverTest, EnablesEncodedOutputOnChannelRestart) {
189   InSequence s;
190   MockVideoSink sink;
191   Source()->AddEncodedSink(&sink);
192   EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(4711, _));
193   receiver_->SetupMediaChannel(4711);
194   EXPECT_CALL(channel_, ClearRecordableEncodedFrameCallback(4711));
195   EXPECT_CALL(channel_, SetRecordableEncodedFrameCallback(0, _));
196   receiver_->SetupUnsignaledMediaChannel();
197 }
198 
199 }  // namespace
200 }  // namespace webrtc
201