Implement 'toffset' extension in VideoSendStream.

BUG=2229
R=holmer@google.com, stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4722 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/video_engine/internal/video_send_stream.cc b/webrtc/video_engine/internal/video_send_stream.cc
index 0a4e738..979631b 100644
--- a/webrtc/video_engine/internal/video_send_stream.cc
+++ b/webrtc/video_engine/internal/video_send_stream.cc
@@ -105,7 +105,17 @@
   }
   rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
   rtp_rtcp_->SetTransmissionSmoothingStatus(channel_, config_.pacing);
-  rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, 1);
+
+  for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
+    const std::string& extension = config_.rtp.extensions[i].name;
+    int id = config_.rtp.extensions[i].id;
+    if (extension == "toffset") {
+      if (rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id) != 0)
+        abort();
+    } else {
+      abort();  // Unsupported extension.
+    }
+  }
 
   char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
   assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength);
@@ -142,7 +152,7 @@
         new ResolutionAdaptor(codec_, channel_, config_.codec.width,
                               config_.codec.height));
     video_engine_base_->RegisterCpuOveruseObserver(channel_,
-                                                overuse_observer_.get());
+                                                   overuse_observer_.get());
   }
 }
 
diff --git a/webrtc/video_engine/new_include/config.h b/webrtc/video_engine/new_include/config.h
index 45c74b9..5eff973 100644
--- a/webrtc/video_engine/new_include/config.h
+++ b/webrtc/video_engine/new_include/config.h
@@ -73,7 +73,7 @@
 
 // RTP header extension to use for the video stream, see RFC 5285.
 struct RtpExtension {
-  RtpExtension() : id(0) {}
+  RtpExtension(const char* name, int id) : name(name), id(id) {}
   // TODO(mflodman) Add API to query supported extensions.
   std::string name;
   int id;
diff --git a/webrtc/video_engine/test/rampup_tests.cc b/webrtc/video_engine/test/rampup_tests.cc
index 18c1688..8e3e027 100644
--- a/webrtc/video_engine/test/rampup_tests.cc
+++ b/webrtc/video_engine/test/rampup_tests.cc
@@ -31,6 +31,10 @@
 
 namespace webrtc {
 
+namespace {
+  static const int kTOffsetExtensionId = 7;
+}
+
 class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
  public:
   typedef std::map<uint32_t, int> BytesSentMap;
@@ -55,7 +59,7 @@
     rtp_rtcp_->SetREMBStatus(true);
     rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
     rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
-                                            1);
+                                            kTOffsetExtensionId);
     AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
     remote_bitrate_estimator_.reset(rbe_factory.Create(this, clock));
   }
@@ -150,6 +154,8 @@
   send_config.internal_source = false;
   test::FakeEncoder::SetCodecSettings(&send_config.codec, 3);
   send_config.pacing = GetParam();
+  send_config.rtp.extensions.push_back(
+      RtpExtension("toffset", kTOffsetExtensionId));
 
   test::GenerateRandomSsrcs(&send_config, &reserved_ssrcs_);
 
diff --git a/webrtc/video_engine/test/send_stream_tests.cc b/webrtc/video_engine/test/send_stream_tests.cc
index 8117e75..645cda0 100644
--- a/webrtc/video_engine/test/send_stream_tests.cc
+++ b/webrtc/video_engine/test/send_stream_tests.cc
@@ -13,6 +13,7 @@
 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
 #include "webrtc/system_wrappers/interface/event_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
 #include "webrtc/video_engine/test/common/fake_encoder.h"
 #include "webrtc/video_engine/test/common/frame_generator.h"
@@ -137,6 +138,52 @@
   RunSendTest(call.get(), send_config, &observer);
 }
 
+TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
+  static const uint8_t kTOffsetExtensionId = 13;
+  class DelayedEncoder : public test::FakeEncoder {
+   public:
+    DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
+    virtual int32_t Encode(
+        const I420VideoFrame& input_image,
+        const CodecSpecificInfo* codec_specific_info,
+        const std::vector<VideoFrameType>* frame_types) OVERRIDE {
+      // A delay needs to be introduced to assure that we get a timestamp
+      // offset.
+      SleepMs(5);
+      return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
+    }
+  } encoder(Clock::GetRealTimeClock());
+
+  class TransmissionTimeOffsetObserver : public SendTransportObserver {
+   public:
+    TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
+      EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
+          kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
+    }
+
+    virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
+      RTPHeader header;
+      EXPECT_TRUE(
+          rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
+
+      EXPECT_GT(header.extension.transmissionTimeOffset, 0);
+      send_test_complete_->Set();
+
+      return true;
+    }
+  } observer;
+
+  Call::Config call_config(&observer);
+  scoped_ptr<Call> call(Call::Create(call_config));
+
+  VideoSendStream::Config send_config = GetSendTestConfig(call.get());
+  send_config.encoder = &encoder;
+  send_config.rtp.extensions.push_back(
+      RtpExtension("toffset", kTOffsetExtensionId));
+
+  RunSendTest(call.get(), send_config, &observer);
+}
+
 TEST_F(VideoSendStreamTest, RespondsToNack) {
   class NackObserver : public SendTransportObserver, webrtc::Transport {
    public: