| /* | |
| * Copyright (c) 2025 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/transport/rtp/corruption_detection_message.h" | |
| #include <optional> | |
| #include <span> | |
| #include <utility> | |
| #include "api/video/corruption_detection/frame_instrumentation_data.h" | |
| #include "rtc_base/checks.h" | |
| namespace webrtc { | |
| namespace { | |
| constexpr double kMaxStdDev = 40.0; | |
| constexpr int kMaxErrorThreshold = 15; | |
| } // namespace | |
| CorruptionDetectionMessage | |
| CorruptionDetectionMessage::FromFrameInstrumentationData( | |
| const FrameInstrumentationData& frame_instrumentation) { | |
| int transmitted_sequence_index = | |
| frame_instrumentation.holds_upper_bits() | |
| ? frame_instrumentation.sequence_index() >> 7 | |
| : (frame_instrumentation.sequence_index() & 0b0111'1111); | |
| Builder builder; | |
| builder.WithSequenceIndex(transmitted_sequence_index) | |
| .WithInterpretSequenceIndexAsMostSignificantBits( | |
| frame_instrumentation.holds_upper_bits()); | |
| if (!frame_instrumentation.is_sync_only()) { | |
| builder.WithStdDev(frame_instrumentation.std_dev()) | |
| .WithLumaErrorThreshold(frame_instrumentation.luma_error_threshold()) | |
| .WithChromaErrorThreshold( | |
| frame_instrumentation.chroma_error_threshold()) | |
| .WithSampleValues(frame_instrumentation.sample_values()); | |
| } | |
| // The setter values of `FrameInstrumentationData` has already validated the | |
| // values, so this should never return nullopt; | |
| std::optional<CorruptionDetectionMessage> message = builder.Build(); | |
| RTC_DCHECK(message.has_value()); | |
| return std::move(*message); | |
| } | |
| std::optional<CorruptionDetectionMessage> | |
| CorruptionDetectionMessage::Builder::Build() { | |
| if (message_.sequence_index_ < 0 || message_.sequence_index_ > 0b0111'1111) { | |
| return std::nullopt; | |
| } | |
| if (message_.std_dev_ < 0.0 || message_.std_dev_ > kMaxStdDev) { | |
| return std::nullopt; | |
| } | |
| if (message_.luma_error_threshold_ < 0 || | |
| message_.luma_error_threshold_ > kMaxErrorThreshold) { | |
| return std::nullopt; | |
| } | |
| if (message_.chroma_error_threshold_ < 0 || | |
| message_.chroma_error_threshold_ > kMaxErrorThreshold) { | |
| return std::nullopt; | |
| } | |
| if (message_.sample_values_.size() > kMaxSampleSize) { | |
| return std::nullopt; | |
| } | |
| for (double sample_value : message_.sample_values_) { | |
| if (sample_value < 0.0 || sample_value > 255.0) { | |
| return std::nullopt; | |
| } | |
| } | |
| return message_; | |
| } | |
| CorruptionDetectionMessage::Builder& | |
| CorruptionDetectionMessage::Builder::WithSequenceIndex(int sequence_index) { | |
| message_.sequence_index_ = sequence_index; | |
| return *this; | |
| } | |
| CorruptionDetectionMessage::Builder& CorruptionDetectionMessage::Builder:: | |
| WithInterpretSequenceIndexAsMostSignificantBits( | |
| bool interpret_sequence_index_as_most_significant_bits) { | |
| message_.interpret_sequence_index_as_most_significant_bits_ = | |
| interpret_sequence_index_as_most_significant_bits; | |
| return *this; | |
| } | |
| CorruptionDetectionMessage::Builder& | |
| CorruptionDetectionMessage::Builder::WithStdDev(double std_dev) { | |
| message_.std_dev_ = std_dev; | |
| return *this; | |
| } | |
| CorruptionDetectionMessage::Builder& | |
| CorruptionDetectionMessage::Builder::WithLumaErrorThreshold( | |
| int luma_error_threshold) { | |
| message_.luma_error_threshold_ = luma_error_threshold; | |
| return *this; | |
| } | |
| CorruptionDetectionMessage::Builder& | |
| CorruptionDetectionMessage::Builder::WithChromaErrorThreshold( | |
| int chroma_error_threshold) { | |
| message_.chroma_error_threshold_ = chroma_error_threshold; | |
| return *this; | |
| } | |
| CorruptionDetectionMessage::Builder& | |
| CorruptionDetectionMessage::Builder::WithSampleValues( | |
| const std::span<const double>& sample_values) { | |
| message_.sample_values_.assign(sample_values.begin(), sample_values.end()); | |
| return *this; | |
| } | |
| } // namespace webrtc |