blob: 62d33f573bb37567a69ba61577cc5957a97735be [file] [log] [blame]
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "pc/video_rtp_track_source.h"
#include <optional>
#include "api/scoped_refptr.h"
#include "api/units/timestamp.h"
#include "api/video/color_space.h"
#include "api/video/encoded_image.h"
#include "api/video/video_codec_type.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
class MockCallback : public VideoRtpTrackSource::Callback {
public:
MOCK_METHOD(void, OnGenerateKeyFrame, (), (override));
MOCK_METHOD(void, OnEncodedSinkEnabled, (bool), (override));
};
class MockSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> {
public:
MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override));
};
rtc::scoped_refptr<VideoRtpTrackSource> MakeSource(
VideoRtpTrackSource::Callback* callback) {
return rtc::make_ref_counted<VideoRtpTrackSource>(callback);
}
TEST(VideoRtpTrackSourceTest, CreatesWithRemoteAtttributeSet) {
EXPECT_TRUE(MakeSource(nullptr)->remote());
}
TEST(VideoRtpTrackSourceTest, EnablesEncodingOutputOnAddingSink) {
MockCallback mock_callback;
EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
auto source = MakeSource(&mock_callback);
MockSink sink;
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
source->AddEncodedSink(&sink);
}
TEST(VideoRtpTrackSourceTest, EnablesEncodingOutputOnceOnAddingTwoSinks) {
MockCallback mock_callback;
EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
auto source = MakeSource(&mock_callback);
MockSink sink;
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true)).Times(1);
source->AddEncodedSink(&sink);
MockSink sink2;
source->AddEncodedSink(&sink2);
}
TEST(VideoRtpTrackSourceTest, DisablesEncodingOutputOnOneSinkRemoved) {
MockCallback mock_callback;
EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false)).Times(0);
auto source = MakeSource(&mock_callback);
MockSink sink;
source->AddEncodedSink(&sink);
testing::Mock::VerifyAndClearExpectations(&mock_callback);
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false));
source->RemoveEncodedSink(&sink);
}
TEST(VideoRtpTrackSourceTest, DisablesEncodingOutputOnLastSinkRemoved) {
MockCallback mock_callback;
EXPECT_CALL(mock_callback, OnGenerateKeyFrame).Times(0);
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(true));
auto source = MakeSource(&mock_callback);
MockSink sink;
source->AddEncodedSink(&sink);
MockSink sink2;
source->AddEncodedSink(&sink2);
source->RemoveEncodedSink(&sink);
testing::Mock::VerifyAndClearExpectations(&mock_callback);
EXPECT_CALL(mock_callback, OnEncodedSinkEnabled(false));
source->RemoveEncodedSink(&sink2);
}
TEST(VideoRtpTrackSourceTest, GeneratesKeyFrameWhenRequested) {
MockCallback mock_callback;
auto source = MakeSource(&mock_callback);
EXPECT_CALL(mock_callback, OnGenerateKeyFrame);
source->GenerateKeyFrame();
}
TEST(VideoRtpTrackSourceTest, NoCallbacksAfterClearedCallback) {
testing::StrictMock<MockCallback> mock_callback;
auto source = MakeSource(&mock_callback);
source->ClearCallback();
MockSink sink;
source->AddEncodedSink(&sink);
source->GenerateKeyFrame();
source->RemoveEncodedSink(&sink);
}
class TestFrame : public RecordableEncodedFrame {
public:
rtc::scoped_refptr<const EncodedImageBufferInterface> encoded_buffer()
const override {
return nullptr;
}
std::optional<ColorSpace> color_space() const override {
return std::nullopt;
}
VideoCodecType codec() const override { return kVideoCodecGeneric; }
bool is_key_frame() const override { return false; }
EncodedResolution resolution() const override {
return EncodedResolution{0, 0};
}
Timestamp render_time() const override { return Timestamp::Zero(); }
};
TEST(VideoRtpTrackSourceTest, BroadcastsFrames) {
auto source = MakeSource(nullptr);
MockSink sink;
source->AddEncodedSink(&sink);
MockSink sink2;
source->AddEncodedSink(&sink2);
TestFrame frame;
EXPECT_CALL(sink, OnFrame);
EXPECT_CALL(sink2, OnFrame);
source->BroadcastRecordableEncodedFrame(frame);
}
} // namespace
} // namespace webrtc