blob: 490a36298acc4df81a8810a30fc3e7c786a20336 [file] [log] [blame]
Per69b332d2016-06-02 15:45:42 +02001/*
2 * Copyright (c) 2016 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/protection_bitrate_calculator.h"
Per69b332d2016-06-02 15:45:42 +020012
13namespace webrtc {
14
15using rtc::CritScope;
16
17struct ProtectionBitrateCalculator::EncodedFrameSample {
18 EncodedFrameSample(size_t size_bytes,
19 uint32_t timestamp,
20 int64_t time_complete_ms)
21 : size_bytes(size_bytes),
22 timestamp(timestamp),
23 time_complete_ms(time_complete_ms) {}
24 size_t size_bytes;
25 uint32_t timestamp;
26 int64_t time_complete_ms;
27};
28
29ProtectionBitrateCalculator::ProtectionBitrateCalculator(
30 Clock* clock,
31 VCMProtectionCallback* protection_callback)
32 : clock_(clock),
33 protection_callback_(protection_callback),
34 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
35 clock_->TimeInMilliseconds())),
36 max_payload_size_(1460) {}
37
38ProtectionBitrateCalculator::~ProtectionBitrateCalculator(void) {
39 loss_prot_logic_->Release();
40}
41
perkjc2c24f72016-07-11 01:47:32 -070042void ProtectionBitrateCalculator::SetEncodingData(size_t width,
43 size_t height,
Per69b332d2016-06-02 15:45:42 +020044 size_t num_temporal_layers,
45 size_t max_payload_size) {
46 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020047 loss_prot_logic_->UpdateFrameSize(width, height);
48 loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
49 max_payload_size_ = max_payload_size;
50}
51
52uint32_t ProtectionBitrateCalculator::SetTargetRates(
53 uint32_t estimated_bitrate_bps,
54 int actual_framerate_fps,
55 uint8_t fraction_lost,
56 int64_t round_trip_time_ms) {
57 float target_bitrate_kbps =
58 static_cast<float>(estimated_bitrate_bps) / 1000.0f;
59 // Sanity check.
60 if (actual_framerate_fps < 1.0) {
61 actual_framerate_fps = 1.0;
62 }
63
64 FecProtectionParams delta_fec_params;
65 FecProtectionParams key_fec_params;
66 {
67 CritScope lock(&crit_sect_);
68
69 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
70 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
71
72 // Update frame rate for the loss protection logic class: frame rate should
73 // be the actual/sent rate.
74 loss_prot_logic_->UpdateFrameRate(actual_framerate_fps);
75
76 // Returns the filtered packet loss, used for the protection setting.
77 // The filtered loss may be the received loss (no filter), or some
78 // filtered value (average or max window filter).
79 // Use max window filter for now.
80 media_optimization::FilterPacketLossMode filter_mode =
81 media_optimization::kMaxFilter;
82 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
83 clock_->TimeInMilliseconds(), filter_mode, fraction_lost);
84
85 // For now use the filtered loss for computing the robustness settings.
86 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
87
88 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
89 return estimated_bitrate_bps;
90 }
91
92 // Update method will compute the robustness settings for the given
93 // protection method and the overhead cost
94 // the protection method is set by the user via SetVideoProtection.
95 loss_prot_logic_->UpdateMethod();
96
97 // Get the bit cost of protection method, based on the amount of
98 // overhead data actually transmitted (including headers) the last
99 // second.
100
101 // Get the FEC code rate for Key frames (set to 0 when NA).
102 key_fec_params.fec_rate =
103 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK();
104
105 // Get the FEC code rate for Delta frames (set to 0 when NA).
106 delta_fec_params.fec_rate =
107 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD();
108
109 // The RTP module currently requires the same |max_fec_frames| for both
110 // key and delta frames.
111 delta_fec_params.max_fec_frames =
112 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
113 key_fec_params.max_fec_frames =
114 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
115 }
116
117 // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
118 // consecutive losses and little/no packet re-ordering. As we currently
119 // do not have feedback data on the degree of correlated losses and packet
120 // re-ordering, we keep default setting to |kFecMaskRandom| for now.
121 delta_fec_params.fec_mask_type = kFecMaskRandom;
122 key_fec_params.fec_mask_type = kFecMaskRandom;
123
124 // Update protection callback with protection settings.
125 uint32_t sent_video_rate_bps = 0;
126 uint32_t sent_nack_rate_bps = 0;
127 uint32_t sent_fec_rate_bps = 0;
128 // Rate cost of the protection methods.
129 float protection_overhead_rate = 0.0f;
130
131 // TODO(Marco): Pass FEC protection values per layer.
132 protection_callback_->ProtectionRequest(
133 &delta_fec_params, &key_fec_params, &sent_video_rate_bps,
134 &sent_nack_rate_bps, &sent_fec_rate_bps);
135
136 uint32_t sent_total_rate_bps =
137 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
138 // Estimate the overhead costs of the next second as staying the same
139 // wrt the source bitrate.
140 if (sent_total_rate_bps > 0) {
141 protection_overhead_rate =
142 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
143 sent_total_rate_bps;
144 }
145 // Cap the overhead estimate to 50%.
146 if (protection_overhead_rate > 0.5)
147 protection_overhead_rate = 0.5;
148
149 // Source coding rate: total rate - protection overhead.
150 return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
151}
152
153void ProtectionBitrateCalculator::SetProtectionMethod(bool enable_fec,
154 bool enable_nack) {
155 media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone);
156 if (enable_fec && enable_nack) {
157 method = media_optimization::kNackFec;
158 } else if (enable_nack) {
159 method = media_optimization::kNack;
160 } else if (enable_fec) {
161 method = media_optimization::kFec;
162 }
163 CritScope lock(&crit_sect_);
164 loss_prot_logic_->SetMethod(method);
165}
166
167void ProtectionBitrateCalculator::UpdateWithEncodedData(
168 const EncodedImage& encoded_image) {
169 const size_t encoded_length = encoded_image._length;
170 CritScope lock(&crit_sect_);
171 if (encoded_length > 0) {
172 const bool delta_frame = encoded_image._frameType != kVideoFrameKey;
173
174 if (max_payload_size_ > 0 && encoded_length > 0) {
175 const float min_packets_per_frame =
176 encoded_length / static_cast<float>(max_payload_size_);
177 if (delta_frame) {
178 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
179 clock_->TimeInMilliseconds());
180 } else {
181 loss_prot_logic_->UpdatePacketsPerFrameKey(
182 min_packets_per_frame, clock_->TimeInMilliseconds());
183 }
184 }
185 if (!delta_frame && encoded_length > 0) {
186 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
187 }
188 }
189}
190
191} // namespace webrtc