Use Payload Type suggester for all codec merging
Bug: webrtc:360058654 Change-Id: Id475762253c427c1800c2352a60fc0121c2dc388 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/364783 Reviewed-by: Florent Castelli <orphis@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43267}
This commit is contained in:
parent
cdc38b9b4e
commit
0bac2aae59
@ -801,6 +801,17 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("fake_payload_type_suggester") {
|
||||||
|
testonly = true
|
||||||
|
sources = [ "fake_payload_type_suggester.h" ]
|
||||||
|
deps = [
|
||||||
|
":payload_type",
|
||||||
|
":payload_type_picker",
|
||||||
|
"../api:rtc_error",
|
||||||
|
"../media:codec",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_library("fake_network_pipe_unittests") {
|
rtc_library("fake_network_pipe_unittests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
|
|
||||||
|
|||||||
@ -70,5 +70,8 @@ specific_include_rules = {
|
|||||||
],
|
],
|
||||||
"call\.cc": [
|
"call\.cc": [
|
||||||
"+media/base/codec.h",
|
"+media/base/codec.h",
|
||||||
|
],
|
||||||
|
"fake_payload_type_suggester": [
|
||||||
|
"+media/base/codec.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
45
call/fake_payload_type_suggester.h
Normal file
45
call/fake_payload_type_suggester.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALL_FAKE_PAYLOAD_TYPE_SUGGESTER_H_
|
||||||
|
#define CALL_FAKE_PAYLOAD_TYPE_SUGGESTER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "api/rtc_error.h"
|
||||||
|
#include "call/payload_type.h"
|
||||||
|
#include "call/payload_type_picker.h"
|
||||||
|
#include "media/base/codec.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
// Fake payload type suggester, for use in tests.
|
||||||
|
// It uses a real PayloadTypePicker in order to do consistent PT
|
||||||
|
// assignment.
|
||||||
|
class FakePayloadTypeSuggester : public webrtc::PayloadTypeSuggester {
|
||||||
|
public:
|
||||||
|
webrtc::RTCErrorOr<webrtc::PayloadType> SuggestPayloadType(
|
||||||
|
const std::string& mid,
|
||||||
|
cricket::Codec codec) override {
|
||||||
|
// Ignores mid argument.
|
||||||
|
return pt_picker_.SuggestMapping(codec, nullptr);
|
||||||
|
}
|
||||||
|
webrtc::RTCError AddLocalMapping(const std::string& mid,
|
||||||
|
webrtc::PayloadType payload_type,
|
||||||
|
const cricket::Codec& codec) override {
|
||||||
|
return webrtc::RTCError::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
webrtc::PayloadTypePicker pt_picker_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // CALL_FAKE_PAYLOAD_TYPE_SUGGESTER_H_
|
||||||
@ -26,11 +26,24 @@ class PayloadType : public StrongAlias<class PayloadTypeTag, uint8_t> {
|
|||||||
// removed once calling code is upgraded.
|
// removed once calling code is upgraded.
|
||||||
PayloadType(uint8_t pt) { value_ = pt; } // NOLINT: explicit
|
PayloadType(uint8_t pt) { value_ = pt; } // NOLINT: explicit
|
||||||
constexpr operator uint8_t() const& { return value_; } // NOLINT: Explicit
|
constexpr operator uint8_t() const& { return value_; } // NOLINT: Explicit
|
||||||
|
static bool IsValid(PayloadType id, bool rtcp_mux) {
|
||||||
|
if (rtcp_mux && (id > 63 && id < 96)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return id >= 0 && id <= 127;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Does not compile either within or after class
|
||||||
|
// static const PayloadType kFirstDynamicPayloadTypeUpperRange{96};
|
||||||
|
// static const PayloadType kLastDynamicPayloadTypeUpperRange{127};
|
||||||
|
// static const PayloadType kFirstDynamicPayloadTypeLowerRange{35};
|
||||||
|
// static const PayloadType kLastDynamicPayloadTypeLowerRange{63};
|
||||||
|
|
||||||
class PayloadTypeSuggester {
|
class PayloadTypeSuggester {
|
||||||
public:
|
public:
|
||||||
virtual ~PayloadTypeSuggester() = default;
|
virtual ~PayloadTypeSuggester() = default;
|
||||||
|
|
||||||
// Suggest a payload type for a given codec on a given media section.
|
// Suggest a payload type for a given codec on a given media section.
|
||||||
// Media section is indicated by MID.
|
// Media section is indicated by MID.
|
||||||
// The function will either return a PT already in use on the connection
|
// The function will either return a PT already in use on the connection
|
||||||
|
|||||||
@ -140,10 +140,11 @@ RTCErrorOr<PayloadType> PayloadTypePicker::SuggestMapping(
|
|||||||
// The first matching entry is returned, unless excluder
|
// The first matching entry is returned, unless excluder
|
||||||
// maps it to something different.
|
// maps it to something different.
|
||||||
for (auto entry : entries_) {
|
for (auto entry : entries_) {
|
||||||
if (MatchesWithCodecRules(entry.codec(), codec)) {
|
if (MatchesWithReferenceAttributes(entry.codec(), codec)) {
|
||||||
if (excluder) {
|
if (excluder) {
|
||||||
auto result = excluder->LookupCodec(entry.payload_type());
|
auto result = excluder->LookupCodec(entry.payload_type());
|
||||||
if (result.ok() && !MatchesWithCodecRules(result.value(), codec)) {
|
if (result.ok() &&
|
||||||
|
!MatchesWithReferenceAttributes(result.value(), codec)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +165,7 @@ RTCError PayloadTypePicker::AddMapping(PayloadType payload_type,
|
|||||||
// Multiple mappings for the same codec and the same PT are legal;
|
// Multiple mappings for the same codec and the same PT are legal;
|
||||||
for (auto entry : entries_) {
|
for (auto entry : entries_) {
|
||||||
if (payload_type == entry.payload_type() &&
|
if (payload_type == entry.payload_type() &&
|
||||||
MatchesWithCodecRules(codec, entry.codec())) {
|
MatchesWithReferenceAttributes(codec, entry.codec())) {
|
||||||
return RTCError::OK();
|
return RTCError::OK();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@ RTCError PayloadTypeRecorder::AddMapping(PayloadType payload_type,
|
|||||||
cricket::Codec codec) {
|
cricket::Codec codec) {
|
||||||
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)) {
|
!MatchesWithReferenceAttributes(codec, existing_codec_it->second)) {
|
||||||
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,8 +186,8 @@ 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.
|
||||||
}
|
}
|
||||||
@ -211,7 +212,7 @@ RTCErrorOr<PayloadType> PayloadTypeRecorder::LookupPayloadType(
|
|||||||
auto result =
|
auto result =
|
||||||
std::find_if(payload_type_to_codec_.begin(), payload_type_to_codec_.end(),
|
std::find_if(payload_type_to_codec_.begin(), payload_type_to_codec_.end(),
|
||||||
[codec](const auto& iter) {
|
[codec](const auto& iter) {
|
||||||
return MatchesWithCodecRules(iter.second, codec);
|
return MatchesWithReferenceAttributes(iter.second, codec);
|
||||||
});
|
});
|
||||||
if (result == payload_type_to_codec_.end()) {
|
if (result == payload_type_to_codec_.end()) {
|
||||||
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
||||||
|
|||||||
@ -818,6 +818,7 @@ if (rtc_include_tests) {
|
|||||||
"../api/video:video_rtp_headers",
|
"../api/video:video_rtp_headers",
|
||||||
"../api/video_codecs:video_codecs_api",
|
"../api/video_codecs:video_codecs_api",
|
||||||
"../call:call_interfaces",
|
"../call:call_interfaces",
|
||||||
|
"../call:fake_payload_type_suggester",
|
||||||
"../call:mock_rtp_interfaces",
|
"../call:mock_rtp_interfaces",
|
||||||
"../call:payload_type",
|
"../call:payload_type",
|
||||||
"../call:payload_type_picker",
|
"../call:payload_type_picker",
|
||||||
|
|||||||
@ -25,6 +25,9 @@ specific_include_rules = {
|
|||||||
".*webrtc_video_engine\.h": [
|
".*webrtc_video_engine\.h": [
|
||||||
"+video/config",
|
"+video/config",
|
||||||
],
|
],
|
||||||
|
".*webrtc_video_engine\.cc": [
|
||||||
|
"+video/config",
|
||||||
|
],
|
||||||
".*media_channel\.h": [
|
".*media_channel\.h": [
|
||||||
"+video/config",
|
"+video/config",
|
||||||
],
|
],
|
||||||
|
|||||||
@ -278,6 +278,11 @@ bool MatchesWithCodecRules(const Codec& left_codec, const Codec& right_codec) {
|
|||||||
return matches_id && matches_type_specific();
|
return matches_id && matches_type_specific();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MatchesWithReferenceAttributes(const Codec& codec1, const Codec& codec2) {
|
||||||
|
return MatchesWithReferenceAttributesAndComparator(
|
||||||
|
codec1, codec2, [](int a, int b) { return a == b; });
|
||||||
|
}
|
||||||
|
|
||||||
// Finds a codec in `codecs2` that matches `codec_to_match`, which is
|
// Finds a codec in `codecs2` that matches `codec_to_match`, which is
|
||||||
// a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both
|
// a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both
|
||||||
// the codecs themselves and their associated codecs must match.
|
// the codecs themselves and their associated codecs must match.
|
||||||
|
|||||||
@ -18,14 +18,15 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Comparison used in the PayloadTypePicker
|
|
||||||
bool MatchesForSdp(const cricket::Codec& codec_1,
|
|
||||||
const cricket::Codec& codec_2);
|
|
||||||
|
|
||||||
// Comparison used for the Codec::Matches function
|
// Comparison used for the Codec::Matches function
|
||||||
bool MatchesWithCodecRules(const cricket::Codec& left_codec,
|
bool MatchesWithCodecRules(const cricket::Codec& left_codec,
|
||||||
const cricket::Codec& codec);
|
const cricket::Codec& codec);
|
||||||
|
|
||||||
|
// Comparison that also checks on codecs referenced by PT in the
|
||||||
|
// fmtp line, as used with RED and RTX "codecs".
|
||||||
|
bool MatchesWithReferenceAttributes(const cricket::Codec& left_codec,
|
||||||
|
const cricket::Codec& right_codec);
|
||||||
|
|
||||||
// Finds a codec in `codecs2` that matches `codec_to_match`, which is
|
// Finds a codec in `codecs2` that matches `codec_to_match`, which is
|
||||||
// a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both
|
// a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both
|
||||||
// the codecs themselves and their associated codecs must match.
|
// the codecs themselves and their associated codecs must match.
|
||||||
|
|||||||
@ -37,7 +37,6 @@
|
|||||||
#include "api/environment/environment.h"
|
#include "api/environment/environment.h"
|
||||||
#include "api/frame_transformer_interface.h"
|
#include "api/frame_transformer_interface.h"
|
||||||
#include "api/media_types.h"
|
#include "api/media_types.h"
|
||||||
#include "api/rtc_error.h"
|
|
||||||
#include "api/rtp_headers.h"
|
#include "api/rtp_headers.h"
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
#include "api/rtp_sender_interface.h"
|
#include "api/rtp_sender_interface.h"
|
||||||
@ -54,15 +53,14 @@
|
|||||||
#include "call/audio_receive_stream.h"
|
#include "call/audio_receive_stream.h"
|
||||||
#include "call/audio_send_stream.h"
|
#include "call/audio_send_stream.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
|
#include "call/fake_payload_type_suggester.h"
|
||||||
#include "call/flexfec_receive_stream.h"
|
#include "call/flexfec_receive_stream.h"
|
||||||
#include "call/packet_receiver.h"
|
#include "call/packet_receiver.h"
|
||||||
#include "call/payload_type.h"
|
#include "call/payload_type.h"
|
||||||
#include "call/payload_type_picker.h"
|
|
||||||
#include "call/rtp_transport_controller_send_interface.h"
|
#include "call/rtp_transport_controller_send_interface.h"
|
||||||
#include "call/test/mock_rtp_transport_controller_send.h"
|
#include "call/test/mock_rtp_transport_controller_send.h"
|
||||||
#include "call/video_receive_stream.h"
|
#include "call/video_receive_stream.h"
|
||||||
#include "call/video_send_stream.h"
|
#include "call/video_send_stream.h"
|
||||||
#include "media/base/codec.h"
|
|
||||||
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
#include "rtc_base/buffer.h"
|
#include "rtc_base/buffer.h"
|
||||||
@ -395,26 +393,6 @@ class FakeFlexfecReceiveStream final : public webrtc::FlexfecReceiveStream {
|
|||||||
webrtc::FlexfecReceiveStream::Config config_;
|
webrtc::FlexfecReceiveStream::Config config_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fake payload type suggester.
|
|
||||||
// This is injected into FakeCall at initialization.
|
|
||||||
class FakePayloadTypeSuggester : public webrtc::PayloadTypeSuggester {
|
|
||||||
public:
|
|
||||||
webrtc::RTCErrorOr<webrtc::PayloadType> SuggestPayloadType(
|
|
||||||
const std::string& mid,
|
|
||||||
cricket::Codec codec) override {
|
|
||||||
// Ignores mid argument.
|
|
||||||
return pt_picker_.SuggestMapping(codec, nullptr);
|
|
||||||
}
|
|
||||||
webrtc::RTCError AddLocalMapping(const std::string& mid,
|
|
||||||
webrtc::PayloadType payload_type,
|
|
||||||
const cricket::Codec& codec) override {
|
|
||||||
return webrtc::RTCError::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
webrtc::PayloadTypePicker pt_picker_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
||||||
public:
|
public:
|
||||||
explicit FakeCall(const webrtc::Environment& env);
|
explicit FakeCall(const webrtc::Environment& env);
|
||||||
@ -558,7 +536,7 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
|||||||
int num_created_send_streams_;
|
int num_created_send_streams_;
|
||||||
int num_created_receive_streams_;
|
int num_created_receive_streams_;
|
||||||
|
|
||||||
FakePayloadTypeSuggester pt_suggester_;
|
webrtc::FakePayloadTypeSuggester pt_suggester_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cricket
|
} // namespace cricket
|
||||||
|
|||||||
@ -14,28 +14,46 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/algorithm/container.h"
|
#include "absl/algorithm/container.h"
|
||||||
#include "absl/container/inlined_vector.h"
|
|
||||||
#include "absl/functional/bind_front.h"
|
#include "absl/functional/bind_front.h"
|
||||||
#include "absl/strings/match.h"
|
#include "absl/strings/match.h"
|
||||||
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "api/array_view.h"
|
||||||
|
#include "api/crypto/crypto_options.h"
|
||||||
|
#include "api/crypto/frame_decryptor_interface.h"
|
||||||
|
#include "api/field_trials_view.h"
|
||||||
|
#include "api/frame_transformer_interface.h"
|
||||||
#include "api/make_ref_counted.h"
|
#include "api/make_ref_counted.h"
|
||||||
#include "api/media_stream_interface.h"
|
#include "api/media_stream_interface.h"
|
||||||
#include "api/media_types.h"
|
#include "api/media_types.h"
|
||||||
#include "api/priority.h"
|
#include "api/priority.h"
|
||||||
#include "api/rtc_error.h"
|
#include "api/rtc_error.h"
|
||||||
|
#include "api/rtp_headers.h"
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
|
#include "api/rtp_sender_interface.h"
|
||||||
#include "api/rtp_transceiver_direction.h"
|
#include "api/rtp_transceiver_direction.h"
|
||||||
|
#include "api/scoped_refptr.h"
|
||||||
|
#include "api/sequence_checker.h"
|
||||||
|
#include "api/task_queue/pending_task_safety_flag.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
|
#include "api/transport/rtp/rtp_source.h"
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
#include "api/video/resolution.h"
|
#include "api/video/recordable_encoded_frame.h"
|
||||||
|
#include "api/video/video_bitrate_allocator_factory.h"
|
||||||
#include "api/video/video_codec_type.h"
|
#include "api/video/video_codec_type.h"
|
||||||
|
#include "api/video/video_sink_interface.h"
|
||||||
|
#include "api/video/video_source_interface.h"
|
||||||
#include "api/video_codecs/scalability_mode.h"
|
#include "api/video_codecs/scalability_mode.h"
|
||||||
#include "api/video_codecs/sdp_video_format.h"
|
#include "api/video_codecs/sdp_video_format.h"
|
||||||
#include "api/video_codecs/video_codec.h"
|
#include "api/video_codecs/video_codec.h"
|
||||||
@ -43,23 +61,29 @@
|
|||||||
#include "api/video_codecs/video_encoder.h"
|
#include "api/video_codecs/video_encoder.h"
|
||||||
#include "api/video_codecs/video_encoder_factory.h"
|
#include "api/video_codecs/video_encoder_factory.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
|
#include "call/flexfec_receive_stream.h"
|
||||||
#include "call/packet_receiver.h"
|
#include "call/packet_receiver.h"
|
||||||
#include "call/receive_stream.h"
|
#include "call/receive_stream.h"
|
||||||
#include "call/rtp_config.h"
|
#include "call/rtp_config.h"
|
||||||
#include "call/rtp_transport_controller_send_interface.h"
|
#include "call/rtp_transport_controller_send_interface.h"
|
||||||
|
#include "call/video_receive_stream.h"
|
||||||
#include "call/video_send_stream.h"
|
#include "call/video_send_stream.h"
|
||||||
#include "common_video/frame_counts.h"
|
#include "common_video/frame_counts.h"
|
||||||
#include "common_video/include/quality_limitation_reason.h"
|
|
||||||
#include "media/base/codec.h"
|
#include "media/base/codec.h"
|
||||||
#include "media/base/media_channel.h"
|
#include "media/base/media_channel.h"
|
||||||
|
#include "media/base/media_channel_impl.h"
|
||||||
|
#include "media/base/media_config.h"
|
||||||
#include "media/base/media_constants.h"
|
#include "media/base/media_constants.h"
|
||||||
|
#include "media/base/media_engine.h"
|
||||||
#include "media/base/rid_description.h"
|
#include "media/base/rid_description.h"
|
||||||
#include "media/base/rtp_utils.h"
|
#include "media/base/rtp_utils.h"
|
||||||
|
#include "media/base/stream_params.h"
|
||||||
#include "media/engine/webrtc_media_engine.h"
|
#include "media/engine/webrtc_media_engine.h"
|
||||||
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
|
||||||
#include "modules/rtp_rtcp/include/rtcp_statistics.h"
|
#include "modules/rtp_rtcp/include/rtcp_statistics.h"
|
||||||
|
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
|
||||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_util.h"
|
#include "modules/rtp_rtcp/source/rtp_util.h"
|
||||||
#include "modules/video_coding/svc/scalability_mode_util.h"
|
#include "modules/video_coding/svc/scalability_mode_util.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
@ -68,8 +92,10 @@
|
|||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/socket.h"
|
#include "rtc_base/socket.h"
|
||||||
#include "rtc_base/strings/string_builder.h"
|
#include "rtc_base/strings/string_builder.h"
|
||||||
|
#include "rtc_base/synchronization/mutex.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
#include "rtc_base/trace_event.h"
|
#include "rtc_base/trace_event.h"
|
||||||
|
#include "video/config/video_encoder_config.h"
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
|
|
||||||
@ -583,8 +609,7 @@ std::vector<VideoCodecSettings> MapCodecs(const std::vector<Codec>& codecs) {
|
|||||||
const int payload_type = in_codec.id;
|
const int payload_type = in_codec.id;
|
||||||
|
|
||||||
if (payload_codec_type.find(payload_type) != payload_codec_type.end()) {
|
if (payload_codec_type.find(payload_type) != payload_codec_type.end()) {
|
||||||
RTC_LOG(LS_ERROR) << "Payload type already registered: "
|
RTC_LOG(LS_ERROR) << "Payload type already registered: " << in_codec;
|
||||||
<< in_codec.ToString();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
payload_codec_type[payload_type] = in_codec.GetResiliencyType();
|
payload_codec_type[payload_type] = in_codec.GetResiliencyType();
|
||||||
|
|||||||
@ -2025,6 +2025,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||||
"../api/video:recordable_encoded_frame",
|
"../api/video:recordable_encoded_frame",
|
||||||
"../api/video/test:mock_recordable_encoded_frame",
|
"../api/video/test:mock_recordable_encoded_frame",
|
||||||
|
"../call:fake_payload_type_suggester",
|
||||||
"../call:payload_type_picker",
|
"../call:payload_type_picker",
|
||||||
"../call:rtp_interfaces",
|
"../call:rtp_interfaces",
|
||||||
"../call:rtp_receiver",
|
"../call:rtp_receiver",
|
||||||
@ -2565,6 +2566,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../api:ice_transport_interface",
|
"../api:ice_transport_interface",
|
||||||
"../api:libjingle_logging_api",
|
"../api:libjingle_logging_api",
|
||||||
"../api:libjingle_peerconnection_api",
|
"../api:libjingle_peerconnection_api",
|
||||||
|
"../api:make_ref_counted",
|
||||||
"../api:media_stream_interface",
|
"../api:media_stream_interface",
|
||||||
"../api:mock_async_dns_resolver",
|
"../api:mock_async_dns_resolver",
|
||||||
"../api:mock_rtp",
|
"../api:mock_rtp",
|
||||||
@ -2575,6 +2577,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../api:rtp_sender_interface",
|
"../api:rtp_sender_interface",
|
||||||
"../api:rtp_transceiver_direction",
|
"../api:rtp_transceiver_direction",
|
||||||
"../api:scoped_refptr",
|
"../api:scoped_refptr",
|
||||||
|
"../api:sequence_checker",
|
||||||
"../api/audio:audio_device",
|
"../api/audio:audio_device",
|
||||||
"../api/audio:audio_mixer_api",
|
"../api/audio:audio_mixer_api",
|
||||||
"../api/audio:audio_processing",
|
"../api/audio:audio_processing",
|
||||||
@ -2582,6 +2585,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../api/crypto:frame_decryptor_interface",
|
"../api/crypto:frame_decryptor_interface",
|
||||||
"../api/crypto:frame_encryptor_interface",
|
"../api/crypto:frame_encryptor_interface",
|
||||||
"../api/crypto:options",
|
"../api/crypto:options",
|
||||||
|
"../api/metronome",
|
||||||
"../api/rtc_event_log",
|
"../api/rtc_event_log",
|
||||||
"../api/rtc_event_log:rtc_event_log_factory",
|
"../api/rtc_event_log:rtc_event_log_factory",
|
||||||
"../api/task_queue",
|
"../api/task_queue",
|
||||||
@ -2628,6 +2632,8 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../rtc_base:rtc_json",
|
"../rtc_base:rtc_json",
|
||||||
"../rtc_base:safe_conversions",
|
"../rtc_base:safe_conversions",
|
||||||
"../rtc_base:socket_address",
|
"../rtc_base:socket_address",
|
||||||
|
"../rtc_base:socket_factory",
|
||||||
|
"../rtc_base:socket_server",
|
||||||
"../rtc_base:ssl",
|
"../rtc_base:ssl",
|
||||||
"../rtc_base:ssl_adapter",
|
"../rtc_base:ssl_adapter",
|
||||||
"../rtc_base:task_queue_for_test",
|
"../rtc_base:task_queue_for_test",
|
||||||
@ -2645,6 +2651,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
|||||||
"../test/pc/sctp:fake_sctp_transport",
|
"../test/pc/sctp:fake_sctp_transport",
|
||||||
"../test/time_controller",
|
"../test/time_controller",
|
||||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||||
|
"//third_party/abseil-cpp/absl/functional:any_invocable",
|
||||||
"//third_party/abseil-cpp/absl/memory",
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -495,7 +495,6 @@ webrtc::RTCError AssignCodecIdsAndLinkRed(
|
|||||||
char buffer[100];
|
char buffer[100];
|
||||||
rtc::SimpleStringBuilder param(buffer);
|
rtc::SimpleStringBuilder param(buffer);
|
||||||
param << opus_codec << "/" << opus_codec;
|
param << opus_codec << "/" << opus_codec;
|
||||||
RTC_LOG(LS_ERROR) << "DEBUG: Setting RED param to " << param.str();
|
|
||||||
codec.SetParam(kCodecParamNotInNameValueFormat, param.str());
|
codec.SetParam(kCodecParamNotInNameValueFormat, param.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,9 +640,10 @@ const Codec* GetAssociatedCodecForRed(const std::vector<Codec>& codec_list,
|
|||||||
// Adds all codecs from `reference_codecs` to `offered_codecs` that don't
|
// Adds all codecs from `reference_codecs` to `offered_codecs` that don't
|
||||||
// already exist in `offered_codecs` and ensure the payload types don't
|
// already exist in `offered_codecs` and ensure the payload types don't
|
||||||
// collide.
|
// collide.
|
||||||
void MergeCodecs(const std::vector<Codec>& reference_codecs,
|
webrtc::RTCError MergeCodecs(const std::vector<Codec>& reference_codecs,
|
||||||
std::vector<Codec>* offered_codecs,
|
std::vector<Codec>* offered_codecs,
|
||||||
UsedPayloadTypes* used_pltypes) {
|
std::string mid,
|
||||||
|
webrtc::PayloadTypeSuggester& pt_suggester) {
|
||||||
// Add all new codecs that are not RTX/RED codecs.
|
// Add all new codecs that are not RTX/RED codecs.
|
||||||
// The two-pass splitting of the loops means preferring payload types
|
// The two-pass splitting of the loops means preferring payload types
|
||||||
// of actual codecs with respect to collisions.
|
// of actual codecs with respect to collisions.
|
||||||
@ -653,7 +653,11 @@ void MergeCodecs(const std::vector<Codec>& reference_codecs,
|
|||||||
!webrtc::FindMatchingCodec(reference_codecs, *offered_codecs,
|
!webrtc::FindMatchingCodec(reference_codecs, *offered_codecs,
|
||||||
reference_codec)) {
|
reference_codec)) {
|
||||||
Codec codec = reference_codec;
|
Codec codec = reference_codec;
|
||||||
used_pltypes->FindAndSetIdUsed(&codec);
|
auto id_or_error = pt_suggester.SuggestPayloadType(mid, codec);
|
||||||
|
if (!id_or_error.ok()) {
|
||||||
|
return id_or_error.MoveError();
|
||||||
|
}
|
||||||
|
codec.id = id_or_error.value();
|
||||||
offered_codecs->push_back(codec);
|
offered_codecs->push_back(codec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -681,15 +685,35 @@ void MergeCodecs(const std::vector<Codec>& reference_codecs,
|
|||||||
|
|
||||||
rtx_codec.params[kCodecParamAssociatedPayloadType] =
|
rtx_codec.params[kCodecParamAssociatedPayloadType] =
|
||||||
rtc::ToString(matching_codec->id);
|
rtc::ToString(matching_codec->id);
|
||||||
used_pltypes->FindAndSetIdUsed(&rtx_codec);
|
auto id_or_error = pt_suggester.SuggestPayloadType(mid, rtx_codec);
|
||||||
|
if (!id_or_error.ok()) {
|
||||||
|
return id_or_error.MoveError();
|
||||||
|
}
|
||||||
|
rtx_codec.id = id_or_error.value();
|
||||||
offered_codecs->push_back(rtx_codec);
|
offered_codecs->push_back(rtx_codec);
|
||||||
} else if (reference_codec.GetResiliencyType() ==
|
} else if (reference_codec.GetResiliencyType() ==
|
||||||
Codec::ResiliencyType::kRed &&
|
Codec::ResiliencyType::kRed &&
|
||||||
!webrtc::FindMatchingCodec(reference_codecs, *offered_codecs,
|
!webrtc::FindMatchingCodec(reference_codecs, *offered_codecs,
|
||||||
reference_codec)) {
|
reference_codec)) {
|
||||||
Codec red_codec = reference_codec;
|
Codec red_codec = reference_codec;
|
||||||
const Codec* associated_codec =
|
const Codec* associated_codec = nullptr;
|
||||||
GetAssociatedCodecForRed(reference_codecs, red_codec);
|
// Special case: For voice RED, if parameter is not set, look for
|
||||||
|
// OPUS as the matching codec.
|
||||||
|
// This is because we add the RED codec in audio engine init, but
|
||||||
|
// can't set the parameter until PTs are assigned.
|
||||||
|
if (red_codec.type == Codec::Type::kAudio &&
|
||||||
|
red_codec.params.find(kCodecParamNotInNameValueFormat) ==
|
||||||
|
red_codec.params.end()) {
|
||||||
|
for (const Codec& codec : reference_codecs) {
|
||||||
|
if (absl::EqualsIgnoreCase(codec.name, kOpusCodecName)) {
|
||||||
|
associated_codec = &codec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
associated_codec =
|
||||||
|
GetAssociatedCodecForRed(reference_codecs, red_codec);
|
||||||
|
}
|
||||||
if (associated_codec) {
|
if (associated_codec) {
|
||||||
std::optional<Codec> matching_codec = webrtc::FindMatchingCodec(
|
std::optional<Codec> matching_codec = webrtc::FindMatchingCodec(
|
||||||
reference_codecs, *offered_codecs, *associated_codec);
|
reference_codecs, *offered_codecs, *associated_codec);
|
||||||
@ -703,10 +727,15 @@ void MergeCodecs(const std::vector<Codec>& reference_codecs,
|
|||||||
rtc::ToString(matching_codec->id) + "/" +
|
rtc::ToString(matching_codec->id) + "/" +
|
||||||
rtc::ToString(matching_codec->id);
|
rtc::ToString(matching_codec->id);
|
||||||
}
|
}
|
||||||
used_pltypes->FindAndSetIdUsed(&red_codec);
|
auto id_or_error = pt_suggester.SuggestPayloadType(mid, red_codec);
|
||||||
|
if (!id_or_error.ok()) {
|
||||||
|
return id_or_error.MoveError();
|
||||||
|
}
|
||||||
|
red_codec.id = id_or_error.value();
|
||||||
offered_codecs->push_back(red_codec);
|
offered_codecs->push_back(red_codec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return webrtc::RTCError::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
// `codecs` is a full list of codecs with correct payload type mappings, which
|
// `codecs` is a full list of codecs with correct payload type mappings, which
|
||||||
@ -795,20 +824,28 @@ std::vector<Codec> MatchCodecPreference(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute the union of `codecs1` and `codecs2`.
|
// Compute the union of `codecs1` and `codecs2`.
|
||||||
std::vector<Codec> ComputeCodecsUnion(const std::vector<Codec>& codecs1,
|
webrtc::RTCErrorOr<std::vector<Codec>> ComputeCodecsUnion(
|
||||||
const std::vector<Codec>& codecs2) {
|
const std::vector<Codec>& codecs1,
|
||||||
|
const std::vector<Codec>& codecs2,
|
||||||
|
std::string mid,
|
||||||
|
webrtc::PayloadTypeSuggester& pt_suggester) {
|
||||||
std::vector<Codec> all_codecs;
|
std::vector<Codec> all_codecs;
|
||||||
UsedPayloadTypes used_payload_types;
|
|
||||||
for (const Codec& codec : codecs1) {
|
for (const Codec& codec : codecs1) {
|
||||||
Codec codec_mutable = codec;
|
Codec codec_mutable = codec;
|
||||||
used_payload_types.FindAndSetIdUsed(&codec_mutable);
|
auto id_or_error = pt_suggester.SuggestPayloadType(mid, codec);
|
||||||
|
if (!id_or_error.ok()) {
|
||||||
|
return id_or_error.MoveError();
|
||||||
|
}
|
||||||
|
codec_mutable.id = id_or_error.value();
|
||||||
all_codecs.push_back(codec_mutable);
|
all_codecs.push_back(codec_mutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use MergeCodecs to merge the second half of our list as it already checks
|
// Use MergeCodecs to merge the second half of our list as it already checks
|
||||||
// and fixes problems with duplicate payload types.
|
// and fixes problems with duplicate payload types.
|
||||||
MergeCodecs(codecs2, &all_codecs, &used_payload_types);
|
webrtc::RTCError error = MergeCodecs(codecs2, &all_codecs, mid, pt_suggester);
|
||||||
|
if (!error.ok()) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
return all_codecs;
|
return all_codecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1147,7 +1184,8 @@ webrtc::RTCErrorOr<Codecs> GetNegotiatedCodecsForAnswer(
|
|||||||
const MediaSessionOptions& session_options,
|
const MediaSessionOptions& session_options,
|
||||||
const ContentInfo* current_content,
|
const ContentInfo* current_content,
|
||||||
const std::vector<Codec>& codecs,
|
const std::vector<Codec>& codecs,
|
||||||
const std::vector<Codec>& supported_codecs) {
|
const std::vector<Codec>& supported_codecs,
|
||||||
|
webrtc::PayloadTypeSuggester& pt_suggester) {
|
||||||
std::vector<Codec> filtered_codecs;
|
std::vector<Codec> filtered_codecs;
|
||||||
|
|
||||||
if (!media_description_options.codec_preferences.empty()) {
|
if (!media_description_options.codec_preferences.empty()) {
|
||||||
@ -1187,7 +1225,19 @@ webrtc::RTCErrorOr<Codecs> GetNegotiatedCodecsForAnswer(
|
|||||||
|
|
||||||
// Use ComputeCodecsUnion to avoid having duplicate payload IDs.
|
// Use ComputeCodecsUnion to avoid having duplicate payload IDs.
|
||||||
// This is a no-op for audio until RTX is added.
|
// This is a no-op for audio until RTX is added.
|
||||||
filtered_codecs = ComputeCodecsUnion(filtered_codecs, other_codecs);
|
// TODO(hta): figure out why current_content is not always there.
|
||||||
|
std::string mid;
|
||||||
|
if (current_content) {
|
||||||
|
mid = current_content->name;
|
||||||
|
} else {
|
||||||
|
mid = "";
|
||||||
|
}
|
||||||
|
auto codecs_or_error =
|
||||||
|
ComputeCodecsUnion(filtered_codecs, other_codecs, mid, pt_suggester);
|
||||||
|
if (!codecs_or_error.ok()) {
|
||||||
|
return codecs_or_error.MoveError();
|
||||||
|
}
|
||||||
|
filtered_codecs = codecs_or_error.MoveValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media_description_options.type == MEDIA_TYPE_AUDIO &&
|
if (media_description_options.type == MEDIA_TYPE_AUDIO &&
|
||||||
@ -1264,6 +1314,7 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
|
|||||||
transport_desc_factory_->trials().IsEnabled(
|
transport_desc_factory_->trials().IsEnabled(
|
||||||
"WebRTC-PayloadTypesInTransport")) {
|
"WebRTC-PayloadTypesInTransport")) {
|
||||||
RTC_CHECK(transport_desc_factory_);
|
RTC_CHECK(transport_desc_factory_);
|
||||||
|
RTC_CHECK(pt_suggester_);
|
||||||
if (media_engine) {
|
if (media_engine) {
|
||||||
audio_send_codecs_ = media_engine->voice().send_codecs();
|
audio_send_codecs_ = media_engine->voice().send_codecs();
|
||||||
audio_recv_codecs_ = media_engine->voice().recv_codecs();
|
audio_recv_codecs_ = media_engine->voice().recv_codecs();
|
||||||
@ -1726,20 +1777,29 @@ const Codecs& MediaSessionDescriptionFactory::GetVideoCodecsForAnswer(
|
|||||||
RTC_CHECK_NOTREACHED();
|
RTC_CHECK_NOTREACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeCodecsFromDescription(
|
webrtc::RTCError MergeCodecsFromDescription(
|
||||||
const std::vector<const ContentInfo*>& current_active_contents,
|
const std::vector<const ContentInfo*>& current_active_contents,
|
||||||
Codecs* audio_codecs,
|
Codecs* audio_codecs,
|
||||||
Codecs* video_codecs,
|
Codecs* video_codecs,
|
||||||
UsedPayloadTypes* used_pltypes) {
|
webrtc::PayloadTypeSuggester& pt_suggester) {
|
||||||
for (const ContentInfo* content : current_active_contents) {
|
for (const ContentInfo* content : current_active_contents) {
|
||||||
if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
|
if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
|
||||||
MergeCodecs(content->media_description()->codecs(), audio_codecs,
|
webrtc::RTCError error =
|
||||||
used_pltypes);
|
MergeCodecs(content->media_description()->codecs(), audio_codecs,
|
||||||
|
content->name, pt_suggester);
|
||||||
|
if (!error.ok()) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
} else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) {
|
} else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) {
|
||||||
MergeCodecs(content->media_description()->codecs(), video_codecs,
|
webrtc::RTCError error =
|
||||||
used_pltypes);
|
MergeCodecs(content->media_description()->codecs(), video_codecs,
|
||||||
|
content->name, pt_suggester);
|
||||||
|
if (!error.ok()) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return webrtc::RTCError::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting codecs for an offer involves these steps:
|
// Getting codecs for an offer involves these steps:
|
||||||
@ -1755,13 +1815,15 @@ void MediaSessionDescriptionFactory::GetCodecsForOffer(
|
|||||||
// First - get all codecs from the current description if the media type
|
// First - get all codecs from the current description if the media type
|
||||||
// is used. Add them to `used_pltypes` so the payload type is not reused if a
|
// is used. Add them to `used_pltypes` so the payload type is not reused if a
|
||||||
// new media type is added.
|
// new media type is added.
|
||||||
UsedPayloadTypes used_pltypes;
|
webrtc::RTCError error = MergeCodecsFromDescription(
|
||||||
MergeCodecsFromDescription(current_active_contents, audio_codecs,
|
current_active_contents, audio_codecs, video_codecs, *pt_suggester_);
|
||||||
video_codecs, &used_pltypes);
|
RTC_CHECK(error.ok());
|
||||||
|
|
||||||
// Add our codecs that are not in the current description.
|
// Add our codecs that are not in the current description.
|
||||||
MergeCodecs(all_audio_codecs_, audio_codecs, &used_pltypes);
|
error = MergeCodecs(all_audio_codecs_, audio_codecs, "", *pt_suggester_);
|
||||||
MergeCodecs(all_video_codecs_, video_codecs, &used_pltypes);
|
RTC_CHECK(error.ok());
|
||||||
|
error = MergeCodecs(all_video_codecs_, video_codecs, "", *pt_suggester_);
|
||||||
|
RTC_CHECK(error.ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getting codecs for an answer involves these steps:
|
// Getting codecs for an answer involves these steps:
|
||||||
@ -1779,9 +1841,9 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
|
|||||||
// First - get all codecs from the current description if the media type
|
// First - get all codecs from the current description if the media type
|
||||||
// is used. Add them to `used_pltypes` so the payload type is not reused if a
|
// is used. Add them to `used_pltypes` so the payload type is not reused if a
|
||||||
// new media type is added.
|
// new media type is added.
|
||||||
UsedPayloadTypes used_pltypes;
|
webrtc::RTCError error = MergeCodecsFromDescription(
|
||||||
MergeCodecsFromDescription(current_active_contents, audio_codecs,
|
current_active_contents, audio_codecs, video_codecs, *pt_suggester_);
|
||||||
video_codecs, &used_pltypes);
|
RTC_CHECK(error.ok());
|
||||||
|
|
||||||
// Second - filter out codecs that we don't support at all and should ignore.
|
// Second - filter out codecs that we don't support at all and should ignore.
|
||||||
Codecs filtered_offered_audio_codecs;
|
Codecs filtered_offered_audio_codecs;
|
||||||
@ -1814,8 +1876,12 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
|
|||||||
|
|
||||||
// Add codecs that are not in the current description but were in
|
// Add codecs that are not in the current description but were in
|
||||||
// `remote_offer`.
|
// `remote_offer`.
|
||||||
MergeCodecs(filtered_offered_audio_codecs, audio_codecs, &used_pltypes);
|
error = MergeCodecs(filtered_offered_audio_codecs, audio_codecs, "",
|
||||||
MergeCodecs(filtered_offered_video_codecs, video_codecs, &used_pltypes);
|
*pt_suggester_);
|
||||||
|
RTC_CHECK(error.ok());
|
||||||
|
error = MergeCodecs(filtered_offered_video_codecs, video_codecs, "",
|
||||||
|
*pt_suggester_);
|
||||||
|
RTC_CHECK(error.ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaSessionDescriptionFactory::AudioVideoRtpHeaderExtensions
|
MediaSessionDescriptionFactory::AudioVideoRtpHeaderExtensions
|
||||||
@ -2123,7 +2189,8 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForAnswer(
|
|||||||
: GetVideoCodecsForAnswer(offer_rtd, answer_rtd);
|
: GetVideoCodecsForAnswer(offer_rtd, answer_rtd);
|
||||||
webrtc::RTCErrorOr<std::vector<Codec>> error_or_filtered_codecs =
|
webrtc::RTCErrorOr<std::vector<Codec>> error_or_filtered_codecs =
|
||||||
GetNegotiatedCodecsForAnswer(media_description_options, session_options,
|
GetNegotiatedCodecsForAnswer(media_description_options, session_options,
|
||||||
current_content, codecs, supported_codecs);
|
current_content, codecs, supported_codecs,
|
||||||
|
*pt_suggester_);
|
||||||
if (!error_or_filtered_codecs.ok()) {
|
if (!error_or_filtered_codecs.ok()) {
|
||||||
return error_or_filtered_codecs.MoveError();
|
return error_or_filtered_codecs.MoveError();
|
||||||
}
|
}
|
||||||
@ -2345,9 +2412,10 @@ void MediaSessionDescriptionFactory::ComputeVideoCodecsIntersectionAndUnion() {
|
|||||||
video_sendrecv_codecs_.clear();
|
video_sendrecv_codecs_.clear();
|
||||||
|
|
||||||
// Use ComputeCodecsUnion to avoid having duplicate payload IDs
|
// Use ComputeCodecsUnion to avoid having duplicate payload IDs
|
||||||
all_video_codecs_ =
|
auto error_or_codecs = ComputeCodecsUnion(
|
||||||
ComputeCodecsUnion(video_recv_codecs_, video_send_codecs_);
|
video_recv_codecs_, video_send_codecs_, "", *pt_suggester_);
|
||||||
|
RTC_CHECK(error_or_codecs.ok());
|
||||||
|
all_video_codecs_ = error_or_codecs.MoveValue();
|
||||||
// Use NegotiateCodecs to merge our codec lists, since the operation is
|
// Use NegotiateCodecs to merge our codec lists, since the operation is
|
||||||
// essentially the same. Put send_codecs as the offered_codecs, which is the
|
// essentially the same. Put send_codecs as the offered_codecs, which is the
|
||||||
// order we'd like to follow. The reasoning is that encoding is usually more
|
// order we'd like to follow. The reasoning is that encoding is usually more
|
||||||
|
|||||||
@ -23,11 +23,13 @@
|
|||||||
#include "absl/algorithm/container.h"
|
#include "absl/algorithm/container.h"
|
||||||
#include "absl/strings/match.h"
|
#include "absl/strings/match.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "api/array_view.h"
|
||||||
#include "api/audio_codecs/audio_format.h"
|
#include "api/audio_codecs/audio_format.h"
|
||||||
#include "api/candidate.h"
|
#include "api/candidate.h"
|
||||||
#include "api/media_types.h"
|
#include "api/media_types.h"
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
#include "api/rtp_transceiver_direction.h"
|
#include "api/rtp_transceiver_direction.h"
|
||||||
|
#include "call/fake_payload_type_suggester.h"
|
||||||
#include "media/base/codec.h"
|
#include "media/base/codec.h"
|
||||||
#include "media/base/media_constants.h"
|
#include "media/base/media_constants.h"
|
||||||
#include "media/base/rid_description.h"
|
#include "media/base/rid_description.h"
|
||||||
@ -117,6 +119,26 @@ const Codec kVideoCodecs2[] = {CreateVideoCodec(126, "H264"),
|
|||||||
|
|
||||||
const Codec kVideoCodecsAnswer[] = {CreateVideoCodec(97, "H264")};
|
const Codec kVideoCodecsAnswer[] = {CreateVideoCodec(97, "H264")};
|
||||||
|
|
||||||
|
// Match two codec lists for content, but ignore the ID.
|
||||||
|
bool CodecListsMatch(rtc::ArrayView<const Codec> list1,
|
||||||
|
rtc::ArrayView<const Codec> list2) {
|
||||||
|
if (list1.size() != list2.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < list1.size(); ++i) {
|
||||||
|
Codec codec1 = list1[i];
|
||||||
|
Codec codec2 = list2[i];
|
||||||
|
codec1.id = Codec::kIdNotSet;
|
||||||
|
codec2.id = Codec::kIdNotSet;
|
||||||
|
if (codec1 != codec2) {
|
||||||
|
RTC_LOG(LS_ERROR) << "Mismatch at position " << i << " between " << codec1
|
||||||
|
<< " and " << codec2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const RtpExtension kAudioRtpExtension1[] = {
|
const RtpExtension kAudioRtpExtension1[] = {
|
||||||
RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
|
RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
|
||||||
RtpExtension("http://google.com/testing/audio_something", 10),
|
RtpExtension("http://google.com/testing/audio_something", 10),
|
||||||
@ -438,8 +460,8 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
|
|||||||
MediaSessionDescriptionFactoryTest()
|
MediaSessionDescriptionFactoryTest()
|
||||||
: tdf1_(field_trials),
|
: tdf1_(field_trials),
|
||||||
tdf2_(field_trials),
|
tdf2_(field_trials),
|
||||||
f1_(nullptr, false, &ssrc_generator1, &tdf1_, nullptr),
|
f1_(nullptr, false, &ssrc_generator1, &tdf1_, &pt_suggester_1_),
|
||||||
f2_(nullptr, false, &ssrc_generator2, &tdf2_, nullptr) {
|
f2_(nullptr, false, &ssrc_generator2, &tdf2_, &pt_suggester_2_) {
|
||||||
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
|
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
|
||||||
MAKE_VECTOR(kAudioCodecs1));
|
MAKE_VECTOR(kAudioCodecs1));
|
||||||
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
|
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
|
||||||
@ -688,6 +710,8 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
|
|||||||
UniqueRandomIdGenerator ssrc_generator2;
|
UniqueRandomIdGenerator ssrc_generator2;
|
||||||
TransportDescriptionFactory tdf1_;
|
TransportDescriptionFactory tdf1_;
|
||||||
TransportDescriptionFactory tdf2_;
|
TransportDescriptionFactory tdf2_;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester_1_;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester_2_;
|
||||||
MediaSessionDescriptionFactory f1_;
|
MediaSessionDescriptionFactory f1_;
|
||||||
MediaSessionDescriptionFactory f2_;
|
MediaSessionDescriptionFactory f2_;
|
||||||
};
|
};
|
||||||
@ -2947,11 +2971,11 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
|
|
||||||
const AudioContentDescription* updated_acd =
|
const AudioContentDescription* updated_acd =
|
||||||
GetFirstAudioContentDescription(updated_offer.get());
|
GetFirstAudioContentDescription(updated_offer.get());
|
||||||
EXPECT_THAT(updated_acd->codecs(), ElementsAreArray(kUpdatedAudioCodecOffer));
|
EXPECT_TRUE(CodecListsMatch(updated_acd->codecs(), kUpdatedAudioCodecOffer));
|
||||||
|
|
||||||
const VideoContentDescription* updated_vcd =
|
const VideoContentDescription* updated_vcd =
|
||||||
GetFirstVideoContentDescription(updated_offer.get());
|
GetFirstVideoContentDescription(updated_offer.get());
|
||||||
EXPECT_THAT(updated_vcd->codecs(), ElementsAreArray(kUpdatedVideoCodecOffer));
|
EXPECT_TRUE(CodecListsMatch(updated_vcd->codecs(), kUpdatedVideoCodecOffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a reoffer does not reuse audio codecs from a previous media section
|
// Test that a reoffer does not reuse audio codecs from a previous media section
|
||||||
@ -2979,7 +3003,13 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
// section was not recycled the payload types would match the initial offerer.
|
// section was not recycled the payload types would match the initial offerer.
|
||||||
const AudioContentDescription* acd =
|
const AudioContentDescription* acd =
|
||||||
GetFirstAudioContentDescription(reoffer.get());
|
GetFirstAudioContentDescription(reoffer.get());
|
||||||
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecs2));
|
// EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecs2)),
|
||||||
|
// except that we don't want to check the PT numbers.
|
||||||
|
EXPECT_EQ(acd->codecs().size(),
|
||||||
|
sizeof(kAudioCodecs2) / sizeof(kAudioCodecs2[0]));
|
||||||
|
for (size_t i = 0; i < acd->codecs().size(); ++i) {
|
||||||
|
EXPECT_EQ(acd->codecs()[i].name, kAudioCodecs2[i].name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a reoffer does not reuse video codecs from a previous media section
|
// Test that a reoffer does not reuse video codecs from a previous media section
|
||||||
@ -3006,7 +3036,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
// section was not recycled the payload types would match the initial offerer.
|
// section was not recycled the payload types would match the initial offerer.
|
||||||
const VideoContentDescription* vcd =
|
const VideoContentDescription* vcd =
|
||||||
GetFirstVideoContentDescription(reoffer.get());
|
GetFirstVideoContentDescription(reoffer.get());
|
||||||
EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecs2));
|
EXPECT_TRUE(CodecListsMatch(vcd->codecs(), kVideoCodecs2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a reanswer does not reuse audio codecs from a previous media
|
// Test that a reanswer does not reuse audio codecs from a previous media
|
||||||
@ -3104,7 +3134,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
|
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
|
||||||
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
||||||
|
|
||||||
EXPECT_EQ(expected_codecs, vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, vcd->codecs()));
|
||||||
|
|
||||||
// Now, make sure we get same result (except for the order) if `f2_` creates
|
// Now, make sure we get same result (except for the order) if `f2_` creates
|
||||||
// an updated offer even though the default payload types between `f1_` and
|
// an updated offer even though the default payload types between `f1_` and
|
||||||
@ -3119,7 +3149,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
const VideoContentDescription* updated_vcd =
|
const VideoContentDescription* updated_vcd =
|
||||||
GetFirstVideoContentDescription(updated_answer.get());
|
GetFirstVideoContentDescription(updated_answer.get());
|
||||||
|
|
||||||
EXPECT_EQ(expected_codecs, updated_vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, updated_vcd->codecs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test for:
|
// Regression test for:
|
||||||
@ -3274,7 +3304,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
// New offer should attempt to add H263, and RTX for H264.
|
// New offer should attempt to add H263, and RTX for H264.
|
||||||
expected_codecs.push_back(kVideoCodecs2[1]);
|
expected_codecs.push_back(kVideoCodecs2[1]);
|
||||||
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[1].id), &expected_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[1].id), &expected_codecs);
|
||||||
EXPECT_EQ(expected_codecs, updated_vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, updated_vcd->codecs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that RTX is ignored when there is no associated payload type parameter.
|
// Test that RTX is ignored when there is no associated payload type parameter.
|
||||||
@ -3383,7 +3413,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
|
|||||||
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
|
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
|
||||||
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
||||||
|
|
||||||
EXPECT_EQ(expected_codecs, vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, vcd->codecs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that after one RTX codec has been negotiated, a new offer can attempt
|
// Test that after one RTX codec has been negotiated, a new offer can attempt
|
||||||
@ -3406,7 +3436,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
|
|||||||
|
|
||||||
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
|
std::vector<Codec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
|
||||||
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(126, kVideoCodecs1[1].id), &expected_codecs);
|
||||||
EXPECT_EQ(expected_codecs, vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, vcd->codecs()));
|
||||||
|
|
||||||
// Now, attempt to add RTX for H264-SVC.
|
// Now, attempt to add RTX for H264-SVC.
|
||||||
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
|
||||||
@ -3418,7 +3448,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
|
|||||||
vcd = GetFirstVideoContentDescription(updated_offer.get());
|
vcd = GetFirstVideoContentDescription(updated_offer.get());
|
||||||
|
|
||||||
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[0].id), &expected_codecs);
|
AddRtxCodec(CreateVideoRtxCodec(125, kVideoCodecs1[0].id), &expected_codecs);
|
||||||
EXPECT_EQ(expected_codecs, vcd->codecs());
|
EXPECT_TRUE(CodecListsMatch(expected_codecs, vcd->codecs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
|
// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
|
||||||
@ -4507,8 +4537,8 @@ class MediaProtocolTest : public testing::TestWithParam<const char*> {
|
|||||||
MediaProtocolTest()
|
MediaProtocolTest()
|
||||||
: tdf1_(field_trials_),
|
: tdf1_(field_trials_),
|
||||||
tdf2_(field_trials_),
|
tdf2_(field_trials_),
|
||||||
f1_(nullptr, false, &ssrc_generator1, &tdf1_, nullptr),
|
f1_(nullptr, false, &ssrc_generator1, &tdf1_, &pt_suggester_1_),
|
||||||
f2_(nullptr, false, &ssrc_generator2, &tdf2_, nullptr) {
|
f2_(nullptr, false, &ssrc_generator2, &tdf2_, &pt_suggester_2_) {
|
||||||
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
|
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
|
||||||
MAKE_VECTOR(kAudioCodecs1));
|
MAKE_VECTOR(kAudioCodecs1));
|
||||||
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
|
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
|
||||||
@ -4527,6 +4557,8 @@ class MediaProtocolTest : public testing::TestWithParam<const char*> {
|
|||||||
webrtc::test::ScopedKeyValueConfig field_trials_;
|
webrtc::test::ScopedKeyValueConfig field_trials_;
|
||||||
TransportDescriptionFactory tdf1_;
|
TransportDescriptionFactory tdf1_;
|
||||||
TransportDescriptionFactory tdf2_;
|
TransportDescriptionFactory tdf2_;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester_1_;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester_2_;
|
||||||
MediaSessionDescriptionFactory f1_;
|
MediaSessionDescriptionFactory f1_;
|
||||||
MediaSessionDescriptionFactory f2_;
|
MediaSessionDescriptionFactory f2_;
|
||||||
UniqueRandomIdGenerator ssrc_generator1;
|
UniqueRandomIdGenerator ssrc_generator1;
|
||||||
@ -4571,8 +4603,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
|
|||||||
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
|
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
|
||||||
|
|
||||||
UniqueRandomIdGenerator ssrc_generator;
|
UniqueRandomIdGenerator ssrc_generator;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester;
|
||||||
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf,
|
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf,
|
||||||
nullptr);
|
&pt_suggester);
|
||||||
std::vector<Codec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
|
std::vector<Codec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
|
||||||
std::vector<Codec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
|
std::vector<Codec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
|
||||||
|
|
||||||
@ -4643,8 +4676,9 @@ void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
|
|||||||
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
|
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id"))));
|
||||||
|
|
||||||
UniqueRandomIdGenerator ssrc_generator;
|
UniqueRandomIdGenerator ssrc_generator;
|
||||||
|
webrtc::FakePayloadTypeSuggester pt_suggester;
|
||||||
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf,
|
MediaSessionDescriptionFactory sf(nullptr, false, &ssrc_generator, &tdf,
|
||||||
nullptr);
|
&pt_suggester);
|
||||||
const std::vector<Codec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
|
const std::vector<Codec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
|
||||||
const std::vector<Codec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
|
const std::vector<Codec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
|
||||||
const std::vector<Codec> sendrecv_codecs = MAKE_VECTOR(kAudioCodecsAnswer);
|
const std::vector<Codec> sendrecv_codecs = MAKE_VECTOR(kAudioCodecsAnswer);
|
||||||
@ -4685,13 +4719,15 @@ void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Codec kOfferAnswerCodecs[] = {CreateAudioCodec(0, "codec0", 16000, 1),
|
// Since the PT suggester reserves the static range for specific codecs,
|
||||||
CreateAudioCodec(1, "codec1", 8000, 1),
|
// PT numbers from the 36-63 range are used.
|
||||||
CreateAudioCodec(2, "codec2", 8000, 1),
|
const Codec kOfferAnswerCodecs[] = {CreateAudioCodec(40, "codec0", 16000, 1),
|
||||||
CreateAudioCodec(3, "codec3", 8000, 1),
|
CreateAudioCodec(41, "codec1", 8000, 1),
|
||||||
CreateAudioCodec(4, "codec4", 8000, 2),
|
CreateAudioCodec(42, "codec2", 8000, 1),
|
||||||
CreateAudioCodec(5, "codec5", 32000, 1),
|
CreateAudioCodec(43, "codec3", 8000, 1),
|
||||||
CreateAudioCodec(6, "codec6", 48000, 1)};
|
CreateAudioCodec(44, "codec4", 8000, 2),
|
||||||
|
CreateAudioCodec(45, "codec5", 32000, 1),
|
||||||
|
CreateAudioCodec(46, "codec6", 48000, 1)};
|
||||||
|
|
||||||
/* The codecs groups below are chosen as per the matrix below. The objective
|
/* The codecs groups below are chosen as per the matrix below. The objective
|
||||||
* is to have different sets of codecs in the inputs, to get unique sets of
|
* is to have different sets of codecs in the inputs, to get unique sets of
|
||||||
@ -4747,10 +4783,12 @@ void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
|
|||||||
rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
||||||
new rtc::FakeSSLIdentity("answer_id"))));
|
new rtc::FakeSSLIdentity("answer_id"))));
|
||||||
UniqueRandomIdGenerator ssrc_generator1, ssrc_generator2;
|
UniqueRandomIdGenerator ssrc_generator1, ssrc_generator2;
|
||||||
|
webrtc::FakePayloadTypeSuggester offer_pt_suggester;
|
||||||
MediaSessionDescriptionFactory offer_factory(nullptr, false, &ssrc_generator1,
|
MediaSessionDescriptionFactory offer_factory(nullptr, false, &ssrc_generator1,
|
||||||
&offer_tdf, nullptr);
|
&offer_tdf, &offer_pt_suggester);
|
||||||
|
webrtc::FakePayloadTypeSuggester answer_pt_suggester;
|
||||||
MediaSessionDescriptionFactory answer_factory(
|
MediaSessionDescriptionFactory answer_factory(
|
||||||
nullptr, false, &ssrc_generator2, &answer_tdf, nullptr);
|
nullptr, false, &ssrc_generator2, &answer_tdf, &answer_pt_suggester);
|
||||||
|
|
||||||
offer_factory.set_audio_codecs(
|
offer_factory.set_audio_codecs(
|
||||||
VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
|
VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
|
||||||
@ -4833,7 +4871,7 @@ void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
|
|||||||
bool first = true;
|
bool first = true;
|
||||||
os << "{";
|
os << "{";
|
||||||
for (const auto& c : codecs) {
|
for (const auto& c : codecs) {
|
||||||
os << (first ? " " : ", ") << c.id;
|
os << (first ? " " : ", ") << c.id << ":" << c.name;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
os << " }";
|
os << " }";
|
||||||
|
|||||||
@ -84,7 +84,6 @@
|
|||||||
#include "pc/stream_collection.h"
|
#include "pc/stream_collection.h"
|
||||||
#include "pc/transceiver_list.h"
|
#include "pc/transceiver_list.h"
|
||||||
#include "pc/usage_pattern.h"
|
#include "pc/usage_pattern.h"
|
||||||
#include "pc/used_ids.h"
|
|
||||||
#include "pc/webrtc_session_description_factory.h"
|
#include "pc/webrtc_session_description_factory.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/crypto_random.h"
|
#include "rtc_base/crypto_random.h"
|
||||||
@ -592,8 +591,7 @@ RTCError ValidatePayloadTypes(const cricket::SessionDescription& description) {
|
|||||||
if (type == cricket::MEDIA_TYPE_AUDIO ||
|
if (type == cricket::MEDIA_TYPE_AUDIO ||
|
||||||
type == cricket::MEDIA_TYPE_VIDEO) {
|
type == cricket::MEDIA_TYPE_VIDEO) {
|
||||||
for (const auto& codec : media_description->codecs()) {
|
for (const auto& codec : media_description->codecs()) {
|
||||||
if (!cricket::UsedPayloadTypes::IsIdValid(
|
if (!PayloadType::IsValid(codec.id, media_description->rtcp_mux())) {
|
||||||
codec, media_description->rtcp_mux())) {
|
|
||||||
LOG_AND_RETURN_ERROR(
|
LOG_AND_RETURN_ERROR(
|
||||||
RTCErrorType::INVALID_PARAMETER,
|
RTCErrorType::INVALID_PARAMETER,
|
||||||
"The media section with MID='" + content.mid() +
|
"The media section with MID='" + content.mid() +
|
||||||
|
|||||||
@ -10,7 +10,37 @@
|
|||||||
|
|
||||||
#include "pc/test/integration_test_helpers.h"
|
#include "pc/test/integration_test_helpers.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/functional/any_invocable.h"
|
||||||
#include "api/audio/builtin_audio_processing_factory.h"
|
#include "api/audio/builtin_audio_processing_factory.h"
|
||||||
|
#include "api/enable_media_with_defaults.h"
|
||||||
|
#include "api/jsep.h"
|
||||||
|
#include "api/peer_connection_interface.h"
|
||||||
|
#include "api/rtc_event_log/rtc_event_log_factory.h"
|
||||||
|
#include "api/sequence_checker.h"
|
||||||
|
#include "api/stats/rtcstats_objects.h"
|
||||||
|
#include "api/task_queue/default_task_queue_factory.h"
|
||||||
|
#include "api/task_queue/pending_task_safety_flag.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
|
#include "api/transport/field_trial_based_config.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
|
#include "logging/rtc_event_log/fake_rtc_event_log_factory.h"
|
||||||
|
#include "p2p/base/basic_packet_socket_factory.h"
|
||||||
|
#include "p2p/base/port_allocator.h"
|
||||||
|
#include "p2p/client/basic_port_allocator.h"
|
||||||
|
#include "pc/peer_connection_factory.h"
|
||||||
|
#include "pc/test/fake_audio_capture_module.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/fake_network.h"
|
||||||
|
#include "rtc_base/socket_server.h"
|
||||||
|
#include "rtc_base/thread.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -27,66 +26,44 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/algorithm/container.h"
|
#include "absl/functional/any_invocable.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "api/audio/audio_device.h"
|
|
||||||
#include "api/audio/audio_processing.h"
|
|
||||||
#include "api/audio_options.h"
|
#include "api/audio_options.h"
|
||||||
#include "api/candidate.h"
|
#include "api/candidate.h"
|
||||||
#include "api/crypto/crypto_options.h"
|
#include "api/crypto/crypto_options.h"
|
||||||
#include "api/data_channel_interface.h"
|
#include "api/data_channel_interface.h"
|
||||||
#include "api/enable_media_with_defaults.h"
|
|
||||||
#include "api/field_trials_view.h"
|
#include "api/field_trials_view.h"
|
||||||
#include "api/ice_transport_interface.h"
|
#include "api/ice_transport_interface.h"
|
||||||
#include "api/jsep.h"
|
#include "api/jsep.h"
|
||||||
|
#include "api/make_ref_counted.h"
|
||||||
#include "api/media_stream_interface.h"
|
#include "api/media_stream_interface.h"
|
||||||
#include "api/media_types.h"
|
#include "api/media_types.h"
|
||||||
|
#include "api/metronome/metronome.h"
|
||||||
#include "api/peer_connection_interface.h"
|
#include "api/peer_connection_interface.h"
|
||||||
#include "api/rtc_error.h"
|
#include "api/rtc_error.h"
|
||||||
#include "api/rtc_event_log/rtc_event_log_factory.h"
|
|
||||||
#include "api/rtc_event_log/rtc_event_log_factory_interface.h"
|
|
||||||
#include "api/rtc_event_log_output.h"
|
#include "api/rtc_event_log_output.h"
|
||||||
#include "api/rtp_receiver_interface.h"
|
#include "api/rtp_receiver_interface.h"
|
||||||
#include "api/rtp_sender_interface.h"
|
#include "api/rtp_sender_interface.h"
|
||||||
#include "api/rtp_transceiver_interface.h"
|
#include "api/rtp_transceiver_interface.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "api/stats/rtc_stats.h"
|
#include "api/sequence_checker.h"
|
||||||
#include "api/stats/rtc_stats_report.h"
|
#include "api/stats/rtc_stats_report.h"
|
||||||
#include "api/stats/rtcstats_objects.h"
|
#include "api/stats/rtcstats_objects.h"
|
||||||
#include "api/task_queue/default_task_queue_factory.h"
|
|
||||||
#include "api/task_queue/pending_task_safety_flag.h"
|
#include "api/task_queue/pending_task_safety_flag.h"
|
||||||
#include "api/task_queue/task_queue_factory.h"
|
|
||||||
#include "api/test/mock_async_dns_resolver.h"
|
#include "api/test/mock_async_dns_resolver.h"
|
||||||
#include "api/transport/field_trial_based_config.h"
|
|
||||||
#include "api/uma_metrics.h"
|
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "api/video/video_rotation.h"
|
#include "api/video/video_rotation.h"
|
||||||
#include "api/video_codecs/sdp_video_format.h"
|
|
||||||
#include "api/video_codecs/video_decoder_factory.h"
|
|
||||||
#include "api/video_codecs/video_encoder_factory.h"
|
|
||||||
#include "call/call.h"
|
|
||||||
#include "logging/rtc_event_log/fake_rtc_event_log_factory.h"
|
#include "logging/rtc_event_log/fake_rtc_event_log_factory.h"
|
||||||
#include "media/base/media_engine.h"
|
|
||||||
#include "media/base/stream_params.h"
|
#include "media/base/stream_params.h"
|
||||||
#include "media/engine/fake_webrtc_video_engine.h"
|
|
||||||
#include "p2p/base/fake_ice_transport.h"
|
#include "p2p/base/fake_ice_transport.h"
|
||||||
#include "p2p/base/ice_transport_internal.h"
|
#include "p2p/base/ice_transport_internal.h"
|
||||||
#include "p2p/base/p2p_constants.h"
|
|
||||||
#include "p2p/base/port.h"
|
#include "p2p/base/port.h"
|
||||||
#include "p2p/base/port_allocator.h"
|
#include "p2p/base/port_allocator.h"
|
||||||
#include "p2p/base/port_interface.h"
|
#include "p2p/base/port_interface.h"
|
||||||
#include "p2p/base/test_stun_server.h"
|
|
||||||
#include "p2p/base/test_turn_customizer.h"
|
#include "p2p/base/test_turn_customizer.h"
|
||||||
#include "p2p/base/test_turn_server.h"
|
#include "p2p/base/test_turn_server.h"
|
||||||
#include "p2p/client/basic_port_allocator.h"
|
|
||||||
#include "pc/dtmf_sender.h"
|
|
||||||
#include "pc/local_audio_source.h"
|
|
||||||
#include "pc/media_session.h"
|
|
||||||
#include "pc/peer_connection.h"
|
|
||||||
#include "pc/peer_connection_factory.h"
|
#include "pc/peer_connection_factory.h"
|
||||||
#include "pc/peer_connection_proxy.h"
|
|
||||||
#include "pc/rtp_media_utils.h"
|
|
||||||
#include "pc/session_description.h"
|
#include "pc/session_description.h"
|
||||||
#include "pc/test/fake_audio_capture_module.h"
|
#include "pc/test/fake_audio_capture_module.h"
|
||||||
#include "pc/test/fake_periodic_video_source.h"
|
#include "pc/test/fake_periodic_video_source.h"
|
||||||
@ -97,28 +74,23 @@
|
|||||||
#include "pc/video_track_source.h"
|
#include "pc/video_track_source.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/crypto_random.h"
|
#include "rtc_base/crypto_random.h"
|
||||||
#include "rtc_base/event.h"
|
|
||||||
#include "rtc_base/fake_clock.h"
|
|
||||||
#include "rtc_base/fake_mdns_responder.h"
|
#include "rtc_base/fake_mdns_responder.h"
|
||||||
#include "rtc_base/fake_network.h"
|
#include "rtc_base/fake_network.h"
|
||||||
#include "rtc_base/firewall_socket_server.h"
|
#include "rtc_base/firewall_socket_server.h"
|
||||||
#include "rtc_base/gunit.h"
|
#include "rtc_base/gunit.h"
|
||||||
#include "rtc_base/ip_address.h"
|
#include "rtc_base/ip_address.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/mdns_responder_interface.h"
|
|
||||||
#include "rtc_base/numerics/safe_conversions.h"
|
|
||||||
#include "rtc_base/rtc_certificate_generator.h"
|
|
||||||
#include "rtc_base/socket_address.h"
|
#include "rtc_base/socket_address.h"
|
||||||
|
#include "rtc_base/socket_factory.h"
|
||||||
|
#include "rtc_base/socket_server.h"
|
||||||
#include "rtc_base/ssl_stream_adapter.h"
|
#include "rtc_base/ssl_stream_adapter.h"
|
||||||
#include "rtc_base/task_queue_for_test.h"
|
#include "rtc_base/task_queue_for_test.h"
|
||||||
#include "rtc_base/task_utils/repeating_task.h"
|
|
||||||
#include "rtc_base/test_certificate_verifier.h"
|
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
#include "rtc_base/thread_annotations.h"
|
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
#include "rtc_base/virtual_socket_server.h"
|
#include "rtc_base/virtual_socket_server.h"
|
||||||
#include "system_wrappers/include/metrics.h"
|
#include "system_wrappers/include/metrics.h"
|
||||||
#include "test/gmock.h"
|
#include "test/gmock.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
#include "test/scoped_key_value_config.h"
|
#include "test/scoped_key_value_config.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -666,9 +638,7 @@ class PeerConnectionIntegrationWrapper : public PeerConnectionObserver,
|
|||||||
|
|
||||||
bool SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc) {
|
bool SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc) {
|
||||||
auto observer = rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>();
|
auto observer = rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>();
|
||||||
std::string str;
|
RTC_LOG(LS_INFO) << debug_name_ << ": SetRemoteDescription SDP:" << desc;
|
||||||
desc->ToString(&str);
|
|
||||||
RTC_LOG(LS_INFO) << debug_name_ << ": SetRemoteDescription SDP:\n" << str;
|
|
||||||
pc()->SetRemoteDescription(std::move(desc), observer); // desc.release());
|
pc()->SetRemoteDescription(std::move(desc), observer); // desc.release());
|
||||||
RemoveUnusedVideoRenderers();
|
RemoveUnusedVideoRenderers();
|
||||||
EXPECT_TRUE_WAIT(observer->called(), kDefaultTimeout);
|
EXPECT_TRUE_WAIT(observer->called(), kDefaultTimeout);
|
||||||
|
|||||||
@ -14,9 +14,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "api/rtp_parameters.h"
|
#include "api/rtp_parameters.h"
|
||||||
#include "media/base/codec.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
|
||||||
|
|
||||||
namespace cricket {
|
namespace cricket {
|
||||||
template <typename IdStruct>
|
template <typename IdStruct>
|
||||||
@ -88,41 +86,6 @@ class UsedIds {
|
|||||||
std::set<int> id_set_;
|
std::set<int> id_set_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper class used for finding duplicate RTP payload types among audio, video
|
|
||||||
// and data codecs. When bundle is used the payload types may not collide.
|
|
||||||
class UsedPayloadTypes : public UsedIds<Codec> {
|
|
||||||
public:
|
|
||||||
UsedPayloadTypes()
|
|
||||||
: UsedIds<Codec>(kFirstDynamicPayloadTypeLowerRange,
|
|
||||||
kLastDynamicPayloadTypeUpperRange) {}
|
|
||||||
|
|
||||||
// Check if a payload type is valid. The range [64-95] is forbidden
|
|
||||||
// when rtcp-mux is used.
|
|
||||||
static bool IsIdValid(Codec codec, bool rtcp_mux) {
|
|
||||||
if (rtcp_mux && (codec.id > kLastDynamicPayloadTypeLowerRange &&
|
|
||||||
codec.id < kFirstDynamicPayloadTypeUpperRange)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return codec.id >= 0 && codec.id <= kLastDynamicPayloadTypeUpperRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool IsIdUsed(int new_id) override {
|
|
||||||
// Range marked for RTCP avoidance is "used".
|
|
||||||
if (new_id > kLastDynamicPayloadTypeLowerRange &&
|
|
||||||
new_id < kFirstDynamicPayloadTypeUpperRange)
|
|
||||||
return true;
|
|
||||||
return UsedIds<Codec>::IsIdUsed(new_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int kFirstDynamicPayloadTypeLowerRange = 35;
|
|
||||||
static const int kLastDynamicPayloadTypeLowerRange = 63;
|
|
||||||
|
|
||||||
static const int kFirstDynamicPayloadTypeUpperRange = 96;
|
|
||||||
static const int kLastDynamicPayloadTypeUpperRange = 127;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper class used for finding duplicate RTP Header extension ids among
|
// Helper class used for finding duplicate RTP Header extension ids among
|
||||||
// audio and video extensions.
|
// audio and video extensions.
|
||||||
class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
|
class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user