Guard against redefining a PT within a single codec list.
Bug: webrtc:360058654 Change-Id: I433031a11f40a70cedc3862edb3eee4e94ddbdc9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366563 Reviewed-by: Florent Castelli <orphis@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43318}
This commit is contained in:
parent
c4f61fbde3
commit
75a106672e
@ -394,6 +394,7 @@ rtc_library("payload_type_picker") {
|
|||||||
"../api/audio_codecs:audio_codecs_api",
|
"../api/audio_codecs:audio_codecs_api",
|
||||||
"../media:codec",
|
"../media:codec",
|
||||||
"../media:media_constants",
|
"../media:media_constants",
|
||||||
|
"../rtc_base:checks",
|
||||||
"../rtc_base:logging",
|
"../rtc_base:logging",
|
||||||
"../rtc_base:strong_alias",
|
"../rtc_base:strong_alias",
|
||||||
"//third_party/abseil-cpp/absl/strings",
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include "media/base/codec.h"
|
#include "media/base/codec.h"
|
||||||
#include "media/base/codec_comparators.h"
|
#include "media/base/codec_comparators.h"
|
||||||
#include "media/base/media_constants.h"
|
#include "media/base/media_constants.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -178,6 +179,17 @@ RTCError PayloadTypeRecorder::AddMapping(PayloadType payload_type,
|
|||||||
auto existing_codec_it = payload_type_to_codec_.find(payload_type);
|
auto existing_codec_it = payload_type_to_codec_.find(payload_type);
|
||||||
if (existing_codec_it != payload_type_to_codec_.end() &&
|
if (existing_codec_it != payload_type_to_codec_.end() &&
|
||||||
!MatchesWithCodecRules(codec, existing_codec_it->second)) {
|
!MatchesWithCodecRules(codec, existing_codec_it->second)) {
|
||||||
|
// Redefinition attempted.
|
||||||
|
if (disallow_redefinition_level_ > 0) {
|
||||||
|
if (accepted_definitions_.count(payload_type) > 0) {
|
||||||
|
// We have already defined this PT in this scope.
|
||||||
|
RTC_LOG(LS_WARNING)
|
||||||
|
<< "Rejected attempt to redefine mapping for PT " << payload_type
|
||||||
|
<< " from " << existing_codec_it->second << " to " << codec;
|
||||||
|
return RTCError(RTCErrorType::INVALID_MODIFICATION,
|
||||||
|
"Attempt to redefine a codec mapping");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (absl::EqualsIgnoreCase(codec.name, existing_codec_it->second.name)) {
|
if (absl::EqualsIgnoreCase(codec.name, existing_codec_it->second.name)) {
|
||||||
// The difference is in clock rate, channels or FMTP parameters.
|
// The difference is in clock rate, channels or FMTP parameters.
|
||||||
RTC_LOG(LS_INFO) << "Warning: Attempt to change a codec's parameters";
|
RTC_LOG(LS_INFO) << "Warning: Attempt to change a codec's parameters";
|
||||||
@ -185,15 +197,17 @@ RTCError PayloadTypeRecorder::AddMapping(PayloadType payload_type,
|
|||||||
// This is done in production today, so we can't return an error.
|
// This is done in production today, so we can't return an error.
|
||||||
} else {
|
} else {
|
||||||
RTC_LOG(LS_WARNING) << "Warning: You attempted to redefine a codec from "
|
RTC_LOG(LS_WARNING) << "Warning: You attempted to redefine a codec from "
|
||||||
<< existing_codec_it->second.ToString() << " to "
|
<< existing_codec_it->second << " to "
|
||||||
<< " new codec " << codec.ToString();
|
<< " new codec " << codec;
|
||||||
// This is a spec violation.
|
// This is a spec violation.
|
||||||
// TODO: https://issues.webrtc.org/41480892 - return an error.
|
// TODO: https://issues.webrtc.org/41480892 - return an error.
|
||||||
}
|
}
|
||||||
// Accept redefinition.
|
// Accept redefinition.
|
||||||
|
accepted_definitions_.emplace(payload_type);
|
||||||
payload_type_to_codec_.insert_or_assign(payload_type, codec);
|
payload_type_to_codec_.insert_or_assign(payload_type, codec);
|
||||||
return RTCError::OK();
|
return RTCError::OK();
|
||||||
}
|
}
|
||||||
|
accepted_definitions_.emplace(payload_type);
|
||||||
payload_type_to_codec_.emplace(payload_type, codec);
|
payload_type_to_codec_.emplace(payload_type, codec);
|
||||||
suggester_.AddMapping(payload_type, codec);
|
suggester_.AddMapping(payload_type, codec);
|
||||||
return RTCError::OK();
|
return RTCError::OK();
|
||||||
@ -229,6 +243,18 @@ RTCErrorOr<cricket::Codec> PayloadTypeRecorder::LookupCodec(
|
|||||||
return result->second;
|
return result->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PayloadTypeRecorder::DisallowRedefinition() {
|
||||||
|
if (disallow_redefinition_level_ == 0) {
|
||||||
|
accepted_definitions_.clear();
|
||||||
|
}
|
||||||
|
++disallow_redefinition_level_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayloadTypeRecorder::ReallowRedefinition() {
|
||||||
|
RTC_CHECK(disallow_redefinition_level_ > 0);
|
||||||
|
--disallow_redefinition_level_;
|
||||||
|
}
|
||||||
|
|
||||||
void PayloadTypeRecorder::Commit() {
|
void PayloadTypeRecorder::Commit() {
|
||||||
checkpoint_payload_type_to_codec_ = payload_type_to_codec_;
|
checkpoint_payload_type_to_codec_ = payload_type_to_codec_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "api/rtc_error.h"
|
#include "api/rtc_error.h"
|
||||||
#include "media/base/codec.h"
|
|
||||||
#include "call/payload_type.h"
|
#include "call/payload_type.h"
|
||||||
|
#include "media/base/codec.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -57,11 +58,23 @@ class PayloadTypeRecorder {
|
|||||||
public:
|
public:
|
||||||
explicit PayloadTypeRecorder(PayloadTypePicker& suggester)
|
explicit PayloadTypeRecorder(PayloadTypePicker& suggester)
|
||||||
: suggester_(suggester) {}
|
: suggester_(suggester) {}
|
||||||
|
~PayloadTypeRecorder() {
|
||||||
|
// Ensure consistent use of paired Disallow/ReallowRedefintion calls.
|
||||||
|
RTC_DCHECK(disallow_redefinition_level_ == 0);
|
||||||
|
}
|
||||||
|
|
||||||
RTCError AddMapping(PayloadType payload_type, cricket::Codec codec);
|
RTCError AddMapping(PayloadType payload_type, cricket::Codec codec);
|
||||||
std::vector<std::pair<PayloadType, cricket::Codec>> GetMappings() const;
|
std::vector<std::pair<PayloadType, cricket::Codec>> GetMappings() const;
|
||||||
RTCErrorOr<PayloadType> LookupPayloadType(cricket::Codec codec) const;
|
RTCErrorOr<PayloadType> LookupPayloadType(cricket::Codec codec) const;
|
||||||
RTCErrorOr<cricket::Codec> LookupCodec(PayloadType payload_type) const;
|
RTCErrorOr<cricket::Codec> LookupCodec(PayloadType payload_type) const;
|
||||||
|
// Redefinition guard.
|
||||||
|
// In some scenarios, redefinition must be allowed between one offer/answer
|
||||||
|
// set and the next offer/answer set, but within the processing of one
|
||||||
|
// SDP, it should never be allowed.
|
||||||
|
// Implemented as a stack push/pop for convenience; if Disallow has
|
||||||
|
// been called more times than Reallow, redefinition is prohibited.
|
||||||
|
void DisallowRedefinition();
|
||||||
|
void ReallowRedefinition();
|
||||||
// Transaction support.
|
// Transaction support.
|
||||||
// Commit() commits previous changes.
|
// Commit() commits previous changes.
|
||||||
void Commit();
|
void Commit();
|
||||||
@ -72,6 +85,8 @@ class PayloadTypeRecorder {
|
|||||||
PayloadTypePicker& suggester_;
|
PayloadTypePicker& suggester_;
|
||||||
std::map<PayloadType, cricket::Codec> payload_type_to_codec_;
|
std::map<PayloadType, cricket::Codec> payload_type_to_codec_;
|
||||||
std::map<PayloadType, cricket::Codec> checkpoint_payload_type_to_codec_;
|
std::map<PayloadType, cricket::Codec> checkpoint_payload_type_to_codec_;
|
||||||
|
int disallow_redefinition_level_ = 0;
|
||||||
|
std::set<PayloadType> accepted_definitions_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -67,6 +67,24 @@ TEST(PayloadTypePicker, ModifyingPtIsIgnored) {
|
|||||||
EXPECT_EQ(result.value(), b_codec);
|
EXPECT_EQ(result.value(), b_codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PayloadTypePicker, ModifyingPtIsAnErrorIfDisallowed) {
|
||||||
|
PayloadTypePicker picker;
|
||||||
|
PayloadTypeRecorder recorder(picker);
|
||||||
|
const PayloadType a_payload_type(123);
|
||||||
|
cricket::Codec a_codec =
|
||||||
|
cricket::CreateVideoCodec(cricket::Codec::kIdNotSet, "vp8");
|
||||||
|
cricket::Codec b_codec =
|
||||||
|
cricket::CreateVideoCodec(cricket::Codec::kIdNotSet, "vp9");
|
||||||
|
recorder.DisallowRedefinition();
|
||||||
|
recorder.AddMapping(a_payload_type, a_codec);
|
||||||
|
auto error = recorder.AddMapping(a_payload_type, b_codec);
|
||||||
|
EXPECT_FALSE(error.ok());
|
||||||
|
auto result = recorder.LookupCodec(a_payload_type);
|
||||||
|
// Attempted redefinition should be ignored.
|
||||||
|
EXPECT_EQ(result.value(), a_codec);
|
||||||
|
recorder.ReallowRedefinition();
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PayloadTypePicker, RollbackAndCommit) {
|
TEST(PayloadTypePicker, RollbackAndCommit) {
|
||||||
PayloadTypePicker picker;
|
PayloadTypePicker picker;
|
||||||
PayloadTypeRecorder recorder(picker);
|
PayloadTypeRecorder recorder(picker);
|
||||||
|
|||||||
@ -377,18 +377,28 @@ webrtc::RTCError JsepTransport::RecordPayloadTypes(bool local,
|
|||||||
webrtc::SdpType type,
|
webrtc::SdpType type,
|
||||||
const ContentInfo& content) {
|
const ContentInfo& content) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread_);
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
|
if (local) {
|
||||||
|
local_payload_types_.DisallowRedefinition();
|
||||||
|
} else {
|
||||||
|
remote_payload_types_.DisallowRedefinition();
|
||||||
|
}
|
||||||
|
webrtc::RTCError result = webrtc::RTCError::OK();
|
||||||
for (auto codec : content.media_description()->codecs()) {
|
for (auto codec : content.media_description()->codecs()) {
|
||||||
webrtc::RTCError result;
|
|
||||||
if (local) {
|
if (local) {
|
||||||
result = local_payload_types_.AddMapping(codec.id, codec);
|
result = local_payload_types_.AddMapping(codec.id, codec);
|
||||||
} else {
|
} else {
|
||||||
result = remote_payload_types_.AddMapping(codec.id, codec);
|
result = remote_payload_types_.AddMapping(codec.id, codec);
|
||||||
}
|
}
|
||||||
if (!result.ok()) {
|
if (!result.ok()) {
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return webrtc::RTCError::OK();
|
if (local) {
|
||||||
|
local_payload_types_.ReallowRedefinition();
|
||||||
|
} else {
|
||||||
|
remote_payload_types_.ReallowRedefinition();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsepTransport::SetRemoteIceParameters(
|
void JsepTransport::SetRemoteIceParameters(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user