Relanding r3952: VCM: Updating receiver logic
BUG=r1734
R=stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3970 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/source/receiver.cc b/webrtc/modules/video_coding/main/source/receiver.cc
index c77936c..3457260 100644
--- a/webrtc/modules/video_coding/main/source/receiver.cc
+++ b/webrtc/modules/video_coding/main/source/receiver.cc
@@ -103,59 +103,31 @@
                    packet.seqNum, packet.timestamp,
                    MaskWord64ToUWord32(clock_->TimeInMilliseconds()));
     }
-
-    const int64_t now_ms = clock_->TimeInMilliseconds();
-
-    int64_t render_time_ms = timing_->RenderTimeMs(packet.timestamp, now_ms);
-
-    if (render_time_ms < 0) {
-      // Render time error. Assume that this is due to some change in the
-      // incoming video stream and reset the JB and the timing.
-      jitter_buffer_.Flush();
-      timing_->Reset(clock_->TimeInMilliseconds());
-      return VCM_FLUSH_INDICATOR;
-    } 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.",
-                   max_video_delay_ms_);
-      jitter_buffer_.Flush();
-      timing_->Reset(clock_->TimeInMilliseconds());
-      return VCM_FLUSH_INDICATOR;
-    } 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.", max_video_delay_ms_);
-      jitter_buffer_.Flush();
-      timing_->Reset(clock_->TimeInMilliseconds());
-      return VCM_FLUSH_INDICATOR;
-    }
-
     // First packet received belonging to this frame.
-    if (buffer->Length() == 0) {
+    if (buffer->Length() == 0 && master_) {
       const int64_t now_ms = clock_->TimeInMilliseconds();
-      if (master_) {
-        // Only trace the primary receiver to make it possible to parse and plot
-        // the trace file.
-        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
-                     VCMId(vcm_id_, receiver_id_),
-                     "First packet of frame %u at %u", packet.timestamp,
-                     MaskWord64ToUWord32(now_ms));
-      }
-      render_time_ms = timing_->RenderTimeMs(packet.timestamp, now_ms);
-      if (render_time_ms >= 0) {
-        buffer->SetRenderTime(render_time_ms);
-      } else {
-        buffer->SetRenderTime(now_ms);
-      }
+      // Only trace the primary receiver to make it possible to parse and plot
+      // the trace file.
+      WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
+          VCMId(vcm_id_, receiver_id_),
+          "First packet of frame %u at %u", packet.timestamp,
+          MaskWord64ToUWord32(now_ms));
     }
 
     // Insert packet into the jitter buffer both media and empty packets.
     const VCMFrameBufferEnum
     ret = jitter_buffer_.InsertPacket(buffer, packet);
+    if (ret == kCompleteSession) {
+      bool retransmitted = false;
+      const int64_t last_packet_time_ms =
+         jitter_buffer_.LastPacketTime(buffer, &retransmitted);
+      if (last_packet_time_ms >= 0 && !retransmitted) {
+        // We don't want to include timestamps which have suffered from
+        // retransmission here, since we compensate with extra retransmission
+        // delay within the jitter estimate.
+        timing_->IncomingTimestamp(packet.timestamp, last_packet_time_ms);
+      }
+    }
     if (ret == kFlushIndicator) {
       return VCM_FLUSH_INDICATOR;
     } else if (ret < 0) {
@@ -175,155 +147,101 @@
     bool render_timing,
     VCMReceiver* dual_receiver) {
   TRACE_EVENT0("webrtc", "Recv::FrameForDecoding");
-  // No need to enter the critical section here since the jitter buffer
-  // is thread-safe.
-  FrameType incoming_frame_type = kVideoFrameDelta;
-  next_render_time_ms = -1;
   const int64_t start_time_ms = clock_->TimeInMilliseconds();
-  int64_t ret = jitter_buffer_.NextTimestamp(max_wait_time_ms,
-                                             &incoming_frame_type,
-                                             &next_render_time_ms);
-  if (ret < 0) {
-    // No timestamp in jitter buffer at the moment.
+  uint32_t frame_timestamp = 0;
+  // Exhaust wait time to get a complete frame for decoding.
+  bool found_frame = jitter_buffer_.NextCompleteTimestamp(
+      max_wait_time_ms, &frame_timestamp);
+
+  if (!found_frame) {
+    // Get an incomplete frame when enabled.
+    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
+        dual_receiver->State() == kPassive &&
+        dual_receiver->NackMode() == kNack);
+    if (dual_receiver_enabled_and_passive &&
+        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
+      // Jitter buffer state might get corrupt with this frame.
+      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
+    }
+    found_frame = jitter_buffer_.NextMaybeIncompleteTimestamp(
+        &frame_timestamp);
+  }
+
+  if (!found_frame) {
     return NULL;
   }
-  const uint32_t time_stamp = static_cast<uint32_t>(ret);
 
-  // Update the timing.
+  // We have a frame - Set timing and render timestamp.
   timing_->SetRequiredDelay(jitter_buffer_.EstimatedJitterMs());
-  timing_->UpdateCurrentDelay(time_stamp);
-
-  const int32_t temp_wait_time = max_wait_time_ms -
-      static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms);
-  uint16_t new_max_wait_time = static_cast<uint16_t>(VCM_MAX(temp_wait_time,
-                                                             0));
-
-  VCMEncodedFrame* frame = NULL;
-
-  if (render_timing) {
-    frame = FrameForDecoding(new_max_wait_time, next_render_time_ms,
-                             dual_receiver);
-  } else {
-    frame = FrameForRendering(new_max_wait_time, next_render_time_ms,
-                              dual_receiver);
+  const int64_t now_ms = clock_->TimeInMilliseconds();
+  timing_->UpdateCurrentDelay(frame_timestamp);
+  next_render_time_ms = timing_->RenderTimeMs(frame_timestamp, now_ms);
+  // Check render timing.
+  bool timing_error = false;
+  // Assume that render timing errors are due to changes in the video stream.
+  if (next_render_time_ms < 0) {
+    timing_error = true;
+  } else if (next_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.",
+                 max_video_delay_ms_);
+    timing_error = true;
+  } 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.", max_video_delay_ms_);
+    timing_error = true;
   }
 
-  if (frame != NULL) {
+  if (timing_error) {
+    // Timing error => reset timing and flush the jitter buffer.
+    jitter_buffer_.Flush();
+    timing_->Reset(clock_->TimeInMilliseconds());
+    return NULL;
+  }
+
+  if (!render_timing) {
+    // Decode frame as close as possible to the render timestamp.
+    TRACE_EVENT0("webrtc", "FrameForRendering");
+    const int32_t available_wait_time = max_wait_time_ms -
+        static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms);
+    uint16_t new_max_wait_time = static_cast<uint16_t>(
+        VCM_MAX(available_wait_time, 0));
+    uint32_t wait_time_ms = timing_->MaxWaitingTime(
+        next_render_time_ms, clock_->TimeInMilliseconds());
+    if (new_max_wait_time < wait_time_ms) {
+      // We're not allowed to wait until the frame is supposed to be rendered,
+      // waiting as long as we're allowed to avoid busy looping, and then return
+      // NULL. Next call to this function might return the frame.
+      render_wait_event_->Wait(max_wait_time_ms);
+      return NULL;
+    }
+    // Wait until it's time to render.
+    render_wait_event_->Wait(wait_time_ms);
+  }
+
+  // Extract the frame from the jitter buffer and set the render time.
+  VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp);
+  assert(frame);
+  frame->SetRenderTime(next_render_time_ms);
+  if (dual_receiver != NULL) {
+    dual_receiver->UpdateState(*frame);
+  }
+  if (!frame->Complete()) {
+    // Update stats for incomplete frames.
     bool retransmitted = false;
     const int64_t last_packet_time_ms =
-      jitter_buffer_.LastPacketTime(frame, &retransmitted);
+        jitter_buffer_.LastPacketTime(frame, &retransmitted);
     if (last_packet_time_ms >= 0 && !retransmitted) {
       // We don't want to include timestamps which have suffered from
       // retransmission here, since we compensate with extra retransmission
       // delay within the jitter estimate.
-      timing_->IncomingTimestamp(time_stamp, last_packet_time_ms);
+      timing_->IncomingTimestamp(frame_timestamp, last_packet_time_ms);
     }
-    if (dual_receiver != NULL) {
-      dual_receiver->UpdateState(*frame);
-    }
-  }
-  return frame;
-}
-
-VCMEncodedFrame* VCMReceiver::FrameForDecoding(
-    uint16_t max_wait_time_ms,
-    int64_t next_render_time_ms,
-    VCMReceiver* dual_receiver) {
-  TRACE_EVENT1("webrtc", "FrameForDecoding",
-               "max_wait", max_wait_time_ms);
-  // How long can we wait until we must decode the next frame.
-  uint32_t wait_time_ms = timing_->MaxWaitingTime(
-      next_render_time_ms, clock_->TimeInMilliseconds());
-
-  // Try to get a complete frame from the jitter buffer.
-  VCMEncodedFrame* frame = jitter_buffer_.GetCompleteFrameForDecoding(0);
-
-  if (frame == NULL && max_wait_time_ms == 0 && wait_time_ms > 0) {
-    // If we're not allowed to wait for frames to get complete we must
-    // calculate if it's time to decode, and if it's not we will just return
-    // for now.
-    return NULL;
-  }
-
-  if (frame == NULL && VCM_MIN(wait_time_ms, max_wait_time_ms) == 0) {
-    // No time to wait for a complete frame, check if we have an incomplete.
-    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
-        dual_receiver->State() == kPassive &&
-        dual_receiver->NackMode() == kNack);
-    if (dual_receiver_enabled_and_passive &&
-        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
-      // Jitter buffer state might get corrupt with this frame.
-      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
-    }
-    frame = jitter_buffer_.MaybeGetIncompleteFrameForDecoding();
-  }
-  if (frame == NULL) {
-    // Wait for a complete frame.
-    frame = jitter_buffer_.GetCompleteFrameForDecoding(max_wait_time_ms);
-  }
-  if (frame == NULL) {
-    // Get an incomplete frame.
-    if (timing_->MaxWaitingTime(next_render_time_ms,
-                                clock_->TimeInMilliseconds()) > 0) {
-      // Still time to wait for a complete frame.
-      return NULL;
-    }
-
-    // No time left to wait, we must decode this frame now.
-    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
-        dual_receiver->State() == kPassive &&
-        dual_receiver->NackMode() == kNack);
-    if (dual_receiver_enabled_and_passive &&
-        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
-      // Jitter buffer state might get corrupt with this frame.
-      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
-    }
-
-    frame = jitter_buffer_.MaybeGetIncompleteFrameForDecoding();
-  }
-  return frame;
-}
-
-VCMEncodedFrame* VCMReceiver::FrameForRendering(uint16_t max_wait_time_ms,
-                                                int64_t next_render_time_ms,
-                                                VCMReceiver* dual_receiver) {
-  TRACE_EVENT0("webrtc", "FrameForRendering");
-  // How long MUST we wait until we must decode the next frame. This is
-  // different for the case where we have a renderer which can render at a
-  // specified time. Here we must wait as long as possible before giving the
-  // frame to the decoder, which will render the frame as soon as it has been
-  // decoded.
-  uint32_t wait_time_ms = timing_->MaxWaitingTime(
-      next_render_time_ms, clock_->TimeInMilliseconds());
-  if (max_wait_time_ms < wait_time_ms) {
-    // If we're not allowed to wait until the frame is supposed to be rendered,
-    // waiting as long as we're allowed to avoid busy looping, and then return
-    // NULL. Next call to this function might return the frame.
-    render_wait_event_->Wait(max_wait_time_ms);
-    return NULL;
-  }
-  // Wait until it's time to render.
-  render_wait_event_->Wait(wait_time_ms);
-
-  // Get a complete frame if possible.
-  // Note: This might cause us to wait more than a total of |max_wait_time_ms|.
-  // This is necessary to avoid a possible busy loop if no complete frame
-  // has been received.
-  VCMEncodedFrame* frame = jitter_buffer_.GetCompleteFrameForDecoding(
-      max_wait_time_ms);
-
-  if (frame == NULL) {
-    // Get an incomplete frame.
-    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
-        dual_receiver->State() == kPassive &&
-        dual_receiver->NackMode() == kNack);
-    if (dual_receiver_enabled_and_passive &&
-        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
-      // Jitter buffer state might get corrupt with this frame.
-      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
-    }
-
-    frame = jitter_buffer_.MaybeGetIncompleteFrameForDecoding();
   }
   return frame;
 }
@@ -430,7 +348,6 @@
   if (desired_delay_ms < 0 || desired_delay_ms > kMaxReceiverDelayMs) {
     return -1;
   }
-  // Enable a max filter on the jitter estimate for non-zero delays.
   jitter_buffer_.SetMaxJitterEstimate(desired_delay_ms > 0);
   max_video_delay_ms_ = desired_delay_ms + kMaxVideoDelayMs;
   // Initializing timing to the desired delay.
@@ -439,7 +356,21 @@
 }
 
 int VCMReceiver::RenderBufferSizeMs() {
-  return jitter_buffer_.RenderBufferSizeMs();
+  uint32_t timestamp_start = 0u;
+  uint32_t timestamp_end = 0u;
+  // Render timestamps are computed just prior to decoding. Therefore this is
+  // only an estimate based on frames' timestamps and current timing state.
+  jitter_buffer_.RenderBufferSize(&timestamp_start, &timestamp_end);
+  if (timestamp_start == timestamp_end) {
+    return 0;
+  }
+  // Update timing.
+  const int64_t now_ms = clock_->TimeInMilliseconds();
+  timing_->SetRequiredDelay(jitter_buffer_.EstimatedJitterMs());
+  // Get render timestamps.
+  uint32_t render_start = timing_->RenderTimeMs(timestamp_start, now_ms);
+  uint32_t render_end = timing_->RenderTimeMs(timestamp_end, now_ms);
+  return render_end - render_start;
 }
 
 void VCMReceiver::UpdateState(VCMReceiverState new_state) {