Update jitter delay on per-superframe level from FrameBuffer

Current way with updates on each frame caused a bogus jitter estimate
and lots of dropped frames in unfiltered KSVC stream.

Bug: chromium:912122
Change-Id: I4a1af71a242af3f9b5f5a411b194331b2df24f68
Reviewed-on: https://webrtc-review.googlesource.com/c/117566
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26322}
This commit is contained in:
Ilya Nikolaevskiy
2019-01-18 13:33:38 +01:00
committed by Commit Bot
parent 3de32e6e8c
commit fdfe1c96a3

View File

@ -190,41 +190,35 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame(
{ {
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
now_ms = clock_->TimeInMilliseconds(); now_ms = clock_->TimeInMilliseconds();
// TODO(ilnik): remove |frames_out| use frames_to_decode_ directly.
std::vector<EncodedFrame*> frames_out; std::vector<EncodedFrame*> frames_out;
if (!frames_to_decode_.empty()) {
bool superframe_delayed_by_retransmission = false;
size_t superframe_size = 0;
EncodedFrame* first_frame = frames_to_decode_[0]->second.frame.get();
int64_t render_time_ms = first_frame->RenderTime();
int64_t receive_time_ms = first_frame->ReceivedTime();
// Gracefully handle bad RTP timestamps and render time issues.
if (HasBadRenderTiming(*first_frame, now_ms)) {
jitter_estimator_->Reset();
timing_->Reset();
render_time_ms =
timing_->RenderTimeMs(first_frame->Timestamp(), now_ms);
}
for (FrameMap::iterator& frame_it : frames_to_decode_) { for (FrameMap::iterator& frame_it : frames_to_decode_) {
RTC_DCHECK(frame_it != frames_.end()); RTC_DCHECK(frame_it != frames_.end());
EncodedFrame* frame = frame_it->second.frame.release(); EncodedFrame* frame = frame_it->second.frame.release();
if (!frame->delayed_by_retransmission()) { frame->SetRenderTime(render_time_ms);
int64_t frame_delay;
if (inter_frame_delay_.CalculateDelay(frame->Timestamp(), &frame_delay, superframe_delayed_by_retransmission |=
frame->ReceivedTime())) { frame->delayed_by_retransmission();
jitter_estimator_->UpdateEstimate(frame_delay, frame->size()); receive_time_ms = std::max(receive_time_ms, frame->ReceivedTime());
} superframe_size += frame->size();
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
if (RttMultExperiment::RttMultEnabled()) {
rtt_mult = RttMultExperiment::GetRttMultValue();
}
timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
timing_->UpdateCurrentDelay(frame->RenderTime(), now_ms);
} else {
if (RttMultExperiment::RttMultEnabled() || add_rtt_to_playout_delay_)
jitter_estimator_->FrameNacked();
}
// Gracefully handle bad RTP timestamps and render time issues.
if (HasBadRenderTiming(*frame, now_ms)) {
jitter_estimator_->Reset();
timing_->Reset();
frame->SetRenderTime(timing_->RenderTimeMs(frame->Timestamp(), now_ms));
}
UpdateJitterDelay();
UpdateTimingFrameInfo();
PropagateDecodability(frame_it->second); PropagateDecodability(frame_it->second);
decoded_frames_history_.InsertDecoded(frame_it->first, decoded_frames_history_.InsertDecoded(frame_it->first,
frame->Timestamp()); frame->Timestamp());
@ -234,6 +228,28 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame(
frames_out.push_back(frame); frames_out.push_back(frame);
} }
if (!superframe_delayed_by_retransmission) {
int64_t frame_delay;
if (inter_frame_delay_.CalculateDelay(first_frame->Timestamp(),
&frame_delay, receive_time_ms)) {
jitter_estimator_->UpdateEstimate(frame_delay, superframe_size);
}
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
if (RttMultExperiment::RttMultEnabled()) {
rtt_mult = RttMultExperiment::GetRttMultValue();
}
timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
timing_->UpdateCurrentDelay(render_time_ms, now_ms);
} else {
if (RttMultExperiment::RttMultEnabled() || add_rtt_to_playout_delay_)
jitter_estimator_->FrameNacked();
}
UpdateJitterDelay();
UpdateTimingFrameInfo();
}
if (!frames_out.empty()) { if (!frames_out.empty()) {
if (frames_out.size() == 1) { if (frames_out.size() == 1) {
frame_out->reset(frames_out[0]); frame_out->reset(frames_out[0]);