xref: /aosp_15_r20/external/webrtc/video/encoder_rtcp_feedback.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2012 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/encoder_rtcp_feedback.h"
12 
13 #include <algorithm>
14 #include <utility>
15 
16 #include "absl/types/optional.h"
17 #include "api/video_codecs/video_encoder.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/experiments/keyframe_interval_settings.h"
20 
21 namespace webrtc {
22 
23 namespace {
24 constexpr int kMinKeyframeSendIntervalMs = 300;
25 }  // namespace
26 
EncoderRtcpFeedback(Clock * clock,const std::vector<uint32_t> & ssrcs,VideoStreamEncoderInterface * encoder,std::function<std::vector<RtpSequenceNumberMap::Info> (uint32_t ssrc,const std::vector<uint16_t> & seq_nums)> get_packet_infos)27 EncoderRtcpFeedback::EncoderRtcpFeedback(
28     Clock* clock,
29     const std::vector<uint32_t>& ssrcs,
30     VideoStreamEncoderInterface* encoder,
31     std::function<std::vector<RtpSequenceNumberMap::Info>(
32         uint32_t ssrc,
33         const std::vector<uint16_t>& seq_nums)> get_packet_infos)
34     : clock_(clock),
35       ssrcs_(ssrcs),
36       get_packet_infos_(std::move(get_packet_infos)),
37       video_stream_encoder_(encoder),
38       time_last_packet_delivery_queue_(Timestamp::Zero()),
39       min_keyframe_send_interval_(
40           TimeDelta::Millis(KeyframeIntervalSettings::ParseFromFieldTrials()
41                                 .MinKeyframeSendIntervalMs()
42                                 .value_or(kMinKeyframeSendIntervalMs))) {
43   RTC_DCHECK(!ssrcs.empty());
44   packet_delivery_queue_.Detach();
45 }
46 
47 // Called via Call::DeliverRtcp.
OnReceivedIntraFrameRequest(uint32_t ssrc)48 void EncoderRtcpFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) {
49   RTC_DCHECK_RUN_ON(&packet_delivery_queue_);
50   RTC_DCHECK(std::find(ssrcs_.begin(), ssrcs_.end(), ssrc) != ssrcs_.end());
51 
52   const Timestamp now = clock_->CurrentTime();
53   if (time_last_packet_delivery_queue_ + min_keyframe_send_interval_ > now)
54     return;
55 
56   time_last_packet_delivery_queue_ = now;
57 
58   // Always produce key frame for all streams.
59   video_stream_encoder_->SendKeyFrame();
60 }
61 
OnReceivedLossNotification(uint32_t ssrc,uint16_t seq_num_of_last_decodable,uint16_t seq_num_of_last_received,bool decodability_flag)62 void EncoderRtcpFeedback::OnReceivedLossNotification(
63     uint32_t ssrc,
64     uint16_t seq_num_of_last_decodable,
65     uint16_t seq_num_of_last_received,
66     bool decodability_flag) {
67   RTC_DCHECK(get_packet_infos_) << "Object initialization incomplete.";
68 
69   const std::vector<uint16_t> seq_nums = {seq_num_of_last_decodable,
70                                           seq_num_of_last_received};
71   const std::vector<RtpSequenceNumberMap::Info> infos =
72       get_packet_infos_(ssrc, seq_nums);
73   if (infos.empty()) {
74     return;
75   }
76   RTC_DCHECK_EQ(infos.size(), 2u);
77 
78   const RtpSequenceNumberMap::Info& last_decodable = infos[0];
79   const RtpSequenceNumberMap::Info& last_received = infos[1];
80 
81   VideoEncoder::LossNotification loss_notification;
82   loss_notification.timestamp_of_last_decodable = last_decodable.timestamp;
83   loss_notification.timestamp_of_last_received = last_received.timestamp;
84 
85   // Deduce decodability of the last received frame and of its dependencies.
86   if (last_received.is_first && last_received.is_last) {
87     // The frame consists of a single packet, and that packet has evidently
88     // been received in full; the frame is therefore assemblable.
89     // In this case, the decodability of the dependencies is communicated by
90     // the decodability flag, and the frame itself is decodable if and only
91     // if they are decodable.
92     loss_notification.dependencies_of_last_received_decodable =
93         decodability_flag;
94     loss_notification.last_received_decodable = decodability_flag;
95   } else if (last_received.is_first && !last_received.is_last) {
96     // In this case, the decodability flag communicates the decodability of
97     // the dependencies. If any is undecodable, we also know that the frame
98     // itself will not be decodable; if all are decodable, the frame's own
99     // decodability will remain unknown, as not all of its packets have
100     // been received.
101     loss_notification.dependencies_of_last_received_decodable =
102         decodability_flag;
103     loss_notification.last_received_decodable =
104         !decodability_flag ? absl::make_optional(false) : absl::nullopt;
105   } else if (!last_received.is_first && last_received.is_last) {
106     if (decodability_flag) {
107       // The frame has been received in full, and found to be decodable.
108       // (Messages of this type are not sent by WebRTC at the moment, but are
109       // theoretically possible, for example for serving as acks.)
110       loss_notification.dependencies_of_last_received_decodable = true;
111       loss_notification.last_received_decodable = true;
112     } else {
113       // It is impossible to tell whether some dependencies were undecodable,
114       // or whether the frame was unassemblable, but in either case, the frame
115       // itself was undecodable.
116       loss_notification.dependencies_of_last_received_decodable = absl::nullopt;
117       loss_notification.last_received_decodable = false;
118     }
119   } else {  // !last_received.is_first && !last_received.is_last
120     if (decodability_flag) {
121       // The frame has not yet been received in full, but no gaps have
122       // been encountered so far, and the dependencies were all decodable.
123       // (Messages of this type are not sent by WebRTC at the moment, but are
124       // theoretically possible, for example for serving as acks.)
125       loss_notification.dependencies_of_last_received_decodable = true;
126       loss_notification.last_received_decodable = absl::nullopt;
127     } else {
128       // It is impossible to tell whether some dependencies were undecodable,
129       // or whether the frame was unassemblable, but in either case, the frame
130       // itself was undecodable.
131       loss_notification.dependencies_of_last_received_decodable = absl::nullopt;
132       loss_notification.last_received_decodable = false;
133     }
134   }
135 
136   video_stream_encoder_->OnLossNotification(loss_notification);
137 }
138 
139 }  // namespace webrtc
140