Bug: webrtc:358039777 Change-Id: Ic27e162d67c64958844908cdd8413c406e88ea39 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/375201 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Fanny Linderborg <linderborg@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43804}
140 lines
5.0 KiB
C++
140 lines
5.0 KiB
C++
/*
|
|
* Copyright 2024 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 "common_video/corruption_detection_converters.h"
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include "api/transport/rtp/corruption_detection_message.h"
|
|
#include "common_video/frame_instrumentation_data.h"
|
|
#include "rtc_base/checks.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
int GetFullSequenceIndex(int previous_sequence_index,
|
|
int sequence_index_update,
|
|
bool update_the_most_significant_bits) {
|
|
RTC_CHECK_GE(previous_sequence_index, 0)
|
|
<< "previous_sequence_index must not be negative";
|
|
RTC_CHECK_LE(previous_sequence_index, 0x7FFF)
|
|
<< "previous_sequence_index must be at most 15 bits";
|
|
RTC_CHECK_GE(sequence_index_update, 0)
|
|
<< "sequence_index_update must not be negative";
|
|
RTC_CHECK_LE(sequence_index_update, 0b0111'1111)
|
|
<< "sequence_index_update must be at most 7 bits";
|
|
if (update_the_most_significant_bits) {
|
|
// Reset LSB.
|
|
return sequence_index_update << 7;
|
|
}
|
|
int upper_bits = previous_sequence_index & 0b0011'1111'1000'0000;
|
|
if (sequence_index_update < (previous_sequence_index & 0b0111'1111)) {
|
|
// Assume one and only one wraparound has happened.
|
|
upper_bits += 0b1000'0000;
|
|
}
|
|
// Replace the lowest bits with the bits from the update.
|
|
return upper_bits + sequence_index_update;
|
|
}
|
|
|
|
int GetSequenceIndexForMessage(int sequence_index,
|
|
bool communicate_upper_bits) {
|
|
return communicate_upper_bits ? (sequence_index >> 7)
|
|
: (sequence_index & 0b0111'1111);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::optional<FrameInstrumentationData>
|
|
ConvertCorruptionDetectionMessageToFrameInstrumentationData(
|
|
const CorruptionDetectionMessage& message,
|
|
int previous_sequence_index) {
|
|
if (previous_sequence_index < 0) {
|
|
return std::nullopt;
|
|
}
|
|
if (message.sample_values().empty()) {
|
|
return std::nullopt;
|
|
}
|
|
int full_sequence_index = GetFullSequenceIndex(
|
|
previous_sequence_index, message.sequence_index(),
|
|
message.interpret_sequence_index_as_most_significant_bits());
|
|
std::vector<double> sample_values(message.sample_values().cbegin(),
|
|
message.sample_values().cend());
|
|
return FrameInstrumentationData{
|
|
.sequence_index = full_sequence_index,
|
|
.communicate_upper_bits =
|
|
message.interpret_sequence_index_as_most_significant_bits(),
|
|
.std_dev = message.std_dev(),
|
|
.luma_error_threshold = message.luma_error_threshold(),
|
|
.chroma_error_threshold = message.chroma_error_threshold(),
|
|
.sample_values = sample_values};
|
|
}
|
|
|
|
std::optional<FrameInstrumentationSyncData>
|
|
ConvertCorruptionDetectionMessageToFrameInstrumentationSyncData(
|
|
const CorruptionDetectionMessage& message,
|
|
int previous_sequence_index) {
|
|
if (previous_sequence_index < 0) {
|
|
return std::nullopt;
|
|
}
|
|
if (!message.sample_values().empty()) {
|
|
return std::nullopt;
|
|
}
|
|
if (!message.interpret_sequence_index_as_most_significant_bits()) {
|
|
return std::nullopt;
|
|
}
|
|
return FrameInstrumentationSyncData{
|
|
.sequence_index = GetFullSequenceIndex(
|
|
previous_sequence_index, message.sequence_index(),
|
|
/*update_the_most_significant_bits=*/true),
|
|
.communicate_upper_bits = true};
|
|
}
|
|
|
|
std::optional<CorruptionDetectionMessage>
|
|
ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
|
|
const FrameInstrumentationData& data) {
|
|
if (data.sequence_index < 0 || data.sequence_index > 0b0011'1111'1111'1111) {
|
|
return std::nullopt;
|
|
}
|
|
// Frame instrumentation data must have sample values.
|
|
if (data.sample_values.empty()) {
|
|
return std::nullopt;
|
|
}
|
|
return CorruptionDetectionMessage::Builder()
|
|
.WithSequenceIndex(GetSequenceIndexForMessage(
|
|
data.sequence_index, data.communicate_upper_bits))
|
|
.WithInterpretSequenceIndexAsMostSignificantBits(
|
|
data.communicate_upper_bits)
|
|
.WithStdDev(data.std_dev)
|
|
.WithLumaErrorThreshold(data.luma_error_threshold)
|
|
.WithChromaErrorThreshold(data.chroma_error_threshold)
|
|
.WithSampleValues(data.sample_values)
|
|
.Build();
|
|
}
|
|
|
|
std::optional<CorruptionDetectionMessage>
|
|
ConvertFrameInstrumentationSyncDataToCorruptionDetectionMessage(
|
|
const FrameInstrumentationSyncData& data) {
|
|
RTC_DCHECK(data.communicate_upper_bits)
|
|
<< "FrameInstrumentationSyncData data must always send the upper bits.";
|
|
|
|
if (data.sequence_index < 0 || data.sequence_index > 0b0011'1111'1111'1111) {
|
|
return std::nullopt;
|
|
}
|
|
return CorruptionDetectionMessage::Builder()
|
|
.WithSequenceIndex(GetSequenceIndexForMessage(
|
|
data.sequence_index, data.communicate_upper_bits))
|
|
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
|
.Build();
|
|
}
|
|
|
|
} // namespace webrtc
|