1 /*
2  *  Copyright (c) 2016 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 "modules/video_coding/generic_decoder.h"
12 
13 #include <vector>
14 
15 #include "absl/types/optional.h"
16 #include "api/task_queue/default_task_queue_factory.h"
17 #include "common_video/test/utilities.h"
18 #include "modules/video_coding/timing.h"
19 #include "rtc_base/event.h"
20 #include "rtc_base/synchronization/mutex.h"
21 #include "system_wrappers/include/clock.h"
22 #include "test/fake_decoder.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25 
26 namespace webrtc {
27 namespace video_coding {
28 
29 class ReceiveCallback : public VCMReceiveCallback {
30  public:
FrameToRender(VideoFrame & videoFrame,absl::optional<uint8_t> qp,int32_t decode_time_ms,VideoContentType content_type)31   int32_t FrameToRender(VideoFrame& videoFrame,  // NOLINT
32                         absl::optional<uint8_t> qp,
33                         int32_t decode_time_ms,
34                         VideoContentType content_type) override {
35     {
36       MutexLock lock(&lock_);
37       last_frame_ = videoFrame;
38     }
39     received_frame_event_.Set();
40     return 0;
41   }
42 
GetLastFrame()43   absl::optional<VideoFrame> GetLastFrame() {
44     MutexLock lock(&lock_);
45     return last_frame_;
46   }
47 
WaitForFrame(int64_t wait_ms)48   absl::optional<VideoFrame> WaitForFrame(int64_t wait_ms) {
49     if (received_frame_event_.Wait(wait_ms)) {
50       MutexLock lock(&lock_);
51       return last_frame_;
52     } else {
53       return absl::nullopt;
54     }
55   }
56 
57  private:
58   Mutex lock_;
59   rtc::Event received_frame_event_;
60   absl::optional<VideoFrame> last_frame_ RTC_GUARDED_BY(lock_);
61 };
62 
63 class GenericDecoderTest : public ::testing::Test {
64  protected:
GenericDecoderTest()65   GenericDecoderTest()
66       : clock_(0),
67         timing_(&clock_),
68         task_queue_factory_(CreateDefaultTaskQueueFactory()),
69         decoder_(task_queue_factory_.get()),
70         vcm_callback_(&timing_, &clock_),
71         generic_decoder_(&decoder_, /*isExternal=*/true) {}
72 
SetUp()73   void SetUp() override {
74     generic_decoder_.RegisterDecodeCompleteCallback(&vcm_callback_);
75     vcm_callback_.SetUserReceiveCallback(&user_callback_);
76     VideoCodec settings;
77     settings.codecType = kVideoCodecVP8;
78     settings.width = 10;
79     settings.height = 10;
80     generic_decoder_.InitDecode(&settings, /*numberOfCores=*/4);
81   }
82 
83   SimulatedClock clock_;
84   VCMTiming timing_;
85   std::unique_ptr<TaskQueueFactory> task_queue_factory_;
86   webrtc::test::FakeDecoder decoder_;
87   VCMDecodedFrameCallback vcm_callback_;
88   VCMGenericDecoder generic_decoder_;
89   ReceiveCallback user_callback_;
90 };
91 
TEST_F(GenericDecoderTest,PassesPacketInfos)92 TEST_F(GenericDecoderTest, PassesPacketInfos) {
93   RtpPacketInfos packet_infos = CreatePacketInfos(3);
94   VCMEncodedFrame encoded_frame;
95   encoded_frame.SetPacketInfos(packet_infos);
96   generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
97   absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
98   ASSERT_TRUE(decoded_frame.has_value());
99   EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
100 }
101 
TEST_F(GenericDecoderTest,PassesPacketInfosForDelayedDecoders)102 TEST_F(GenericDecoderTest, PassesPacketInfosForDelayedDecoders) {
103   RtpPacketInfos packet_infos = CreatePacketInfos(3);
104   decoder_.SetDelayedDecoding(100);
105 
106   {
107     // Ensure the original frame is destroyed before the decoding is completed.
108     VCMEncodedFrame encoded_frame;
109     encoded_frame.SetPacketInfos(packet_infos);
110     generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
111   }
112 
113   absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(200);
114   ASSERT_TRUE(decoded_frame.has_value());
115   EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
116 }
117 
TEST_F(GenericDecoderTest,MaxCompositionDelayNotSetByDefault)118 TEST_F(GenericDecoderTest, MaxCompositionDelayNotSetByDefault) {
119   VCMEncodedFrame encoded_frame;
120   generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
121   absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
122   ASSERT_TRUE(decoded_frame.has_value());
123   EXPECT_FALSE(decoded_frame->max_composition_delay_in_frames());
124 }
125 
TEST_F(GenericDecoderTest,MaxCompositionDelayActivatedByPlayoutDelay)126 TEST_F(GenericDecoderTest, MaxCompositionDelayActivatedByPlayoutDelay) {
127   VCMEncodedFrame encoded_frame;
128   // VideoReceiveStream2 would set MaxCompositionDelayInFrames if playout delay
129   // is specified as X,Y, where X=0, Y>0.
130   const VideoPlayoutDelay kPlayoutDelay = {0, 50};
131   constexpr int kMaxCompositionDelayInFrames = 3;  // ~50 ms at 60 fps.
132   encoded_frame.SetPlayoutDelay(kPlayoutDelay);
133   timing_.SetMaxCompositionDelayInFrames(
134       absl::make_optional(kMaxCompositionDelayInFrames));
135   generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
136   absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
137   ASSERT_TRUE(decoded_frame.has_value());
138   EXPECT_EQ(kMaxCompositionDelayInFrames,
139             decoded_frame->max_composition_delay_in_frames());
140 }
141 
142 }  // namespace video_coding
143 }  // namespace webrtc
144