blob: 0d26fc515dc3da866506f33909cca0a94655c552 [file] [log] [blame]
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +00001/*
2 * Copyright (c) 2013 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
Erik Språngc84cd952018-10-15 11:55:13 +020011#include "api/test/mock_video_decoder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "modules/video_coding/include/mock/mock_vcm_callbacks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/video_coding/include/video_coding.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/video_coding/timing.h"
15#include "modules/video_coding/video_coding_impl.h"
16#include "system_wrappers/include/clock.h"
17#include "test/gtest.h"
18#include "test/video_codec_settings.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000019
20using ::testing::_;
tommid0a71ba2017-03-14 04:16:20 -070021using ::testing::AnyNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000022using ::testing::NiceMock;
23
24namespace webrtc {
25namespace vcm {
26namespace {
27
28class TestVideoReceiver : public ::testing::Test {
29 protected:
30 static const int kUnusedPayloadType = 10;
Åsa Persson86202532019-01-09 14:03:59 +010031 static const uint16_t kMaxWaitTimeMs = 100;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000032
Åsa Persson86202532019-01-09 14:03:59 +010033 TestVideoReceiver()
34 : clock_(0), timing_(&clock_), receiver_(&clock_, &timing_) {}
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000035
36 virtual void SetUp() {
Åsa Persson86202532019-01-09 14:03:59 +010037 // Register decoder.
38 receiver_.RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
39 webrtc::test::CodecSettings(kVideoCodecVP8, &settings_);
40 settings_.plType = kUnusedPayloadType;
41 EXPECT_EQ(0, receiver_.RegisterReceiveCodec(&settings_, 1, true));
42
43 // Set protection mode.
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000044 const size_t kMaxNackListSize = 250;
45 const int kMaxPacketAgeToNack = 450;
Åsa Persson86202532019-01-09 14:03:59 +010046 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
47 EXPECT_EQ(0, receiver_.SetVideoProtection(kProtectionNack, true));
48 EXPECT_EQ(
49 0, receiver_.RegisterPacketRequestCallback(&packet_request_callback_));
tommid0a71ba2017-03-14 04:16:20 -070050
51 // Since we call Decode, we need to provide a valid receive callback.
52 // However, for the purposes of these tests, we ignore the callbacks.
53 EXPECT_CALL(receive_callback_, OnIncomingPayloadType(_)).Times(AnyNumber());
54 EXPECT_CALL(receive_callback_, OnDecoderImplementationName(_))
55 .Times(AnyNumber());
Åsa Persson86202532019-01-09 14:03:59 +010056 receiver_.RegisterReceiveCallback(&receive_callback_);
57 }
58
59 WebRtcRTPHeader GetDefaultVp8Header() const {
60 WebRtcRTPHeader header = {};
61 header.frameType = kEmptyFrame;
62 header.header.markerBit = false;
63 header.header.payloadType = kUnusedPayloadType;
64 header.header.ssrc = 1;
65 header.header.headerLength = 12;
66 header.video_header().codec = kVideoCodecVP8;
67 return header;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000068 }
69
70 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000071 WebRtcRTPHeader* header) {
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000072 for (int j = 0; j < 5; ++j) {
73 // Padding only packets are passed to the VCM with payload size 0.
Åsa Persson86202532019-01-09 14:03:59 +010074 EXPECT_EQ(0, receiver_.IncomingPacket(payload, 0, *header));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000075 ++header->header.sequenceNumber;
76 }
Åsa Persson86202532019-01-09 14:03:59 +010077 receiver_.Process();
Niels Möller8df3a382018-05-07 16:10:01 +020078 EXPECT_CALL(decoder_, Decode(_, _, _, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +010079 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000080 }
81
82 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000083 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000084 WebRtcRTPHeader* header) {
Åsa Persson86202532019-01-09 14:03:59 +010085 EXPECT_EQ(0, receiver_.IncomingPacket(payload, length, *header));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000086 ++header->header.sequenceNumber;
87 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +010088
89 receiver_.Process();
Niels Möller8df3a382018-05-07 16:10:01 +020090 EXPECT_CALL(decoder_, Decode(_, _, _, _)).Times(1);
Åsa Persson86202532019-01-09 14:03:59 +010091 EXPECT_EQ(0, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000092 }
93
94 SimulatedClock clock_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000095 VideoCodec settings_;
96 NiceMock<MockVideoDecoder> decoder_;
97 NiceMock<MockPacketRequestCallback> packet_request_callback_;
Åsa Persson86202532019-01-09 14:03:59 +010098 VCMTiming timing_;
tommid0a71ba2017-03-14 04:16:20 -070099 MockVCMReceiveCallback receive_callback_;
Åsa Persson86202532019-01-09 14:03:59 +0100100 VideoReceiver receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000101};
102
103TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000104 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100105 const uint8_t kPayload[kPaddingSize] = {0};
106 WebRtcRTPHeader header = GetDefaultVp8Header();
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000107 header.header.paddingLength = kPaddingSize;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000108 for (int i = 0; i < 10; ++i) {
109 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +0100110 InsertAndVerifyPaddingFrame(kPayload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000111 clock_.AdvanceTimeMilliseconds(33);
112 header.header.timestamp += 3000;
113 }
114}
115
116TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000117 const size_t kFrameSize = 1200;
118 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100119 const uint8_t kPayload[kFrameSize] = {0};
120 WebRtcRTPHeader header = GetDefaultVp8Header();
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000121 header.header.paddingLength = kPaddingSize;
Philip Eliassond52a1a62018-09-07 13:03:55 +0000122 header.video_header().video_type_header.emplace<RTPVideoHeaderVP8>();
Åsa Persson86202532019-01-09 14:03:59 +0100123
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000124 // Insert one video frame to get one frame decoded.
125 header.frameType = kVideoFrameKey;
philipelcb96ad82018-07-02 14:41:58 +0200126 header.video_header().is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000127 header.header.markerBit = true;
Åsa Persson86202532019-01-09 14:03:59 +0100128 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header);
129
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000130 clock_.AdvanceTimeMilliseconds(33);
131 header.header.timestamp += 3000;
pbos22993e12015-10-19 02:39:06 -0700132 header.frameType = kEmptyFrame;
philipelcb96ad82018-07-02 14:41:58 +0200133 header.video_header().is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000134 header.header.markerBit = false;
135 // Insert padding frames.
136 for (int i = 0; i < 10; ++i) {
137 // Lose one packet from the 6th frame.
138 if (i == 5) {
139 ++header.header.sequenceNumber;
140 }
141 // Lose the 4th frame.
142 if (i == 3) {
143 header.header.sequenceNumber += 5;
144 } else {
145 if (i > 3 && i < 5) {
146 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
147 } else if (i >= 5) {
148 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
149 } else {
150 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
151 }
Åsa Persson86202532019-01-09 14:03:59 +0100152 InsertAndVerifyPaddingFrame(kPayload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000153 }
154 clock_.AdvanceTimeMilliseconds(33);
155 header.header.timestamp += 3000;
156 }
157}
158
159TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000160 const size_t kFrameSize = 1200;
161 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100162 const uint8_t kPayload[kFrameSize] = {0};
163 WebRtcRTPHeader header = GetDefaultVp8Header();
philipelcb96ad82018-07-02 14:41:58 +0200164 header.video_header().is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000165 header.header.paddingLength = kPaddingSize;
Philip Eliassond52a1a62018-09-07 13:03:55 +0000166 auto& vp8_header =
167 header.video.video_type_header.emplace<RTPVideoHeaderVP8>();
168 vp8_header.pictureId = -1;
169 vp8_header.tl0PicIdx = -1;
Åsa Persson86202532019-01-09 14:03:59 +0100170
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000171 for (int i = 0; i < 3; ++i) {
172 // Insert 2 video frames.
173 for (int j = 0; j < 2; ++j) {
174 if (i == 0 && j == 0) // First frame should be a key frame.
175 header.frameType = kVideoFrameKey;
176 else
177 header.frameType = kVideoFrameDelta;
philipelcb96ad82018-07-02 14:41:58 +0200178 header.video_header().is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000179 header.header.markerBit = true;
Åsa Persson86202532019-01-09 14:03:59 +0100180 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000181 clock_.AdvanceTimeMilliseconds(33);
182 header.header.timestamp += 3000;
183 }
184
185 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700186 header.frameType = kEmptyFrame;
philipelcb96ad82018-07-02 14:41:58 +0200187 header.video_header().is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000188 header.header.markerBit = false;
189 for (int j = 0; j < 2; ++j) {
Åsa Persson86202532019-01-09 14:03:59 +0100190 // InsertAndVerifyPaddingFrame(kPayload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000191 clock_.AdvanceTimeMilliseconds(33);
192 header.header.timestamp += 3000;
193 }
194 }
195}
196
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000197} // namespace
198} // namespace vcm
199} // namespace webrtc