blob: d9d9aea2f030346c2ceb96be5ccd6af8eae5133d [file] [log] [blame]
mflodman15d83572016-10-06 15:35:111/*
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
Elad Alon14d1c9d2019-04-08 12:16:1711#include "video/encoder_rtcp_feedback.h"
mflodman15d83572016-10-06 15:35:1112
Tommi28e96532021-06-03 09:52:1513#include <algorithm>
14#include <utility>
15
Rasmus Brandt3dde4502019-03-21 10:46:1716#include "absl/types/optional.h"
Danil Chapovalovb57178b2024-05-02 14:48:1617#include "api/environment/environment.h"
Elad Alonb6ef99b2019-04-10 14:37:0718#include "api/video_codecs/video_encoder.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "rtc_base/checks.h"
Rasmus Brandt3dde4502019-03-21 10:46:1720#include "rtc_base/experiments/keyframe_interval_settings.h"
Danil Chapovalovb57178b2024-05-02 14:48:1621#include "system_wrappers/include/clock.h"
mflodman15d83572016-10-06 15:35:1122
23namespace webrtc {
24
Rasmus Brandt3dde4502019-03-21 10:46:1725namespace {
26constexpr int kMinKeyframeSendIntervalMs = 300;
27} // namespace
28
Tommi28e96532021-06-03 09:52:1529EncoderRtcpFeedback::EncoderRtcpFeedback(
Danil Chapovalovb57178b2024-05-02 14:48:1630 const Environment& env,
Philipp Hancke7c5f9cf2024-02-20 14:28:1431 bool per_layer_keyframes,
Tommi28e96532021-06-03 09:52:1532 const std::vector<uint32_t>& ssrcs,
33 VideoStreamEncoderInterface* encoder,
34 std::function<std::vector<RtpSequenceNumberMap::Info>(
35 uint32_t ssrc,
36 const std::vector<uint16_t>& seq_nums)> get_packet_infos)
Danil Chapovalovb57178b2024-05-02 14:48:1637 : env_(env),
mflodman15d83572016-10-06 15:35:1138 ssrcs_(ssrcs),
Philipp Hancke7c5f9cf2024-02-20 14:28:1439 per_layer_keyframes_(per_layer_keyframes),
Tommi28e96532021-06-03 09:52:1540 get_packet_infos_(std::move(get_packet_infos)),
mflodmancc3d4422017-08-03 15:27:5141 video_stream_encoder_(encoder),
Philipp Hancke7c5f9cf2024-02-20 14:28:1442 time_last_packet_delivery_queue_(per_layer_keyframes ? ssrcs.size() : 1,
43 Timestamp::Zero()),
Tommi28e96532021-06-03 09:52:1544 min_keyframe_send_interval_(
Danil Chapovalovb57178b2024-05-02 14:48:1645 TimeDelta::Millis(KeyframeIntervalSettings(env_.field_trials())
Tommi28e96532021-06-03 09:52:1546 .MinKeyframeSendIntervalMs()
47 .value_or(kMinKeyframeSendIntervalMs))) {
mflodman15d83572016-10-06 15:35:1148 RTC_DCHECK(!ssrcs.empty());
Tommi28e96532021-06-03 09:52:1549 packet_delivery_queue_.Detach();
mflodman15d83572016-10-06 15:35:1150}
51
Tommi28e96532021-06-03 09:52:1552// Called via Call::DeliverRtcp.
Elad Alon14d1c9d2019-04-08 12:16:1753void EncoderRtcpFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) {
Tommi28e96532021-06-03 09:52:1554 RTC_DCHECK_RUN_ON(&packet_delivery_queue_);
55 RTC_DCHECK(std::find(ssrcs_.begin(), ssrcs_.end(), ssrc) != ssrcs_.end());
56
Philipp Hancke7c5f9cf2024-02-20 14:28:1457 auto it = std::find(ssrcs_.begin(), ssrcs_.end(), ssrc);
58 if (it == ssrcs_.end()) {
59 RTC_LOG(LS_WARNING) << "SSRC " << ssrc << " not found.";
60 return;
61 }
62 size_t ssrc_index =
63 per_layer_keyframes_ ? std::distance(ssrcs_.begin(), it) : 0;
64 RTC_CHECK_LE(ssrc_index, time_last_packet_delivery_queue_.size());
Danil Chapovalovb57178b2024-05-02 14:48:1665 const Timestamp now = env_.clock().CurrentTime();
Philipp Hancke7c5f9cf2024-02-20 14:28:1466 if (time_last_packet_delivery_queue_[ssrc_index] +
67 min_keyframe_send_interval_ >
68 now)
Tommi28e96532021-06-03 09:52:1569 return;
70
Philipp Hancke7c5f9cf2024-02-20 14:28:1471 time_last_packet_delivery_queue_[ssrc_index] = now;
mflodman15d83572016-10-06 15:35:1172
Philipp Hancke7c5f9cf2024-02-20 14:28:1473 std::vector<VideoFrameType> layers(ssrcs_.size(),
74 VideoFrameType::kVideoFrameDelta);
75 if (!per_layer_keyframes_) {
76 // Always produce key frame for all streams.
77 video_stream_encoder_->SendKeyFrame();
78 } else {
79 // Determine on which layer we ask for key frames.
80 layers[ssrc_index] = VideoFrameType::kVideoFrameKey;
81 video_stream_encoder_->SendKeyFrame(layers);
82 }
mflodman15d83572016-10-06 15:35:1183}
84
Elad Alon0a8562e2019-04-09 09:55:1385void EncoderRtcpFeedback::OnReceivedLossNotification(
86 uint32_t ssrc,
87 uint16_t seq_num_of_last_decodable,
88 uint16_t seq_num_of_last_received,
89 bool decodability_flag) {
Tommi28e96532021-06-03 09:52:1590 RTC_DCHECK(get_packet_infos_) << "Object initialization incomplete.";
Elad Alonb6ef99b2019-04-10 14:37:0791
92 const std::vector<uint16_t> seq_nums = {seq_num_of_last_decodable,
93 seq_num_of_last_received};
94 const std::vector<RtpSequenceNumberMap::Info> infos =
Tommi28e96532021-06-03 09:52:1595 get_packet_infos_(ssrc, seq_nums);
Elad Alonb6ef99b2019-04-10 14:37:0796 if (infos.empty()) {
97 return;
98 }
99 RTC_DCHECK_EQ(infos.size(), 2u);
100
101 const RtpSequenceNumberMap::Info& last_decodable = infos[0];
102 const RtpSequenceNumberMap::Info& last_received = infos[1];
103
104 VideoEncoder::LossNotification loss_notification;
105 loss_notification.timestamp_of_last_decodable = last_decodable.timestamp;
106 loss_notification.timestamp_of_last_received = last_received.timestamp;
107
108 // Deduce decodability of the last received frame and of its dependencies.
109 if (last_received.is_first && last_received.is_last) {
110 // The frame consists of a single packet, and that packet has evidently
111 // been received in full; the frame is therefore assemblable.
112 // In this case, the decodability of the dependencies is communicated by
113 // the decodability flag, and the frame itself is decodable if and only
114 // if they are decodable.
115 loss_notification.dependencies_of_last_received_decodable =
116 decodability_flag;
117 loss_notification.last_received_decodable = decodability_flag;
118 } else if (last_received.is_first && !last_received.is_last) {
119 // In this case, the decodability flag communicates the decodability of
120 // the dependencies. If any is undecodable, we also know that the frame
121 // itself will not be decodable; if all are decodable, the frame's own
122 // decodability will remain unknown, as not all of its packets have
123 // been received.
124 loss_notification.dependencies_of_last_received_decodable =
125 decodability_flag;
126 loss_notification.last_received_decodable =
127 !decodability_flag ? absl::make_optional(false) : absl::nullopt;
128 } else if (!last_received.is_first && last_received.is_last) {
129 if (decodability_flag) {
130 // The frame has been received in full, and found to be decodable.
131 // (Messages of this type are not sent by WebRTC at the moment, but are
132 // theoretically possible, for example for serving as acks.)
133 loss_notification.dependencies_of_last_received_decodable = true;
134 loss_notification.last_received_decodable = true;
135 } else {
136 // It is impossible to tell whether some dependencies were undecodable,
137 // or whether the frame was unassemblable, but in either case, the frame
138 // itself was undecodable.
139 loss_notification.dependencies_of_last_received_decodable = absl::nullopt;
140 loss_notification.last_received_decodable = false;
141 }
142 } else { // !last_received.is_first && !last_received.is_last
143 if (decodability_flag) {
144 // The frame has not yet been received in full, but no gaps have
145 // been encountered so far, and the dependencies were all decodable.
146 // (Messages of this type are not sent by WebRTC at the moment, but are
147 // theoretically possible, for example for serving as acks.)
148 loss_notification.dependencies_of_last_received_decodable = true;
149 loss_notification.last_received_decodable = absl::nullopt;
150 } else {
151 // It is impossible to tell whether some dependencies were undecodable,
152 // or whether the frame was unassemblable, but in either case, the frame
153 // itself was undecodable.
154 loss_notification.dependencies_of_last_received_decodable = absl::nullopt;
155 loss_notification.last_received_decodable = false;
156 }
157 }
158
159 video_stream_encoder_->OnLossNotification(loss_notification);
Elad Alon0a8562e2019-04-09 09:55:13160}
161
mflodman15d83572016-10-06 15:35:11162} // namespace webrtc