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