summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc')
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc353
1 files changed, 353 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
new file mode 100644
index 0000000000..f403c91a74
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2020 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 "modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.h"
+
+#include <cstdio>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "api/call/transport.h"
+#include "api/test/mock_transformable_video_frame.h"
+#include "api/units/timestamp.h"
+#include "call/video_receive_stream.h"
+#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
+#include "rtc_base/event.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/mock_frame_transformer.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::SaveArg;
+
+const int kFirstSeqNum = 1;
+const int kLastSeqNum = 2;
+
+std::unique_ptr<RtpFrameObject> CreateRtpFrameObject(
+ const RTPVideoHeader& video_header,
+ std::vector<uint32_t> csrcs) {
+ RtpPacketInfo packet_info(/*ssrc=*/123, csrcs, /*rtc_timestamp=*/0,
+ /*receive_time=*/Timestamp::Seconds(123456));
+ return std::make_unique<RtpFrameObject>(
+ kFirstSeqNum, kLastSeqNum, /*markerBit=*/true,
+ /*times_nacked=*/3, /*first_packet_received_time=*/4,
+ /*last_packet_received_time=*/5, /*rtp_timestamp=*/6, /*ntp_time_ms=*/7,
+ VideoSendTiming(), /*payload_type=*/8, video_header.codec,
+ kVideoRotation_0, VideoContentType::UNSPECIFIED, video_header,
+ absl::nullopt, RtpPacketInfos({packet_info}),
+ EncodedImageBuffer::Create(0));
+}
+
+std::unique_ptr<RtpFrameObject> CreateRtpFrameObject() {
+ return CreateRtpFrameObject(RTPVideoHeader(), /*csrcs=*/{});
+}
+
+class TestRtpVideoFrameReceiver : public RtpVideoFrameReceiver {
+ public:
+ TestRtpVideoFrameReceiver() {}
+ ~TestRtpVideoFrameReceiver() override = default;
+
+ MOCK_METHOD(void,
+ ManageFrame,
+ (std::unique_ptr<RtpFrameObject> frame),
+ (override));
+};
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ RegisterTransformedFrameCallbackSinkOnInit) {
+ TestRtpVideoFrameReceiver receiver;
+ auto frame_transformer(rtc::make_ref_counted<MockFrameTransformer>());
+ SimulatedClock clock(0);
+ auto delegate(
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, frame_transformer, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111));
+ EXPECT_CALL(*frame_transformer,
+ RegisterTransformedFrameSinkCallback(testing::_, 1111));
+ delegate->Init();
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ UnregisterTransformedFrameSinkCallbackOnReset) {
+ TestRtpVideoFrameReceiver receiver;
+ auto frame_transformer(rtc::make_ref_counted<MockFrameTransformer>());
+ SimulatedClock clock(0);
+ auto delegate(
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, frame_transformer, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111));
+ EXPECT_CALL(*frame_transformer, UnregisterTransformedFrameSinkCallback(1111));
+ delegate->Reset();
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest, TransformFrame) {
+ TestRtpVideoFrameReceiver receiver;
+ auto frame_transformer(
+ rtc::make_ref_counted<testing::NiceMock<MockFrameTransformer>>());
+ SimulatedClock clock(0);
+ auto delegate(
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, frame_transformer, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111));
+ auto frame = CreateRtpFrameObject();
+ EXPECT_CALL(*frame_transformer, Transform);
+ delegate->TransformFrame(std::move(frame));
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ ManageFrameOnTransformedFrame) {
+ rtc::AutoThread main_thread_;
+ TestRtpVideoFrameReceiver receiver;
+ auto mock_frame_transformer(
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>());
+ SimulatedClock clock(0);
+ std::vector<uint32_t> csrcs = {234, 345, 456};
+ auto delegate =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, mock_frame_transformer, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111);
+
+ rtc::scoped_refptr<TransformedFrameCallback> callback;
+ EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback)
+ .WillOnce(SaveArg<0>(&callback));
+ delegate->Init();
+ ASSERT_TRUE(callback);
+
+ EXPECT_CALL(receiver, ManageFrame)
+ .WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
+ EXPECT_EQ(frame->Csrcs(), csrcs);
+ EXPECT_EQ(frame->first_seq_num(), kFirstSeqNum);
+ EXPECT_EQ(frame->last_seq_num(), kLastSeqNum);
+ });
+ ON_CALL(*mock_frame_transformer, Transform)
+ .WillByDefault(
+ [&callback](std::unique_ptr<TransformableFrameInterface> frame) {
+ EXPECT_STRCASEEQ("video/Generic", frame->GetMimeType().c_str());
+ callback->OnTransformedFrame(std::move(frame));
+ });
+ delegate->TransformFrame(CreateRtpFrameObject(RTPVideoHeader(), csrcs));
+ rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ TransformableFrameMetadataHasCorrectValue) {
+ TestRtpVideoFrameReceiver receiver;
+ auto mock_frame_transformer =
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
+ SimulatedClock clock(0);
+ auto delegate =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, mock_frame_transformer, rtc::Thread::Current(),
+ 1111);
+ delegate->Init();
+ RTPVideoHeader video_header;
+ video_header.width = 1280u;
+ video_header.height = 720u;
+ RTPVideoHeader::GenericDescriptorInfo& generic =
+ video_header.generic.emplace();
+ generic.frame_id = 10;
+ generic.temporal_index = 3;
+ generic.spatial_index = 2;
+ generic.decode_target_indications = {DecodeTargetIndication::kSwitch};
+ generic.dependencies = {5};
+
+ std::vector<uint32_t> csrcs = {234, 345, 456};
+
+ // Check that the transformable frame passed to the frame transformer has the
+ // correct metadata.
+ EXPECT_CALL(*mock_frame_transformer, Transform)
+ .WillOnce([&](std::unique_ptr<TransformableFrameInterface>
+ transformable_frame) {
+ auto frame =
+ absl::WrapUnique(static_cast<TransformableVideoFrameInterface*>(
+ transformable_frame.release()));
+ ASSERT_TRUE(frame);
+ auto metadata = frame->Metadata();
+ EXPECT_EQ(metadata.GetWidth(), 1280u);
+ EXPECT_EQ(metadata.GetHeight(), 720u);
+ EXPECT_EQ(metadata.GetFrameId(), 10);
+ EXPECT_EQ(metadata.GetTemporalIndex(), 3);
+ EXPECT_EQ(metadata.GetSpatialIndex(), 2);
+ EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5));
+ EXPECT_THAT(metadata.GetDecodeTargetIndications(),
+ ElementsAre(DecodeTargetIndication::kSwitch));
+ EXPECT_EQ(metadata.GetCsrcs(), csrcs);
+ });
+ // The delegate creates a transformable frame from the RtpFrameObject.
+ delegate->TransformFrame(CreateRtpFrameObject(video_header, csrcs));
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ TransformableFrameMetadataHasCorrectValueAfterSetMetadata) {
+ rtc::AutoThread main_thread;
+ TestRtpVideoFrameReceiver receiver;
+ auto mock_frame_transformer =
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
+ SimulatedClock clock(1000);
+ auto delegate =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, mock_frame_transformer, rtc::Thread::Current(),
+ 1111);
+
+ rtc::scoped_refptr<TransformedFrameCallback> callback;
+ EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback)
+ .WillOnce(SaveArg<0>(&callback));
+ delegate->Init();
+ ASSERT_TRUE(callback);
+
+ RTPVideoHeader video_header;
+ RTPVideoHeader::GenericDescriptorInfo& generic =
+ video_header.generic.emplace();
+ generic.frame_id = 10;
+ generic.dependencies = {5};
+
+ std::vector<uint32_t> csrcs = {234, 345, 456};
+
+ // Checks that the recieved RTPFrameObject has the new metadata.
+ EXPECT_CALL(receiver, ManageFrame)
+ .WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
+ const absl::optional<RTPVideoHeader::GenericDescriptorInfo>&
+ descriptor = frame->GetRtpVideoHeader().generic;
+ if (!descriptor.has_value()) {
+ ADD_FAILURE() << "GenericDescriptorInfo in RTPVideoHeader doesn't "
+ "have a value.";
+ } else {
+ EXPECT_EQ(descriptor->frame_id, 20);
+ EXPECT_THAT(descriptor->dependencies, ElementsAre(15));
+ }
+ EXPECT_EQ(frame->Csrcs(), csrcs);
+ });
+
+ // Sets new metadata to the transformable frame.
+ ON_CALL(*mock_frame_transformer, Transform)
+ .WillByDefault([&](std::unique_ptr<TransformableFrameInterface>
+ transformable_frame) {
+ ASSERT_THAT(transformable_frame, NotNull());
+ auto& video_frame = static_cast<TransformableVideoFrameInterface&>(
+ *transformable_frame);
+ VideoFrameMetadata metadata = video_frame.Metadata();
+ EXPECT_EQ(metadata.GetFrameId(), 10);
+ EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5));
+ EXPECT_EQ(metadata.GetCsrcs(), csrcs);
+
+ metadata.SetFrameId(20);
+ metadata.SetFrameDependencies(std::vector<int64_t>{15});
+ video_frame.SetMetadata(metadata);
+ callback->OnTransformedFrame(std::move(transformable_frame));
+ });
+
+ // The delegate creates a transformable frame from the RtpFrameObject.
+ delegate->TransformFrame(CreateRtpFrameObject(video_header, csrcs));
+ rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ SenderFramesAreConvertedToReceiverFrames) {
+ rtc::AutoThread main_thread_;
+ TestRtpVideoFrameReceiver receiver;
+ auto mock_frame_transformer =
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
+ SimulatedClock clock(/*initial_timestamp_us=*/12345000);
+ auto delegate =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver, &clock, mock_frame_transformer, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111);
+
+ auto mock_sender_frame =
+ std::make_unique<NiceMock<MockTransformableVideoFrame>>();
+ ON_CALL(*mock_sender_frame, GetDirection)
+ .WillByDefault(Return(TransformableFrameInterface::Direction::kSender));
+ VideoFrameMetadata metadata;
+ metadata.SetCodec(kVideoCodecVP8);
+ metadata.SetRTPVideoHeaderCodecSpecifics(RTPVideoHeaderVP8());
+ ON_CALL(*mock_sender_frame, Metadata).WillByDefault(Return(metadata));
+ rtc::scoped_refptr<EncodedImageBufferInterface> buffer =
+ EncodedImageBuffer::Create(1);
+ ON_CALL(*mock_sender_frame, GetData)
+ .WillByDefault(Return(rtc::ArrayView<const uint8_t>(*buffer)));
+
+ rtc::scoped_refptr<TransformedFrameCallback> callback;
+ EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback)
+ .WillOnce(SaveArg<0>(&callback));
+ delegate->Init();
+ ASSERT_TRUE(callback);
+
+ EXPECT_CALL(receiver, ManageFrame)
+ .WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
+ EXPECT_EQ(frame->codec_type(), metadata.GetCodec());
+ EXPECT_EQ(frame->ReceivedTime(), 12345);
+ });
+ callback->OnTransformedFrame(std::move(mock_sender_frame));
+ rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
+}
+
+TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
+ ManageFrameFromDifferentReceiver) {
+ rtc::AutoThread main_thread_;
+ std::vector<uint32_t> csrcs = {234, 345, 456};
+ const int frame_id = 11;
+
+ TestRtpVideoFrameReceiver receiver1;
+ auto mock_frame_transformer1(
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>());
+ SimulatedClock clock(0);
+ auto delegate1 =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver1, &clock, mock_frame_transformer1, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111);
+
+ TestRtpVideoFrameReceiver receiver2;
+ auto mock_frame_transformer2(
+ rtc::make_ref_counted<NiceMock<MockFrameTransformer>>());
+ auto delegate2 =
+ rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
+ &receiver2, &clock, mock_frame_transformer2, rtc::Thread::Current(),
+ /*remote_ssrc*/ 1111);
+
+ delegate1->Init();
+ rtc::scoped_refptr<TransformedFrameCallback> callback_for_2;
+ EXPECT_CALL(*mock_frame_transformer2, RegisterTransformedFrameSinkCallback)
+ .WillOnce(SaveArg<0>(&callback_for_2));
+ delegate2->Init();
+ ASSERT_TRUE(callback_for_2);
+
+ // Expect a call on receiver2's ManageFrame with sequence numbers overwritten
+ // with the frame's ID.
+ EXPECT_CALL(receiver2, ManageFrame)
+ .WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
+ EXPECT_EQ(frame->Csrcs(), csrcs);
+ EXPECT_EQ(frame->first_seq_num(), frame_id);
+ EXPECT_EQ(frame->last_seq_num(), frame_id);
+ });
+ // When the frame transformer for receiver 1 receives the frame to transform,
+ // pipe it over to the callback for receiver 2.
+ ON_CALL(*mock_frame_transformer1, Transform)
+ .WillByDefault([&callback_for_2](
+ std::unique_ptr<TransformableFrameInterface> frame) {
+ callback_for_2->OnTransformedFrame(std::move(frame));
+ });
+ std::unique_ptr<RtpFrameObject> untransformed_frame =
+ CreateRtpFrameObject(RTPVideoHeader(), csrcs);
+ untransformed_frame->SetId(frame_id);
+ delegate1->TransformFrame(std::move(untransformed_frame));
+ rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
+}
+
+} // namespace
+} // namespace webrtc