Home | History | Annotate | Download | only in source
      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 
     22 using ::testing::_;
     23 using ::testing::NiceMock;
     24 
     25 namespace webrtc {
     26 namespace vcm {
     27 namespace {
     28 
     29 class 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 
     86 TEST_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 
    109 TEST_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 
    160 TEST_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 
    205 TEST_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