blob: 037754d404c7abf50b6981bc04a0a1ed41c31e91 [file] [log] [blame]
Evan Shrubsole476f18d2022-08-15 15:21:16 +00001/*
2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video/video_stream_buffer_controller.h"
12
13#include <algorithm>
14#include <memory>
15#include <utility>
16
17#include "absl/base/attributes.h"
18#include "absl/functional/bind_front.h"
19#include "api/sequence_checker.h"
20#include "api/task_queue/task_queue_base.h"
21#include "api/units/data_size.h"
22#include "api/video/encoded_frame.h"
23#include "api/video/frame_buffer.h"
24#include "api/video/video_content_type.h"
25#include "modules/video_coding/frame_helpers.h"
26#include "modules/video_coding/timing/inter_frame_delay.h"
27#include "modules/video_coding/timing/jitter_estimator.h"
28#include "rtc_base/checks.h"
29#include "rtc_base/logging.h"
30#include "rtc_base/thread_annotations.h"
31#include "video/frame_decode_timing.h"
32#include "video/task_queue_frame_decode_scheduler.h"
33#include "video/video_receive_stream_timeout_tracker.h"
34
35namespace webrtc {
36
37namespace {
38
39// Max number of frames the buffer will hold.
40static constexpr size_t kMaxFramesBuffered = 800;
41// Max number of decoded frame info that will be saved.
42static constexpr int kMaxFramesHistory = 1 << 13;
43
44// Default value for the maximum decode queue size that is used when the
45// low-latency renderer is used.
46static constexpr size_t kZeroPlayoutDelayDefaultMaxDecodeQueueSize = 8;
47
48struct FrameMetadata {
49 explicit FrameMetadata(const EncodedFrame& frame)
50 : is_last_spatial_layer(frame.is_last_spatial_layer),
51 is_keyframe(frame.is_keyframe()),
52 size(frame.size()),
53 contentType(frame.contentType()),
54 delayed_by_retransmission(frame.delayed_by_retransmission()),
55 rtp_timestamp(frame.Timestamp()),
56 receive_time(frame.ReceivedTimestamp()) {}
57
58 const bool is_last_spatial_layer;
59 const bool is_keyframe;
60 const size_t size;
61 const VideoContentType contentType;
62 const bool delayed_by_retransmission;
63 const uint32_t rtp_timestamp;
64 const absl::optional<Timestamp> receive_time;
65};
66
67Timestamp ReceiveTime(const EncodedFrame& frame) {
68 absl::optional<Timestamp> ts = frame.ReceivedTimestamp();
69 RTC_DCHECK(ts.has_value()) << "Received frame must have a timestamp set!";
70 return *ts;
71}
72
73enum class FrameBufferArm {
74 kFrameBuffer3,
75 kSyncDecode,
76};
77
78constexpr const char* kFrameBufferFieldTrial = "WebRTC-FrameBuffer3";
79
80FrameBufferArm ParseFrameBufferFieldTrial(const FieldTrialsView& field_trials) {
81 webrtc::FieldTrialEnum<FrameBufferArm> arm(
82 "arm", FrameBufferArm::kFrameBuffer3,
83 {
84 {"FrameBuffer3", FrameBufferArm::kFrameBuffer3},
85 {"SyncDecoding", FrameBufferArm::kSyncDecode},
86 });
87 ParseFieldTrial({&arm}, field_trials.Lookup(kFrameBufferFieldTrial));
88 return arm.Get();
89}
90
91} // namespace
92
93std::unique_ptr<VideoStreamBufferController>
94VideoStreamBufferController::CreateFromFieldTrial(
95 Clock* clock,
96 TaskQueueBase* worker_queue,
97 VCMTiming* timing,
98 VCMReceiveStatisticsCallback* stats_proxy,
Evan Shrubsole476f18d2022-08-15 15:21:16 +000099 FrameSchedulingReceiver* receiver,
100 TimeDelta max_wait_for_keyframe,
101 TimeDelta max_wait_for_frame,
102 DecodeSynchronizer* decode_sync,
103 const FieldTrialsView& field_trials) {
104 switch (ParseFrameBufferFieldTrial(field_trials)) {
105 case FrameBufferArm::kSyncDecode: {
106 std::unique_ptr<FrameDecodeScheduler> scheduler;
107 if (decode_sync) {
108 scheduler = decode_sync->CreateSynchronizedFrameScheduler();
109 } else {
110 RTC_LOG(LS_ERROR) << "In FrameBuffer with sync decode trial, but "
111 "no DecodeSynchronizer was present!";
112 // Crash in debug, but in production use the task queue scheduler.
113 RTC_DCHECK_NOTREACHED();
114 scheduler = std::make_unique<TaskQueueFrameDecodeScheduler>(
115 clock, worker_queue);
116 }
117 return std::make_unique<VideoStreamBufferController>(
Evan Shrubsole214cab52022-08-16 09:48:23 +0000118 clock, worker_queue, timing, stats_proxy, receiver,
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000119 max_wait_for_keyframe, max_wait_for_frame, std::move(scheduler),
120 field_trials);
121 }
122 case FrameBufferArm::kFrameBuffer3:
123 ABSL_FALLTHROUGH_INTENDED;
124 default: {
125 auto scheduler =
126 std::make_unique<TaskQueueFrameDecodeScheduler>(clock, worker_queue);
127 return std::make_unique<VideoStreamBufferController>(
Evan Shrubsole214cab52022-08-16 09:48:23 +0000128 clock, worker_queue, timing, stats_proxy, receiver,
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000129 max_wait_for_keyframe, max_wait_for_frame, std::move(scheduler),
130 field_trials);
131 }
132 }
133}
134
135VideoStreamBufferController::VideoStreamBufferController(
136 Clock* clock,
137 TaskQueueBase* worker_queue,
138 VCMTiming* timing,
139 VCMReceiveStatisticsCallback* stats_proxy,
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000140 FrameSchedulingReceiver* receiver,
141 TimeDelta max_wait_for_keyframe,
142 TimeDelta max_wait_for_frame,
143 std::unique_ptr<FrameDecodeScheduler> frame_decode_scheduler,
144 const FieldTrialsView& field_trials)
145 : field_trials_(field_trials),
146 clock_(clock),
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000147 stats_proxy_(stats_proxy),
148 receiver_(receiver),
149 timing_(timing),
150 frame_decode_scheduler_(std::move(frame_decode_scheduler)),
151 jitter_estimator_(clock_, field_trials),
152 buffer_(std::make_unique<FrameBuffer>(kMaxFramesBuffered,
153 kMaxFramesHistory,
154 field_trials)),
155 decode_timing_(clock_, timing_),
156 timeout_tracker_(
157 clock_,
Evan Shrubsole214cab52022-08-16 09:48:23 +0000158 worker_queue,
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000159 VideoReceiveStreamTimeoutTracker::Timeouts{
160 .max_wait_for_keyframe = max_wait_for_keyframe,
161 .max_wait_for_frame = max_wait_for_frame},
162 absl::bind_front(&VideoStreamBufferController::OnTimeout, this)),
163 zero_playout_delay_max_decode_queue_size_(
164 "max_decode_queue_size",
165 kZeroPlayoutDelayDefaultMaxDecodeQueueSize) {
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000166 RTC_DCHECK(stats_proxy_);
167 RTC_DCHECK(receiver_);
168 RTC_DCHECK(timing_);
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000169 RTC_DCHECK(clock_);
170 RTC_DCHECK(frame_decode_scheduler_);
171 RTC_LOG(LS_WARNING) << "Using FrameBuffer3";
172
173 ParseFieldTrial({&zero_playout_delay_max_decode_queue_size_},
174 field_trials.Lookup("WebRTC-ZeroPlayoutDelay"));
175}
176
Evan Shrubsole214cab52022-08-16 09:48:23 +0000177void VideoStreamBufferController::Stop() {
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000178 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
179 frame_decode_scheduler_->Stop();
180 timeout_tracker_.Stop();
181 decoder_ready_for_new_frame_ = false;
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000182}
183
184void VideoStreamBufferController::SetProtectionMode(
185 VCMVideoProtection protection_mode) {
186 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
187 protection_mode_ = protection_mode;
188}
189
190void VideoStreamBufferController::Clear() {
191 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
192 stats_proxy_->OnDroppedFrames(buffer_->CurrentSize());
193 buffer_ = std::make_unique<FrameBuffer>(kMaxFramesBuffered, kMaxFramesHistory,
194 field_trials_);
195 frame_decode_scheduler_->CancelOutstanding();
196}
197
198absl::optional<int64_t> VideoStreamBufferController::InsertFrame(
199 std::unique_ptr<EncodedFrame> frame) {
200 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
201 FrameMetadata metadata(*frame);
202 int complete_units = buffer_->GetTotalNumberOfContinuousTemporalUnits();
203 if (buffer_->InsertFrame(std::move(frame))) {
204 RTC_DCHECK(metadata.receive_time) << "Frame receive time must be set!";
205 if (!metadata.delayed_by_retransmission && metadata.receive_time)
206 timing_->IncomingTimestamp(metadata.rtp_timestamp,
207 *metadata.receive_time);
208 if (complete_units < buffer_->GetTotalNumberOfContinuousTemporalUnits()) {
209 stats_proxy_->OnCompleteFrame(metadata.is_keyframe, metadata.size,
210 metadata.contentType);
211 MaybeScheduleFrameForRelease();
212 }
213 }
214
215 return buffer_->LastContinuousFrameId();
216}
217
218void VideoStreamBufferController::UpdateRtt(int64_t max_rtt_ms) {
219 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
220 jitter_estimator_.UpdateRtt(TimeDelta::Millis(max_rtt_ms));
221}
222
223void VideoStreamBufferController::SetMaxWaits(TimeDelta max_wait_for_keyframe,
224 TimeDelta max_wait_for_frame) {
225 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
226 timeout_tracker_.SetTimeouts({.max_wait_for_keyframe = max_wait_for_keyframe,
227 .max_wait_for_frame = max_wait_for_frame});
228}
229
230void VideoStreamBufferController::StartNextDecode(bool keyframe_required) {
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000231 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
232 if (!timeout_tracker_.Running())
233 timeout_tracker_.Start(keyframe_required);
234 keyframe_required_ = keyframe_required;
235 if (keyframe_required_) {
236 timeout_tracker_.SetWaitingForKeyframe();
237 }
238 decoder_ready_for_new_frame_ = true;
239 MaybeScheduleFrameForRelease();
240}
241
242int VideoStreamBufferController::Size() {
243 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
244 return buffer_->CurrentSize();
245}
246
247void VideoStreamBufferController::OnFrameReady(
248 absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> frames,
249 Timestamp render_time) {
250 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
251 RTC_DCHECK(!frames.empty());
252
253 timeout_tracker_.OnEncodedFrameReleased();
254
255 Timestamp now = clock_->CurrentTime();
256 bool superframe_delayed_by_retransmission = false;
257 DataSize superframe_size = DataSize::Zero();
258 const EncodedFrame& first_frame = *frames.front();
259 Timestamp receive_time = ReceiveTime(first_frame);
260
261 if (first_frame.is_keyframe())
262 keyframe_required_ = false;
263
264 // Gracefully handle bad RTP timestamps and render time issues.
265 if (FrameHasBadRenderTiming(render_time, now, timing_->TargetVideoDelay())) {
266 jitter_estimator_.Reset();
267 timing_->Reset();
268 render_time = timing_->RenderTime(first_frame.Timestamp(), now);
269 }
270
271 for (std::unique_ptr<EncodedFrame>& frame : frames) {
272 frame->SetRenderTime(render_time.ms());
273
274 superframe_delayed_by_retransmission |= frame->delayed_by_retransmission();
275 receive_time = std::max(receive_time, ReceiveTime(*frame));
276 superframe_size += DataSize::Bytes(frame->size());
277 }
278
279 if (!superframe_delayed_by_retransmission) {
280 auto frame_delay = inter_frame_delay_.CalculateDelay(
281 first_frame.Timestamp(), receive_time);
282 if (frame_delay) {
283 jitter_estimator_.UpdateEstimate(*frame_delay, superframe_size);
284 }
285
286 float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
287 absl::optional<TimeDelta> rtt_mult_add_cap_ms = absl::nullopt;
288 if (rtt_mult_settings_.has_value()) {
289 rtt_mult = rtt_mult_settings_->rtt_mult_setting;
290 rtt_mult_add_cap_ms =
291 TimeDelta::Millis(rtt_mult_settings_->rtt_mult_add_cap_ms);
292 }
293 timing_->SetJitterDelay(
294 jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms));
295 timing_->UpdateCurrentDelay(render_time, now);
296 } else if (RttMultExperiment::RttMultEnabled()) {
297 jitter_estimator_.FrameNacked();
298 }
299
300 // Update stats.
301 UpdateDroppedFrames();
302 UpdateJitterDelay();
303 UpdateTimingFrameInfo();
304
305 std::unique_ptr<EncodedFrame> frame =
306 CombineAndDeleteFrames(std::move(frames));
307
308 timing_->SetLastDecodeScheduledTimestamp(now);
309
310 decoder_ready_for_new_frame_ = false;
Evan Shrubsole214cab52022-08-16 09:48:23 +0000311 receiver_->OnEncodedFrame(std::move(frame));
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000312}
313
314void VideoStreamBufferController::OnTimeout(TimeDelta delay) {
315 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
Evan Shrubsole214cab52022-08-16 09:48:23 +0000316
317 // Stop sending timeouts until receiver starts waiting for a new frame.
318 timeout_tracker_.Stop();
319
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000320 // If the stream is paused then ignore the timeout.
321 if (!decoder_ready_for_new_frame_) {
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000322 return;
323 }
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000324 decoder_ready_for_new_frame_ = false;
Evan Shrubsole214cab52022-08-16 09:48:23 +0000325 receiver_->OnDecodableFrameTimeout(delay);
Evan Shrubsole476f18d2022-08-15 15:21:16 +0000326}
327
328void VideoStreamBufferController::FrameReadyForDecode(uint32_t rtp_timestamp,
329 Timestamp render_time) {
330 RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
331 auto frames = buffer_->ExtractNextDecodableTemporalUnit();
332 RTC_DCHECK(frames[0]->Timestamp() == rtp_timestamp)
333 << "Frame buffer's next decodable frame was not the one sent for "
334 "extraction rtp="
335 << rtp_timestamp << " extracted rtp=" << frames[0]->Timestamp();
336 OnFrameReady(std::move(frames), render_time);
337}
338
339void VideoStreamBufferController::UpdateDroppedFrames()
340 RTC_RUN_ON(&worker_sequence_checker_) {
341 const int dropped_frames = buffer_->GetTotalNumberOfDroppedFrames() -
342 frames_dropped_before_last_new_frame_;
343 if (dropped_frames > 0)
344 stats_proxy_->OnDroppedFrames(dropped_frames);
345 frames_dropped_before_last_new_frame_ =
346 buffer_->GetTotalNumberOfDroppedFrames();
347}
348
349void VideoStreamBufferController::UpdateJitterDelay() {
350 auto timings = timing_->GetTimings();
351 if (timings.num_decoded_frames) {
352 stats_proxy_->OnFrameBufferTimingsUpdated(
353 timings.max_decode_duration.ms(), timings.current_delay.ms(),
354 timings.target_delay.ms(), timings.jitter_buffer_delay.ms(),
355 timings.min_playout_delay.ms(), timings.render_delay.ms());
356 }
357}
358
359void VideoStreamBufferController::UpdateTimingFrameInfo() {
360 absl::optional<TimingFrameInfo> info = timing_->GetTimingFrameInfo();
361 if (info)
362 stats_proxy_->OnTimingFrameInfoUpdated(*info);
363}
364
365bool VideoStreamBufferController::IsTooManyFramesQueued() const
366 RTC_RUN_ON(&worker_sequence_checker_) {
367 return buffer_->CurrentSize() > zero_playout_delay_max_decode_queue_size_;
368}
369
370void VideoStreamBufferController::ForceKeyFrameReleaseImmediately()
371 RTC_RUN_ON(&worker_sequence_checker_) {
372 RTC_DCHECK(keyframe_required_);
373 // Iterate through the frame buffer until there is a complete keyframe and
374 // release this right away.
375 while (buffer_->DecodableTemporalUnitsInfo()) {
376 auto next_frame = buffer_->ExtractNextDecodableTemporalUnit();
377 if (next_frame.empty()) {
378 RTC_DCHECK_NOTREACHED()
379 << "Frame buffer should always return at least 1 frame.";
380 continue;
381 }
382 // Found keyframe - decode right away.
383 if (next_frame.front()->is_keyframe()) {
384 auto render_time = timing_->RenderTime(next_frame.front()->Timestamp(),
385 clock_->CurrentTime());
386 OnFrameReady(std::move(next_frame), render_time);
387 return;
388 }
389 }
390}
391
392void VideoStreamBufferController::MaybeScheduleFrameForRelease()
393 RTC_RUN_ON(&worker_sequence_checker_) {
394 auto decodable_tu_info = buffer_->DecodableTemporalUnitsInfo();
395 if (!decoder_ready_for_new_frame_ || !decodable_tu_info) {
396 return;
397 }
398
399 if (keyframe_required_) {
400 return ForceKeyFrameReleaseImmediately();
401 }
402
403 // If already scheduled then abort.
404 if (frame_decode_scheduler_->ScheduledRtpTimestamp() ==
405 decodable_tu_info->next_rtp_timestamp) {
406 return;
407 }
408
409 TimeDelta max_wait = timeout_tracker_.TimeUntilTimeout();
410 // Ensures the frame is scheduled for decode before the stream times out.
411 // This is otherwise a race condition.
412 max_wait = std::max(max_wait - TimeDelta::Millis(1), TimeDelta::Zero());
413 absl::optional<FrameDecodeTiming::FrameSchedule> schedule;
414 while (decodable_tu_info) {
415 schedule = decode_timing_.OnFrameBufferUpdated(
416 decodable_tu_info->next_rtp_timestamp,
417 decodable_tu_info->last_rtp_timestamp, max_wait,
418 IsTooManyFramesQueued());
419 if (schedule) {
420 // Don't schedule if already waiting for the same frame.
421 if (frame_decode_scheduler_->ScheduledRtpTimestamp() !=
422 decodable_tu_info->next_rtp_timestamp) {
423 frame_decode_scheduler_->CancelOutstanding();
424 frame_decode_scheduler_->ScheduleFrame(
425 decodable_tu_info->next_rtp_timestamp, *schedule,
426 absl::bind_front(&VideoStreamBufferController::FrameReadyForDecode,
427 this));
428 }
429 return;
430 }
431 // If no schedule for current rtp, drop and try again.
432 buffer_->DropNextDecodableTemporalUnit();
433 decodable_tu_info = buffer_->DecodableTemporalUnitsInfo();
434 }
435}
436
437} // namespace webrtc