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