xref: /aosp_15_r20/external/webrtc/video/video_receive_stream_timeout_tracker.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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_receive_stream_timeout_tracker.h"
12 
13 #include <algorithm>
14 #include <utility>
15 
16 #include "rtc_base/logging.h"
17 
18 namespace webrtc {
19 
VideoReceiveStreamTimeoutTracker(Clock * clock,TaskQueueBase * const bookkeeping_queue,const Timeouts & timeouts,TimeoutCallback callback)20 VideoReceiveStreamTimeoutTracker::VideoReceiveStreamTimeoutTracker(
21     Clock* clock,
22     TaskQueueBase* const bookkeeping_queue,
23     const Timeouts& timeouts,
24     TimeoutCallback callback)
25     : clock_(clock),
26       bookkeeping_queue_(bookkeeping_queue),
27       timeouts_(timeouts),
28       timeout_cb_(std::move(callback)) {}
29 
~VideoReceiveStreamTimeoutTracker()30 VideoReceiveStreamTimeoutTracker::~VideoReceiveStreamTimeoutTracker() {
31   RTC_DCHECK(!timeout_task_.Running());
32 }
33 
Running() const34 bool VideoReceiveStreamTimeoutTracker::Running() const {
35   return timeout_task_.Running();
36 }
37 
TimeUntilTimeout() const38 TimeDelta VideoReceiveStreamTimeoutTracker::TimeUntilTimeout() const {
39   return std::max(timeout_ - clock_->CurrentTime(), TimeDelta::Zero());
40 }
41 
Start(bool waiting_for_keyframe)42 void VideoReceiveStreamTimeoutTracker::Start(bool waiting_for_keyframe) {
43   RTC_DCHECK_RUN_ON(bookkeeping_queue_);
44   RTC_DCHECK(!timeout_task_.Running());
45   waiting_for_keyframe_ = waiting_for_keyframe;
46   TimeDelta timeout_delay = TimeoutForNextFrame();
47   last_frame_ = clock_->CurrentTime();
48   timeout_ = last_frame_ + timeout_delay;
49   timeout_task_ =
50       RepeatingTaskHandle::DelayedStart(bookkeeping_queue_, timeout_delay,
51                                         [this] { return HandleTimeoutTask(); });
52 }
53 
Stop()54 void VideoReceiveStreamTimeoutTracker::Stop() {
55   timeout_task_.Stop();
56 }
57 
SetWaitingForKeyframe()58 void VideoReceiveStreamTimeoutTracker::SetWaitingForKeyframe() {
59   RTC_DCHECK_RUN_ON(bookkeeping_queue_);
60   waiting_for_keyframe_ = true;
61   TimeDelta timeout_delay = TimeoutForNextFrame();
62   if (clock_->CurrentTime() + timeout_delay < timeout_) {
63     Stop();
64     Start(waiting_for_keyframe_);
65   }
66 }
67 
OnEncodedFrameReleased()68 void VideoReceiveStreamTimeoutTracker::OnEncodedFrameReleased() {
69   RTC_DCHECK_RUN_ON(bookkeeping_queue_);
70   // If we were waiting for a keyframe, then it has just been released.
71   waiting_for_keyframe_ = false;
72   last_frame_ = clock_->CurrentTime();
73   timeout_ = last_frame_ + TimeoutForNextFrame();
74 }
75 
HandleTimeoutTask()76 TimeDelta VideoReceiveStreamTimeoutTracker::HandleTimeoutTask() {
77   RTC_DCHECK_RUN_ON(bookkeeping_queue_);
78   Timestamp now = clock_->CurrentTime();
79   // `timeout_` is hit and we have timed out. Schedule the next timeout at
80   // the timeout delay.
81   if (now >= timeout_) {
82     RTC_DLOG(LS_VERBOSE) << "Stream timeout at " << now;
83     TimeDelta timeout_delay = TimeoutForNextFrame();
84     timeout_ = now + timeout_delay;
85     timeout_cb_(now - last_frame_);
86     return timeout_delay;
87   }
88   // Otherwise, `timeout_` changed since we scheduled a timeout. Reschedule
89   // a timeout check.
90   return timeout_ - now;
91 }
92 
SetTimeouts(Timeouts timeouts)93 void VideoReceiveStreamTimeoutTracker::SetTimeouts(Timeouts timeouts) {
94   RTC_DCHECK_RUN_ON(bookkeeping_queue_);
95   timeouts_ = timeouts;
96 }
97 
98 }  // namespace webrtc
99