1/*
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
11#include <vector>
12
13#include "testing/gtest/include/gtest/gtest.h"
14#include "webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h"
15#include "webrtc/modules/video_coding/main/interface/mock/mock_vcm_callbacks.h"
16#include "webrtc/modules/video_coding/main/interface/video_coding.h"
17#include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
18#include "webrtc/modules/video_coding/main/test/test_util.h"
19#include "webrtc/system_wrappers/interface/clock.h"
20#include "webrtc/system_wrappers/interface/scoped_ptr.h"
21
22using ::testing::_;
23using ::testing::NiceMock;
24
25namespace webrtc {
26namespace vcm {
27namespace {
28
29class TestVideoReceiver : public ::testing::Test {
30 protected:
31  static const int kUnusedPayloadType = 10;
32
33  TestVideoReceiver() : clock_(0) {}
34
35  virtual void SetUp() {
36    receiver_.reset(new VideoReceiver(&clock_, &event_factory_));
37    EXPECT_EQ(0, receiver_->InitializeReceiver());
38    EXPECT_EQ(0,
39              receiver_->RegisterExternalDecoder(
40                  &decoder_, kUnusedPayloadType, true));
41    const size_t kMaxNackListSize = 250;
42    const int kMaxPacketAgeToNack = 450;
43    receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
44
45    memset(&settings_, 0, sizeof(settings_));
46    EXPECT_EQ(0, VideoCodingModule::Codec(kVideoCodecVP8, &settings_));
47    settings_.plType = kUnusedPayloadType;  // Use the mocked encoder.
48    EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
49  }
50
51  void InsertAndVerifyPaddingFrame(const uint8_t* payload,
52                                   int length,
53                                   WebRtcRTPHeader* header) {
54    ASSERT_TRUE(header != NULL);
55    for (int j = 0; j < 5; ++j) {
56      // Padding only packets are passed to the VCM with payload size 0.
57      EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
58      ++header->header.sequenceNumber;
59    }
60    EXPECT_EQ(0, receiver_->Process());
61    EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
62    EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0));
63  }
64
65  void InsertAndVerifyDecodableFrame(const uint8_t* payload,
66                                     int length,
67                                     WebRtcRTPHeader* header) {
68    ASSERT_TRUE(header != NULL);
69    EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
70    ++header->header.sequenceNumber;
71    EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
72    EXPECT_EQ(0, receiver_->Process());
73    EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
74    EXPECT_EQ(0, receiver_->Decode(0));
75  }
76
77  SimulatedClock clock_;
78  NullEventFactory event_factory_;
79  VideoCodec settings_;
80  NiceMock<MockVideoDecoder> decoder_;
81  NiceMock<MockPacketRequestCallback> packet_request_callback_;
82
83  scoped_ptr<VideoReceiver> receiver_;
84};
85
86TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
87  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
88  EXPECT_EQ(
89      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
90  const unsigned int kPaddingSize = 220;
91  const uint8_t payload[kPaddingSize] = {0};
92  WebRtcRTPHeader header;
93  memset(&header, 0, sizeof(header));
94  header.frameType = kFrameEmpty;
95  header.header.markerBit = false;
96  header.header.paddingLength = kPaddingSize;
97  header.header.payloadType = kUnusedPayloadType;
98  header.header.ssrc = 1;
99  header.header.headerLength = 12;
100  header.type.Video.codec = kRtpVideoVp8;
101  for (int i = 0; i < 10; ++i) {
102    EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
103    InsertAndVerifyPaddingFrame(payload, 0, &header);
104    clock_.AdvanceTimeMilliseconds(33);
105    header.header.timestamp += 3000;
106  }
107}
108
109TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
110  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
111  EXPECT_EQ(
112      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
113  const unsigned int kFrameSize = 1200;
114  const unsigned int kPaddingSize = 220;
115  const uint8_t payload[kFrameSize] = {0};
116  WebRtcRTPHeader header;
117  memset(&header, 0, sizeof(header));
118  header.frameType = kFrameEmpty;
119  header.header.markerBit = false;
120  header.header.paddingLength = kPaddingSize;
121  header.header.payloadType = kUnusedPayloadType;
122  header.header.ssrc = 1;
123  header.header.headerLength = 12;
124  header.type.Video.codec = kRtpVideoVp8;
125  // Insert one video frame to get one frame decoded.
126  header.frameType = kVideoFrameKey;
127  header.type.Video.isFirstPacket = true;
128  header.header.markerBit = true;
129  InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
130  clock_.AdvanceTimeMilliseconds(33);
131  header.header.timestamp += 3000;
132
133  header.frameType = kFrameEmpty;
134  header.type.Video.isFirstPacket = false;
135  header.header.markerBit = false;
136  // Insert padding frames.
137  for (int i = 0; i < 10; ++i) {
138    // Lose one packet from the 6th frame.
139    if (i == 5) {
140      ++header.header.sequenceNumber;
141    }
142    // Lose the 4th frame.
143    if (i == 3) {
144      header.header.sequenceNumber += 5;
145    } else {
146      if (i > 3 && i < 5) {
147        EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
148      } else if (i >= 5) {
149        EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
150      } else {
151        EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
152      }
153      InsertAndVerifyPaddingFrame(payload, 0, &header);
154    }
155    clock_.AdvanceTimeMilliseconds(33);
156    header.header.timestamp += 3000;
157  }
158}
159
160TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
161  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
162  EXPECT_EQ(
163      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
164  const unsigned int kFrameSize = 1200;
165  const unsigned int kPaddingSize = 220;
166  const uint8_t payload[kFrameSize] = {0};
167  WebRtcRTPHeader header;
168  memset(&header, 0, sizeof(header));
169  header.frameType = kFrameEmpty;
170  header.type.Video.isFirstPacket = false;
171  header.header.markerBit = false;
172  header.header.paddingLength = kPaddingSize;
173  header.header.payloadType = kUnusedPayloadType;
174  header.header.ssrc = 1;
175  header.header.headerLength = 12;
176  header.type.Video.codec = kRtpVideoVp8;
177  header.type.Video.codecHeader.VP8.pictureId = -1;
178  header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
179  for (int i = 0; i < 3; ++i) {
180    // Insert 2 video frames.
181    for (int j = 0; j < 2; ++j) {
182      if (i == 0 && j == 0)  // First frame should be a key frame.
183        header.frameType = kVideoFrameKey;
184      else
185        header.frameType = kVideoFrameDelta;
186      header.type.Video.isFirstPacket = true;
187      header.header.markerBit = true;
188      InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
189      clock_.AdvanceTimeMilliseconds(33);
190      header.header.timestamp += 3000;
191    }
192
193    // Insert 2 padding only frames.
194    header.frameType = kFrameEmpty;
195    header.type.Video.isFirstPacket = false;
196    header.header.markerBit = false;
197    for (int j = 0; j < 2; ++j) {
198      // InsertAndVerifyPaddingFrame(payload, 0, &header);
199      clock_.AdvanceTimeMilliseconds(33);
200      header.header.timestamp += 3000;
201    }
202  }
203}
204
205TEST_F(TestVideoReceiver, ReceiverDelay) {
206  EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
207  EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
208  EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
209  EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
210}
211
212}  // namespace
213}  // namespace vcm
214}  // namespace webrtc
215