1 /*
2 * Copyright (c) 2020 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 "video/rtp_video_stream_receiver_frame_transformer_delegate.h"
12
13 #include <cstdio>
14 #include <memory>
15 #include <utility>
16 #include <vector>
17
18 #include "absl/memory/memory.h"
19 #include "api/call/transport.h"
20 #include "call/video_receive_stream.h"
21 #include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
22 #include "modules/utility/include/process_thread.h"
23 #include "rtc_base/event.h"
24 #include "rtc_base/ref_counted_object.h"
25 #include "rtc_base/task_utils/to_queued_task.h"
26 #include "test/gmock.h"
27 #include "test/gtest.h"
28 #include "test/mock_frame_transformer.h"
29
30 namespace webrtc {
31 namespace {
32
33 using ::testing::_;
34 using ::testing::ElementsAre;
35 using ::testing::NiceMock;
36 using ::testing::SaveArg;
37
CreateRtpFrameObject(const RTPVideoHeader & video_header)38 std::unique_ptr<video_coding::RtpFrameObject> CreateRtpFrameObject(
39 const RTPVideoHeader& video_header) {
40 return std::make_unique<video_coding::RtpFrameObject>(
41 0, 0, true, 0, 0, 0, 0, 0, VideoSendTiming(), 0, video_header.codec,
42 kVideoRotation_0, VideoContentType::UNSPECIFIED, video_header,
43 absl::nullopt, RtpPacketInfos(), EncodedImageBuffer::Create(0));
44 }
45
CreateRtpFrameObject()46 std::unique_ptr<video_coding::RtpFrameObject> CreateRtpFrameObject() {
47 return CreateRtpFrameObject(RTPVideoHeader());
48 }
49
50 class TestRtpVideoFrameReceiver : public RtpVideoFrameReceiver {
51 public:
TestRtpVideoFrameReceiver()52 TestRtpVideoFrameReceiver() {}
53 ~TestRtpVideoFrameReceiver() override = default;
54
55 MOCK_METHOD(void,
56 ManageFrame,
57 (std::unique_ptr<video_coding::RtpFrameObject> frame),
58 (override));
59 };
60
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,RegisterTransformedFrameCallbackSinkOnInit)61 TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
62 RegisterTransformedFrameCallbackSinkOnInit) {
63 TestRtpVideoFrameReceiver receiver;
64 rtc::scoped_refptr<MockFrameTransformer> frame_transformer(
65 new rtc::RefCountedObject<MockFrameTransformer>());
66 rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate> delegate(
67 new rtc::RefCountedObject<RtpVideoStreamReceiverFrameTransformerDelegate>(
68 &receiver, frame_transformer, rtc::Thread::Current(),
69 /*remote_ssrc*/ 1111));
70 EXPECT_CALL(*frame_transformer,
71 RegisterTransformedFrameSinkCallback(testing::_, 1111));
72 delegate->Init();
73 }
74
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,UnregisterTransformedFrameSinkCallbackOnReset)75 TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
76 UnregisterTransformedFrameSinkCallbackOnReset) {
77 TestRtpVideoFrameReceiver receiver;
78 rtc::scoped_refptr<MockFrameTransformer> frame_transformer(
79 new rtc::RefCountedObject<MockFrameTransformer>());
80 rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate> delegate(
81 new rtc::RefCountedObject<RtpVideoStreamReceiverFrameTransformerDelegate>(
82 &receiver, frame_transformer, rtc::Thread::Current(),
83 /*remote_ssrc*/ 1111));
84 EXPECT_CALL(*frame_transformer, UnregisterTransformedFrameSinkCallback(1111));
85 delegate->Reset();
86 }
87
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,TransformFrame)88 TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest, TransformFrame) {
89 TestRtpVideoFrameReceiver receiver;
90 rtc::scoped_refptr<MockFrameTransformer> frame_transformer(
91 new rtc::RefCountedObject<testing::NiceMock<MockFrameTransformer>>());
92 rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate> delegate(
93 new rtc::RefCountedObject<RtpVideoStreamReceiverFrameTransformerDelegate>(
94 &receiver, frame_transformer, rtc::Thread::Current(),
95 /*remote_ssrc*/ 1111));
96 auto frame = CreateRtpFrameObject();
97 EXPECT_CALL(*frame_transformer, Transform);
98 delegate->TransformFrame(std::move(frame));
99 }
100
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,ManageFrameOnTransformedFrame)101 TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
102 ManageFrameOnTransformedFrame) {
103 TestRtpVideoFrameReceiver receiver;
104 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer(
105 new rtc::RefCountedObject<NiceMock<MockFrameTransformer>>());
106 rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate> delegate =
107 new rtc::RefCountedObject<RtpVideoStreamReceiverFrameTransformerDelegate>(
108 &receiver, mock_frame_transformer, rtc::Thread::Current(),
109 /*remote_ssrc*/ 1111);
110
111 rtc::scoped_refptr<TransformedFrameCallback> callback;
112 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback)
113 .WillOnce(SaveArg<0>(&callback));
114 delegate->Init();
115 ASSERT_TRUE(callback);
116
117 EXPECT_CALL(receiver, ManageFrame);
118 ON_CALL(*mock_frame_transformer, Transform)
119 .WillByDefault(
120 [&callback](std::unique_ptr<TransformableFrameInterface> frame) {
121 callback->OnTransformedFrame(std::move(frame));
122 });
123 delegate->TransformFrame(CreateRtpFrameObject());
124 rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
125 }
126
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,TransformableFrameMetadataHasCorrectValue)127 TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
128 TransformableFrameMetadataHasCorrectValue) {
129 TestRtpVideoFrameReceiver receiver;
130 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
131 new rtc::RefCountedObject<NiceMock<MockFrameTransformer>>();
132 rtc::scoped_refptr<RtpVideoStreamReceiverFrameTransformerDelegate> delegate =
133 new rtc::RefCountedObject<RtpVideoStreamReceiverFrameTransformerDelegate>(
134 &receiver, mock_frame_transformer, rtc::Thread::Current(), 1111);
135 delegate->Init();
136 RTPVideoHeader video_header;
137 video_header.width = 1280u;
138 video_header.height = 720u;
139 RTPVideoHeader::GenericDescriptorInfo& generic =
140 video_header.generic.emplace();
141 generic.frame_id = 10;
142 generic.temporal_index = 3;
143 generic.spatial_index = 2;
144 generic.decode_target_indications = {DecodeTargetIndication::kSwitch};
145 generic.dependencies = {5};
146
147 // Check that the transformable frame passed to the frame transformer has the
148 // correct metadata.
149 EXPECT_CALL(*mock_frame_transformer, Transform)
150 .WillOnce(
151 [](std::unique_ptr<TransformableFrameInterface> transformable_frame) {
152 auto frame =
153 absl::WrapUnique(static_cast<TransformableVideoFrameInterface*>(
154 transformable_frame.release()));
155 ASSERT_TRUE(frame);
156 auto metadata = frame->GetMetadata();
157 EXPECT_EQ(metadata.GetWidth(), 1280u);
158 EXPECT_EQ(metadata.GetHeight(), 720u);
159 EXPECT_EQ(metadata.GetFrameId(), 10);
160 EXPECT_EQ(metadata.GetTemporalIndex(), 3);
161 EXPECT_EQ(metadata.GetSpatialIndex(), 2);
162 EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5));
163 EXPECT_THAT(metadata.GetDecodeTargetIndications(),
164 ElementsAre(DecodeTargetIndication::kSwitch));
165 });
166 // The delegate creates a transformable frame from the RtpFrameObject.
167 delegate->TransformFrame(CreateRtpFrameObject(video_header));
168 }
169
170 } // namespace
171 } // namespace webrtc
172