Add test to verify that padding only frames are passing through the RTP module.

Review URL: https://webrtc-codereview.appspot.com/934023

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@3224 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/rtp_rtcp/test/testAPI/test_api_video.cc b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
index fdd3ed3..7a9d3db 100644
--- a/modules/rtp_rtcp/test/testAPI/test_api_video.cc
+++ b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
@@ -8,88 +8,157 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <stdlib.h>
+
 #include <algorithm>
 #include <vector>
-#include <gtest/gtest.h>
 
-#include "test_api.h"
+#include "gtest/gtest.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
+#include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h"
 
-#include "common_types.h"
-#include "rtp_rtcp.h"
-#include "rtp_rtcp_defines.h"
-
-using namespace webrtc;
+namespace webrtc {
 
 class RtpRtcpVideoTest : public ::testing::Test {
  protected:
-  RtpRtcpVideoTest() {
-    test_id = 123;
-    test_ssrc = 3456;
-    test_timestamp = 4567;
-    test_sequence_number = 2345;
+  RtpRtcpVideoTest()
+      : test_id_(123),
+        test_ssrc_(3456),
+        test_timestamp_(4567),
+        test_sequence_number_(2345) {
   }
   ~RtpRtcpVideoTest() {}
 
   virtual void SetUp() {
-    transport = new LoopBackTransport();
-    receiver = new RtpReceiver();
+    transport_ = new LoopBackTransport();
+    receiver_ = new RtpReceiver();
     RtpRtcp::Configuration configuration;
-    configuration.id = test_id;
+    configuration.id = test_id_;
     configuration.audio = false;
     configuration.clock = &fake_clock;
-    configuration.incoming_data = receiver;
-    configuration.outgoing_transport = transport;
+    configuration.incoming_data = receiver_;
+    configuration.outgoing_transport = transport_;
 
-    video_module = RtpRtcp::CreateRtpRtcp(configuration);
+    video_module_ = RtpRtcp::CreateRtpRtcp(configuration);
 
-    EXPECT_EQ(0, video_module->SetRTCPStatus(kRtcpCompound));
-    EXPECT_EQ(0, video_module->SetSSRC(test_ssrc));
-    EXPECT_EQ(0, video_module->SetNACKStatus(kNackRtcp));
-    EXPECT_EQ(0, video_module->SetStorePacketsStatus(true));
-    EXPECT_EQ(0, video_module->SetSendingStatus(true));
+    EXPECT_EQ(0, video_module_->SetRTCPStatus(kRtcpCompound));
+    EXPECT_EQ(0, video_module_->SetSSRC(test_ssrc_));
+    EXPECT_EQ(0, video_module_->SetNACKStatus(kNackRtcp));
+    EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true));
+    EXPECT_EQ(0, video_module_->SetSendingStatus(true));
 
-    transport->SetSendModule(video_module);
+    transport_->SetSendModule(video_module_);
 
     VideoCodec video_codec;
     memset(&video_codec, 0, sizeof(video_codec));
     video_codec.plType = 123;
     memcpy(video_codec.plName, "I420", 5);
 
-    EXPECT_EQ(0, video_module->RegisterSendPayload(video_codec));
-    EXPECT_EQ(0, video_module->RegisterReceivePayload(video_codec));
+    EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
+    EXPECT_EQ(0, video_module_->RegisterReceivePayload(video_codec));
 
-    payload_data_length = sizeof(payload_data);
+    payload_data_length_ = sizeof(video_frame_);
 
-    for (int n = 0; n < payload_data_length; n++) {
-      payload_data[n] = n%10;
+    for (int n = 0; n < payload_data_length_; n++) {
+      video_frame_[n] = n%10;
     }
   }
 
-  virtual void TearDown() {
-    delete video_module;
-    delete transport;
-    delete receiver;
+  WebRtc_Word32 BuildRTPheader(WebRtc_UWord8* dataBuffer,
+                               WebRtc_UWord32 timestamp,
+                               WebRtc_UWord32 sequence_number) {
+    dataBuffer[0] = static_cast<WebRtc_UWord8>(0x80);  // version 2
+    dataBuffer[1] = static_cast<WebRtc_UWord8>(kPayloadType);
+    ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer + 2,
+                                                    sequence_number);
+    ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer + 4, timestamp);
+    ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer + 8,
+                                                    0x1234);  // SSRC.
+    WebRtc_Word32 rtpHeaderLength = 12;
+    return rtpHeaderLength;
   }
 
-  int test_id;
-  RtpRtcp* video_module;
-  LoopBackTransport* transport;
-  RtpReceiver* receiver;
-  WebRtc_UWord32 test_ssrc;
-  WebRtc_UWord32 test_timestamp;
-  WebRtc_UWord16 test_sequence_number;
-  WebRtc_UWord8  payload_data[65000];
-  int payload_data_length;
+  int PaddingPacket(uint8_t* buffer,
+                    WebRtc_UWord32 timestamp,
+                    WebRtc_UWord32 sequence_number,
+                    WebRtc_Word32 bytes) {
+    // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
+    int max_length = 224;
+
+    int padding_bytes_in_packet = max_length;
+    if (bytes < max_length) {
+      padding_bytes_in_packet = (bytes + 16) & 0xffe0;  // Keep our modulus 32.
+    }
+    // Correct seq num, timestamp and payload type.
+    int header_length = BuildRTPheader(buffer, timestamp,
+                                       sequence_number);
+    buffer[0] |= 0x20;  // Set padding bit.
+    WebRtc_Word32* data =
+        reinterpret_cast<WebRtc_Word32*>(&(buffer[header_length]));
+
+    // Fill data buffer with random data.
+    for (int j = 0; j < (padding_bytes_in_packet >> 2); j++) {
+      data[j] = rand();  // NOLINT
+    }
+    // Set number of padding bytes in the last byte of the packet.
+    buffer[header_length + padding_bytes_in_packet - 1] =
+        padding_bytes_in_packet;
+    return padding_bytes_in_packet + header_length;
+  }
+
+  virtual void TearDown() {
+    delete video_module_;
+    delete transport_;
+    delete receiver_;
+  }
+
+  int test_id_;
+  RtpRtcp* video_module_;
+  LoopBackTransport* transport_;
+  RtpReceiver* receiver_;
+  WebRtc_UWord32 test_ssrc_;
+  WebRtc_UWord32 test_timestamp_;
+  WebRtc_UWord16 test_sequence_number_;
+  WebRtc_UWord8  video_frame_[65000];
+  int payload_data_length_;
   FakeRtpRtcpClock fake_clock;
+  enum { kPayloadType = 100 };
 };
 
 TEST_F(RtpRtcpVideoTest, BasicVideo) {
   WebRtc_UWord32 timestamp = 3000;
-  EXPECT_EQ(0, video_module->SendOutgoingData(webrtc::kVideoFrameDelta, 123,
-                                             timestamp,
-                                             timestamp / 90,
-                                             payload_data,
-                                             payload_data_length));
-
+  EXPECT_EQ(0, video_module_->SendOutgoingData(kVideoFrameDelta, 123,
+                                               timestamp,
+                                               timestamp / 90,
+                                               video_frame_,
+                                               payload_data_length_));
 }
 
+TEST_F(RtpRtcpVideoTest, PaddingOnlyFrames) {
+  const int kPadSize = 255;
+  uint8_t padding_packet[kPadSize];
+  uint32_t seq_num = 0;
+  uint32_t timestamp = 3000;
+  VideoCodec codec;
+  codec.codecType = kVideoCodecVP8;
+  codec.plType = kPayloadType;
+  strncpy(codec.plName, "VP8", 4);
+  EXPECT_EQ(0, video_module_->RegisterReceivePayload(codec));
+  for (int frame_idx = 0; frame_idx < 10; ++frame_idx) {
+    for (int packet_idx = 0; packet_idx < 5; ++packet_idx) {
+      int packet_size = PaddingPacket(padding_packet, timestamp, seq_num,
+                                      kPadSize);
+      ++seq_num;
+      EXPECT_EQ(0, video_module_->IncomingPacket(padding_packet, packet_size));
+      EXPECT_EQ(0, receiver_->payload_size());
+      EXPECT_EQ(packet_size - 12, receiver_->rtp_header().header.paddingLength);
+    }
+    timestamp += 3000;
+    fake_clock.IncrementTime(33);
+  }
+}
+
+}  // namespace webrtc