Adding a receive side API for buffering mode.
At the same time, renaming the send side API.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3525 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h
index 77bd9ce..1593fb8 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding.h
@@ -553,6 +553,10 @@
     virtual void SetNackSettings(size_t max_nack_list_size,
                                  int max_packet_age_to_nack) = 0;
 
+    // Setting a desired delay to the VCM receiver. Video rendering will be
+    // delayed by at least desired_delay_ms.
+    virtual int SetMinReceiverDelay(int desired_delay_ms) = 0;
+
     // Enables recording of debugging information.
     virtual int StartDebugRecording(const char* file_name_utf8) = 0;
 
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
index d8aefe8..8257a53 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
@@ -772,10 +772,9 @@
   return ret;
 }
 
-void VCMJitterBuffer::EnableMaxJitterEstimate(bool enable,
-                                              uint32_t initial_delay_ms) {
+void VCMJitterBuffer::SetMaxJitterEstimate(uint32_t initial_delay_ms) {
   CriticalSectionScoped cs(crit_sect_);
-  jitter_estimate_.EnableMaxJitterEstimate(enable, initial_delay_ms);
+  jitter_estimate_.SetMaxJitterEstimate(initial_delay_ms);
 }
 
 uint32_t VCMJitterBuffer::EstimatedJitterMs() {
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.h b/webrtc/modules/video_coding/main/source/jitter_buffer.h
index e0b7c47..82f490f 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer.h
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer.h
@@ -127,10 +127,10 @@
   VCMFrameBufferEnum InsertPacket(VCMEncodedFrame* frame,
                                   const VCMPacket& packet);
 
-  // Enable a max filter on the jitter estimate, and setting of the initial
-  // delay (only when in max mode). When disabled (default), the last jitter
+  // Enable a max filter on the jitter estimate by setting an initial
+  // non-zero delay. When set to zero (default), the last jitter
   // estimate will be used.
-  void EnableMaxJitterEstimate(bool enable, uint32_t initial_delay_ms);
+  void SetMaxJitterEstimate(uint32_t initial_delay_ms);
 
   // Returns the estimated jitter in milliseconds.
   uint32_t EstimatedJitterMs();
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_common.h b/webrtc/modules/video_coding/main/source/jitter_buffer_common.h
index 2bfbd60..c981e0e 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer_common.h
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer_common.h
@@ -15,7 +15,7 @@
 
 namespace webrtc {
 
-enum { kMaxNumberOfFrames     = 100 };
+enum { kMaxNumberOfFrames     = 300 };
 enum { kStartNumberOfFrames   = 6 };
 enum { kMaxVideoDelayMs       = 2000 };
 
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
index 3d2ad0c..5aea512 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
@@ -277,25 +277,15 @@
   InsertFrame(kVideoFrameDelta);
   EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
   // Set kMaxEstimate with a 2 seconds initial delay.
-  jitter_buffer_->EnableMaxJitterEstimate(true, 2000u);
+  jitter_buffer_->SetMaxJitterEstimate(2000u);
   EXPECT_EQ(2000u, jitter_buffer_->EstimatedJitterMs());
   InsertFrame(kVideoFrameDelta);
   EXPECT_EQ(2000u, jitter_buffer_->EstimatedJitterMs());
-  // Set kMaxEstimate with a 0S initial delay.
-  jitter_buffer_->EnableMaxJitterEstimate(true, 0u);
-  EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
   // Jitter cannot decrease.
   InsertFrames(2, kVideoFrameDelta);
   uint32_t je1 = jitter_buffer_->EstimatedJitterMs();
   InsertFrames(2, kVideoFrameDelta);
   EXPECT_GE(je1, jitter_buffer_->EstimatedJitterMs());
-
-  // Set kLastEstimate mode (initial delay is arbitrary in this case and will
-  // be ignored).
-  jitter_buffer_->EnableMaxJitterEstimate(false, 2000u);
-  EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
-  InsertFrames(10, kVideoFrameDelta);
-  EXPECT_GT(20u, jitter_buffer_->EstimatedJitterMs());
 }
 
 TEST_F(TestJitterBufferNack, TestEmptyPackets) {
diff --git a/webrtc/modules/video_coding/main/source/jitter_estimator.cc b/webrtc/modules/video_coding/main/source/jitter_estimator.cc
index 68a60da..3c82575 100644
--- a/webrtc/modules/video_coding/main/source/jitter_estimator.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_estimator.cc
@@ -409,10 +409,9 @@
     }
 }
 
-void VCMJitterEstimator::EnableMaxJitterEstimate(bool enable,
-                                              uint32_t initial_delay_ms)
+void VCMJitterEstimator::SetMaxJitterEstimate(uint32_t initial_delay_ms)
 {
-    if (enable) {
+    if (initial_delay_ms > 0) {
         _maxJitterEstimateMs = initial_delay_ms;
         _jitterEstimateMode = kMaxEstimate;
     } else {
diff --git a/webrtc/modules/video_coding/main/source/jitter_estimator.h b/webrtc/modules/video_coding/main/source/jitter_estimator.h
index 44a3455..77d6b6d 100644
--- a/webrtc/modules/video_coding/main/source/jitter_estimator.h
+++ b/webrtc/modules/video_coding/main/source/jitter_estimator.h
@@ -64,10 +64,10 @@
 
     void UpdateMaxFrameSize(WebRtc_UWord32 frameSizeBytes);
 
-    // Enable a max filter on the jitter estimate, and setting of the initial
-    // delay (only when in max mode). When disabled (default), the last jitter
+    // Set a max filter on the jitter estimate by setting an initial
+    // non-zero delay. When set to zero (default), the last jitter
     // estimate will be used.
-    void EnableMaxJitterEstimate(bool enable, uint32_t initial_delay_ms);
+    void SetMaxJitterEstimate(uint32_t initial_delay_ms);
 
     // A constant describing the delay from the jitter buffer
     // to the delay on the receiving side which is not accounted
diff --git a/webrtc/modules/video_coding/main/source/receiver.cc b/webrtc/modules/video_coding/main/source/receiver.cc
index fc5357f..7835366 100644
--- a/webrtc/modules/video_coding/main/source/receiver.cc
+++ b/webrtc/modules/video_coding/main/source/receiver.cc
@@ -21,6 +21,8 @@
 
 namespace webrtc {
 
+enum { kMaxReceiverDelayMs = 10000 };
+
 VCMReceiver::VCMReceiver(VCMTiming* timing,
                          Clock* clock,
                          int32_t vcm_id,
@@ -34,7 +36,8 @@
       jitter_buffer_(clock_, vcm_id, receiver_id, master),
       timing_(timing),
       render_wait_event_(),
-      state_(kPassive) {}
+      state_(kPassive),
+      max_video_delay_ms_(kMaxVideoDelayMs) {}
 
 VCMReceiver::~VCMReceiver() {
   render_wait_event_.Set();
@@ -108,20 +111,21 @@
       jitter_buffer_.Flush();
       timing_->Reset(clock_->TimeInMilliseconds());
       return VCM_FLUSH_INDICATOR;
-    } else if (render_time_ms < now_ms - kMaxVideoDelayMs) {
+    } else if (render_time_ms < now_ms - max_video_delay_ms_) {
       WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                    VCMId(vcm_id_, receiver_id_),
                    "This frame should have been rendered more than %u ms ago."
                    "Flushing jitter buffer and resetting timing.",
-                   kMaxVideoDelayMs);
+                   max_video_delay_ms_);
       jitter_buffer_.Flush();
       timing_->Reset(clock_->TimeInMilliseconds());
       return VCM_FLUSH_INDICATOR;
-    } else if (timing_->TargetVideoDelay() > kMaxVideoDelayMs) {
+    } else if (static_cast<int>(timing_->TargetVideoDelay()) >
+               max_video_delay_ms_) {
       WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                    VCMId(vcm_id_, receiver_id_),
                    "More than %u ms target delay. Flushing jitter buffer and"
-                   "resetting timing.", kMaxVideoDelayMs);
+                   "resetting timing.", max_video_delay_ms_);
       jitter_buffer_.Flush();
       timing_->Reset(clock_->TimeInMilliseconds());
       return VCM_FLUSH_INDICATOR;
@@ -402,6 +406,17 @@
   return state_;
 }
 
+int VCMReceiver::SetMinReceiverDelay(int desired_delay_ms) {
+  CriticalSectionScoped cs(crit_sect_);
+  if (desired_delay_ms < 0 || desired_delay_ms > kMaxReceiverDelayMs) {
+    return -1;
+  }
+  jitter_buffer_.SetMaxJitterEstimate(desired_delay_ms);
+  max_video_delay_ms_ = desired_delay_ms + kMaxVideoDelayMs;
+  timing_->SetMaxVideoDelay(max_video_delay_ms_);
+  return 0;
+}
+
 void VCMReceiver::UpdateState(VCMReceiverState new_state) {
   CriticalSectionScoped cs(crit_sect_);
   assert(!(state_ == kPassive && new_state == kWaitForPrimaryDecode));
diff --git a/webrtc/modules/video_coding/main/source/receiver.h b/webrtc/modules/video_coding/main/source/receiver.h
index 492d616..f790fd2 100644
--- a/webrtc/modules/video_coding/main/source/receiver.h
+++ b/webrtc/modules/video_coding/main/source/receiver.h
@@ -69,6 +69,9 @@
                            VCMReceiver& dual_receiver) const;
   VCMReceiverState State() const;
 
+  // Receiver video delay.
+  int SetMinReceiverDelay(int desired_delay_ms);
+
  private:
   VCMEncodedFrame* FrameForDecoding(uint16_t max_wait_time_ms,
                                     int64_t nextrender_time_ms,
@@ -90,6 +93,7 @@
   VCMTiming* timing_;
   VCMEvent render_wait_event_;
   VCMReceiverState state_;
+  int max_video_delay_ms_;
 
   static int32_t receiver_id_counter_;
 };
diff --git a/webrtc/modules/video_coding/main/source/timing.cc b/webrtc/modules/video_coding/main/source/timing.cc
index 36131b1..26bda7e 100644
--- a/webrtc/modules/video_coding/main/source/timing.cc
+++ b/webrtc/modules/video_coding/main/source/timing.cc
@@ -34,7 +34,8 @@
 _minTotalDelayMs(0),
 _requiredDelayMs(0),
 _currentDelayMs(0),
-_prevFrameTimestamp(0)
+_prevFrameTimestamp(0),
+_maxVideoDelayMs(kMaxVideoDelayMs)
 {
     if (masterTiming == NULL)
     {
@@ -131,7 +132,7 @@
         WebRtc_Word64 delayDiffMs = static_cast<WebRtc_Word64>(targetDelayMs) -
                                     _currentDelayMs;
         // Never change the delay with more than 100 ms every second. If we're changing the
-        // delay in too large steps we will get noticable freezes. By limiting the change we
+        // delay in too large steps we will get noticeable freezes. By limiting the change we
         // can increase the delay in smaller steps, which will be experienced as the video is
         // played in slow motion. When lowering the delay the video will be played at a faster
         // pace.
@@ -249,7 +250,7 @@
 {
     WebRtc_Word64 estimatedCompleteTimeMs =
             _tsExtrapolator->ExtrapolateLocalTime(frameTimestamp);
-    if (estimatedCompleteTimeMs - nowMs > kMaxVideoDelayMs)
+    if (estimatedCompleteTimeMs - nowMs > _maxVideoDelayMs)
     {
         if (_master)
         {
@@ -323,6 +324,12 @@
     return static_cast<WebRtc_Word32>(availableProcessingTimeMs) - maxDecodeTimeMs > 0;
 }
 
+void VCMTiming::SetMaxVideoDelay(int maxVideoDelayMs)
+{
+    CriticalSectionScoped cs(_critSect);
+    _maxVideoDelayMs = maxVideoDelayMs;
+}
+
 WebRtc_UWord32
 VCMTiming::TargetVideoDelay() const
 {
diff --git a/webrtc/modules/video_coding/main/source/timing.h b/webrtc/modules/video_coding/main/source/timing.h
index ac650ec..d1d9cac 100644
--- a/webrtc/modules/video_coding/main/source/timing.h
+++ b/webrtc/modules/video_coding/main/source/timing.h
@@ -82,6 +82,9 @@
     // certain amount of processing time.
     bool EnoughTimeToDecode(WebRtc_UWord32 availableProcessingTimeMs) const;
 
+    // Set the max allowed video delay.
+    void SetMaxVideoDelay(int maxVideoDelayMs);
+
     enum { kDefaultRenderDelayMs = 10 };
     enum { kDelayMaxChangeMsPerS = 100 };
 
@@ -104,6 +107,7 @@
     WebRtc_UWord32                _requiredDelayMs;
     WebRtc_UWord32                _currentDelayMs;
     WebRtc_UWord32                _prevFrameTimestamp;
+    int                           _maxVideoDelayMs;
 };
 
 } // namespace webrtc
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.cc b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
index 25e6c5f..0fb82bb 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.cc
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.cc
@@ -1389,6 +1389,10 @@
                                 max_packet_age_to_nack);
 }
 
+int VideoCodingModuleImpl::SetMinReceiverDelay(int desired_delay_ms) {
+  return _receiver.SetMinReceiverDelay(desired_delay_ms);
+}
+
 int VideoCodingModuleImpl::StartDebugRecording(const char* file_name_utf8) {
   CriticalSectionScoped cs(_sendCritSect);
   _encoderInputFile = fopen(file_name_utf8, "wb");
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h
index 24a1f83..e27a922 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.h
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h
@@ -262,6 +262,9 @@
     virtual void SetNackSettings(size_t max_nack_list_size,
                                  int max_packet_age_to_nack);
 
+    // Set the video delay for the receiver (default = 0).
+    virtual int SetMinReceiverDelay(int desired_delay_ms);
+
     // Enables recording of debugging information.
     virtual int StartDebugRecording(const char* file_name_utf8);
 
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl_unittest.cc b/webrtc/modules/video_coding/main/source/video_coding_impl_unittest.cc
index 14878e5..576ff17 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl_unittest.cc
@@ -287,4 +287,11 @@
   }
 }
 
+TEST_F(TestVideoCodingModule, ReceiverDelay) {
+  EXPECT_EQ(0, vcm_->SetMinReceiverDelay(0));
+  EXPECT_EQ(0, vcm_->SetMinReceiverDelay(5000));
+  EXPECT_EQ(-1, vcm_->SetMinReceiverDelay(-100));
+  EXPECT_EQ(-1, vcm_->SetMinReceiverDelay(10010));
+}
+
 }  // namespace webrtc