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