Use PayloadTypePicker in WebRtcVoiceEngine
This entails passing in a PayloadTypeSuggester as a dependency. PT suggesting is still done according to the old method, but with new code. Bug: webrtc:360058654 Change-Id: I12a7d2aa6aa482fb62ff3dfb34b9761ebb7dddef Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/361200 Commit-Queue: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Florent Castelli <orphis@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42989}
This commit is contained in:
parent
927244db7e
commit
dc56a36ff8
@ -39,7 +39,6 @@ rtc_library("call_interfaces") {
|
||||
deps = [
|
||||
":audio_sender_interface",
|
||||
":payload_type",
|
||||
":payload_type",
|
||||
":receive_stream_interface",
|
||||
":rtp_interfaces",
|
||||
":video_stream_api",
|
||||
|
||||
@ -114,6 +114,11 @@ class PayloadTypeSuggesterForTests : public PayloadTypeSuggester {
|
||||
cricket::Codec codec) override {
|
||||
return payload_type_picker_.SuggestMapping(codec, nullptr);
|
||||
}
|
||||
RTCError AddLocalMapping(const std::string& mid,
|
||||
PayloadType payload_type,
|
||||
const cricket::Codec& codec) override {
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
private:
|
||||
PayloadTypePicker payload_type_picker_;
|
||||
|
||||
@ -37,6 +37,11 @@ class PayloadTypeSuggester {
|
||||
// or a newly suggested one.
|
||||
virtual RTCErrorOr<PayloadType> SuggestPayloadType(const std::string& mid,
|
||||
cricket::Codec codec) = 0;
|
||||
// Register a payload type as mapped to a specific codec for this MID
|
||||
// at this time.
|
||||
virtual RTCError AddLocalMapping(const std::string& mid,
|
||||
PayloadType payload_type,
|
||||
const cricket::Codec& codec) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -136,6 +136,14 @@ PayloadTypePicker::PayloadTypePicker() {
|
||||
RTCErrorOr<PayloadType> PayloadTypePicker::SuggestMapping(
|
||||
cricket::Codec codec,
|
||||
const PayloadTypeRecorder* excluder) {
|
||||
// Test compatibility: If the codec contains a PT, and it is free, use it.
|
||||
// This saves having to rewrite tests that set the codec ID themselves.
|
||||
// Codecs with unassigned IDs should have -1 as their id.
|
||||
if (codec.id >= 0 && codec.id <= kLastDynamicPayloadTypeUpperRange &&
|
||||
seen_payload_types_.count(PayloadType(codec.id)) == 0) {
|
||||
AddMapping(PayloadType(codec.id), codec);
|
||||
return PayloadType(codec.id);
|
||||
}
|
||||
// The first matching entry is returned, unless excluder
|
||||
// maps it to something different.
|
||||
for (auto entry : entries_) {
|
||||
@ -149,6 +157,7 @@ RTCErrorOr<PayloadType> PayloadTypePicker::SuggestMapping(
|
||||
return entry.payload_type();
|
||||
}
|
||||
}
|
||||
// Assign the first free payload type.
|
||||
RTCErrorOr<PayloadType> found_pt = FindFreePayloadType(seen_payload_types_);
|
||||
if (found_pt.ok()) {
|
||||
AddMapping(found_pt.value(), codec);
|
||||
|
||||
@ -344,6 +344,8 @@ rtc_source_set("media_channel") {
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base/network:sent_packet",
|
||||
"../video/config:encoder_config",
|
||||
"//third_party/abseil-cpp/absl/functional:any_invocable",
|
||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||
]
|
||||
}
|
||||
|
||||
@ -592,6 +594,8 @@ rtc_library("rtc_audio_video") {
|
||||
"../api/video_codecs:video_codecs_api",
|
||||
"../call",
|
||||
"../call:call_interfaces",
|
||||
"../call:payload_type",
|
||||
"../call:payload_type_picker",
|
||||
"../call:receive_stream_interface",
|
||||
"../call:rtp_interfaces",
|
||||
"../call:video_stream_api",
|
||||
@ -652,8 +656,6 @@ rtc_library("rtc_audio_video") {
|
||||
sources = [
|
||||
"engine/adm_helpers.cc",
|
||||
"engine/adm_helpers.h",
|
||||
"engine/payload_type_mapper.cc",
|
||||
"engine/payload_type_mapper.h",
|
||||
"engine/webrtc_media_engine.cc",
|
||||
"engine/webrtc_media_engine.h",
|
||||
"engine/webrtc_video_engine.cc",
|
||||
@ -786,12 +788,23 @@ if (rtc_include_tests) {
|
||||
":video_common",
|
||||
"../api:call_api",
|
||||
"../api:fec_controller_api",
|
||||
"../api:frame_transformer_interface",
|
||||
"../api:rtc_error",
|
||||
"../api:rtp_headers",
|
||||
"../api:rtp_parameters",
|
||||
"../api:rtp_sender_interface",
|
||||
"../api:scoped_refptr",
|
||||
"../api/adaptation:resource_adaptation_api",
|
||||
"../api/audio:audio_frame_api",
|
||||
"../api/audio:audio_processing",
|
||||
"../api/audio_codecs:audio_codecs_api",
|
||||
"../api/crypto:frame_decryptor_interface",
|
||||
"../api/environment",
|
||||
"../api/task_queue",
|
||||
"../api/task_queue:pending_task_safety_flag",
|
||||
"../api/transport:bitrate_settings",
|
||||
"../api/transport/rtp:rtp_source",
|
||||
"../api/units:time_delta",
|
||||
"../api/units:timestamp",
|
||||
"../api/video:encoded_image",
|
||||
"../api/video:video_bitrate_allocation",
|
||||
@ -800,9 +813,13 @@ if (rtc_include_tests) {
|
||||
"../api/video_codecs:video_codecs_api",
|
||||
"../call:call_interfaces",
|
||||
"../call:mock_rtp_interfaces",
|
||||
"../call:payload_type",
|
||||
"../call:payload_type_picker",
|
||||
"../call:rtp_interfaces",
|
||||
"../call:video_stream_api",
|
||||
"../common_video",
|
||||
"../modules/audio_processing",
|
||||
"../modules/rtp_rtcp",
|
||||
"../modules/rtp_rtcp:rtp_rtcp_format",
|
||||
"../modules/video_coding:video_codec_interface",
|
||||
"../modules/video_coding:video_coding_utility",
|
||||
@ -820,11 +837,13 @@ if (rtc_include_tests) {
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base:threading",
|
||||
"../rtc_base:timeutils",
|
||||
"../rtc_base/network:sent_packet",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
"../rtc_base/third_party/sigslot",
|
||||
"../test:explicit_key_value_config",
|
||||
"../test:scoped_key_value_config",
|
||||
"../test:test_support",
|
||||
"../video/config:encoder_config",
|
||||
"../video/config:streams_config",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||
@ -882,6 +901,7 @@ if (rtc_include_tests) {
|
||||
":rtc_audio_video",
|
||||
":rtc_internal_video_codecs",
|
||||
":rtc_media",
|
||||
":rtc_media_config",
|
||||
":rtc_media_tests_utils",
|
||||
":rtc_sdp_video_format_utils",
|
||||
":rtc_simulcast_encoder_adapter",
|
||||
@ -891,27 +911,38 @@ if (rtc_include_tests) {
|
||||
":video_adapter",
|
||||
":video_broadcaster",
|
||||
":video_common",
|
||||
"../api:audio_options_api",
|
||||
"../api:call_api",
|
||||
"../api:create_simulcast_test_fixture_api",
|
||||
"../api:field_trials_view",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:make_ref_counted",
|
||||
"../api:mock_encoder_selector",
|
||||
"../api:mock_video_bitrate_allocator",
|
||||
"../api:mock_video_bitrate_allocator_factory",
|
||||
"../api:mock_video_codec_factory",
|
||||
"../api:mock_video_encoder",
|
||||
"../api:priority",
|
||||
"../api:ref_count",
|
||||
"../api:rtc_error",
|
||||
"../api:rtp_headers",
|
||||
"../api:rtp_parameters",
|
||||
"../api:scoped_refptr",
|
||||
"../api:simulcast_test_fixture_api",
|
||||
"../api/audio:audio_processing",
|
||||
"../api/audio_codecs:audio_codecs_api",
|
||||
"../api/audio_codecs:builtin_audio_decoder_factory",
|
||||
"../api/audio_codecs:builtin_audio_encoder_factory",
|
||||
"../api/crypto:options",
|
||||
"../api/environment",
|
||||
"../api/environment:environment_factory",
|
||||
"../api/rtc_event_log",
|
||||
"../api/task_queue",
|
||||
"../api/task_queue:default_task_queue_factory",
|
||||
"../api/test/video:function_video_factory",
|
||||
"../api/transport:bitrate_settings",
|
||||
"../api/transport:field_trial_based_config",
|
||||
"../api/transport/rtp:rtp_source",
|
||||
"../api/units:time_delta",
|
||||
"../api/units:timestamp",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
@ -950,6 +981,8 @@ if (rtc_include_tests) {
|
||||
"../rtc_base:async_packet_socket",
|
||||
"../rtc_base:byte_order",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:copy_on_write_buffer",
|
||||
"../rtc_base:dscp",
|
||||
"../rtc_base:gunit_helpers",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:macromagic",
|
||||
@ -995,7 +1028,6 @@ if (rtc_include_tests) {
|
||||
"base/video_common_unittest.cc",
|
||||
"engine/internal_decoder_factory_unittest.cc",
|
||||
"engine/internal_encoder_factory_unittest.cc",
|
||||
"engine/payload_type_mapper_unittest.cc",
|
||||
"engine/simulcast_encoder_adapter_unittest.cc",
|
||||
"engine/webrtc_media_engine_unittest.cc",
|
||||
"engine/webrtc_video_engine_unittest.cc",
|
||||
|
||||
@ -34,8 +34,7 @@ specific_include_rules = {
|
||||
".*fake_webrtc_call\.cc": [
|
||||
"+video/config",
|
||||
],
|
||||
# temporary
|
||||
".*webrtc_voice_engine\.cc": [
|
||||
"+pc/payload_type_picker.h",
|
||||
".*fake_webrtc_call\.h": [
|
||||
"+video/config",
|
||||
],
|
||||
}
|
||||
|
||||
@ -11,6 +11,9 @@
|
||||
#ifndef MEDIA_BASE_MEDIA_CHANNEL_H_
|
||||
#define MEDIA_BASE_MEDIA_CHANNEL_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@ -19,6 +22,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/audio/audio_processing_statistics.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_options.h"
|
||||
@ -27,37 +32,34 @@
|
||||
#include "api/crypto/frame_encryptor_interface.h"
|
||||
#include "api/frame_transformer_interface.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_sender_interface.h"
|
||||
#include "api/task_queue/pending_task_safety_flag.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/transport/rtp/rtp_source.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/video/recordable_encoded_frame.h"
|
||||
#include "api/video/video_content_type.h"
|
||||
#include "api/video/video_sink_interface.h"
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "api/video/video_timing.h"
|
||||
#include "api/video_codecs/scalability_mode.h"
|
||||
#include "api/video_codecs/video_encoder_factory.h"
|
||||
#include "call/video_receive_stream.h"
|
||||
#include "common_video/include/quality_limitation_reason.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "rtc_base/async_packet_socket.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/dscp.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/network/sent_packet.h"
|
||||
#include "rtc_base/network_route.h"
|
||||
#include "rtc_base/socket.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "video/config/video_encoder_config.h"
|
||||
|
||||
namespace rtc {
|
||||
class Timing;
|
||||
|
||||
@ -20,24 +20,56 @@
|
||||
#ifndef MEDIA_ENGINE_FAKE_WEBRTC_CALL_H_
|
||||
#define MEDIA_ENGINE_FAKE_WEBRTC_CALL_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/adaptation/resource.h"
|
||||
#include "api/audio/audio_frame.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "api/crypto/frame_decryptor_interface.h"
|
||||
#include "api/environment/environment.h"
|
||||
#include "api/frame_transformer_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_sender_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
#include "api/transport/bitrate_settings.h"
|
||||
#include "api/transport/rtp/rtp_source.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/video/video_frame.h"
|
||||
#include "api/video/video_sink_interface.h"
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "api/video_codecs/video_codec.h"
|
||||
#include "call/audio_receive_stream.h"
|
||||
#include "call/audio_send_stream.h"
|
||||
#include "call/call.h"
|
||||
#include "call/flexfec_receive_stream.h"
|
||||
#include "call/packet_receiver.h"
|
||||
#include "call/payload_type.h"
|
||||
#include "call/payload_type_picker.h"
|
||||
#include "call/rtp_transport_controller_send_interface.h"
|
||||
#include "call/test/mock_rtp_transport_controller_send.h"
|
||||
#include "call/video_receive_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/source/rtp_packet_received.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/network/sent_packet.h"
|
||||
#include "test/gmock.h"
|
||||
#include "video/config/video_encoder_config.h"
|
||||
|
||||
namespace cricket {
|
||||
class FakeAudioSendStream final : public webrtc::AudioSendStream {
|
||||
@ -363,6 +395,26 @@ class FakeFlexfecReceiveStream final : public webrtc::FlexfecReceiveStream {
|
||||
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 {
|
||||
public:
|
||||
explicit FakeCall(const webrtc::Environment& env);
|
||||
@ -371,6 +423,10 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
||||
webrtc::TaskQueueBase* network_thread);
|
||||
~FakeCall() override;
|
||||
|
||||
webrtc::PayloadTypeSuggester* GetPayloadTypeSuggester() {
|
||||
return &pt_suggester_;
|
||||
}
|
||||
|
||||
webrtc::MockRtpTransportControllerSend* GetMockTransportControllerSend() {
|
||||
return &transport_controller_send_;
|
||||
}
|
||||
@ -501,6 +557,8 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
||||
|
||||
int num_created_send_streams_;
|
||||
int num_created_receive_streams_;
|
||||
|
||||
FakePayloadTypeSuggester pt_suggester_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 "media/engine/payload_type_mapper.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_constants.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac) {
|
||||
return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
|
||||
}
|
||||
|
||||
PayloadTypeMapper::PayloadTypeMapper()
|
||||
// RFC 3551 reserves payload type numbers in the range 96-127 exclusively
|
||||
// for dynamic assignment. Once those are used up, it is recommended that
|
||||
// payload types unassigned by the RFC are used for dynamic payload type
|
||||
// mapping, before any static payload ids. At this point, we only support
|
||||
// mapping within the exclusive range.
|
||||
: next_unused_payload_type_(96),
|
||||
max_payload_type_(127),
|
||||
mappings_(
|
||||
{// Static payload type assignments according to RFC 3551.
|
||||
{{kPcmuCodecName, 8000, 1}, 0},
|
||||
{{"GSM", 8000, 1}, 3},
|
||||
{{"G723", 8000, 1}, 4},
|
||||
{{"DVI4", 8000, 1}, 5},
|
||||
{{"DVI4", 16000, 1}, 6},
|
||||
{{"LPC", 8000, 1}, 7},
|
||||
{{kPcmaCodecName, 8000, 1}, 8},
|
||||
{{kG722CodecName, 8000, 1}, 9},
|
||||
{{kL16CodecName, 44100, 2}, 10},
|
||||
{{kL16CodecName, 44100, 1}, 11},
|
||||
{{"QCELP", 8000, 1}, 12},
|
||||
{{kCnCodecName, 8000, 1}, 13},
|
||||
// RFC 4566 is a bit ambiguous on the contents of the "encoding
|
||||
// parameters" field, which, for audio, encodes the number of
|
||||
// channels. It is "optional and may be omitted if the number of
|
||||
// channels is one". Does that necessarily imply that an omitted
|
||||
// encoding parameter means one channel? Since RFC 3551 doesn't
|
||||
// specify a value for this parameter for MPA, I've included both 0
|
||||
// and 1 here, to increase the chances it will be correctly used if
|
||||
// someone implements an MPEG audio encoder/decoder.
|
||||
{{"MPA", 90000, 0}, 14},
|
||||
{{"MPA", 90000, 1}, 14},
|
||||
{{"G728", 8000, 1}, 15},
|
||||
{{"DVI4", 11025, 1}, 16},
|
||||
{{"DVI4", 22050, 1}, 17},
|
||||
{{"G729", 8000, 1}, 18},
|
||||
|
||||
// Payload type assignments currently used by WebRTC.
|
||||
// Includes data to reduce collisions (and thus reassignments)
|
||||
{{kIlbcCodecName, 8000, 1}, 102},
|
||||
{{kCnCodecName, 16000, 1}, 105},
|
||||
{{kCnCodecName, 32000, 1}, 106},
|
||||
{{kOpusCodecName,
|
||||
48000,
|
||||
2,
|
||||
{{kCodecParamMinPTime, "10"},
|
||||
{kCodecParamUseInbandFec, kParamValueTrue}}},
|
||||
111},
|
||||
// RED for opus is assigned in the lower range, starting at the top.
|
||||
// Note that the FMTP refers to the opus payload type.
|
||||
{{kRedCodecName,
|
||||
48000,
|
||||
2,
|
||||
{{kCodecParamNotInNameValueFormat, "111/111"}}},
|
||||
63},
|
||||
// TODO(solenberg): Remove the hard coded 16k,32k,48k DTMF once we
|
||||
// assign payload types dynamically for send side as well.
|
||||
{{kDtmfCodecName, 48000, 1}, 110},
|
||||
{{kDtmfCodecName, 32000, 1}, 112},
|
||||
{{kDtmfCodecName, 16000, 1}, 113},
|
||||
{{kDtmfCodecName, 8000, 1}, 126}}) {
|
||||
// TODO(ossu): Try to keep this as change-proof as possible until we're able
|
||||
// to remove the payload type constants from everywhere in the code.
|
||||
for (const auto& mapping : mappings_) {
|
||||
used_payload_types_.insert(mapping.second);
|
||||
}
|
||||
}
|
||||
|
||||
PayloadTypeMapper::~PayloadTypeMapper() = default;
|
||||
|
||||
std::optional<int> PayloadTypeMapper::GetMappingFor(
|
||||
const webrtc::SdpAudioFormat& format) {
|
||||
auto iter = mappings_.find(format);
|
||||
if (iter != mappings_.end())
|
||||
return iter->second;
|
||||
|
||||
for (; next_unused_payload_type_ <= max_payload_type_;
|
||||
++next_unused_payload_type_) {
|
||||
int payload_type = next_unused_payload_type_;
|
||||
if (used_payload_types_.find(payload_type) == used_payload_types_.end()) {
|
||||
used_payload_types_.insert(payload_type);
|
||||
mappings_[format] = payload_type;
|
||||
++next_unused_payload_type_;
|
||||
return payload_type;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<int> PayloadTypeMapper::FindMappingFor(
|
||||
const webrtc::SdpAudioFormat& format) const {
|
||||
auto iter = mappings_.find(format);
|
||||
if (iter != mappings_.end())
|
||||
return iter->second;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Codec> PayloadTypeMapper::ToAudioCodec(
|
||||
const webrtc::SdpAudioFormat& format) {
|
||||
// TODO(ossu): We can safely set bitrate to zero here, since that field is
|
||||
// not presented in the SDP. It is used to ferry around some target bitrate
|
||||
// values for certain codecs (ISAC and Opus) and in ways it really
|
||||
// shouldn't. It should be removed once we no longer use CodecInsts in the
|
||||
// ACM or NetEq.
|
||||
auto opt_payload_type = GetMappingFor(format);
|
||||
if (opt_payload_type) {
|
||||
Codec codec =
|
||||
cricket::CreateAudioCodec(*opt_payload_type, format.name,
|
||||
format.clockrate_hz, format.num_channels);
|
||||
codec.params = format.parameters;
|
||||
return std::move(codec);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool PayloadTypeMapper::SdpAudioFormatOrdering::operator()(
|
||||
const webrtc::SdpAudioFormat& a,
|
||||
const webrtc::SdpAudioFormat& b) const {
|
||||
if (a.clockrate_hz == b.clockrate_hz) {
|
||||
if (a.num_channels == b.num_channels) {
|
||||
int name_cmp =
|
||||
absl::AsciiStrToLower(a.name).compare(absl::AsciiStrToLower(b.name));
|
||||
if (name_cmp == 0)
|
||||
return a.parameters < b.parameters;
|
||||
return name_cmp < 0;
|
||||
}
|
||||
return a.num_channels < b.num_channels;
|
||||
}
|
||||
return a.clockrate_hz < b.clockrate_hz;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
|
||||
#define MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "media/base/codec.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac);
|
||||
|
||||
class PayloadTypeMapper {
|
||||
public:
|
||||
PayloadTypeMapper();
|
||||
~PayloadTypeMapper();
|
||||
|
||||
// Finds the current payload type for `format` or assigns a new one, if no
|
||||
// current mapping exists. Will return an empty value if it was unable to
|
||||
// create a mapping, i.e. if all dynamic payload type ids have been used up.
|
||||
std::optional<int> GetMappingFor(const webrtc::SdpAudioFormat& format);
|
||||
|
||||
// Finds the current payload type for `format`, if any. Returns an empty value
|
||||
// if no payload type mapping exists for the format.
|
||||
std::optional<int> FindMappingFor(const webrtc::SdpAudioFormat& format) const;
|
||||
|
||||
// Like GetMappingFor, but fills in an AudioCodec structure with the necessary
|
||||
// information instead.
|
||||
std::optional<Codec> ToAudioCodec(const webrtc::SdpAudioFormat& format);
|
||||
|
||||
private:
|
||||
struct SdpAudioFormatOrdering {
|
||||
bool operator()(const webrtc::SdpAudioFormat& a,
|
||||
const webrtc::SdpAudioFormat& b) const;
|
||||
};
|
||||
|
||||
int next_unused_payload_type_;
|
||||
int max_payload_type_;
|
||||
std::map<webrtc::SdpAudioFormat, int, SdpAudioFormatOrdering> mappings_;
|
||||
std::set<int> used_payload_types_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
#endif // MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
|
||||
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 "media/engine/payload_type_mapper.h"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class PayloadTypeMapperTest : public ::testing::Test {
|
||||
protected:
|
||||
PayloadTypeMapper mapper_;
|
||||
};
|
||||
|
||||
TEST_F(PayloadTypeMapperTest, StaticPayloadTypes) {
|
||||
EXPECT_EQ(0, mapper_.FindMappingFor({"pcmu", 8000, 1}));
|
||||
EXPECT_EQ(3, mapper_.FindMappingFor({"gsm", 8000, 1}));
|
||||
EXPECT_EQ(4, mapper_.FindMappingFor({"g723", 8000, 1}));
|
||||
EXPECT_EQ(5, mapper_.FindMappingFor({"dvi4", 8000, 1}));
|
||||
EXPECT_EQ(6, mapper_.FindMappingFor({"dvi4", 16000, 1}));
|
||||
EXPECT_EQ(7, mapper_.FindMappingFor({"lpc", 8000, 1}));
|
||||
EXPECT_EQ(8, mapper_.FindMappingFor({"pcma", 8000, 1}));
|
||||
EXPECT_EQ(9, mapper_.FindMappingFor({"g722", 8000, 1}));
|
||||
EXPECT_EQ(10, mapper_.FindMappingFor({"l16", 44100, 2}));
|
||||
EXPECT_EQ(11, mapper_.FindMappingFor({"l16", 44100, 1}));
|
||||
EXPECT_EQ(12, mapper_.FindMappingFor({"qcelp", 8000, 1}));
|
||||
EXPECT_EQ(13, mapper_.FindMappingFor({"cn", 8000, 1}));
|
||||
EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 0}));
|
||||
EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 1}));
|
||||
EXPECT_EQ(15, mapper_.FindMappingFor({"g728", 8000, 1}));
|
||||
EXPECT_EQ(16, mapper_.FindMappingFor({"dvi4", 11025, 1}));
|
||||
EXPECT_EQ(17, mapper_.FindMappingFor({"dvi4", 22050, 1}));
|
||||
EXPECT_EQ(18, mapper_.FindMappingFor({"g729", 8000, 1}));
|
||||
}
|
||||
|
||||
TEST_F(PayloadTypeMapperTest, WebRTCPayloadTypes) {
|
||||
// Tests that the payload mapper knows about the audio formats we've
|
||||
// been using in WebRTC, with their hard coded values.
|
||||
EXPECT_EQ(102, mapper_.FindMappingFor({kIlbcCodecName, 8000, 1}));
|
||||
EXPECT_EQ(105, mapper_.FindMappingFor({kCnCodecName, 16000, 1}));
|
||||
EXPECT_EQ(106, mapper_.FindMappingFor({kCnCodecName, 32000, 1}));
|
||||
EXPECT_EQ(111, mapper_.FindMappingFor(
|
||||
{kOpusCodecName,
|
||||
48000,
|
||||
2,
|
||||
{{"minptime", "10"}, {"useinbandfec", "1"}}}));
|
||||
EXPECT_EQ(
|
||||
63, mapper_.FindMappingFor({kRedCodecName, 48000, 2, {{"", "111/111"}}}));
|
||||
// TODO(solenberg): Remove 16k, 32k, 48k DTMF checks once these payload types
|
||||
// are dynamically assigned.
|
||||
EXPECT_EQ(110, mapper_.FindMappingFor({kDtmfCodecName, 48000, 1}));
|
||||
EXPECT_EQ(112, mapper_.FindMappingFor({kDtmfCodecName, 32000, 1}));
|
||||
EXPECT_EQ(113, mapper_.FindMappingFor({kDtmfCodecName, 16000, 1}));
|
||||
EXPECT_EQ(126, mapper_.FindMappingFor({kDtmfCodecName, 8000, 1}));
|
||||
}
|
||||
|
||||
TEST_F(PayloadTypeMapperTest, ValidDynamicPayloadTypes) {
|
||||
// RFC 3551 says:
|
||||
// "This profile reserves payload type numbers in the range 96-127
|
||||
// exclusively for dynamic assignment. Applications SHOULD first use
|
||||
// values in this range for dynamic payload types. Those applications
|
||||
// which need to define more than 32 dynamic payload types MAY bind
|
||||
// codes below 96, in which case it is RECOMMENDED that unassigned
|
||||
// payload type numbers be used first. However, the statically assigned
|
||||
// payload types are default bindings and MAY be dynamically bound to
|
||||
// new encodings if needed."
|
||||
|
||||
// Tests that the payload mapper uses values in the dynamic payload type range
|
||||
// (96 - 127) before any others and that the values returned are all valid.
|
||||
bool has_been_below_96 = false;
|
||||
std::set<int> used_payload_types;
|
||||
for (int i = 0; i != 256; ++i) {
|
||||
std::string format_name = "unknown_format_" + std::to_string(i);
|
||||
webrtc::SdpAudioFormat format(format_name.c_str(), i * 100, (i % 2) + 1);
|
||||
auto opt_payload_type = mapper_.GetMappingFor(format);
|
||||
bool mapper_is_full = false;
|
||||
|
||||
// There's a limited number of slots for payload types. We're fine with not
|
||||
// being able to map them all.
|
||||
if (opt_payload_type) {
|
||||
int payload_type = *opt_payload_type;
|
||||
EXPECT_FALSE(mapper_is_full) << "Mapping should not fail sporadically";
|
||||
EXPECT_EQ(used_payload_types.find(payload_type), used_payload_types.end())
|
||||
<< "Payload types must not be reused";
|
||||
used_payload_types.insert(payload_type);
|
||||
EXPECT_GE(payload_type, 0) << "Negative payload types are invalid";
|
||||
EXPECT_LE(payload_type, 127) << "Payload types above 127 are invalid";
|
||||
EXPECT_FALSE(payload_type >= 96 && has_been_below_96);
|
||||
if (payload_type < 96)
|
||||
has_been_below_96 = true;
|
||||
|
||||
EXPECT_EQ(payload_type, mapper_.FindMappingFor(format))
|
||||
<< "Mapping must be permanent after successful call to "
|
||||
"GetMappingFor";
|
||||
EXPECT_EQ(payload_type, mapper_.GetMappingFor(format))
|
||||
<< "Subsequent calls to GetMappingFor must return the same value";
|
||||
} else {
|
||||
mapper_is_full = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Also, we must've been able to map at least one dynamic payload type.
|
||||
EXPECT_FALSE(used_payload_types.empty())
|
||||
<< "Mapper must support at least one user-defined payload type";
|
||||
}
|
||||
|
||||
TEST_F(PayloadTypeMapperTest, ToAudioCodec) {
|
||||
webrtc::SdpAudioFormat format("unknown_format", 4711, 17);
|
||||
auto opt_payload_type = mapper_.GetMappingFor(format);
|
||||
EXPECT_TRUE(opt_payload_type);
|
||||
auto opt_audio_codec = mapper_.ToAudioCodec(format);
|
||||
EXPECT_TRUE(opt_audio_codec);
|
||||
|
||||
if (opt_payload_type && opt_audio_codec) {
|
||||
int payload_type = *opt_payload_type;
|
||||
const Codec& codec = *opt_audio_codec;
|
||||
|
||||
EXPECT_EQ(codec.id, payload_type);
|
||||
EXPECT_EQ(codec.name, format.name);
|
||||
EXPECT_EQ(codec.clockrate, format.clockrate_hz);
|
||||
EXPECT_EQ(codec.channels, format.num_channels);
|
||||
EXPECT_THAT(codec.params, ::testing::ContainerEq(format.parameters));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
@ -12,54 +12,77 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/audio/audio_frame.h"
|
||||
#include "api/audio/audio_frame_processor.h"
|
||||
#include "api/audio/audio_mixer.h"
|
||||
#include "api/audio/audio_processing.h"
|
||||
#include "api/audio/audio_processing_statistics.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_encoder_factory.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "api/audio_options.h"
|
||||
#include "api/call/audio_sink.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/media_types.h"
|
||||
#include "api/priority.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_sender_interface.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/transport/bitrate_settings.h"
|
||||
#include "api/transport/rtp/rtp_source.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "call/audio_receive_stream.h"
|
||||
#include "call/audio_send_stream.h"
|
||||
#include "call/audio_state.h"
|
||||
#include "call/call.h"
|
||||
#include "call/packet_receiver.h"
|
||||
#include "call/payload_type_picker.h"
|
||||
#include "call/rtp_config.h"
|
||||
#include "call/rtp_transport_controller_send_interface.h"
|
||||
#include "media/base/audio_source.h"
|
||||
#include "media/base/codec.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_engine.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "media/engine/adm_helpers.h"
|
||||
#include "media/engine/payload_type_mapper.h"
|
||||
#include "media/engine/webrtc_media_engine.h"
|
||||
#include "modules/async_audio_processing/async_audio_processing.h"
|
||||
#include "modules/audio_mixer/audio_mixer_impl.h"
|
||||
#include "modules/rtp_rtcp/include/report_block_data.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_util.h"
|
||||
@ -72,6 +95,7 @@
|
||||
#include "rtc_base/strings/audio_format_to_string.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "rtc_base/strings/string_format.h"
|
||||
#include "rtc_base/system/file_wrapper.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
@ -332,6 +356,91 @@ bool CheckRedParameters(
|
||||
return true;
|
||||
}
|
||||
|
||||
webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac) {
|
||||
return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
|
||||
}
|
||||
|
||||
// Assign the payload types for the codecs of this voice engine.
|
||||
// This is a "preliminary" pass, done to prime the
|
||||
// payload type picker with a normal set of PTs.
|
||||
// TODO: https://issues.webrtc.org/360058654 - remove.
|
||||
std::vector<Codec> LegacyCollectCodecs(
|
||||
const std::vector<webrtc::AudioCodecSpec>& specs) {
|
||||
// Once payload assignment is done in the channel not in the factory,
|
||||
// this needs to be a variable. But then this function should go away.
|
||||
webrtc::PayloadTypePicker pt_mapper;
|
||||
std::vector<Codec> out;
|
||||
|
||||
// Only generate CN payload types for these clockrates:
|
||||
std::map<int, bool, std::greater<int>> generate_cn = {
|
||||
{8000, false}, {16000, false}, {32000, false}};
|
||||
// Only generate telephone-event payload types for these clockrates:
|
||||
std::map<int, bool, std::greater<int>> generate_dtmf = {
|
||||
{8000, false}, {16000, false}, {32000, false}, {48000, false}};
|
||||
|
||||
for (const auto& spec : specs) {
|
||||
cricket::Codec codec = CreateAudioCodec(spec.format);
|
||||
auto pt_or_error = pt_mapper.SuggestMapping(codec, nullptr);
|
||||
// We need to do some extra stuff before adding the main codecs to out.
|
||||
if (pt_or_error.ok()) {
|
||||
codec.id = pt_or_error.value();
|
||||
if (spec.info.supports_network_adaption) {
|
||||
codec.AddFeedbackParam(
|
||||
FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
|
||||
}
|
||||
|
||||
if (spec.info.allow_comfort_noise) {
|
||||
// Generate a CN entry if the decoder allows it and we support the
|
||||
// clockrate.
|
||||
auto cn = generate_cn.find(spec.format.clockrate_hz);
|
||||
if (cn != generate_cn.end()) {
|
||||
cn->second = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a telephone-event entry if we support the clockrate.
|
||||
auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
|
||||
if (dtmf != generate_dtmf.end()) {
|
||||
dtmf->second = true;
|
||||
}
|
||||
|
||||
out.push_back(codec);
|
||||
|
||||
// TODO(hta): Don't assign RED codecs until we know that the PT for Opus
|
||||
// is final
|
||||
if (codec.name == kOpusCodecName) {
|
||||
std::string red_fmtp =
|
||||
rtc::ToString(codec.id) + "/" + rtc::ToString(codec.id);
|
||||
cricket::Codec red_codec =
|
||||
CreateAudioCodec({kRedCodecName, 48000, 2, {{"", red_fmtp}}});
|
||||
red_codec.id = pt_mapper.SuggestMapping(red_codec, nullptr).value();
|
||||
out.push_back(red_codec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add CN codecs after "proper" audio codecs.
|
||||
for (const auto& cn : generate_cn) {
|
||||
if (cn.second) {
|
||||
cricket::Codec cn_codec = CreateAudioCodec({kCnCodecName, cn.first, 1});
|
||||
cn_codec.id = pt_mapper.SuggestMapping(cn_codec, nullptr).value();
|
||||
out.push_back(cn_codec);
|
||||
}
|
||||
}
|
||||
|
||||
// Add telephone-event codecs last.
|
||||
for (const auto& dtmf : generate_dtmf) {
|
||||
if (dtmf.second) {
|
||||
cricket::Codec dtmf_codec =
|
||||
CreateAudioCodec({kDtmfCodecName, dtmf.first, 1});
|
||||
dtmf_codec.id = pt_mapper.SuggestMapping(dtmf_codec, nullptr).value();
|
||||
out.push_back(dtmf_codec);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine(
|
||||
@ -383,13 +492,13 @@ void WebRtcVoiceEngine::Init() {
|
||||
|
||||
// Load our audio codec lists.
|
||||
RTC_LOG(LS_VERBOSE) << "Supported send codecs in order of preference:";
|
||||
send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
|
||||
send_codecs_ = LegacyCollectCodecs(encoder_factory_->GetSupportedEncoders());
|
||||
for (const Codec& codec : send_codecs_) {
|
||||
RTC_LOG(LS_VERBOSE) << ToString(codec);
|
||||
}
|
||||
|
||||
RTC_LOG(LS_VERBOSE) << "Supported recv codecs in order of preference:";
|
||||
recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
|
||||
recv_codecs_ = LegacyCollectCodecs(decoder_factory_->GetSupportedDecoders());
|
||||
for (const Codec& codec : recv_codecs_) {
|
||||
RTC_LOG(LS_VERBOSE) << ToString(codec);
|
||||
}
|
||||
@ -708,84 +817,6 @@ webrtc::AudioState* WebRtcVoiceEngine::audio_state() {
|
||||
return audio_state_.get();
|
||||
}
|
||||
|
||||
std::vector<Codec> WebRtcVoiceEngine::CollectCodecs(
|
||||
const std::vector<webrtc::AudioCodecSpec>& specs) const {
|
||||
PayloadTypeMapper mapper;
|
||||
std::vector<Codec> out;
|
||||
|
||||
// Only generate CN payload types for these clockrates:
|
||||
std::map<int, bool, std::greater<int>> generate_cn = {
|
||||
{8000, false}, {16000, false}, {32000, false}};
|
||||
// Only generate telephone-event payload types for these clockrates:
|
||||
std::map<int, bool, std::greater<int>> generate_dtmf = {
|
||||
{8000, false}, {16000, false}, {32000, false}, {48000, false}};
|
||||
|
||||
auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
|
||||
std::vector<Codec>* out) {
|
||||
std::optional<Codec> opt_codec = mapper.ToAudioCodec(format);
|
||||
if (opt_codec) {
|
||||
if (out) {
|
||||
out->push_back(*opt_codec);
|
||||
}
|
||||
} else {
|
||||
RTC_LOG(LS_ERROR) << "Unable to assign payload type to format: "
|
||||
<< rtc::ToString(format);
|
||||
}
|
||||
|
||||
return opt_codec;
|
||||
};
|
||||
|
||||
for (const auto& spec : specs) {
|
||||
// We need to do some extra stuff before adding the main codecs to out.
|
||||
std::optional<Codec> opt_codec = map_format(spec.format, nullptr);
|
||||
if (opt_codec) {
|
||||
Codec& codec = *opt_codec;
|
||||
if (spec.info.supports_network_adaption) {
|
||||
codec.AddFeedbackParam(
|
||||
FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
|
||||
}
|
||||
|
||||
if (spec.info.allow_comfort_noise) {
|
||||
// Generate a CN entry if the decoder allows it and we support the
|
||||
// clockrate.
|
||||
auto cn = generate_cn.find(spec.format.clockrate_hz);
|
||||
if (cn != generate_cn.end()) {
|
||||
cn->second = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a telephone-event entry if we support the clockrate.
|
||||
auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
|
||||
if (dtmf != generate_dtmf.end()) {
|
||||
dtmf->second = true;
|
||||
}
|
||||
|
||||
out.push_back(codec);
|
||||
|
||||
if (codec.name == kOpusCodecName) {
|
||||
std::string red_fmtp =
|
||||
rtc::ToString(codec.id) + "/" + rtc::ToString(codec.id);
|
||||
map_format({kRedCodecName, 48000, 2, {{"", red_fmtp}}}, &out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add CN codecs after "proper" audio codecs.
|
||||
for (const auto& cn : generate_cn) {
|
||||
if (cn.second) {
|
||||
map_format({kCnCodecName, cn.first, 1}, &out);
|
||||
}
|
||||
}
|
||||
|
||||
// Add telephone-event codecs last.
|
||||
for (const auto& dtmf : generate_dtmf) {
|
||||
if (dtmf.second) {
|
||||
map_format({kDtmfCodecName, dtmf.first, 1}, &out);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// --------------------------------- WebRtcVoiceSendChannel ------------------
|
||||
|
||||
@ -2151,11 +2182,20 @@ bool WebRtcVoiceReceiveChannel::SetOptions(const AudioOptions& options) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceReceiveChannel::SetRecvCodecs(
|
||||
const std::vector<Codec>& codecs) {
|
||||
const std::vector<Codec>& codecs_in) {
|
||||
RTC_DCHECK_RUN_ON(worker_thread_);
|
||||
|
||||
// Set the payload types to be used for incoming media.
|
||||
RTC_LOG(LS_INFO) << "Setting receive voice codecs.";
|
||||
auto codecs = codecs_in;
|
||||
// Record the payload types used in the payload type suggester.
|
||||
RTC_LOG(LS_INFO) << "Setting receive voice codecs. Mid is " << mid_;
|
||||
for (auto& codec : codecs) {
|
||||
auto error = call_->GetPayloadTypeSuggester()->AddLocalMapping(
|
||||
mid_, codec.id, codec);
|
||||
if (!error.ok()) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to register PT for " << codec.ToString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!VerifyUniquePayloadTypes(codecs)) {
|
||||
RTC_LOG(LS_ERROR) << "Codec payload types overlap.";
|
||||
|
||||
@ -34,13 +34,14 @@
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "api/audio_options.h"
|
||||
#include "api/call/audio_sink.h"
|
||||
#include "api/call/transport.h"
|
||||
#include "api/crypto/crypto_options.h"
|
||||
#include "api/crypto/frame_decryptor_interface.h"
|
||||
#include "api/crypto/frame_encryptor_interface.h"
|
||||
#include "api/field_trials_view.h"
|
||||
#include "api/frame_transformer_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_sender_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
@ -57,12 +58,11 @@
|
||||
#include "media/base/media_channel_impl.h"
|
||||
#include "media/base/media_config.h"
|
||||
#include "media/base/media_engine.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "modules/async_audio_processing/async_audio_processing.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/network/sent_packet.h"
|
||||
#include "rtc_base/network_route.h"
|
||||
#include "rtc_base/system/file_wrapper.h"
|
||||
@ -147,9 +147,6 @@ class WebRtcVoiceEngine final : public VoiceEngineInterface {
|
||||
webrtc::AudioProcessing* apm() const;
|
||||
webrtc::AudioState* audio_state();
|
||||
|
||||
std::vector<Codec> CollectCodecs(
|
||||
const std::vector<webrtc::AudioCodecSpec>& specs) const;
|
||||
|
||||
webrtc::SequenceChecker signal_thread_checker_{
|
||||
webrtc::SequenceChecker::kDetached};
|
||||
webrtc::SequenceChecker worker_thread_checker_{
|
||||
|
||||
@ -79,6 +79,7 @@ rtc_source_set("channel") {
|
||||
"../api:scoped_refptr",
|
||||
"../api:sequence_checker",
|
||||
"../api/crypto:options",
|
||||
"../api/task_queue",
|
||||
"../api/task_queue:pending_task_safety_flag",
|
||||
"../api/units:timestamp",
|
||||
"../call:rtp_interfaces",
|
||||
@ -1105,6 +1106,7 @@ rtc_source_set("peer_connection") {
|
||||
"../api:ice_transport_interface",
|
||||
"../api:libjingle_logging_api",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:make_ref_counted",
|
||||
"../api:media_stream_interface",
|
||||
"../api:rtc_error",
|
||||
"../api:rtc_stats_api",
|
||||
@ -1115,16 +1117,20 @@ rtc_source_set("peer_connection") {
|
||||
"../api:sequence_checker",
|
||||
"../api:turn_customizer",
|
||||
"../api/adaptation:resource_adaptation_api",
|
||||
"../api/audio:audio_device",
|
||||
"../api/crypto:options",
|
||||
"../api/environment",
|
||||
"../api/rtc_event_log",
|
||||
"../api/task_queue:pending_task_safety_flag",
|
||||
"../api/transport:bandwidth_estimation_settings",
|
||||
"../api/transport:bitrate_settings",
|
||||
"../api/transport:datagram_transport_interface",
|
||||
"../api/transport:enums",
|
||||
"../api/units:time_delta",
|
||||
"../api/video:video_codec_constants",
|
||||
"../call:call_interfaces",
|
||||
"../call:payload_type_picker",
|
||||
"../media:codec",
|
||||
"../media:media_channel",
|
||||
"../media:media_engine",
|
||||
"../media:rid_description",
|
||||
|
||||
@ -12,28 +12,44 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/crypto/crypto_options.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/sequence_checker.h"
|
||||
#include "api/task_queue/pending_task_safety_flag.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "media/base/rid_description.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "p2p/base/dtls_transport_internal.h"
|
||||
#include "pc/rtp_media_utils.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "pc/session_description.h"
|
||||
#include "rtc_base/async_packet_socket.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/containers/flat_set.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/network/sent_packet.h"
|
||||
#include "rtc_base/network_route.h"
|
||||
#include "rtc_base/socket.h"
|
||||
#include "rtc_base/strings/string_format.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
#include "rtc_base/unique_id_generator.h"
|
||||
|
||||
namespace cricket {
|
||||
namespace {
|
||||
@ -907,7 +923,9 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
set_local_content_direction(content->direction());
|
||||
UpdateMediaSendRecvState_w();
|
||||
|
||||
RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
|
||||
// Disabled because suggeting PTs takes thread jumps.
|
||||
// TODO: https://issues.webrtc.org/360058654 - reenable after cleanup
|
||||
// RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
|
||||
|
||||
bool success = MaybeUpdateDemuxerAndRtpExtensions_w(
|
||||
criteria_modified,
|
||||
@ -916,7 +934,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
|
||||
: std::nullopt,
|
||||
error_desc);
|
||||
|
||||
RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
|
||||
// RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/candidate.h"
|
||||
#include "api/ice_transport_interface.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/rtc_error.h"
|
||||
@ -243,6 +242,9 @@ class JsepTransport {
|
||||
const webrtc::PayloadTypeRecorder& local_payload_types() const {
|
||||
return local_payload_types_;
|
||||
}
|
||||
webrtc::PayloadTypeRecorder& local_payload_types() {
|
||||
return local_payload_types_;
|
||||
}
|
||||
void CommitPayloadTypes() {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
local_payload_types_.Commit();
|
||||
|
||||
@ -12,25 +12,58 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/async_dns_resolver.h"
|
||||
#include "api/candidate.h"
|
||||
#include "api/dtls_transport_interface.h"
|
||||
#include "api/environment/environment.h"
|
||||
#include "api/ice_transport_interface.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/sequence_checker.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "api/transport/enums.h"
|
||||
#include "call/payload_type.h"
|
||||
#include "call/payload_type_picker.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/sctp/sctp_transport_internal.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "p2p/base/dtls_transport.h"
|
||||
#include "p2p/base/dtls_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_allocator.h"
|
||||
#include "p2p/base/transport_description.h"
|
||||
#include "p2p/base/transport_info.h"
|
||||
#include "pc/dtls_srtp_transport.h"
|
||||
#include "pc/dtls_transport.h"
|
||||
#include "pc/jsep_transport.h"
|
||||
#include "pc/rtp_transport.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "pc/sctp_transport.h"
|
||||
#include "pc/session_description.h"
|
||||
#include "pc/srtp_transport.h"
|
||||
#include "pc/transport_stats.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/rtc_certificate.h"
|
||||
#include "rtc_base/ssl_certificate.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
|
||||
@ -225,6 +258,15 @@ std::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
|
||||
RTCErrorOr<webrtc::PayloadType> JsepTransportController::SuggestPayloadType(
|
||||
const std::string& mid,
|
||||
cricket::Codec codec) {
|
||||
// Because SDP processing runs on the signal thread and Call processing
|
||||
// runs on the worker thread, we allow cross thread invocation until we
|
||||
// can clean up the thread work.
|
||||
if (!network_thread_->IsCurrent()) {
|
||||
return network_thread_->BlockingCall([&] {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
return SuggestPayloadType(mid, codec);
|
||||
});
|
||||
}
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
const cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
|
||||
if (transport) {
|
||||
@ -245,6 +287,27 @@ RTCErrorOr<webrtc::PayloadType> JsepTransportController::SuggestPayloadType(
|
||||
return payload_type_picker_.SuggestMapping(codec, nullptr);
|
||||
}
|
||||
|
||||
RTCError JsepTransportController::AddLocalMapping(const std::string& mid,
|
||||
PayloadType payload_type,
|
||||
const cricket::Codec& codec) {
|
||||
// Because SDP processing runs on the signal thread and Call processing
|
||||
// runs on the worker thread, we allow cross thread invocation until we
|
||||
// can clean up the thread work.
|
||||
if (!network_thread_->IsCurrent()) {
|
||||
return network_thread_->BlockingCall([&] {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
return AddLocalMapping(mid, payload_type, codec);
|
||||
});
|
||||
}
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
|
||||
if (!transport) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
||||
"AddLocalMapping: no transport for mid");
|
||||
}
|
||||
return transport->local_payload_types().AddMapping(payload_type, codec);
|
||||
}
|
||||
|
||||
bool JsepTransportController::SetLocalCertificate(
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
|
||||
if (!network_thread_->IsCurrent()) {
|
||||
|
||||
@ -243,6 +243,9 @@ class JsepTransportController : public PayloadTypeSuggester,
|
||||
// or a newly suggested one.
|
||||
RTCErrorOr<PayloadType> SuggestPayloadType(const std::string& mid,
|
||||
cricket::Codec codec) override;
|
||||
RTCError AddLocalMapping(const std::string& mid,
|
||||
PayloadType payload_type,
|
||||
const cricket::Codec& codec) override;
|
||||
|
||||
// TODO(deadbeef): GetStats isn't const because all the way down to
|
||||
// OpenSSLStreamAdapter, GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not
|
||||
|
||||
@ -13,54 +13,110 @@
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/adaptation/resource.h"
|
||||
#include "api/audio/audio_device.h"
|
||||
#include "api/candidate.h"
|
||||
#include "api/crypto/crypto_options.h"
|
||||
#include "api/data_channel_interface.h"
|
||||
#include "api/dtls_transport_interface.h"
|
||||
#include "api/environment/environment.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/jsep_ice_candidate.h"
|
||||
#include "api/make_ref_counted.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtc_event_log_output.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_receiver_interface.h"
|
||||
#include "api/rtp_sender_interface.h"
|
||||
#include "api/rtp_transceiver_direction.h"
|
||||
#include "api/rtp_transceiver_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/sctp_transport_interface.h"
|
||||
#include "api/sequence_checker.h"
|
||||
#include "api/set_local_description_observer_interface.h"
|
||||
#include "api/set_remote_description_observer_interface.h"
|
||||
#include "api/stats/rtc_stats_collector_callback.h"
|
||||
#include "api/task_queue/pending_task_safety_flag.h"
|
||||
#include "api/transport/bandwidth_estimation_settings.h"
|
||||
#include "api/transport/bitrate_settings.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "api/transport/enums.h"
|
||||
#include "api/turn_customizer.h"
|
||||
#include "api/uma_metrics.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "call/audio_state.h"
|
||||
#include "call/packet_receiver.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_config.h"
|
||||
#include "media/base/media_engine.h"
|
||||
#include "media/base/rid_description.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "p2p/base/basic_async_resolver_factory.h"
|
||||
#include "p2p/base/connection.h"
|
||||
#include "p2p/base/connection_info.h"
|
||||
#include "p2p/base/dtls_transport_internal.h"
|
||||
#include "p2p/base/ice_transport_internal.h"
|
||||
#include "p2p/base/p2p_constants.h"
|
||||
#include "p2p/base/p2p_transport_channel.h"
|
||||
#include "p2p/base/port.h"
|
||||
#include "p2p/base/port_allocator.h"
|
||||
#include "p2p/base/transport_description.h"
|
||||
#include "p2p/base/transport_info.h"
|
||||
#include "pc/channel_interface.h"
|
||||
#include "pc/connection_context.h"
|
||||
#include "pc/data_channel_utils.h"
|
||||
#include "pc/dtls_transport.h"
|
||||
#include "pc/ice_server_parsing.h"
|
||||
#include "pc/jsep_transport_controller.h"
|
||||
#include "pc/legacy_stats_collector.h"
|
||||
#include "pc/rtc_stats_collector.h"
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "pc/rtp_receiver_proxy.h"
|
||||
#include "pc/rtp_sender.h"
|
||||
#include "pc/rtp_sender_proxy.h"
|
||||
#include "pc/rtp_transceiver.h"
|
||||
#include "pc/rtp_transmission_manager.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "pc/sctp_data_channel.h"
|
||||
#include "pc/sctp_transport.h"
|
||||
#include "pc/sdp_offer_answer.h"
|
||||
#include "pc/session_description.h"
|
||||
#include "pc/simulcast_description.h"
|
||||
#include "pc/webrtc_session_description_factory.h"
|
||||
#include "pc/transceiver_list.h"
|
||||
#include "pc/transport_stats.h"
|
||||
#include "pc/usage_pattern.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/crypto_random.h"
|
||||
#include "rtc_base/ip_address.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/net_helper.h"
|
||||
#include "rtc_base/network.h"
|
||||
#include "rtc_base/network_constants.h"
|
||||
#include "rtc_base/rtc_certificate.h"
|
||||
#include "rtc_base/socket_address.h"
|
||||
#include "rtc_base/ssl_certificate.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
#include "rtc_base/unique_id_generator.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
@ -695,6 +751,12 @@ RTCError PeerConnection::Initialize(
|
||||
kPeerConnectionAddressFamilyCounter_Max);
|
||||
return InitializeTransportController_n(configuration, dependencies);
|
||||
});
|
||||
if (call_ptr_) {
|
||||
worker_thread()->BlockingCall([this, tc = transport_controller_copy_] {
|
||||
RTC_DCHECK_RUN_ON(worker_thread());
|
||||
call_->SetPayloadTypeSuggester(tc);
|
||||
});
|
||||
}
|
||||
|
||||
configuration_ = configuration;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user