blob: ac5d84b50aabd8c2f5ecd1e457af7c92a555a546 [file] [log] [blame]
mflodman351424e2017-08-10 02:43:14 -07001/*
2 * Copyright (c) 2017 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 "api/video_codecs/video_encoder.h"
mflodman351424e2017-08-10 02:43:14 -070012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <string.h>
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +010014#include <algorithm>
Yves Gerey988cc082018-10-23 12:03:01 +020015
16#include "rtc_base/checks.h"
Erik Språng79685302019-11-27 17:26:58 +010017#include "rtc_base/strings/string_builder.h"
Yves Gerey988cc082018-10-23 12:03:01 +020018
mflodman351424e2017-08-10 02:43:14 -070019namespace webrtc {
20
21// TODO(mflodman): Add default complexity for VP9 and VP9.
22VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() {
23 VideoCodecVP8 vp8_settings;
24 memset(&vp8_settings, 0, sizeof(vp8_settings));
25
mflodman351424e2017-08-10 02:43:14 -070026 vp8_settings.numberOfTemporalLayers = 1;
27 vp8_settings.denoisingOn = true;
mflodman351424e2017-08-10 02:43:14 -070028 vp8_settings.automaticResizeOn = false;
29 vp8_settings.frameDroppingOn = true;
30 vp8_settings.keyFrameInterval = 3000;
31
32 return vp8_settings;
33}
34
35VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() {
36 VideoCodecVP9 vp9_settings;
37 memset(&vp9_settings, 0, sizeof(vp9_settings));
38
mflodman351424e2017-08-10 02:43:14 -070039 vp9_settings.numberOfTemporalLayers = 1;
40 vp9_settings.denoisingOn = true;
41 vp9_settings.frameDroppingOn = true;
42 vp9_settings.keyFrameInterval = 3000;
43 vp9_settings.adaptiveQpMode = true;
44 vp9_settings.automaticResizeOn = true;
45 vp9_settings.numberOfSpatialLayers = 1;
46 vp9_settings.flexibleMode = false;
Sergey Silkin6a8f30e2018-04-26 11:03:49 +020047 vp9_settings.interLayerPred = InterLayerPredMode::kOn;
mflodman351424e2017-08-10 02:43:14 -070048
49 return vp9_settings;
50}
51
52VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
53 VideoCodecH264 h264_settings;
54 memset(&h264_settings, 0, sizeof(h264_settings));
55
56 h264_settings.frameDroppingOn = true;
57 h264_settings.keyFrameInterval = 3000;
Johnny Lee1a1c52b2019-02-08 14:25:40 -050058 h264_settings.numberOfTemporalLayers = 1;
mflodman351424e2017-08-10 02:43:14 -070059
60 return h264_settings;
61}
62
Niels Möller225c7872018-02-22 15:03:53 +010063VideoEncoder::ScalingSettings::ScalingSettings() = default;
mflodman351424e2017-08-10 02:43:14 -070064
Niels Möller225c7872018-02-22 15:03:53 +010065VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {}
66
67VideoEncoder::ScalingSettings::ScalingSettings(int low, int high)
68 : thresholds(QpThresholds(low, high)) {}
69
70VideoEncoder::ScalingSettings::ScalingSettings(int low,
asapersson142fcc92017-08-17 08:58:54 -070071 int high,
72 int min_pixels)
Niels Möller225c7872018-02-22 15:03:53 +010073 : thresholds(QpThresholds(low, high)), min_pixels_per_frame(min_pixels) {}
asapersson142fcc92017-08-17 08:58:54 -070074
Niels Möller225c7872018-02-22 15:03:53 +010075VideoEncoder::ScalingSettings::ScalingSettings(const ScalingSettings&) =
76 default;
mflodman351424e2017-08-10 02:43:14 -070077
78VideoEncoder::ScalingSettings::~ScalingSettings() {}
79
Niels Möller225c7872018-02-22 15:03:53 +010080// static
81constexpr VideoEncoder::ScalingSettings::KOff
82 VideoEncoder::ScalingSettings::kOff;
Erik Språngdbdd8392019-01-17 15:27:50 +010083// static
84constexpr uint8_t VideoEncoder::EncoderInfo::kMaxFramerateFraction;
mflodman351424e2017-08-10 02:43:14 -070085
Erik Språng79685302019-11-27 17:26:58 +010086bool VideoEncoder::ResolutionBitrateLimits::operator==(
87 const ResolutionBitrateLimits& rhs) const {
88 return frame_size_pixels == rhs.frame_size_pixels &&
89 min_start_bitrate_bps == rhs.min_start_bitrate_bps &&
90 min_bitrate_bps == rhs.min_bitrate_bps &&
91 max_bitrate_bps == rhs.max_bitrate_bps;
92}
93
Erik Språnge2fd86a2018-10-24 11:32:39 +020094VideoEncoder::EncoderInfo::EncoderInfo()
95 : scaling_settings(VideoEncoder::ScalingSettings::kOff),
Rasmus Brandt5cad55b2019-12-19 09:47:11 +010096 requested_resolution_alignment(1),
Åsa Perssonc5a74ff2020-09-20 17:50:00 +020097 apply_alignment_to_all_simulcast_layers(false),
Erik Språnge2fd86a2018-10-24 11:32:39 +020098 supports_native_handle(false),
Erik Språngd3438aa2018-11-08 16:56:43 +010099 implementation_name("unknown"),
Mirta Dvornicic897a9912018-11-30 13:12:21 +0100100 has_trusted_rate_controller(false),
Mirta Dvornicicccc1b572019-01-15 12:42:18 +0100101 is_hardware_accelerated(true),
Erik Språngdbdd8392019-01-17 15:27:50 +0100102 has_internal_source(false),
103 fps_allocation{absl::InlinedVector<uint8_t, kMaxTemporalStreams>(
104 1,
Erik Språngf4e0c292019-10-01 18:50:03 +0200105 kMaxFramerateFraction)},
Evan Shrubsoleb556b082020-10-08 14:56:45 +0200106 supports_simulcast(false),
107 preferred_pixel_formats{VideoFrameBuffer::Type::kI420} {}
Mirta Dvornicic897a9912018-11-30 13:12:21 +0100108
109VideoEncoder::EncoderInfo::EncoderInfo(const EncoderInfo&) = default;
Erik Språnge2fd86a2018-10-24 11:32:39 +0200110
Erik Språnge2fd86a2018-10-24 11:32:39 +0200111VideoEncoder::EncoderInfo::~EncoderInfo() = default;
112
Erik Språng79685302019-11-27 17:26:58 +0100113std::string VideoEncoder::EncoderInfo::ToString() const {
114 char string_buf[2048];
115 rtc::SimpleStringBuilder oss(string_buf);
116
117 oss << "EncoderInfo { "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100118 "ScalingSettings { ";
Erik Språng79685302019-11-27 17:26:58 +0100119 if (scaling_settings.thresholds) {
120 oss << "Thresholds { "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100121 "low = "
122 << scaling_settings.thresholds->low
Erik Språng79685302019-11-27 17:26:58 +0100123 << ", high = " << scaling_settings.thresholds->high << "}, ";
124 }
125 oss << "min_pixels_per_frame = " << scaling_settings.min_pixels_per_frame
126 << " }";
Rasmus Brandt5cad55b2019-12-19 09:47:11 +0100127 oss << ", requested_resolution_alignment = " << requested_resolution_alignment
Åsa Perssonc5a74ff2020-09-20 17:50:00 +0200128 << ", apply_alignment_to_all_simulcast_layers = "
129 << apply_alignment_to_all_simulcast_layers
Rasmus Brandt5cad55b2019-12-19 09:47:11 +0100130 << ", supports_native_handle = " << supports_native_handle
Jonas Olssonb2b20312020-01-14 12:11:31 +0100131 << ", implementation_name = '" << implementation_name
132 << "'"
133 ", has_trusted_rate_controller = "
134 << has_trusted_rate_controller
Erik Språng79685302019-11-27 17:26:58 +0100135 << ", is_hardware_accelerated = " << is_hardware_accelerated
136 << ", has_internal_source = " << has_internal_source
137 << ", fps_allocation = [";
Erik Språng75941452021-05-31 17:08:02 +0200138 size_t num_spatial_layer_with_fps_allocation = 0;
139 for (size_t i = 0; i < kMaxSpatialLayers; ++i) {
140 if (!fps_allocation[i].empty()) {
141 num_spatial_layer_with_fps_allocation = i + 1;
142 }
143 }
Erik Språng79685302019-11-27 17:26:58 +0100144 bool first = true;
Erik Språng75941452021-05-31 17:08:02 +0200145 for (size_t i = 0; i < num_spatial_layer_with_fps_allocation; ++i) {
146 if (fps_allocation[i].empty()) {
147 break;
148 }
Erik Språng79685302019-11-27 17:26:58 +0100149 if (!first) {
150 oss << ", ";
151 }
152 const absl::InlinedVector<uint8_t, kMaxTemporalStreams>& fractions =
153 fps_allocation[i];
154 if (!fractions.empty()) {
155 first = false;
156 oss << "[ ";
157 for (size_t i = 0; i < fractions.size(); ++i) {
158 if (i > 0) {
159 oss << ", ";
160 }
161 oss << (static_cast<double>(fractions[i]) / kMaxFramerateFraction);
162 }
163 oss << "] ";
164 }
165 }
166 oss << "]";
167 oss << ", resolution_bitrate_limits = [";
168 for (size_t i = 0; i < resolution_bitrate_limits.size(); ++i) {
169 if (i > 0) {
170 oss << ", ";
171 }
172 ResolutionBitrateLimits l = resolution_bitrate_limits[i];
173 oss << "Limits { "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100174 "frame_size_pixels = "
175 << l.frame_size_pixels
Erik Språng79685302019-11-27 17:26:58 +0100176 << ", min_start_bitrate_bps = " << l.min_start_bitrate_bps
177 << ", min_bitrate_bps = " << l.min_bitrate_bps
178 << ", max_bitrate_bps = " << l.max_bitrate_bps << "} ";
179 }
180 oss << "] "
Jonas Olssonb2b20312020-01-14 12:11:31 +0100181 ", supports_simulcast = "
Evan Shrubsoleb556b082020-10-08 14:56:45 +0200182 << supports_simulcast;
183 oss << ", preferred_pixel_formats = [";
184 for (size_t i = 0; i < preferred_pixel_formats.size(); ++i) {
185 if (i > 0)
186 oss << ", ";
187 oss << VideoFrameBufferTypeToString(preferred_pixel_formats.at(i));
188 }
189 oss << "]";
Qiu Jianlinb54cfde2021-07-30 06:48:03 +0800190 if (is_qp_trusted.has_value()) {
191 oss << ", is_qp_trusted = " << is_qp_trusted.value();
192 }
Evan Shrubsoleb556b082020-10-08 14:56:45 +0200193 oss << "}";
Erik Språng79685302019-11-27 17:26:58 +0100194 return oss.str();
195}
196
197bool VideoEncoder::EncoderInfo::operator==(const EncoderInfo& rhs) const {
198 if (scaling_settings.thresholds.has_value() !=
199 rhs.scaling_settings.thresholds.has_value()) {
200 return false;
201 }
202 if (scaling_settings.thresholds.has_value()) {
203 QpThresholds l = *scaling_settings.thresholds;
204 QpThresholds r = *rhs.scaling_settings.thresholds;
205 if (l.low != r.low || l.high != r.high) {
206 return false;
207 }
208 }
209 if (scaling_settings.min_pixels_per_frame !=
210 rhs.scaling_settings.min_pixels_per_frame) {
211 return false;
212 }
213
214 if (supports_native_handle != rhs.supports_native_handle ||
215 implementation_name != rhs.implementation_name ||
216 has_trusted_rate_controller != rhs.has_trusted_rate_controller ||
217 is_hardware_accelerated != rhs.is_hardware_accelerated ||
218 has_internal_source != rhs.has_internal_source) {
219 return false;
220 }
221
222 for (size_t i = 0; i < kMaxSpatialLayers; ++i) {
223 if (fps_allocation[i] != rhs.fps_allocation[i]) {
224 return false;
225 }
226 }
227
228 if (resolution_bitrate_limits != rhs.resolution_bitrate_limits ||
229 supports_simulcast != rhs.supports_simulcast) {
230 return false;
231 }
232
233 return true;
234}
235
Henrik Boströmb0f2e0c2020-03-06 13:32:03 +0100236absl::optional<VideoEncoder::ResolutionBitrateLimits>
237VideoEncoder::EncoderInfo::GetEncoderBitrateLimitsForResolution(
238 int frame_size_pixels) const {
239 std::vector<ResolutionBitrateLimits> bitrate_limits =
240 resolution_bitrate_limits;
241
242 // Sort the list of bitrate limits by resolution.
243 sort(bitrate_limits.begin(), bitrate_limits.end(),
244 [](const ResolutionBitrateLimits& lhs,
245 const ResolutionBitrateLimits& rhs) {
246 return lhs.frame_size_pixels < rhs.frame_size_pixels;
247 });
248
249 for (size_t i = 0; i < bitrate_limits.size(); ++i) {
250 RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 0);
251 RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 0);
252 RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps,
253 bitrate_limits[i].min_bitrate_bps);
254 if (i > 0) {
255 // The bitrate limits aren't expected to decrease with resolution.
256 RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps,
257 bitrate_limits[i - 1].min_bitrate_bps);
258 RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps,
259 bitrate_limits[i - 1].min_start_bitrate_bps);
260 RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps,
261 bitrate_limits[i - 1].max_bitrate_bps);
262 }
263
264 if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels) {
265 return absl::optional<ResolutionBitrateLimits>(bitrate_limits[i]);
266 }
267 }
268
269 return absl::nullopt;
270}
271
Erik Språng4c6ca302019-04-08 15:14:01 +0200272VideoEncoder::RateControlParameters::RateControlParameters()
273 : bitrate(VideoBitrateAllocation()),
274 framerate_fps(0.0),
275 bandwidth_allocation(DataRate::Zero()) {}
276
277VideoEncoder::RateControlParameters::RateControlParameters(
278 const VideoBitrateAllocation& bitrate,
Erik Språng16cb8f52019-04-12 13:59:09 +0200279 double framerate_fps)
280 : bitrate(bitrate),
281 framerate_fps(framerate_fps),
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100282 bandwidth_allocation(DataRate::BitsPerSec(bitrate.get_sum_bps())) {}
Erik Språng16cb8f52019-04-12 13:59:09 +0200283
284VideoEncoder::RateControlParameters::RateControlParameters(
285 const VideoBitrateAllocation& bitrate,
Erik Språng4c6ca302019-04-08 15:14:01 +0200286 double framerate_fps,
287 DataRate bandwidth_allocation)
288 : bitrate(bitrate),
289 framerate_fps(framerate_fps),
290 bandwidth_allocation(bandwidth_allocation) {}
291
Evan Shrubsole7c079f62019-09-26 09:55:03 +0200292bool VideoEncoder::RateControlParameters::operator==(
293 const VideoEncoder::RateControlParameters& rhs) const {
294 return std::tie(bitrate, framerate_fps, bandwidth_allocation) ==
295 std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation);
296}
297
298bool VideoEncoder::RateControlParameters::operator!=(
299 const VideoEncoder::RateControlParameters& rhs) const {
300 return !(rhs == *this);
301}
302
Erik Språng4c6ca302019-04-08 15:14:01 +0200303VideoEncoder::RateControlParameters::~RateControlParameters() = default;
304
Elad Alon8f01c4e2019-06-28 15:19:43 +0200305void VideoEncoder::SetFecControllerOverride(
306 FecControllerOverride* fec_controller_override) {}
307
Elad Alon370f93a2019-06-11 14:57:57 +0200308int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings,
309 int32_t number_of_cores,
310 size_t max_payload_size) {
311 const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false);
312 const VideoEncoder::Settings settings(capabilities, number_of_cores,
313 max_payload_size);
314 // In theory, this and the other version of InitEncode() could end up calling
315 // each other in a loop until we get a stack overflow.
316 // In practice, any subclass of VideoEncoder would overload at least one
317 // of these, and we have a TODO in the header file to make this pure virtual.
318 return InitEncode(codec_settings, settings);
319}
320
321int VideoEncoder::InitEncode(const VideoCodec* codec_settings,
322 const VideoEncoder::Settings& settings) {
323 // In theory, this and the other version of InitEncode() could end up calling
324 // each other in a loop until we get a stack overflow.
325 // In practice, any subclass of VideoEncoder would overload at least one
326 // of these, and we have a TODO in the header file to make this pure virtual.
327 return InitEncode(codec_settings, settings.number_of_cores,
328 settings.max_payload_size);
329}
330
Elad Aloncde8ab22019-03-20 11:56:20 +0100331void VideoEncoder::OnPacketLossRateUpdate(float packet_loss_rate) {}
332
333void VideoEncoder::OnRttUpdate(int64_t rtt_ms) {}
334
Elad Alon6c371ca2019-04-04 12:28:51 +0200335void VideoEncoder::OnLossNotification(
336 const LossNotification& loss_notification) {}
337
Erik Språng6ed4f142018-11-26 13:42:39 +0100338// TODO(webrtc:9722): Remove and make pure virtual.
Erik Språnge2fd86a2018-10-24 11:32:39 +0200339VideoEncoder::EncoderInfo VideoEncoder::GetEncoderInfo() const {
Erik Språng6ed4f142018-11-26 13:42:39 +0100340 return EncoderInfo();
Erik Språnge2fd86a2018-10-24 11:32:39 +0200341}
Erik Språng6ed4f142018-11-26 13:42:39 +0100342
mflodman351424e2017-08-10 02:43:14 -0700343} // namespace webrtc