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