1 /*
2 * Copyright (c) 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_track_source.h"
12
13 #include "rtc_base/ref_counted_object.h"
14 #include "test/gmock.h"
15 #include "test/gtest.h"
16
17 namespace webrtc {
18 namespace {
19
20 class MockCallback : public VideoRtpTrackSource::Callback {
21 public:
22 MOCK_METHOD(void, OnGenerateKeyFrame, (), (override));
23 MOCK_METHOD(void, OnEncodedSinkEnabled, (bool), (override));
24 };
25
26 class MockSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> {
27 public:
28 MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override));
29 };
30
MakeSource(VideoRtpTrackSource::Callback * callback)31 rtc::scoped_refptr<VideoRtpTrackSource> MakeSource(
32 VideoRtpTrackSource::Callback* callback) {
33 rtc::scoped_refptr<VideoRtpTrackSource> source(
34 new rtc::RefCountedObject<VideoRtpTrackSource>(callback));
35 return source;
36 }
37
TEST(VideoRtpTrackSourceTest,CreatesWithRemoteAtttributeSet)38 TEST(VideoRtpTrackSourceTest, CreatesWithRemoteAtttributeSet) {
39 EXPECT_TRUE(MakeSource(nullptr)->remote());
40 }
41
TEST(VideoRtpTrackSourceTest,EnablesEncodingOutputOnAddingSink)42 TEST(VideoRtpTrackSourceTest, EnablesEncodingOutputOnAddingSink) {
43 MockCallback mock_callback;
44 EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
45 auto source = MakeSource(&mock_callback);
46 MockSink sink;
47 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
48 source->AddEncodedSink(&sink);
49 }
50
TEST(VideoRtpTrackSourceTest,EnablesEncodingOutputOnceOnAddingTwoSinks)51 TEST(VideoRtpTrackSourceTest, EnablesEncodingOutputOnceOnAddingTwoSinks) {
52 MockCallback mock_callback;
53 EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
54 auto source = MakeSource(&mock_callback);
55 MockSink sink;
56 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true)).Times(1);
57 source->AddEncodedSink(&sink);
58 MockSink sink2;
59 source->AddEncodedSink(&sink2);
60 }
61
TEST(VideoRtpTrackSourceTest,DisablesEncodingOutputOnOneSinkRemoved)62 TEST(VideoRtpTrackSourceTest, DisablesEncodingOutputOnOneSinkRemoved) {
63 MockCallback mock_callback;
64 EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
65 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
66 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false)).Times(0);
67 auto source = MakeSource(&mock_callback);
68 MockSink sink;
69 source->AddEncodedSink(&sink);
70 testing::Mock::VerifyAndClearExpectations(&mock_callback);
71 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false));
72 source->RemoveEncodedSink(&sink);
73 }
74
TEST(VideoRtpTrackSourceTest,DisablesEncodingOutputOnLastSinkRemoved)75 TEST(VideoRtpTrackSourceTest, DisablesEncodingOutputOnLastSinkRemoved) {
76 MockCallback mock_callback;
77 EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
78 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
79 auto source = MakeSource(&mock_callback);
80 MockSink sink;
81 source->AddEncodedSink(&sink);
82 MockSink sink2;
83 source->AddEncodedSink(&sink2);
84 source->RemoveEncodedSink(&sink);
85 testing::Mock::VerifyAndClearExpectations(&mock_callback);
86 EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false));
87 source->RemoveEncodedSink(&sink2);
88 }
89
TEST(VideoRtpTrackSourceTest,GeneratesKeyFrameWhenRequested)90 TEST(VideoRtpTrackSourceTest, GeneratesKeyFrameWhenRequested) {
91 MockCallback mock_callback;
92 auto source = MakeSource(&mock_callback);
93 EXPECT_CALL(mock_callback, OnGenerateKeyFrame);
94 source->GenerateKeyFrame();
95 }
96
TEST(VideoRtpTrackSourceTest,NoCallbacksAfterClearedCallback)97 TEST(VideoRtpTrackSourceTest, NoCallbacksAfterClearedCallback) {
98 testing::StrictMock<MockCallback> mock_callback;
99 auto source = MakeSource(&mock_callback);
100 source->ClearCallback();
101 MockSink sink;
102 source->AddEncodedSink(&sink);
103 source->GenerateKeyFrame();
104 source->RemoveEncodedSink(&sink);
105 }
106
107 class TestFrame : public RecordableEncodedFrame {
108 public:
encoded_buffer() const109 rtc::scoped_refptr<const webrtc::EncodedImageBufferInterface> encoded_buffer()
110 const override {
111 return nullptr;
112 }
color_space() const113 absl::optional<webrtc::ColorSpace> color_space() const override {
114 return absl::nullopt;
115 }
codec() const116 VideoCodecType codec() const override { return kVideoCodecGeneric; }
is_key_frame() const117 bool is_key_frame() const override { return false; }
resolution() const118 EncodedResolution resolution() const override {
119 return EncodedResolution{0, 0};
120 }
render_time() const121 Timestamp render_time() const override { return Timestamp::Millis(0); }
122 };
123
TEST(VideoRtpTrackSourceTest,BroadcastsFrames)124 TEST(VideoRtpTrackSourceTest, BroadcastsFrames) {
125 auto source = MakeSource(nullptr);
126 MockSink sink;
127 source->AddEncodedSink(&sink);
128 MockSink sink2;
129 source->AddEncodedSink(&sink2);
130 TestFrame frame;
131 EXPECT_CALL(sink, OnFrame);
132 EXPECT_CALL(sink2, OnFrame);
133 source->BroadcastRecordableEncodedFrame(frame);
134 }
135
136 } // namespace
137 } // namespace webrtc
138