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:

committed by
Commit Bot

parent
3de32e6e8c
commit
fdfe1c96a3
@ -190,17 +190,50 @@ 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;
|
||||||
for (FrameMap::iterator& frame_it : frames_to_decode_) {
|
|
||||||
RTC_DCHECK(frame_it != frames_.end());
|
|
||||||
EncodedFrame* frame = frame_it->second.frame.release();
|
|
||||||
|
|
||||||
if (!frame->delayed_by_retransmission()) {
|
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_) {
|
||||||
|
RTC_DCHECK(frame_it != frames_.end());
|
||||||
|
EncodedFrame* frame = frame_it->second.frame.release();
|
||||||
|
|
||||||
|
frame->SetRenderTime(render_time_ms);
|
||||||
|
|
||||||
|
superframe_delayed_by_retransmission |=
|
||||||
|
frame->delayed_by_retransmission();
|
||||||
|
receive_time_ms = std::max(receive_time_ms, frame->ReceivedTime());
|
||||||
|
superframe_size += frame->size();
|
||||||
|
|
||||||
|
PropagateDecodability(frame_it->second);
|
||||||
|
decoded_frames_history_.InsertDecoded(frame_it->first,
|
||||||
|
frame->Timestamp());
|
||||||
|
|
||||||
|
// Remove decoded frame and all undecoded frames before it.
|
||||||
|
frames_.erase(frames_.begin(), ++frame_it);
|
||||||
|
|
||||||
|
frames_out.push_back(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!superframe_delayed_by_retransmission) {
|
||||||
int64_t frame_delay;
|
int64_t frame_delay;
|
||||||
|
|
||||||
if (inter_frame_delay_.CalculateDelay(frame->Timestamp(), &frame_delay,
|
if (inter_frame_delay_.CalculateDelay(first_frame->Timestamp(),
|
||||||
frame->ReceivedTime())) {
|
&frame_delay, receive_time_ms)) {
|
||||||
jitter_estimator_->UpdateEstimate(frame_delay, frame->size());
|
jitter_estimator_->UpdateEstimate(frame_delay, superframe_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
|
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
|
||||||
@ -208,32 +241,15 @@ FrameBuffer::ReturnReason FrameBuffer::NextFrame(
|
|||||||
rtt_mult = RttMultExperiment::GetRttMultValue();
|
rtt_mult = RttMultExperiment::GetRttMultValue();
|
||||||
}
|
}
|
||||||
timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
|
timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
|
||||||
timing_->UpdateCurrentDelay(frame->RenderTime(), now_ms);
|
timing_->UpdateCurrentDelay(render_time_ms, now_ms);
|
||||||
} else {
|
} else {
|
||||||
if (RttMultExperiment::RttMultEnabled() || add_rtt_to_playout_delay_)
|
if (RttMultExperiment::RttMultEnabled() || add_rtt_to_playout_delay_)
|
||||||
jitter_estimator_->FrameNacked();
|
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();
|
UpdateJitterDelay();
|
||||||
UpdateTimingFrameInfo();
|
UpdateTimingFrameInfo();
|
||||||
PropagateDecodability(frame_it->second);
|
|
||||||
|
|
||||||
decoded_frames_history_.InsertDecoded(frame_it->first,
|
|
||||||
frame->Timestamp());
|
|
||||||
|
|
||||||
// Remove decoded frame and all undecoded frames before it.
|
|
||||||
frames_.erase(frames_.begin(), ++frame_it);
|
|
||||||
|
|
||||||
frames_out.push_back(frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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]);
|
||||||
|
Reference in New Issue
Block a user