diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/api/video_codecs/video_encoder.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/api/video_codecs/video_encoder.cc')
-rw-r--r-- | third_party/libwebrtc/api/video_codecs/video_encoder.cc | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder.cc b/third_party/libwebrtc/api/video_codecs/video_encoder.cc new file mode 100644 index 0000000000..d2de985d5c --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder.cc @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "api/video_codecs/video_encoder.h" + +#include <string.h> + +#include <algorithm> + +#include "rtc_base/checks.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +// TODO(mflodman): Add default complexity for VP9 and VP9. +VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() { + VideoCodecVP8 vp8_settings; + memset(&vp8_settings, 0, sizeof(vp8_settings)); + + vp8_settings.numberOfTemporalLayers = 1; + vp8_settings.denoisingOn = true; + vp8_settings.automaticResizeOn = false; + vp8_settings.keyFrameInterval = 3000; + + return vp8_settings; +} + +VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() { + VideoCodecVP9 vp9_settings; + memset(&vp9_settings, 0, sizeof(vp9_settings)); + + vp9_settings.numberOfTemporalLayers = 1; + vp9_settings.denoisingOn = true; + vp9_settings.keyFrameInterval = 3000; + vp9_settings.adaptiveQpMode = true; + vp9_settings.automaticResizeOn = true; + vp9_settings.numberOfSpatialLayers = 1; + vp9_settings.flexibleMode = false; + vp9_settings.interLayerPred = InterLayerPredMode::kOn; + + return vp9_settings; +} + +VideoCodecH264 VideoEncoder::GetDefaultH264Settings() { + VideoCodecH264 h264_settings; + memset(&h264_settings, 0, sizeof(h264_settings)); + + h264_settings.keyFrameInterval = 3000; + h264_settings.numberOfTemporalLayers = 1; + + return h264_settings; +} + +VideoEncoder::ScalingSettings::ScalingSettings() = default; + +VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {} + +VideoEncoder::ScalingSettings::ScalingSettings(int low, int high) + : thresholds(QpThresholds(low, high)) {} + +VideoEncoder::ScalingSettings::ScalingSettings(int low, + int high, + int min_pixels) + : thresholds(QpThresholds(low, high)), min_pixels_per_frame(min_pixels) {} + +VideoEncoder::ScalingSettings::ScalingSettings(const ScalingSettings&) = + default; + +VideoEncoder::ScalingSettings::~ScalingSettings() {} + +// static +constexpr VideoEncoder::ScalingSettings::KOff + VideoEncoder::ScalingSettings::kOff; +// static +constexpr uint8_t VideoEncoder::EncoderInfo::kMaxFramerateFraction; + +bool VideoEncoder::ResolutionBitrateLimits::operator==( + const ResolutionBitrateLimits& rhs) const { + return frame_size_pixels == rhs.frame_size_pixels && + min_start_bitrate_bps == rhs.min_start_bitrate_bps && + min_bitrate_bps == rhs.min_bitrate_bps && + max_bitrate_bps == rhs.max_bitrate_bps; +} + +VideoEncoder::EncoderInfo::EncoderInfo() + : scaling_settings(VideoEncoder::ScalingSettings::kOff), + requested_resolution_alignment(1), + apply_alignment_to_all_simulcast_layers(false), + supports_native_handle(false), + implementation_name("unknown"), + has_trusted_rate_controller(false), + is_hardware_accelerated(true), + fps_allocation{absl::InlinedVector<uint8_t, kMaxTemporalStreams>( + 1, + kMaxFramerateFraction)}, + supports_simulcast(false), + preferred_pixel_formats{VideoFrameBuffer::Type::kI420} {} + +VideoEncoder::EncoderInfo::EncoderInfo(const EncoderInfo&) = default; + +VideoEncoder::EncoderInfo::~EncoderInfo() = default; + +std::string VideoEncoder::EncoderInfo::ToString() const { + char string_buf[2048]; + rtc::SimpleStringBuilder oss(string_buf); + + oss << "EncoderInfo { " + "ScalingSettings { "; + if (scaling_settings.thresholds) { + oss << "Thresholds { " + "low = " + << scaling_settings.thresholds->low + << ", high = " << scaling_settings.thresholds->high << "}, "; + } + oss << "min_pixels_per_frame = " << scaling_settings.min_pixels_per_frame + << " }"; + oss << ", requested_resolution_alignment = " << requested_resolution_alignment + << ", apply_alignment_to_all_simulcast_layers = " + << apply_alignment_to_all_simulcast_layers + << ", supports_native_handle = " << supports_native_handle + << ", implementation_name = '" << implementation_name + << "'" + ", has_trusted_rate_controller = " + << has_trusted_rate_controller + << ", is_hardware_accelerated = " << is_hardware_accelerated + << ", fps_allocation = ["; + size_t num_spatial_layer_with_fps_allocation = 0; + for (size_t i = 0; i < kMaxSpatialLayers; ++i) { + if (!fps_allocation[i].empty()) { + num_spatial_layer_with_fps_allocation = i + 1; + } + } + bool first = true; + for (size_t i = 0; i < num_spatial_layer_with_fps_allocation; ++i) { + if (fps_allocation[i].empty()) { + break; + } + if (!first) { + oss << ", "; + } + const absl::InlinedVector<uint8_t, kMaxTemporalStreams>& fractions = + fps_allocation[i]; + if (!fractions.empty()) { + first = false; + oss << "[ "; + for (size_t i = 0; i < fractions.size(); ++i) { + if (i > 0) { + oss << ", "; + } + oss << (static_cast<double>(fractions[i]) / kMaxFramerateFraction); + } + oss << "] "; + } + } + oss << "]"; + oss << ", resolution_bitrate_limits = ["; + for (size_t i = 0; i < resolution_bitrate_limits.size(); ++i) { + if (i > 0) { + oss << ", "; + } + ResolutionBitrateLimits l = resolution_bitrate_limits[i]; + oss << "Limits { " + "frame_size_pixels = " + << l.frame_size_pixels + << ", min_start_bitrate_bps = " << l.min_start_bitrate_bps + << ", min_bitrate_bps = " << l.min_bitrate_bps + << ", max_bitrate_bps = " << l.max_bitrate_bps << "} "; + } + oss << "] " + ", supports_simulcast = " + << supports_simulcast; + oss << ", preferred_pixel_formats = ["; + for (size_t i = 0; i < preferred_pixel_formats.size(); ++i) { + if (i > 0) + oss << ", "; +#if defined(WEBRTC_MOZILLA_BUILD) + // This could assert, as opposed to throw using the form in the + // else, but since we're in a for loop that uses .size() we can + // be fairly sure that this is safe without doing a further + // check to make sure 'i' is in-range. + oss << VideoFrameBufferTypeToString(preferred_pixel_formats[i]); +#else + oss << VideoFrameBufferTypeToString(preferred_pixel_formats.at(i)); +#endif + } + oss << "]"; + if (is_qp_trusted.has_value()) { + oss << ", is_qp_trusted = " << is_qp_trusted.value(); + } + oss << "}"; + return oss.str(); +} + +bool VideoEncoder::EncoderInfo::operator==(const EncoderInfo& rhs) const { + if (scaling_settings.thresholds.has_value() != + rhs.scaling_settings.thresholds.has_value()) { + return false; + } + if (scaling_settings.thresholds.has_value()) { + QpThresholds l = *scaling_settings.thresholds; + QpThresholds r = *rhs.scaling_settings.thresholds; + if (l.low != r.low || l.high != r.high) { + return false; + } + } + if (scaling_settings.min_pixels_per_frame != + rhs.scaling_settings.min_pixels_per_frame) { + return false; + } + + if (supports_native_handle != rhs.supports_native_handle || + implementation_name != rhs.implementation_name || + has_trusted_rate_controller != rhs.has_trusted_rate_controller || + is_hardware_accelerated != rhs.is_hardware_accelerated) { + return false; + } + + for (size_t i = 0; i < kMaxSpatialLayers; ++i) { + if (fps_allocation[i] != rhs.fps_allocation[i]) { + return false; + } + } + + if (resolution_bitrate_limits != rhs.resolution_bitrate_limits || + supports_simulcast != rhs.supports_simulcast) { + return false; + } + + return true; +} + +absl::optional<VideoEncoder::ResolutionBitrateLimits> +VideoEncoder::EncoderInfo::GetEncoderBitrateLimitsForResolution( + int frame_size_pixels) const { + std::vector<ResolutionBitrateLimits> bitrate_limits = + resolution_bitrate_limits; + + // Sort the list of bitrate limits by resolution. + sort(bitrate_limits.begin(), bitrate_limits.end(), + [](const ResolutionBitrateLimits& lhs, + const ResolutionBitrateLimits& rhs) { + return lhs.frame_size_pixels < rhs.frame_size_pixels; + }); + + for (size_t i = 0; i < bitrate_limits.size(); ++i) { + RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 0); + RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 0); + RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, + bitrate_limits[i].min_bitrate_bps); + if (i > 0) { + // The bitrate limits aren't expected to decrease with resolution. + RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, + bitrate_limits[i - 1].min_bitrate_bps); + RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, + bitrate_limits[i - 1].min_start_bitrate_bps); + RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, + bitrate_limits[i - 1].max_bitrate_bps); + } + + if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels) { + return absl::optional<ResolutionBitrateLimits>(bitrate_limits[i]); + } + } + + return absl::nullopt; +} + +VideoEncoder::RateControlParameters::RateControlParameters() + : bitrate(VideoBitrateAllocation()), + framerate_fps(0.0), + bandwidth_allocation(DataRate::Zero()) {} + +VideoEncoder::RateControlParameters::RateControlParameters( + const VideoBitrateAllocation& bitrate, + double framerate_fps) + : bitrate(bitrate), + framerate_fps(framerate_fps), + bandwidth_allocation(DataRate::BitsPerSec(bitrate.get_sum_bps())) {} + +VideoEncoder::RateControlParameters::RateControlParameters( + const VideoBitrateAllocation& bitrate, + double framerate_fps, + DataRate bandwidth_allocation) + : bitrate(bitrate), + framerate_fps(framerate_fps), + bandwidth_allocation(bandwidth_allocation) {} + +bool VideoEncoder::RateControlParameters::operator==( + const VideoEncoder::RateControlParameters& rhs) const { + return std::tie(bitrate, framerate_fps, bandwidth_allocation) == + std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation); +} + +bool VideoEncoder::RateControlParameters::operator!=( + const VideoEncoder::RateControlParameters& rhs) const { + return !(rhs == *this); +} + +VideoEncoder::RateControlParameters::~RateControlParameters() = default; + +void VideoEncoder::SetFecControllerOverride( + FecControllerOverride* fec_controller_override) {} + +int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings, + int32_t number_of_cores, + size_t max_payload_size) { + const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false); + const VideoEncoder::Settings settings(capabilities, number_of_cores, + max_payload_size); + // In theory, this and the other version of InitEncode() could end up calling + // each other in a loop until we get a stack overflow. + // In practice, any subclass of VideoEncoder would overload at least one + // of these, and we have a TODO in the header file to make this pure virtual. + return InitEncode(codec_settings, settings); +} + +int VideoEncoder::InitEncode(const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings) { + // In theory, this and the other version of InitEncode() could end up calling + // each other in a loop until we get a stack overflow. + // In practice, any subclass of VideoEncoder would overload at least one + // of these, and we have a TODO in the header file to make this pure virtual. + return InitEncode(codec_settings, settings.number_of_cores, + settings.max_payload_size); +} + +void VideoEncoder::OnPacketLossRateUpdate(float packet_loss_rate) {} + +void VideoEncoder::OnRttUpdate(int64_t rtt_ms) {} + +void VideoEncoder::OnLossNotification( + const LossNotification& loss_notification) {} + +} // namespace webrtc |