Delete MediaTransportInterface and DatagramTransportInterface
Bug: webrtc:9719 Change-Id: Ic9936a78ab42f4a9bb4cc3265f0a2cf36946558f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176500 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Reviewed-by: Taylor <deadbeef@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Commit-Queue: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31536}
This commit is contained in:
parent
6476d0bf02
commit
2a70703eb8
43
api/BUILD.gn
43
api/BUILD.gn
@ -183,13 +183,9 @@ rtc_library("libjingle_peerconnection_api") {
|
||||
"rtc_event_log",
|
||||
"task_queue",
|
||||
"transport:bitrate_settings",
|
||||
"transport:datagram_transport_interface",
|
||||
"transport:enums",
|
||||
"transport:network_control",
|
||||
"transport:webrtc_key_value_config",
|
||||
"transport/media:audio_interfaces",
|
||||
"transport/media:media_transport_interface",
|
||||
"transport/media:video_interfaces",
|
||||
"transport/rtp:rtp_source",
|
||||
"units:data_rate",
|
||||
"units:timestamp",
|
||||
@ -277,7 +273,6 @@ rtc_source_set("video_quality_test_fixture_api") {
|
||||
"../test:video_test_common",
|
||||
"transport:bitrate_settings",
|
||||
"transport:network_control",
|
||||
"transport/media:media_transport_interface",
|
||||
"video_codecs:video_codecs_api",
|
||||
]
|
||||
}
|
||||
@ -388,7 +383,6 @@ rtc_source_set("peer_connection_quality_test_fixture_api") {
|
||||
"rtc_event_log",
|
||||
"task_queue",
|
||||
"transport:network_control",
|
||||
"transport/media:media_transport_interface",
|
||||
"units:time_delta",
|
||||
"video:video_frame",
|
||||
"video_codecs:video_codecs_api",
|
||||
@ -972,39 +966,6 @@ if (rtc_include_tests) {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("fake_media_transport") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"test/fake_datagram_transport.h",
|
||||
"test/fake_media_transport.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../rtc_base:checks",
|
||||
"transport:datagram_transport_interface",
|
||||
"transport/media:media_transport_interface",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ]
|
||||
}
|
||||
|
||||
rtc_library("loopback_media_transport") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"test/loopback_media_transport.cc",
|
||||
"test/loopback_media_transport.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../rtc_base",
|
||||
"../rtc_base:checks",
|
||||
"transport:datagram_transport_interface",
|
||||
"transport/media:media_transport_interface",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ]
|
||||
}
|
||||
|
||||
rtc_library("create_time_controller") {
|
||||
visibility = [ "*" ]
|
||||
testonly = true
|
||||
@ -1035,7 +996,6 @@ if (rtc_include_tests) {
|
||||
"rtp_parameters_unittest.cc",
|
||||
"scoped_refptr_unittest.cc",
|
||||
"test/create_time_controller_unittest.cc",
|
||||
"test/loopback_media_transport_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -1043,7 +1003,6 @@ if (rtc_include_tests) {
|
||||
":create_time_controller",
|
||||
":function_view",
|
||||
":libjingle_peerconnection_api",
|
||||
":loopback_media_transport",
|
||||
":rtc_error",
|
||||
":rtc_event_log_output_file",
|
||||
":rtp_packet_info",
|
||||
@ -1074,8 +1033,6 @@ if (rtc_include_tests) {
|
||||
":dummy_peer_connection",
|
||||
":fake_frame_decryptor",
|
||||
":fake_frame_encryptor",
|
||||
":fake_media_transport",
|
||||
":loopback_media_transport",
|
||||
":mock_audio_mixer",
|
||||
":mock_frame_decryptor",
|
||||
":mock_frame_encryptor",
|
||||
|
||||
5
api/DEPS
5
api/DEPS
@ -115,11 +115,6 @@ specific_include_rules = {
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"media_transport_interface\.h": [
|
||||
"+rtc_base/copy_on_write_buffer.h", # As used by datachannelinterface.h
|
||||
"+rtc_base/network_route.h",
|
||||
],
|
||||
|
||||
"packet_socket_factory\.h": [
|
||||
"+rtc_base/proxy_info.h",
|
||||
"+rtc_base/async_packet_socket.h",
|
||||
|
||||
@ -103,7 +103,6 @@
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/transport/bitrate_settings.h"
|
||||
#include "api/transport/enums.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/transport/webrtc_key_value_config.h"
|
||||
#include "api/turn_customizer.h"
|
||||
@ -614,34 +613,6 @@ class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
// correctly. This flag will be deprecated soon. Do not rely on it.
|
||||
bool active_reset_srtp_params = false;
|
||||
|
||||
// DEPRECATED. Do not use. This option is ignored by peer connection.
|
||||
// TODO(webrtc:9719): Delete this option.
|
||||
bool use_media_transport = false;
|
||||
|
||||
// DEPRECATED. Do not use. This option is ignored by peer connection.
|
||||
// TODO(webrtc:9719): Delete this option.
|
||||
bool use_media_transport_for_data_channels = false;
|
||||
|
||||
// If MediaTransportFactory is provided in PeerConnectionFactory, this flag
|
||||
// informs PeerConnection that it should use the DatagramTransportInterface
|
||||
// for packets instead DTLS. It's invalid to set it to |true| if the
|
||||
// MediaTransportFactory wasn't provided.
|
||||
absl::optional<bool> use_datagram_transport;
|
||||
|
||||
// If MediaTransportFactory is provided in PeerConnectionFactory, this flag
|
||||
// informs PeerConnection that it should use the DatagramTransport's
|
||||
// implementation of DataChannelTransportInterface for data channels instead
|
||||
// of SCTP-DTLS.
|
||||
absl::optional<bool> use_datagram_transport_for_data_channels;
|
||||
|
||||
// If true, this PeerConnection will only use datagram transport for data
|
||||
// channels when receiving an incoming offer that includes datagram
|
||||
// transport parameters. It will not request use of a datagram transport
|
||||
// when it creates the initial, outgoing offer.
|
||||
// This setting only applies when |use_datagram_transport_for_data_channels|
|
||||
// is true.
|
||||
absl::optional<bool> use_datagram_transport_for_data_channels_receive_only;
|
||||
|
||||
// Defines advanced optional cryptographic settings related to SRTP and
|
||||
// frame encryption for native WebRTC. Setting this will overwrite any
|
||||
// settings set in PeerConnectionFactory (which is deprecated).
|
||||
@ -1339,7 +1310,6 @@ struct RTC_EXPORT PeerConnectionFactoryDependencies final {
|
||||
std::unique_ptr<NetworkStatePredictorFactoryInterface>
|
||||
network_state_predictor_factory;
|
||||
std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory;
|
||||
std::unique_ptr<MediaTransportFactory> media_transport_factory;
|
||||
std::unique_ptr<NetEqFactory> neteq_factory;
|
||||
std::unique_ptr<WebRtcKeyValueConfig> trials;
|
||||
};
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
|
||||
#include "api/test/fake_frame_decryptor.h"
|
||||
#include "api/test/fake_frame_encryptor.h"
|
||||
#include "api/test/fake_media_transport.h"
|
||||
#include "api/test/loopback_media_transport.h"
|
||||
#include "api/test/mock_audio_mixer.h"
|
||||
#include "api/test/mock_frame_decryptor.h"
|
||||
#include "api/test/mock_frame_encryptor.h"
|
||||
|
||||
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 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 API_TEST_FAKE_DATAGRAM_TRANSPORT_H_
|
||||
#define API_TEST_FAKE_DATAGRAM_TRANSPORT_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Maxmum size of datagrams sent by |FakeDatagramTransport|.
|
||||
constexpr size_t kMaxFakeDatagramSize = 1000;
|
||||
|
||||
// Fake datagram transport. Does not support making an actual connection
|
||||
// or sending data. Only used for tests that need to stub out a transport.
|
||||
class FakeDatagramTransport : public DatagramTransportInterface {
|
||||
public:
|
||||
FakeDatagramTransport(
|
||||
const MediaTransportSettings& settings,
|
||||
std::string transport_parameters,
|
||||
const std::function<bool(absl::string_view, absl::string_view)>&
|
||||
are_parameters_compatible)
|
||||
: settings_(settings),
|
||||
transport_parameters_(transport_parameters),
|
||||
are_parameters_compatible_(are_parameters_compatible) {}
|
||||
|
||||
~FakeDatagramTransport() override { RTC_DCHECK(!state_callback_); }
|
||||
|
||||
void Connect(rtc::PacketTransportInternal* packet_transport) override {
|
||||
packet_transport_ = packet_transport;
|
||||
}
|
||||
|
||||
CongestionControlInterface* congestion_control() override {
|
||||
return nullptr; // Datagram interface doesn't provide this yet.
|
||||
}
|
||||
|
||||
void SetTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) override {
|
||||
state_callback_ = callback;
|
||||
}
|
||||
|
||||
RTCError SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) override {
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
size_t GetLargestDatagramSize() const override {
|
||||
return kMaxFakeDatagramSize;
|
||||
}
|
||||
|
||||
void SetDatagramSink(DatagramSinkInterface* sink) override {}
|
||||
|
||||
std::string GetTransportParameters() const override {
|
||||
if (settings_.remote_transport_parameters) {
|
||||
return *settings_.remote_transport_parameters;
|
||||
}
|
||||
return transport_parameters_;
|
||||
}
|
||||
|
||||
RTCError SetRemoteTransportParameters(
|
||||
absl::string_view remote_parameters) override {
|
||||
if (are_parameters_compatible_(GetTransportParameters(),
|
||||
remote_parameters)) {
|
||||
return RTCError::OK();
|
||||
}
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
|
||||
"Incompatible remote transport parameters");
|
||||
}
|
||||
|
||||
RTCError OpenChannel(int channel_id) override {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
RTCError SendData(int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) override {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
RTCError CloseChannel(int channel_id) override {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
void SetDataSink(DataChannelSink* /*sink*/) override {}
|
||||
|
||||
bool IsReadyToSend() const override { return false; }
|
||||
|
||||
rtc::PacketTransportInternal* packet_transport() { return packet_transport_; }
|
||||
|
||||
void set_state(webrtc::MediaTransportState state) {
|
||||
if (state_callback_) {
|
||||
state_callback_->OnStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
const MediaTransportSettings& settings() { return settings_; }
|
||||
|
||||
private:
|
||||
const MediaTransportSettings settings_;
|
||||
const std::string transport_parameters_;
|
||||
const std::function<bool(absl::string_view, absl::string_view)>
|
||||
are_parameters_compatible_;
|
||||
|
||||
rtc::PacketTransportInternal* packet_transport_ = nullptr;
|
||||
MediaTransportStateCallback* state_callback_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TEST_FAKE_DATAGRAM_TRANSPORT_H_
|
||||
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 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 API_TEST_FAKE_MEDIA_TRANSPORT_H_
|
||||
#define API_TEST_FAKE_MEDIA_TRANSPORT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "api/test/fake_datagram_transport.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Fake media transport factory creates fake media transport.
|
||||
// Also creates fake datagram transport, since both media and datagram
|
||||
// transports are created by |MediaTransportFactory|.
|
||||
class FakeMediaTransportFactory : public MediaTransportFactory {
|
||||
public:
|
||||
explicit FakeMediaTransportFactory(
|
||||
const absl::optional<std::string>& transport_offer = "")
|
||||
: transport_offer_(transport_offer) {}
|
||||
~FakeMediaTransportFactory() = default;
|
||||
|
||||
std::string GetTransportName() const override { return "fake"; }
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
|
||||
rtc::PacketTransportInternal* packet_transport,
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<DatagramTransportInterface>>
|
||||
CreateDatagramTransport(rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override {
|
||||
return std::unique_ptr<DatagramTransportInterface>(
|
||||
new FakeDatagramTransport(settings, transport_offer_.value_or(""),
|
||||
transport_parameters_comparison_));
|
||||
}
|
||||
|
||||
void set_transport_parameters_comparison(
|
||||
std::function<bool(absl::string_view, absl::string_view)> comparison) {
|
||||
transport_parameters_comparison_ = std::move(comparison);
|
||||
}
|
||||
|
||||
private:
|
||||
const absl::optional<std::string> transport_offer_;
|
||||
std::function<bool(absl::string_view, absl::string_view)>
|
||||
transport_parameters_comparison_ =
|
||||
[](absl::string_view local, absl::string_view remote) {
|
||||
return local == remote;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TEST_FAKE_MEDIA_TRANSPORT_H_
|
||||
@ -1,373 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/test/loopback_media_transport.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t kLoopbackMaxDatagramSize = 1200;
|
||||
|
||||
class WrapperDatagramTransport : public DatagramTransportInterface {
|
||||
public:
|
||||
explicit WrapperDatagramTransport(DatagramTransportInterface* wrapped)
|
||||
: wrapped_(wrapped) {}
|
||||
|
||||
// Datagram transport overrides.
|
||||
void Connect(rtc::PacketTransportInternal* packet_transport) override {
|
||||
return wrapped_->Connect(packet_transport);
|
||||
}
|
||||
|
||||
CongestionControlInterface* congestion_control() override {
|
||||
return wrapped_->congestion_control();
|
||||
}
|
||||
|
||||
void SetTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) override {
|
||||
return wrapped_->SetTransportStateCallback(callback);
|
||||
}
|
||||
|
||||
RTCError SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) override {
|
||||
return wrapped_->SendDatagram(data, datagram_id);
|
||||
}
|
||||
|
||||
size_t GetLargestDatagramSize() const override {
|
||||
return wrapped_->GetLargestDatagramSize();
|
||||
}
|
||||
|
||||
void SetDatagramSink(DatagramSinkInterface* sink) override {
|
||||
return wrapped_->SetDatagramSink(sink);
|
||||
}
|
||||
|
||||
std::string GetTransportParameters() const override {
|
||||
return wrapped_->GetTransportParameters();
|
||||
}
|
||||
|
||||
RTCError SetRemoteTransportParameters(absl::string_view parameters) override {
|
||||
return wrapped_->SetRemoteTransportParameters(parameters);
|
||||
}
|
||||
|
||||
// Data channel overrides.
|
||||
RTCError OpenChannel(int channel_id) override {
|
||||
return wrapped_->OpenChannel(channel_id);
|
||||
}
|
||||
|
||||
RTCError SendData(int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) override {
|
||||
return wrapped_->SendData(channel_id, params, buffer);
|
||||
}
|
||||
|
||||
RTCError CloseChannel(int channel_id) override {
|
||||
return wrapped_->CloseChannel(channel_id);
|
||||
}
|
||||
|
||||
void SetDataSink(DataChannelSink* sink) override {
|
||||
wrapped_->SetDataSink(sink);
|
||||
}
|
||||
|
||||
bool IsReadyToSend() const override { return wrapped_->IsReadyToSend(); }
|
||||
|
||||
private:
|
||||
DatagramTransportInterface* wrapped_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WrapperMediaTransportFactory::WrapperMediaTransportFactory(
|
||||
DatagramTransportInterface* wrapped_datagram_transport)
|
||||
: wrapped_datagram_transport_(wrapped_datagram_transport) {}
|
||||
|
||||
WrapperMediaTransportFactory::WrapperMediaTransportFactory(
|
||||
MediaTransportFactory* wrapped)
|
||||
: wrapped_factory_(wrapped) {}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
|
||||
WrapperMediaTransportFactory::CreateMediaTransport(
|
||||
rtc::PacketTransportInternal* packet_transport,
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<DatagramTransportInterface>>
|
||||
WrapperMediaTransportFactory::CreateDatagramTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
created_transport_count_++;
|
||||
if (wrapped_factory_) {
|
||||
return wrapped_factory_->CreateDatagramTransport(network_thread, settings);
|
||||
}
|
||||
return {
|
||||
std::make_unique<WrapperDatagramTransport>(wrapped_datagram_transport_)};
|
||||
}
|
||||
|
||||
std::string WrapperMediaTransportFactory::GetTransportName() const {
|
||||
if (wrapped_factory_) {
|
||||
return wrapped_factory_->GetTransportName();
|
||||
}
|
||||
return "wrapped-transport";
|
||||
}
|
||||
|
||||
int WrapperMediaTransportFactory::created_transport_count() const {
|
||||
return created_transport_count_;
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
|
||||
WrapperMediaTransportFactory::CreateMediaTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
MediaTransportPair::MediaTransportPair(rtc::Thread* thread)
|
||||
: first_datagram_transport_(thread),
|
||||
second_datagram_transport_(thread),
|
||||
first_factory_(&first_datagram_transport_),
|
||||
second_factory_(&second_datagram_transport_) {
|
||||
first_datagram_transport_.Connect(&second_datagram_transport_);
|
||||
second_datagram_transport_.Connect(&first_datagram_transport_);
|
||||
}
|
||||
|
||||
MediaTransportPair::~MediaTransportPair() = default;
|
||||
|
||||
MediaTransportPair::LoopbackDataChannelTransport::LoopbackDataChannelTransport(
|
||||
rtc::Thread* thread)
|
||||
: thread_(thread) {}
|
||||
|
||||
MediaTransportPair::LoopbackDataChannelTransport::
|
||||
~LoopbackDataChannelTransport() {
|
||||
RTC_CHECK(data_sink_ == nullptr);
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::Connect(
|
||||
LoopbackDataChannelTransport* other) {
|
||||
other_ = other;
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDataChannelTransport::OpenChannel(
|
||||
int channel_id) {
|
||||
// No-op. No need to open channels for the loopback.
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDataChannelTransport::SendData(
|
||||
int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) {
|
||||
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_,
|
||||
[this, channel_id, params, buffer] {
|
||||
other_->OnData(channel_id, params.type, buffer);
|
||||
});
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDataChannelTransport::CloseChannel(
|
||||
int channel_id) {
|
||||
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, channel_id] {
|
||||
other_->OnRemoteCloseChannel(channel_id);
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
if (data_sink_) {
|
||||
data_sink_->OnChannelClosed(channel_id);
|
||||
}
|
||||
});
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::SetDataSink(
|
||||
DataChannelSink* sink) {
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
data_sink_ = sink;
|
||||
if (data_sink_ && ready_to_send_) {
|
||||
data_sink_->OnReadyToSend();
|
||||
}
|
||||
}
|
||||
|
||||
bool MediaTransportPair::LoopbackDataChannelTransport::IsReadyToSend() const {
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
return ready_to_send_;
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::FlushAsyncInvokes() {
|
||||
invoker_.Flush(thread_);
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::OnData(
|
||||
int channel_id,
|
||||
DataMessageType type,
|
||||
const rtc::CopyOnWriteBuffer& buffer) {
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
if (data_sink_) {
|
||||
data_sink_->OnDataReceived(channel_id, type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::OnRemoteCloseChannel(
|
||||
int channel_id) {
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
if (data_sink_) {
|
||||
data_sink_->OnChannelClosing(channel_id);
|
||||
data_sink_->OnChannelClosed(channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDataChannelTransport::OnReadyToSend(
|
||||
bool ready_to_send) {
|
||||
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, ready_to_send] {
|
||||
rtc::CritScope lock(&sink_lock_);
|
||||
ready_to_send_ = ready_to_send;
|
||||
// Propagate state to data channel sink, if present.
|
||||
if (data_sink_ && ready_to_send_) {
|
||||
data_sink_->OnReadyToSend();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MediaTransportPair::LoopbackDatagramTransport::LoopbackDatagramTransport(
|
||||
rtc::Thread* thread)
|
||||
: thread_(thread), dc_transport_(thread) {}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::Connect(
|
||||
LoopbackDatagramTransport* other) {
|
||||
other_ = other;
|
||||
dc_transport_.Connect(&other->dc_transport_);
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::Connect(
|
||||
rtc::PacketTransportInternal* packet_transport) {
|
||||
if (state_after_connect_) {
|
||||
SetState(*state_after_connect_);
|
||||
}
|
||||
}
|
||||
|
||||
CongestionControlInterface*
|
||||
MediaTransportPair::LoopbackDatagramTransport::congestion_control() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::SetTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
state_callback_ = callback;
|
||||
if (state_callback_) {
|
||||
state_callback_->OnStateChanged(state_);
|
||||
}
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDatagramTransport::SendDatagram(
|
||||
rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) {
|
||||
rtc::CopyOnWriteBuffer buffer;
|
||||
buffer.SetData(data.data(), data.size());
|
||||
invoker_.AsyncInvoke<void>(
|
||||
RTC_FROM_HERE, thread_, [this, datagram_id, buffer = std::move(buffer)] {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
other_->DeliverDatagram(std::move(buffer));
|
||||
if (sink_) {
|
||||
DatagramAck ack;
|
||||
ack.datagram_id = datagram_id;
|
||||
ack.receive_timestamp = Timestamp::Micros(rtc::TimeMicros());
|
||||
sink_->OnDatagramAcked(ack);
|
||||
}
|
||||
});
|
||||
return RTCError::OK();
|
||||
}
|
||||
|
||||
size_t MediaTransportPair::LoopbackDatagramTransport::GetLargestDatagramSize()
|
||||
const {
|
||||
return kLoopbackMaxDatagramSize;
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::SetDatagramSink(
|
||||
DatagramSinkInterface* sink) {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
sink_ = sink;
|
||||
}
|
||||
|
||||
std::string
|
||||
MediaTransportPair::LoopbackDatagramTransport::GetTransportParameters() const {
|
||||
return transport_parameters_;
|
||||
}
|
||||
|
||||
RTCError
|
||||
MediaTransportPair::LoopbackDatagramTransport::SetRemoteTransportParameters(
|
||||
absl::string_view remote_parameters) {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
if (transport_parameters_comparison_(GetTransportParameters(),
|
||||
remote_parameters)) {
|
||||
return RTCError::OK();
|
||||
}
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
|
||||
"Incompatible remote transport parameters");
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDatagramTransport::OpenChannel(
|
||||
int channel_id) {
|
||||
return dc_transport_.OpenChannel(channel_id);
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDatagramTransport::SendData(
|
||||
int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) {
|
||||
return dc_transport_.SendData(channel_id, params, buffer);
|
||||
}
|
||||
|
||||
RTCError MediaTransportPair::LoopbackDatagramTransport::CloseChannel(
|
||||
int channel_id) {
|
||||
return dc_transport_.CloseChannel(channel_id);
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::SetDataSink(
|
||||
DataChannelSink* sink) {
|
||||
dc_transport_.SetDataSink(sink);
|
||||
}
|
||||
|
||||
bool MediaTransportPair::LoopbackDatagramTransport::IsReadyToSend() const {
|
||||
return dc_transport_.IsReadyToSend();
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::SetState(
|
||||
MediaTransportState state) {
|
||||
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, thread_, [this, state] {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
state_ = state;
|
||||
if (state_callback_) {
|
||||
state_callback_->OnStateChanged(state_);
|
||||
}
|
||||
});
|
||||
dc_transport_.OnReadyToSend(state == MediaTransportState::kWritable);
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::SetStateAfterConnect(
|
||||
MediaTransportState state) {
|
||||
state_after_connect_ = state;
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::FlushAsyncInvokes() {
|
||||
dc_transport_.FlushAsyncInvokes();
|
||||
}
|
||||
|
||||
void MediaTransportPair::LoopbackDatagramTransport::DeliverDatagram(
|
||||
rtc::CopyOnWriteBuffer buffer) {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
if (sink_) {
|
||||
sink_->OnDatagramReceived(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,269 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 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 API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_
|
||||
#define API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "rtc_base/async_invoker.h"
|
||||
#include "rtc_base/critical_section.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Wrapper used to hand out unique_ptrs to loopback media
|
||||
// transport without ownership changes to the underlying
|
||||
// transport.
|
||||
// It works in two modes:
|
||||
// It can either wrap a factory, or it can wrap an existing interface.
|
||||
// In the former mode, it delegates the work to the wrapped factory.
|
||||
// In the latter mode, it always returns static instance of the transport
|
||||
// interface.
|
||||
//
|
||||
// Example use:
|
||||
// Factory wrap_static_interface = Wrapper(media_transport_interface);
|
||||
// Factory wrap_factory = Wrapper(wrap_static_interface);
|
||||
// The second factory may be created multiple times, and ownership may be passed
|
||||
// to the client. The first factory counts the number of invocations of
|
||||
// CreateMediaTransport();
|
||||
class WrapperMediaTransportFactory : public MediaTransportFactory {
|
||||
public:
|
||||
explicit WrapperMediaTransportFactory(
|
||||
DatagramTransportInterface* wrapped_datagram_transport);
|
||||
explicit WrapperMediaTransportFactory(MediaTransportFactory* wrapped);
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
|
||||
rtc::PacketTransportInternal* packet_transport,
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override;
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override;
|
||||
|
||||
RTCErrorOr<std::unique_ptr<DatagramTransportInterface>>
|
||||
CreateDatagramTransport(rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) override;
|
||||
|
||||
std::string GetTransportName() const override;
|
||||
|
||||
int created_transport_count() const;
|
||||
|
||||
private:
|
||||
DatagramTransportInterface* wrapped_datagram_transport_ = nullptr;
|
||||
MediaTransportFactory* wrapped_factory_ = nullptr;
|
||||
int created_transport_count_ = 0;
|
||||
};
|
||||
|
||||
// Contains two MediaTransportsInterfaces that are connected to each other.
|
||||
// Currently supports audio only.
|
||||
class MediaTransportPair {
|
||||
public:
|
||||
struct Stats {
|
||||
int sent_audio_frames = 0;
|
||||
int received_audio_frames = 0;
|
||||
int sent_video_frames = 0;
|
||||
int received_video_frames = 0;
|
||||
};
|
||||
|
||||
explicit MediaTransportPair(rtc::Thread* thread);
|
||||
~MediaTransportPair();
|
||||
|
||||
DatagramTransportInterface* first_datagram_transport() {
|
||||
return &first_datagram_transport_;
|
||||
}
|
||||
DatagramTransportInterface* second_datagram_transport() {
|
||||
return &second_datagram_transport_;
|
||||
}
|
||||
|
||||
std::unique_ptr<MediaTransportFactory> first_factory() {
|
||||
return std::make_unique<WrapperMediaTransportFactory>(&first_factory_);
|
||||
}
|
||||
|
||||
std::unique_ptr<MediaTransportFactory> second_factory() {
|
||||
return std::make_unique<WrapperMediaTransportFactory>(&second_factory_);
|
||||
}
|
||||
|
||||
void SetState(MediaTransportState state) {
|
||||
first_datagram_transport_.SetState(state);
|
||||
second_datagram_transport_.SetState(state);
|
||||
}
|
||||
|
||||
void SetFirstState(MediaTransportState state) {
|
||||
first_datagram_transport_.SetState(state);
|
||||
}
|
||||
|
||||
void SetSecondStateAfterConnect(MediaTransportState state) {
|
||||
second_datagram_transport_.SetState(state);
|
||||
}
|
||||
|
||||
void SetFirstDatagramTransportParameters(const std::string& params) {
|
||||
first_datagram_transport_.set_transport_parameters(params);
|
||||
}
|
||||
|
||||
void SetSecondDatagramTransportParameters(const std::string& params) {
|
||||
second_datagram_transport_.set_transport_parameters(params);
|
||||
}
|
||||
|
||||
void SetFirstDatagramTransportParametersComparison(
|
||||
std::function<bool(absl::string_view, absl::string_view)> comparison) {
|
||||
first_datagram_transport_.set_transport_parameters_comparison(
|
||||
std::move(comparison));
|
||||
}
|
||||
|
||||
void SetSecondDatagramTransportParametersComparison(
|
||||
std::function<bool(absl::string_view, absl::string_view)> comparison) {
|
||||
second_datagram_transport_.set_transport_parameters_comparison(
|
||||
std::move(comparison));
|
||||
}
|
||||
|
||||
void FlushAsyncInvokes() {
|
||||
first_datagram_transport_.FlushAsyncInvokes();
|
||||
second_datagram_transport_.FlushAsyncInvokes();
|
||||
}
|
||||
|
||||
int first_factory_transport_count() const {
|
||||
return first_factory_.created_transport_count();
|
||||
}
|
||||
|
||||
int second_factory_transport_count() const {
|
||||
return second_factory_.created_transport_count();
|
||||
}
|
||||
|
||||
private:
|
||||
class LoopbackDataChannelTransport : public DataChannelTransportInterface {
|
||||
public:
|
||||
explicit LoopbackDataChannelTransport(rtc::Thread* thread);
|
||||
~LoopbackDataChannelTransport() override;
|
||||
|
||||
void Connect(LoopbackDataChannelTransport* other);
|
||||
|
||||
RTCError OpenChannel(int channel_id) override;
|
||||
|
||||
RTCError SendData(int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) override;
|
||||
|
||||
RTCError CloseChannel(int channel_id) override;
|
||||
|
||||
bool IsReadyToSend() const override;
|
||||
|
||||
void SetDataSink(DataChannelSink* sink) override;
|
||||
|
||||
void OnReadyToSend(bool ready_to_send);
|
||||
|
||||
void FlushAsyncInvokes();
|
||||
|
||||
private:
|
||||
void OnData(int channel_id,
|
||||
DataMessageType type,
|
||||
const rtc::CopyOnWriteBuffer& buffer);
|
||||
|
||||
void OnRemoteCloseChannel(int channel_id);
|
||||
|
||||
rtc::Thread* const thread_;
|
||||
rtc::CriticalSection sink_lock_;
|
||||
DataChannelSink* data_sink_ RTC_GUARDED_BY(sink_lock_) = nullptr;
|
||||
|
||||
bool ready_to_send_ RTC_GUARDED_BY(sink_lock_) = false;
|
||||
|
||||
LoopbackDataChannelTransport* other_;
|
||||
|
||||
rtc::AsyncInvoker invoker_;
|
||||
};
|
||||
|
||||
class LoopbackDatagramTransport : public DatagramTransportInterface {
|
||||
public:
|
||||
explicit LoopbackDatagramTransport(rtc::Thread* thread);
|
||||
|
||||
void Connect(LoopbackDatagramTransport* other);
|
||||
|
||||
// Datagram transport overrides.
|
||||
void Connect(rtc::PacketTransportInternal* packet_transport) override;
|
||||
CongestionControlInterface* congestion_control() override;
|
||||
void SetTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) override;
|
||||
RTCError SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) override;
|
||||
size_t GetLargestDatagramSize() const override;
|
||||
void SetDatagramSink(DatagramSinkInterface* sink) override;
|
||||
std::string GetTransportParameters() const override;
|
||||
RTCError SetRemoteTransportParameters(
|
||||
absl::string_view remote_parameters) override;
|
||||
|
||||
// Data channel overrides.
|
||||
RTCError OpenChannel(int channel_id) override;
|
||||
RTCError SendData(int channel_id,
|
||||
const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& buffer) override;
|
||||
RTCError CloseChannel(int channel_id) override;
|
||||
void SetDataSink(DataChannelSink* sink) override;
|
||||
bool IsReadyToSend() const override;
|
||||
|
||||
// Loopback-specific functionality.
|
||||
void SetState(MediaTransportState state);
|
||||
|
||||
// When Connect() is called, the datagram transport will enter this state.
|
||||
// This is useful for mimicking zero-RTT connectivity, for example.
|
||||
void SetStateAfterConnect(MediaTransportState state);
|
||||
void FlushAsyncInvokes();
|
||||
|
||||
void set_transport_parameters(const std::string& value) {
|
||||
transport_parameters_ = value;
|
||||
}
|
||||
|
||||
void set_transport_parameters_comparison(
|
||||
std::function<bool(absl::string_view, absl::string_view)> comparison) {
|
||||
thread_->Invoke<void>(
|
||||
RTC_FROM_HERE, [this, comparison = std::move(comparison)] {
|
||||
RTC_DCHECK_RUN_ON(thread_);
|
||||
transport_parameters_comparison_ = std::move(comparison);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
void DeliverDatagram(rtc::CopyOnWriteBuffer buffer);
|
||||
|
||||
rtc::Thread* thread_;
|
||||
LoopbackDataChannelTransport dc_transport_;
|
||||
|
||||
MediaTransportState state_ RTC_GUARDED_BY(thread_) =
|
||||
MediaTransportState::kPending;
|
||||
DatagramSinkInterface* sink_ RTC_GUARDED_BY(thread_) = nullptr;
|
||||
MediaTransportStateCallback* state_callback_ RTC_GUARDED_BY(thread_) =
|
||||
nullptr;
|
||||
LoopbackDatagramTransport* other_;
|
||||
|
||||
std::string transport_parameters_;
|
||||
std::function<bool(absl::string_view, absl::string_view)>
|
||||
transport_parameters_comparison_ RTC_GUARDED_BY(thread_) =
|
||||
[](absl::string_view a, absl::string_view b) { return a == b; };
|
||||
|
||||
absl::optional<MediaTransportState> state_after_connect_;
|
||||
|
||||
rtc::AsyncInvoker invoker_;
|
||||
};
|
||||
|
||||
LoopbackDatagramTransport first_datagram_transport_;
|
||||
LoopbackDatagramTransport second_datagram_transport_;
|
||||
WrapperMediaTransportFactory first_factory_;
|
||||
WrapperMediaTransportFactory second_factory_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TEST_LOOPBACK_MEDIA_TRANSPORT_H_
|
||||
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/test/loopback_media_transport.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "test/gmock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
class MockMediaTransportAudioSinkInterface
|
||||
: public MediaTransportAudioSinkInterface {
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
OnData,
|
||||
(uint64_t, MediaTransportEncodedAudioFrame),
|
||||
(override));
|
||||
};
|
||||
|
||||
class MockMediaTransportVideoSinkInterface
|
||||
: public MediaTransportVideoSinkInterface {
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
OnData,
|
||||
(uint64_t, MediaTransportEncodedVideoFrame),
|
||||
(override));
|
||||
};
|
||||
|
||||
class MockMediaTransportKeyFrameRequestCallback
|
||||
: public MediaTransportKeyFrameRequestCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, OnKeyFrameRequested, (uint64_t), (override));
|
||||
};
|
||||
|
||||
class MockDataChannelSink : public DataChannelSink {
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
OnDataReceived,
|
||||
(int, DataMessageType, const rtc::CopyOnWriteBuffer&),
|
||||
(override));
|
||||
MOCK_METHOD(void, OnChannelClosing, (int), (override));
|
||||
MOCK_METHOD(void, OnChannelClosed, (int), (override));
|
||||
MOCK_METHOD(void, OnReadyToSend, (), (override));
|
||||
};
|
||||
|
||||
class MockStateCallback : public MediaTransportStateCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, OnStateChanged, (MediaTransportState), (override));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(LoopbackMediaTransport, DataDeliveredToSink) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockDataChannelSink sink;
|
||||
transport_pair.first_datagram_transport()->SetDataSink(&sink);
|
||||
|
||||
const int channel_id = 1;
|
||||
EXPECT_CALL(
|
||||
sink, OnDataReceived(
|
||||
channel_id, DataMessageType::kText,
|
||||
::testing::Property<rtc::CopyOnWriteBuffer, const char*>(
|
||||
&rtc::CopyOnWriteBuffer::cdata, ::testing::StrEq("foo"))));
|
||||
|
||||
SendDataParams params;
|
||||
params.type = DataMessageType::kText;
|
||||
rtc::CopyOnWriteBuffer buffer("foo");
|
||||
transport_pair.second_datagram_transport()->SendData(channel_id, params,
|
||||
buffer);
|
||||
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
transport_pair.first_datagram_transport()->SetDataSink(nullptr);
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockDataChannelSink first_sink;
|
||||
transport_pair.first_datagram_transport()->SetDataSink(&first_sink);
|
||||
|
||||
MockDataChannelSink second_sink;
|
||||
transport_pair.second_datagram_transport()->SetDataSink(&second_sink);
|
||||
|
||||
const int channel_id = 1;
|
||||
{
|
||||
::testing::InSequence s;
|
||||
EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
|
||||
EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
|
||||
EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
|
||||
}
|
||||
|
||||
transport_pair.first_datagram_transport()->CloseChannel(channel_id);
|
||||
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
transport_pair.first_datagram_transport()->SetDataSink(nullptr);
|
||||
transport_pair.second_datagram_transport()->SetDataSink(nullptr);
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockStateCallback state_callback;
|
||||
EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
|
||||
|
||||
thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
|
||||
transport_pair.first_datagram_transport()->SetTransportStateCallback(
|
||||
&state_callback);
|
||||
});
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
transport_pair.SetState(MediaTransportState::kWritable);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
|
||||
MockStateCallback state_callback;
|
||||
|
||||
EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
|
||||
thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
|
||||
transport_pair.first_datagram_transport()->SetTransportStateCallback(
|
||||
&state_callback);
|
||||
});
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockStateCallback state_callback;
|
||||
|
||||
EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
|
||||
EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
|
||||
thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
|
||||
transport_pair.first_datagram_transport()->SetTransportStateCallback(
|
||||
&state_callback);
|
||||
});
|
||||
transport_pair.SetState(MediaTransportState::kWritable);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, NotReadyToSendWhenDataSinkSet) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockDataChannelSink data_channel_sink;
|
||||
EXPECT_CALL(data_channel_sink, OnReadyToSend()).Times(0);
|
||||
|
||||
transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
transport_pair.first_datagram_transport()->SetDataSink(nullptr);
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, ReadyToSendWhenDataSinkSet) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
transport_pair.SetState(MediaTransportState::kWritable);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
|
||||
MockDataChannelSink data_channel_sink;
|
||||
EXPECT_CALL(data_channel_sink, OnReadyToSend());
|
||||
|
||||
transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
transport_pair.first_datagram_transport()->SetDataSink(nullptr);
|
||||
}
|
||||
|
||||
TEST(LoopbackMediaTransport, StateChangeDeliveredToDataSink) {
|
||||
std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
|
||||
thread->Start();
|
||||
MediaTransportPair transport_pair(thread.get());
|
||||
|
||||
MockDataChannelSink data_channel_sink;
|
||||
EXPECT_CALL(data_channel_sink, OnReadyToSend());
|
||||
|
||||
transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
|
||||
transport_pair.SetState(MediaTransportState::kWritable);
|
||||
transport_pair.FlushAsyncInvokes();
|
||||
transport_pair.first_datagram_transport()->SetDataSink(nullptr);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -33,7 +33,6 @@
|
||||
#include "api/test/simulated_network.h"
|
||||
#include "api/test/stats_observer_interface.h"
|
||||
#include "api/test/video_quality_analyzer_interface.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/video_codecs/video_decoder_factory.h"
|
||||
@ -287,8 +286,6 @@ class PeerConnectionE2EQualityTestFixture {
|
||||
virtual PeerConfigurer* SetNetworkControllerFactory(
|
||||
std::unique_ptr<NetworkControllerFactoryInterface>
|
||||
network_controller_factory) = 0;
|
||||
virtual PeerConfigurer* SetMediaTransportFactory(
|
||||
std::unique_ptr<MediaTransportFactory> media_transport_factory) = 0;
|
||||
virtual PeerConfigurer* SetVideoEncoderFactory(
|
||||
std::unique_ptr<VideoEncoderFactory> video_encoder_factory) = 0;
|
||||
virtual PeerConfigurer* SetVideoDecoderFactory(
|
||||
|
||||
@ -66,20 +66,14 @@ rtc_library("field_trial_based_config") {
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
|
||||
}
|
||||
|
||||
# TODO(nisse): Rename?
|
||||
rtc_source_set("datagram_transport_interface") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"congestion_control_interface.h",
|
||||
"data_channel_transport_interface.h",
|
||||
"datagram_transport_interface.h",
|
||||
]
|
||||
sources = [ "data_channel_transport_interface.h" ]
|
||||
deps = [
|
||||
":network_control",
|
||||
"..:array_view",
|
||||
"..:rtc_error",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../units:data_rate",
|
||||
"../units:timestamp",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
/* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media and datagram transports.
|
||||
|
||||
#ifndef API_TRANSPORT_CONGESTION_CONTROL_INTERFACE_H_
|
||||
#define API_TRANSPORT_CONGESTION_CONTROL_INTERFACE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/units/data_rate.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// TODO(nisse): Defined together with MediaTransportInterface. But we should use
|
||||
// types that aren't tied to media, so that MediaTransportInterface can depend
|
||||
// on CongestionControlInterface, but not the other way around.
|
||||
// api/transport/network_control.h may be a reasonable place.
|
||||
class MediaTransportRttObserver;
|
||||
struct MediaTransportAllocatedBitrateLimits;
|
||||
struct MediaTransportTargetRateConstraints;
|
||||
|
||||
// Defines congestion control feedback interface for media and datagram
|
||||
// transports.
|
||||
class CongestionControlInterface {
|
||||
public:
|
||||
virtual ~CongestionControlInterface() = default;
|
||||
|
||||
// Updates allocation limits.
|
||||
virtual void SetAllocatedBitrateLimits(
|
||||
const MediaTransportAllocatedBitrateLimits& limits) = 0;
|
||||
|
||||
// Sets starting rate.
|
||||
virtual void SetTargetBitrateLimits(
|
||||
const MediaTransportTargetRateConstraints& target_rate_constraints) = 0;
|
||||
|
||||
// Intended for receive side. AddRttObserver registers an observer to be
|
||||
// called for each RTT measurement, typically once per ACK. Before media
|
||||
// transport is destructed the observer must be unregistered.
|
||||
//
|
||||
// TODO(sukhanov): Looks like AddRttObserver and RemoveRttObserver were
|
||||
// never implemented for media transport, so keeping noop implementation.
|
||||
virtual void AddRttObserver(MediaTransportRttObserver* observer) {}
|
||||
virtual void RemoveRttObserver(MediaTransportRttObserver* observer) {}
|
||||
|
||||
// Adds a target bitrate observer. Before media transport is destructed
|
||||
// the observer must be unregistered (by calling
|
||||
// RemoveTargetTransferRateObserver).
|
||||
// A newly registered observer will be called back with the latest recorded
|
||||
// target rate, if available.
|
||||
virtual void AddTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer) = 0;
|
||||
|
||||
// Removes an existing |observer| from observers. If observer was never
|
||||
// registered, an error is logged and method does nothing.
|
||||
virtual void RemoveTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer) = 0;
|
||||
|
||||
// Returns the last known target transfer rate as reported to the above
|
||||
// observers.
|
||||
virtual absl::optional<TargetTransferRate> GetLatestTargetTransferRate() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TRANSPORT_CONGESTION_CONTROL_INTERFACE_H_
|
||||
@ -35,8 +35,8 @@ enum class DataMessageType {
|
||||
// sent reliably and in-order, even if the data channel is configured for
|
||||
// unreliable delivery.
|
||||
struct SendDataParams {
|
||||
SendDataParams();
|
||||
SendDataParams(const SendDataParams&);
|
||||
SendDataParams() = default;
|
||||
SendDataParams(const SendDataParams&) = default;
|
||||
|
||||
DataMessageType type = DataMessageType::kText;
|
||||
|
||||
|
||||
@ -1,151 +0,0 @@
|
||||
/* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media and datagram transports.
|
||||
|
||||
#ifndef API_TRANSPORT_DATAGRAM_TRANSPORT_INTERFACE_H_
|
||||
#define API_TRANSPORT_DATAGRAM_TRANSPORT_INTERFACE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/transport/congestion_control_interface.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "api/units/timestamp.h"
|
||||
|
||||
namespace rtc {
|
||||
class PacketTransportInternal;
|
||||
} // namespace rtc
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MediaTransportStateCallback;
|
||||
|
||||
typedef int64_t DatagramId;
|
||||
|
||||
struct DatagramAck {
|
||||
// |datagram_id| is same as passed in
|
||||
// DatagramTransportInterface::SendDatagram.
|
||||
DatagramId datagram_id;
|
||||
|
||||
// The timestamp at which the remote peer received the identified datagram,
|
||||
// according to that peer's clock.
|
||||
Timestamp receive_timestamp = Timestamp::MinusInfinity();
|
||||
};
|
||||
|
||||
// All sink methods are called on network thread.
|
||||
class DatagramSinkInterface {
|
||||
public:
|
||||
virtual ~DatagramSinkInterface() {}
|
||||
|
||||
// Called when new packet is received.
|
||||
virtual void OnDatagramReceived(rtc::ArrayView<const uint8_t> data) = 0;
|
||||
|
||||
// Called when datagram is actually sent (datragram can be delayed due
|
||||
// to congestion control or fusing). |datagram_id| is same as passed in
|
||||
// DatagramTransportInterface::SendDatagram.
|
||||
virtual void OnDatagramSent(DatagramId datagram_id) = 0;
|
||||
|
||||
// Called when datagram is ACKed.
|
||||
virtual void OnDatagramAcked(const DatagramAck& datagram_ack) = 0;
|
||||
|
||||
// Called when a datagram is lost.
|
||||
virtual void OnDatagramLost(DatagramId datagram_id) = 0;
|
||||
};
|
||||
|
||||
// Datagram transport allows to send and receive unreliable packets (datagrams)
|
||||
// and receive feedback from congestion control (via
|
||||
// CongestionControlInterface). The idea is to send RTP packets as datagrams and
|
||||
// have underlying implementation of datagram transport to use QUIC datagram
|
||||
// protocol.
|
||||
class DatagramTransportInterface : public DataChannelTransportInterface {
|
||||
public:
|
||||
virtual ~DatagramTransportInterface() = default;
|
||||
|
||||
// Connect the datagram transport to the ICE transport.
|
||||
// The implementation must be able to ignore incoming packets that don't
|
||||
// belong to it.
|
||||
virtual void Connect(rtc::PacketTransportInternal* packet_transport) = 0;
|
||||
|
||||
// Returns congestion control feedback interface or nullptr if datagram
|
||||
// transport does not implement congestion control.
|
||||
//
|
||||
// Note that right now datagram transport is used without congestion control,
|
||||
// but we plan to use it in the future.
|
||||
virtual CongestionControlInterface* congestion_control() = 0;
|
||||
|
||||
// Sets a state observer callback. Before datagram transport is destroyed, the
|
||||
// callback must be unregistered by setting it to nullptr.
|
||||
// A newly registered callback will be called with the current state.
|
||||
// Datagram transport does not invoke this callback concurrently.
|
||||
virtual void SetTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) = 0;
|
||||
|
||||
// Start asynchronous send of datagram. The status returned by this method
|
||||
// only pertains to the synchronous operations (e.g. serialization /
|
||||
// packetization), not to the asynchronous operation.
|
||||
//
|
||||
// Datagrams larger than GetLargestDatagramSize() will fail and return error.
|
||||
//
|
||||
// Datagrams are sent in FIFO order.
|
||||
//
|
||||
// |datagram_id| is only used in ACK/LOST notifications in
|
||||
// DatagramSinkInterface and does not need to be unique.
|
||||
virtual RTCError SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) = 0;
|
||||
|
||||
// Returns maximum size of datagram message, does not change.
|
||||
// TODO(sukhanov): Because value may be undefined before connection setup
|
||||
// is complete, consider returning error when called before connection is
|
||||
// established. Currently returns hardcoded const, because integration
|
||||
// prototype may call before connection is established.
|
||||
virtual size_t GetLargestDatagramSize() const = 0;
|
||||
|
||||
// Sets packet sink. Sink must be unset by calling
|
||||
// SetDataTransportSink(nullptr) before the data transport is destroyed or
|
||||
// before new sink is set.
|
||||
virtual void SetDatagramSink(DatagramSinkInterface* sink) = 0;
|
||||
|
||||
// Retrieves transport parameters for this datagram transport. May be called
|
||||
// on either client- or server-perspective transports.
|
||||
//
|
||||
// For servers, the parameters represent what kind of connections and data the
|
||||
// server is prepared to accept. This is generally a superset of acceptable
|
||||
// parameters.
|
||||
//
|
||||
// For clients, the parameters echo the server configuration used to create
|
||||
// the client, possibly removing any fields or parameters which the client
|
||||
// does not understand.
|
||||
virtual std::string GetTransportParameters() const = 0;
|
||||
|
||||
// Sets remote transport parameters. |remote_params| is a serialized string
|
||||
// of opaque parameters, understood by the datagram transport implementation.
|
||||
// Returns an error if |remote_params| are not compatible with this transport.
|
||||
//
|
||||
// TODO(mellem): Make pure virtual. The default implementation maintains
|
||||
// original negotiation behavior (negotiation falls back to RTP if the
|
||||
// remote datagram transport fails to echo exactly the local parameters).
|
||||
virtual RTCError SetRemoteTransportParameters(
|
||||
absl::string_view remote_params) {
|
||||
if (remote_params == GetTransportParameters()) {
|
||||
return RTCError::OK();
|
||||
}
|
||||
return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
|
||||
"Local and remote transport parameters do not match");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TRANSPORT_DATAGRAM_TRANSPORT_INTERFACE_H_
|
||||
@ -1,52 +0,0 @@
|
||||
# Copyright (c) 2019 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.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
|
||||
rtc_library("media_transport_interface") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"media_transport_config.cc",
|
||||
"media_transport_config.h",
|
||||
"media_transport_interface.cc",
|
||||
"media_transport_interface.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_interfaces",
|
||||
":video_interfaces",
|
||||
"..:datagram_transport_interface",
|
||||
"..:network_control",
|
||||
"../..:array_view",
|
||||
"../..:rtc_error",
|
||||
"../../..:webrtc_common",
|
||||
"../../../rtc_base",
|
||||
"../../../rtc_base:checks",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:stringutils",
|
||||
"../../units:data_rate",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
|
||||
rtc_library("audio_interfaces") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"audio_transport.cc",
|
||||
"audio_transport.h",
|
||||
]
|
||||
deps = [ "../..:array_view" ]
|
||||
}
|
||||
|
||||
rtc_library("video_interfaces") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"video_transport.cc",
|
||||
"video_transport.h",
|
||||
]
|
||||
deps = [ "../../video:encoded_image" ]
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#include "api/transport/media/audio_transport.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaTransportEncodedAudioFrame::~MediaTransportEncodedAudioFrame() {}
|
||||
|
||||
MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
|
||||
int sampling_rate_hz,
|
||||
int starting_sample_index,
|
||||
int samples_per_channel,
|
||||
int sequence_number,
|
||||
FrameType frame_type,
|
||||
int payload_type,
|
||||
std::vector<uint8_t> encoded_data)
|
||||
: sampling_rate_hz_(sampling_rate_hz),
|
||||
starting_sample_index_(starting_sample_index),
|
||||
samples_per_channel_(samples_per_channel),
|
||||
sequence_number_(sequence_number),
|
||||
frame_type_(frame_type),
|
||||
payload_type_(payload_type),
|
||||
encoded_data_(std::move(encoded_data)) {}
|
||||
|
||||
MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
|
||||
const MediaTransportEncodedAudioFrame&) = default;
|
||||
|
||||
MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
|
||||
MediaTransportEncodedAudioFrame&&) = default;
|
||||
|
||||
MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
|
||||
const MediaTransportEncodedAudioFrame&) = default;
|
||||
|
||||
MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
|
||||
MediaTransportEncodedAudioFrame&&) = default;
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,120 +0,0 @@
|
||||
/* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#ifndef API_TRANSPORT_MEDIA_AUDIO_TRANSPORT_H_
|
||||
#define API_TRANSPORT_MEDIA_AUDIO_TRANSPORT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Represents encoded audio frame in any encoding (type of encoding is opaque).
|
||||
// To avoid copying of encoded data use move semantics when passing by value.
|
||||
class MediaTransportEncodedAudioFrame final {
|
||||
public:
|
||||
enum class FrameType {
|
||||
// Normal audio frame (equivalent to webrtc::kAudioFrameSpeech).
|
||||
kSpeech,
|
||||
|
||||
// DTX frame (equivalent to webrtc::kAudioFrameCN).
|
||||
kDiscontinuousTransmission,
|
||||
// TODO(nisse): Mis-spelled version, update users, then delete.
|
||||
kDiscountinuousTransmission = kDiscontinuousTransmission,
|
||||
};
|
||||
|
||||
MediaTransportEncodedAudioFrame(
|
||||
// Audio sampling rate, for example 48000.
|
||||
int sampling_rate_hz,
|
||||
|
||||
// Starting sample index of the frame, i.e. how many audio samples were
|
||||
// before this frame since the beginning of the call or beginning of time
|
||||
// in one channel (the starting point should not matter for NetEq). In
|
||||
// WebRTC it is used as a timestamp of the frame.
|
||||
// TODO(sukhanov): Starting_sample_index is currently adjusted on the
|
||||
// receiver side in RTP path. Non-RTP implementations should preserve it.
|
||||
// For NetEq initial offset should not matter so we should consider fixing
|
||||
// RTP path.
|
||||
int starting_sample_index,
|
||||
|
||||
// Number of audio samples in audio frame in 1 channel.
|
||||
int samples_per_channel,
|
||||
|
||||
// Sequence number of the frame in the order sent, it is currently
|
||||
// required by NetEq, but we can fix NetEq, because starting_sample_index
|
||||
// should be enough.
|
||||
int sequence_number,
|
||||
|
||||
// If audio frame is a speech or discontinued transmission.
|
||||
FrameType frame_type,
|
||||
|
||||
// Opaque payload type. In RTP codepath payload type is stored in RTP
|
||||
// header. In other implementations it should be simply passed through the
|
||||
// wire -- it's needed for decoder.
|
||||
int payload_type,
|
||||
|
||||
// Vector with opaque encoded data.
|
||||
std::vector<uint8_t> encoded_data);
|
||||
|
||||
~MediaTransportEncodedAudioFrame();
|
||||
MediaTransportEncodedAudioFrame(const MediaTransportEncodedAudioFrame&);
|
||||
MediaTransportEncodedAudioFrame& operator=(
|
||||
const MediaTransportEncodedAudioFrame& other);
|
||||
MediaTransportEncodedAudioFrame& operator=(
|
||||
MediaTransportEncodedAudioFrame&& other);
|
||||
MediaTransportEncodedAudioFrame(MediaTransportEncodedAudioFrame&&);
|
||||
|
||||
// Getters.
|
||||
int sampling_rate_hz() const { return sampling_rate_hz_; }
|
||||
int starting_sample_index() const { return starting_sample_index_; }
|
||||
int samples_per_channel() const { return samples_per_channel_; }
|
||||
int sequence_number() const { return sequence_number_; }
|
||||
|
||||
int payload_type() const { return payload_type_; }
|
||||
FrameType frame_type() const { return frame_type_; }
|
||||
|
||||
rtc::ArrayView<const uint8_t> encoded_data() const { return encoded_data_; }
|
||||
|
||||
private:
|
||||
int sampling_rate_hz_;
|
||||
int starting_sample_index_;
|
||||
int samples_per_channel_;
|
||||
|
||||
// TODO(sukhanov): Refactor NetEq so we don't need sequence number.
|
||||
// Having sample_index and samples_per_channel should be enough.
|
||||
int sequence_number_;
|
||||
|
||||
FrameType frame_type_;
|
||||
|
||||
int payload_type_;
|
||||
|
||||
std::vector<uint8_t> encoded_data_;
|
||||
};
|
||||
|
||||
// Interface for receiving encoded audio frames from MediaTransportInterface
|
||||
// implementations.
|
||||
class MediaTransportAudioSinkInterface {
|
||||
public:
|
||||
virtual ~MediaTransportAudioSinkInterface() = default;
|
||||
|
||||
// Called when new encoded audio frame is received.
|
||||
virtual void OnData(uint64_t channel_id,
|
||||
MediaTransportEncodedAudioFrame frame) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_TRANSPORT_MEDIA_AUDIO_TRANSPORT_H_
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaTransportConfig::MediaTransportConfig(size_t rtp_max_packet_size)
|
||||
: rtp_max_packet_size(rtp_max_packet_size) {
|
||||
RTC_DCHECK_GT(rtp_max_packet_size, 0);
|
||||
}
|
||||
|
||||
std::string MediaTransportConfig::DebugString() const {
|
||||
rtc::StringBuilder result;
|
||||
result << "{rtp_max_packet_size: " << rtp_max_packet_size.value_or(0) << "}";
|
||||
return result.Release();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,38 +0,0 @@
|
||||
/* Copyright 2018 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 API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_CONFIG_H_
|
||||
#define API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_CONFIG_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Media transport config is made available to both transport and audio / video
|
||||
// layers, but access to individual interfaces should not be open without
|
||||
// necessity.
|
||||
struct MediaTransportConfig {
|
||||
// Default constructor for no-media transport scenarios.
|
||||
MediaTransportConfig() = default;
|
||||
|
||||
// Constructor for datagram transport scenarios.
|
||||
explicit MediaTransportConfig(size_t rtp_max_packet_size);
|
||||
|
||||
std::string DebugString() const;
|
||||
|
||||
// If provided, limits RTP packet size (excludes ICE, IP or network overhead).
|
||||
absl::optional<size_t> rtp_max_packet_size;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_CONFIG_H_
|
||||
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaTransportSettings::MediaTransportSettings() = default;
|
||||
MediaTransportSettings::MediaTransportSettings(const MediaTransportSettings&) =
|
||||
default;
|
||||
MediaTransportSettings& MediaTransportSettings::operator=(
|
||||
const MediaTransportSettings&) = default;
|
||||
MediaTransportSettings::~MediaTransportSettings() = default;
|
||||
|
||||
SendDataParams::SendDataParams() = default;
|
||||
SendDataParams::SendDataParams(const SendDataParams&) = default;
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
|
||||
MediaTransportFactory::CreateMediaTransport(
|
||||
rtc::PacketTransportInternal* packet_transport,
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
return std::unique_ptr<MediaTransportInterface>(nullptr);
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
|
||||
MediaTransportFactory::CreateMediaTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
return std::unique_ptr<MediaTransportInterface>(nullptr);
|
||||
}
|
||||
|
||||
RTCErrorOr<std::unique_ptr<DatagramTransportInterface>>
|
||||
MediaTransportFactory::CreateDatagramTransport(
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings) {
|
||||
return std::unique_ptr<DatagramTransportInterface>(nullptr);
|
||||
}
|
||||
|
||||
std::string MediaTransportFactory::GetTransportName() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
MediaTransportInterface::MediaTransportInterface() = default;
|
||||
MediaTransportInterface::~MediaTransportInterface() = default;
|
||||
|
||||
absl::optional<std::string>
|
||||
MediaTransportInterface::GetTransportParametersOffer() const {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
void MediaTransportInterface::Connect(
|
||||
rtc::PacketTransportInternal* packet_transport) {}
|
||||
|
||||
void MediaTransportInterface::SetKeyFrameRequestCallback(
|
||||
MediaTransportKeyFrameRequestCallback* callback) {}
|
||||
|
||||
absl::optional<TargetTransferRate>
|
||||
MediaTransportInterface::GetLatestTargetTransferRate() {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
void MediaTransportInterface::AddNetworkChangeCallback(
|
||||
MediaTransportNetworkChangeCallback* callback) {}
|
||||
|
||||
void MediaTransportInterface::RemoveNetworkChangeCallback(
|
||||
MediaTransportNetworkChangeCallback* callback) {}
|
||||
|
||||
void MediaTransportInterface::SetFirstAudioPacketReceivedObserver(
|
||||
AudioPacketReceivedObserver* observer) {}
|
||||
|
||||
void MediaTransportInterface::AddTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer) {}
|
||||
void MediaTransportInterface::RemoveTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer) {}
|
||||
|
||||
void MediaTransportInterface::AddRttObserver(
|
||||
MediaTransportRttObserver* observer) {}
|
||||
void MediaTransportInterface::RemoveRttObserver(
|
||||
MediaTransportRttObserver* observer) {}
|
||||
|
||||
size_t MediaTransportInterface::GetAudioPacketOverhead() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MediaTransportInterface::SetAllocatedBitrateLimits(
|
||||
const MediaTransportAllocatedBitrateLimits& limits) {}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,320 +0,0 @@
|
||||
/* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#ifndef API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_INTERFACE_H_
|
||||
#define API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_INTERFACE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "api/transport/media/audio_transport.h"
|
||||
#include "api/transport/media/video_transport.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/network_route.h"
|
||||
|
||||
namespace rtc {
|
||||
class PacketTransportInternal;
|
||||
class Thread;
|
||||
} // namespace rtc
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class DatagramTransportInterface;
|
||||
class RtcEventLog;
|
||||
|
||||
class AudioPacketReceivedObserver {
|
||||
public:
|
||||
virtual ~AudioPacketReceivedObserver() = default;
|
||||
|
||||
// Invoked for the first received audio packet on a given channel id.
|
||||
// It will be invoked once for each channel id.
|
||||
virtual void OnFirstAudioPacketReceived(int64_t channel_id) = 0;
|
||||
};
|
||||
|
||||
// Used to configure stream allocations.
|
||||
struct MediaTransportAllocatedBitrateLimits {
|
||||
DataRate min_pacing_rate = DataRate::Zero();
|
||||
DataRate max_padding_bitrate = DataRate::Zero();
|
||||
DataRate max_total_allocated_bitrate = DataRate::Zero();
|
||||
};
|
||||
|
||||
// Used to configure target bitrate constraints.
|
||||
// If the value is provided, the constraint is updated.
|
||||
// If the value is omitted, the value is left unchanged.
|
||||
struct MediaTransportTargetRateConstraints {
|
||||
absl::optional<DataRate> min_bitrate;
|
||||
absl::optional<DataRate> max_bitrate;
|
||||
absl::optional<DataRate> starting_bitrate;
|
||||
};
|
||||
|
||||
// A collection of settings for creation of media transport.
|
||||
struct MediaTransportSettings final {
|
||||
MediaTransportSettings();
|
||||
MediaTransportSettings(const MediaTransportSettings&);
|
||||
MediaTransportSettings& operator=(const MediaTransportSettings&);
|
||||
~MediaTransportSettings();
|
||||
|
||||
// Group calls are not currently supported, in 1:1 call one side must set
|
||||
// is_caller = true and another is_caller = false.
|
||||
bool is_caller;
|
||||
|
||||
// Must be set if a pre-shared key is used for the call.
|
||||
// TODO(bugs.webrtc.org/9944): This should become zero buffer in the distant
|
||||
// future.
|
||||
absl::optional<std::string> pre_shared_key;
|
||||
|
||||
// If present, this is a config passed from the caller to the answerer in the
|
||||
// offer. Each media transport knows how to understand its own parameters.
|
||||
absl::optional<std::string> remote_transport_parameters;
|
||||
|
||||
// If present, provides the event log that media transport should use.
|
||||
// Media transport does not own it. The lifetime of |event_log| will exceed
|
||||
// the lifetime of the instance of MediaTransportInterface instance.
|
||||
RtcEventLog* event_log = nullptr;
|
||||
};
|
||||
|
||||
// Callback to notify about network route changes.
|
||||
class MediaTransportNetworkChangeCallback {
|
||||
public:
|
||||
virtual ~MediaTransportNetworkChangeCallback() = default;
|
||||
|
||||
// Called when the network route is changed, with the new network route.
|
||||
virtual void OnNetworkRouteChanged(
|
||||
const rtc::NetworkRoute& new_network_route) = 0;
|
||||
};
|
||||
|
||||
// State of the media transport. Media transport begins in the pending state.
|
||||
// It transitions to writable when it is ready to send media. It may transition
|
||||
// back to pending if the connection is blocked. It may transition to closed at
|
||||
// any time. Closed is terminal: a transport will never re-open once closed.
|
||||
enum class MediaTransportState {
|
||||
kPending,
|
||||
kWritable,
|
||||
kClosed,
|
||||
};
|
||||
|
||||
// Callback invoked whenever the state of the media transport changes.
|
||||
class MediaTransportStateCallback {
|
||||
public:
|
||||
virtual ~MediaTransportStateCallback() = default;
|
||||
|
||||
// Invoked whenever the state of the media transport changes.
|
||||
virtual void OnStateChanged(MediaTransportState state) = 0;
|
||||
};
|
||||
|
||||
// Callback for RTT measurements on the receive side.
|
||||
// TODO(nisse): Related interfaces: CallStatsObserver and RtcpRttStats. It's
|
||||
// somewhat unclear what type of measurement is needed. It's used to configure
|
||||
// NACK generation and playout buffer. Either raw measurement values or recent
|
||||
// maximum would make sense for this use. Need consolidation of RTT signalling.
|
||||
class MediaTransportRttObserver {
|
||||
public:
|
||||
virtual ~MediaTransportRttObserver() = default;
|
||||
|
||||
// Invoked when a new RTT measurement is available, typically once per ACK.
|
||||
virtual void OnRttUpdated(int64_t rtt_ms) = 0;
|
||||
};
|
||||
|
||||
// Media transport interface for sending / receiving encoded audio/video frames
|
||||
// and receiving bandwidth estimate update from congestion control.
|
||||
class MediaTransportInterface : public DataChannelTransportInterface {
|
||||
public:
|
||||
MediaTransportInterface();
|
||||
virtual ~MediaTransportInterface();
|
||||
|
||||
// Retrieves callers config (i.e. media transport offer) that should be passed
|
||||
// to the callee, before the call is connected. Such config is opaque to SDP
|
||||
// (sdp just passes it through). The config is a binary blob, so SDP may
|
||||
// choose to use base64 to serialize it (or any other approach that guarantees
|
||||
// that the binary blob goes through). This should only be called for the
|
||||
// caller's perspective.
|
||||
//
|
||||
// This may return an unset optional, which means that the given media
|
||||
// transport is not supported / disabled and shouldn't be reported in SDP.
|
||||
//
|
||||
// It may also return an empty string, in which case the media transport is
|
||||
// supported, but without any extra settings.
|
||||
// TODO(psla): Make abstract.
|
||||
virtual absl::optional<std::string> GetTransportParametersOffer() const;
|
||||
|
||||
// Connect the media transport to the ICE transport.
|
||||
// The implementation must be able to ignore incoming packets that don't
|
||||
// belong to it.
|
||||
// TODO(psla): Make abstract.
|
||||
virtual void Connect(rtc::PacketTransportInternal* packet_transport);
|
||||
|
||||
// Start asynchronous send of audio frame. The status returned by this method
|
||||
// only pertains to the synchronous operations (e.g.
|
||||
// serialization/packetization), not to the asynchronous operation.
|
||||
|
||||
virtual RTCError SendAudioFrame(uint64_t channel_id,
|
||||
MediaTransportEncodedAudioFrame frame) = 0;
|
||||
|
||||
// Start asynchronous send of video frame. The status returned by this method
|
||||
// only pertains to the synchronous operations (e.g.
|
||||
// serialization/packetization), not to the asynchronous operation.
|
||||
virtual RTCError SendVideoFrame(
|
||||
uint64_t channel_id,
|
||||
const MediaTransportEncodedVideoFrame& frame) = 0;
|
||||
|
||||
// Used by video sender to be notified on key frame requests.
|
||||
virtual void SetKeyFrameRequestCallback(
|
||||
MediaTransportKeyFrameRequestCallback* callback);
|
||||
|
||||
// Requests a keyframe for the particular channel (stream). The caller should
|
||||
// check that the keyframe is not present in a jitter buffer already (i.e.
|
||||
// don't request a keyframe if there is one that you will get from the jitter
|
||||
// buffer in a moment).
|
||||
virtual RTCError RequestKeyFrame(uint64_t channel_id) = 0;
|
||||
|
||||
// Sets audio sink. Sink must be unset by calling SetReceiveAudioSink(nullptr)
|
||||
// before the media transport is destroyed or before new sink is set.
|
||||
virtual void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) = 0;
|
||||
|
||||
// Registers a video sink. Before destruction of media transport, you must
|
||||
// pass a nullptr.
|
||||
virtual void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) = 0;
|
||||
|
||||
// Adds a target bitrate observer. Before media transport is destructed
|
||||
// the observer must be unregistered (by calling
|
||||
// RemoveTargetTransferRateObserver).
|
||||
// A newly registered observer will be called back with the latest recorded
|
||||
// target rate, if available.
|
||||
virtual void AddTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer);
|
||||
|
||||
// Removes an existing |observer| from observers. If observer was never
|
||||
// registered, an error is logged and method does nothing.
|
||||
virtual void RemoveTargetTransferRateObserver(
|
||||
TargetTransferRateObserver* observer);
|
||||
|
||||
// Sets audio packets observer, which gets informed about incoming audio
|
||||
// packets. Before destruction, the observer must be unregistered by setting
|
||||
// nullptr.
|
||||
//
|
||||
// This method may be temporary, when the multiplexer is implemented (or
|
||||
// multiplexer may use it to demultiplex channel ids).
|
||||
virtual void SetFirstAudioPacketReceivedObserver(
|
||||
AudioPacketReceivedObserver* observer);
|
||||
|
||||
// Intended for receive side. AddRttObserver registers an observer to be
|
||||
// called for each RTT measurement, typically once per ACK. Before media
|
||||
// transport is destructed the observer must be unregistered.
|
||||
virtual void AddRttObserver(MediaTransportRttObserver* observer);
|
||||
virtual void RemoveRttObserver(MediaTransportRttObserver* observer);
|
||||
|
||||
// Returns the last known target transfer rate as reported to the above
|
||||
// observers.
|
||||
virtual absl::optional<TargetTransferRate> GetLatestTargetTransferRate();
|
||||
|
||||
// Gets the audio packet overhead in bytes. Returned overhead does not include
|
||||
// transport overhead (ipv4/6, turn channeldata, tcp/udp, etc.).
|
||||
// If the transport is capable of fusing packets together, this overhead
|
||||
// might not be a very accurate number.
|
||||
// TODO(nisse): Deprecated.
|
||||
virtual size_t GetAudioPacketOverhead() const;
|
||||
|
||||
// Corresponding observers for audio and video overhead. Before destruction,
|
||||
// the observers must be unregistered by setting nullptr.
|
||||
|
||||
// Registers an observer for network change events. If the network route is
|
||||
// already established when the callback is added, |callback| will be called
|
||||
// immediately with the current network route. Before media transport is
|
||||
// destroyed, the callback must be removed.
|
||||
virtual void AddNetworkChangeCallback(
|
||||
MediaTransportNetworkChangeCallback* callback);
|
||||
virtual void RemoveNetworkChangeCallback(
|
||||
MediaTransportNetworkChangeCallback* callback);
|
||||
|
||||
// Sets a state observer callback. Before media transport is destroyed, the
|
||||
// callback must be unregistered by setting it to nullptr.
|
||||
// A newly registered callback will be called with the current state.
|
||||
// Media transport does not invoke this callback concurrently.
|
||||
virtual void SetMediaTransportStateCallback(
|
||||
MediaTransportStateCallback* callback) = 0;
|
||||
|
||||
// Updates allocation limits.
|
||||
// TODO(psla): Make abstract when downstream implementation implement it.
|
||||
virtual void SetAllocatedBitrateLimits(
|
||||
const MediaTransportAllocatedBitrateLimits& limits);
|
||||
|
||||
// Sets starting rate.
|
||||
// TODO(psla): Make abstract when downstream implementation implement it.
|
||||
virtual void SetTargetBitrateLimits(
|
||||
const MediaTransportTargetRateConstraints& target_rate_constraints) {}
|
||||
|
||||
// TODO(sukhanov): RtcEventLogs.
|
||||
};
|
||||
|
||||
// If media transport factory is set in peer connection factory, it will be
|
||||
// used to create media transport for sending/receiving encoded frames and
|
||||
// this transport will be used instead of default RTP/SRTP transport.
|
||||
//
|
||||
// Currently Media Transport negotiation is not supported in SDP.
|
||||
// If application is using media transport, it must negotiate it before
|
||||
// setting media transport factory in peer connection.
|
||||
class MediaTransportFactory {
|
||||
public:
|
||||
virtual ~MediaTransportFactory() = default;
|
||||
|
||||
// Creates media transport.
|
||||
// - Does not take ownership of packet_transport or network_thread.
|
||||
// - Does not support group calls, in 1:1 call one side must set
|
||||
// is_caller = true and another is_caller = false.
|
||||
virtual RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
|
||||
CreateMediaTransport(rtc::PacketTransportInternal* packet_transport,
|
||||
rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings);
|
||||
|
||||
// Creates a new Media Transport in a disconnected state. If the media
|
||||
// transport for the caller is created, one can then call
|
||||
// MediaTransportInterface::GetTransportParametersOffer on that new instance.
|
||||
// TODO(psla): Make abstract.
|
||||
virtual RTCErrorOr<std::unique_ptr<webrtc::MediaTransportInterface>>
|
||||
CreateMediaTransport(rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings);
|
||||
|
||||
// Creates a new Datagram Transport in a disconnected state. If the datagram
|
||||
// transport for the caller is created, one can then call
|
||||
// DatagramTransportInterface::GetTransportParametersOffer on that new
|
||||
// instance.
|
||||
//
|
||||
// TODO(sukhanov): Consider separating media and datagram transport factories.
|
||||
// TODO(sukhanov): Move factory to a separate .h file.
|
||||
virtual RTCErrorOr<std::unique_ptr<DatagramTransportInterface>>
|
||||
CreateDatagramTransport(rtc::Thread* network_thread,
|
||||
const MediaTransportSettings& settings);
|
||||
|
||||
// Gets a transport name which is supported by the implementation.
|
||||
// Different factories should return different transport names, and at runtime
|
||||
// it will be checked that different names were used.
|
||||
// For example, "rtp" or "generic" may be returned by two different
|
||||
// implementations.
|
||||
// The value returned by this method must never change in the lifetime of the
|
||||
// factory.
|
||||
// TODO(psla): Make abstract.
|
||||
virtual std::string GetTransportName() const;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_TRANSPORT_MEDIA_MEDIA_TRANSPORT_INTERFACE_H_
|
||||
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#include "api/transport/media/video_transport.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame() = default;
|
||||
|
||||
MediaTransportEncodedVideoFrame::~MediaTransportEncodedVideoFrame() = default;
|
||||
|
||||
MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
|
||||
int64_t frame_id,
|
||||
std::vector<int64_t> referenced_frame_ids,
|
||||
int payload_type,
|
||||
const webrtc::EncodedImage& encoded_image)
|
||||
: payload_type_(payload_type),
|
||||
encoded_image_(encoded_image),
|
||||
frame_id_(frame_id),
|
||||
referenced_frame_ids_(std::move(referenced_frame_ids)) {}
|
||||
|
||||
MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
|
||||
const MediaTransportEncodedVideoFrame&) = default;
|
||||
|
||||
MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
|
||||
MediaTransportEncodedVideoFrame&&) = default;
|
||||
|
||||
MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
|
||||
const MediaTransportEncodedVideoFrame& o)
|
||||
: MediaTransportEncodedVideoFrame() {
|
||||
*this = o;
|
||||
}
|
||||
|
||||
MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
|
||||
MediaTransportEncodedVideoFrame&& o)
|
||||
: MediaTransportEncodedVideoFrame() {
|
||||
*this = std::move(o);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,101 +0,0 @@
|
||||
/* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
// This is EXPERIMENTAL interface for media transport.
|
||||
//
|
||||
// The goal is to refactor WebRTC code so that audio and video frames
|
||||
// are sent / received through the media transport interface. This will
|
||||
// enable different media transport implementations, including QUIC-based
|
||||
// media transport.
|
||||
|
||||
#ifndef API_TRANSPORT_MEDIA_VIDEO_TRANSPORT_H_
|
||||
#define API_TRANSPORT_MEDIA_VIDEO_TRANSPORT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "api/video/encoded_image.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Represents encoded video frame, along with the codec information.
|
||||
class MediaTransportEncodedVideoFrame final {
|
||||
public:
|
||||
MediaTransportEncodedVideoFrame(int64_t frame_id,
|
||||
std::vector<int64_t> referenced_frame_ids,
|
||||
int payload_type,
|
||||
const webrtc::EncodedImage& encoded_image);
|
||||
~MediaTransportEncodedVideoFrame();
|
||||
MediaTransportEncodedVideoFrame(const MediaTransportEncodedVideoFrame&);
|
||||
MediaTransportEncodedVideoFrame& operator=(
|
||||
const MediaTransportEncodedVideoFrame& other);
|
||||
MediaTransportEncodedVideoFrame& operator=(
|
||||
MediaTransportEncodedVideoFrame&& other);
|
||||
MediaTransportEncodedVideoFrame(MediaTransportEncodedVideoFrame&&);
|
||||
|
||||
int payload_type() const { return payload_type_; }
|
||||
const webrtc::EncodedImage& encoded_image() const { return encoded_image_; }
|
||||
|
||||
int64_t frame_id() const { return frame_id_; }
|
||||
const std::vector<int64_t>& referenced_frame_ids() const {
|
||||
return referenced_frame_ids_;
|
||||
}
|
||||
|
||||
// Hack to workaround lack of ownership of the EncodedImage buffer. If we
|
||||
// don't already own the underlying data, make a copy.
|
||||
void Retain() { encoded_image_.Retain(); }
|
||||
|
||||
private:
|
||||
MediaTransportEncodedVideoFrame();
|
||||
|
||||
int payload_type_;
|
||||
|
||||
// The buffer is not always owned by the encoded image. On the sender it means
|
||||
// that it will need to make a copy using the Retain() method, if it wants to
|
||||
// deliver it asynchronously.
|
||||
webrtc::EncodedImage encoded_image_;
|
||||
|
||||
// Frame id uniquely identifies a frame in a stream. It needs to be unique in
|
||||
// a given time window (i.e. technically unique identifier for the lifetime of
|
||||
// the connection is not needed, but you need to guarantee that remote side
|
||||
// got rid of the previous frame_id if you plan to reuse it).
|
||||
//
|
||||
// It is required by a remote jitter buffer, and is the same as
|
||||
// EncodedFrame::id::picture_id.
|
||||
//
|
||||
// This data must be opaque to the media transport, and media transport should
|
||||
// itself not make any assumptions about what it is and its uniqueness.
|
||||
int64_t frame_id_;
|
||||
|
||||
// A single frame might depend on other frames. This is set of identifiers on
|
||||
// which the current frame depends.
|
||||
std::vector<int64_t> referenced_frame_ids_;
|
||||
};
|
||||
|
||||
// Interface for receiving encoded video frames from MediaTransportInterface
|
||||
// implementations.
|
||||
class MediaTransportVideoSinkInterface {
|
||||
public:
|
||||
virtual ~MediaTransportVideoSinkInterface() = default;
|
||||
|
||||
// Called when new encoded video frame is received.
|
||||
virtual void OnData(uint64_t channel_id,
|
||||
MediaTransportEncodedVideoFrame frame) = 0;
|
||||
};
|
||||
|
||||
// Interface for video sender to be notified of received key frame request.
|
||||
class MediaTransportKeyFrameRequestCallback {
|
||||
public:
|
||||
virtual ~MediaTransportKeyFrameRequestCallback() = default;
|
||||
|
||||
// Called when a key frame request is received on the transport.
|
||||
virtual void OnKeyFrameRequested(uint64_t channel_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_TRANSPORT_MEDIA_VIDEO_TRANSPORT_H_
|
||||
@ -96,7 +96,6 @@ rtc_library("rtc_media_base") {
|
||||
"../api/crypto:frame_encryptor_interface",
|
||||
"../api/crypto:options",
|
||||
"../api/transport:stun_types",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/transport/rtp:rtp_source",
|
||||
"../api/video:video_bitrate_allocation",
|
||||
"../api/video:video_bitrate_allocator_factory",
|
||||
@ -292,8 +291,6 @@ rtc_library("rtc_audio_video") {
|
||||
"../api/audio_codecs:audio_codecs_api",
|
||||
"../api/task_queue",
|
||||
"../api/transport:bitrate_settings",
|
||||
"../api/transport:datagram_transport_interface",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/transport/rtp:rtp_source",
|
||||
"../api/units:data_rate",
|
||||
"../api/video:video_bitrate_allocation",
|
||||
@ -561,7 +558,6 @@ if (rtc_include_tests) {
|
||||
"../api/task_queue:default_task_queue_factory",
|
||||
"../api/test/video:function_video_factory",
|
||||
"../api/transport:field_trial_based_config",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/units:time_delta",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
"../api/video:video_bitrate_allocation",
|
||||
|
||||
@ -23,12 +23,9 @@ MediaChannel::MediaChannel() : enable_dscp_(false) {}
|
||||
|
||||
MediaChannel::~MediaChannel() {}
|
||||
|
||||
void MediaChannel::SetInterface(
|
||||
NetworkInterface* iface,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) {
|
||||
void MediaChannel::SetInterface(NetworkInterface* iface) {
|
||||
rtc::CritScope cs(&network_interface_crit_);
|
||||
network_interface_ = iface;
|
||||
media_transport_config_ = media_transport_config;
|
||||
UpdateDscp();
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "api/transport/rtp/rtp_source.h"
|
||||
#include "api/video/video_content_type.h"
|
||||
#include "api/video/video_sink_interface.h"
|
||||
@ -195,15 +194,8 @@ class MediaChannel : public sigslot::has_slots<> {
|
||||
|
||||
virtual cricket::MediaType media_type() const = 0;
|
||||
|
||||
// Sets the abstract interface class for sending RTP/RTCP data and
|
||||
// interface for media transport (experimental). If media transport is
|
||||
// provided, it should be used instead of RTP/RTCP.
|
||||
// TODO(sukhanov): Currently media transport can co-exist with RTP/RTCP, but
|
||||
// in the future we will refactor code to send all frames with media
|
||||
// transport.
|
||||
virtual void SetInterface(
|
||||
NetworkInterface* iface,
|
||||
const webrtc::MediaTransportConfig& media_transport_config)
|
||||
// Sets the abstract interface class for sending RTP/RTCP data.
|
||||
virtual void SetInterface(NetworkInterface* iface)
|
||||
RTC_LOCKS_EXCLUDED(network_interface_crit_);
|
||||
// Called when a RTP packet is received.
|
||||
virtual void OnPacketReceived(rtc::CopyOnWriteBuffer packet,
|
||||
@ -270,10 +262,6 @@ class MediaChannel : public sigslot::has_slots<> {
|
||||
return SetOptionLocked(type, opt, option);
|
||||
}
|
||||
|
||||
const webrtc::MediaTransportConfig& media_transport_config() const {
|
||||
return media_transport_config_;
|
||||
}
|
||||
|
||||
// Corresponds to the SDP attribute extmap-allow-mixed, see RFC8285.
|
||||
// Set to true if it's allowed to mix one- and two-byte RTP header extensions
|
||||
// in the same stream. The setter and getter must only be called from
|
||||
@ -361,7 +349,6 @@ class MediaChannel : public sigslot::has_slots<> {
|
||||
nullptr;
|
||||
rtc::DiffServCodePoint preferred_dscp_
|
||||
RTC_GUARDED_BY(network_interface_crit_) = rtc::DSCP_DEFAULT;
|
||||
webrtc::MediaTransportConfig media_transport_config_;
|
||||
bool extmap_allow_mixed_ = false;
|
||||
};
|
||||
|
||||
|
||||
@ -75,7 +75,7 @@ class RtpDataMediaChannelTest : public ::testing::Test {
|
||||
cricket::MediaConfig config;
|
||||
cricket::RtpDataMediaChannel* channel =
|
||||
static_cast<cricket::RtpDataMediaChannel*>(dme->CreateChannel(config));
|
||||
channel->SetInterface(iface_.get(), webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(iface_.get());
|
||||
channel->SignalDataReceived.connect(receiver_.get(),
|
||||
&FakeDataReceiver::OnDataReceived);
|
||||
return channel;
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "api/video/video_codec_constants.h"
|
||||
#include "api/video/video_codec_type.h"
|
||||
@ -1298,13 +1297,6 @@ bool WebRtcVideoChannel::AddSendStream(const StreamParams& sp) {
|
||||
config.rtp.extmap_allow_mixed = ExtmapAllowMixed();
|
||||
config.rtcp_report_interval_ms = video_config_.rtcp_report_interval_ms;
|
||||
|
||||
// If sending through Datagram Transport, limit packet size to maximum
|
||||
// packet size supported by datagram_transport.
|
||||
if (media_transport_config().rtp_max_packet_size) {
|
||||
config.rtp.max_packet_size =
|
||||
media_transport_config().rtp_max_packet_size.value();
|
||||
}
|
||||
|
||||
WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
|
||||
call_, sp, std::move(config), default_send_options_,
|
||||
video_config_.enable_cpu_adaptation, bitrate_config_.max_bitrate_bps,
|
||||
@ -1758,11 +1750,9 @@ void WebRtcVideoChannel::OnNetworkRouteChanged(
|
||||
network_route.packet_overhead);
|
||||
}
|
||||
|
||||
void WebRtcVideoChannel::SetInterface(
|
||||
NetworkInterface* iface,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) {
|
||||
void WebRtcVideoChannel::SetInterface(NetworkInterface* iface) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
MediaChannel::SetInterface(iface, media_transport_config);
|
||||
MediaChannel::SetInterface(iface);
|
||||
// Set the RTP recv/send buffer to a bigger size.
|
||||
|
||||
// The group should be a positive integer with an explicit size, in
|
||||
|
||||
@ -169,9 +169,7 @@ class WebRtcVideoChannel : public VideoMediaChannel,
|
||||
void OnReadyToSend(bool ready) override;
|
||||
void OnNetworkRouteChanged(const std::string& transport_name,
|
||||
const rtc::NetworkRoute& network_route) override;
|
||||
void SetInterface(
|
||||
NetworkInterface* iface,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) override;
|
||||
void SetInterface(NetworkInterface* iface) override;
|
||||
|
||||
// E2E Encrypted Video Frame API
|
||||
// Set a frame decryptor to a particular ssrc that will intercept all
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include "api/test/mock_video_encoder_factory.h"
|
||||
#include "api/test/video/function_video_decoder_factory.h"
|
||||
#include "api/transport/field_trial_based_config.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/video/builtin_video_bitrate_allocator_factory.h"
|
||||
#include "api/video/i420_buffer.h"
|
||||
@ -1335,7 +1334,7 @@ class WebRtcVideoChannelEncodedFrameCallbackTest : public ::testing::Test {
|
||||
webrtc::CryptoOptions(),
|
||||
video_bitrate_allocator_factory_.get())))) {
|
||||
network_interface_.SetDestination(channel_.get());
|
||||
channel_->SetInterface(&network_interface_, webrtc::MediaTransportConfig());
|
||||
channel_->SetInterface(&network_interface_);
|
||||
cricket::VideoRecvParameters parameters;
|
||||
parameters.codecs = engine_.recv_codecs();
|
||||
channel_->SetRecvParameters(parameters);
|
||||
@ -1481,7 +1480,7 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test {
|
||||
channel_->OnReadyToSend(true);
|
||||
EXPECT_TRUE(channel_.get() != NULL);
|
||||
network_interface_.SetDestination(channel_.get());
|
||||
channel_->SetInterface(&network_interface_, webrtc::MediaTransportConfig());
|
||||
channel_->SetInterface(&network_interface_);
|
||||
cricket::VideoRecvParameters parameters;
|
||||
parameters.codecs = engine_.send_codecs();
|
||||
channel_->SetRecvParameters(parameters);
|
||||
@ -5064,8 +5063,7 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
|
||||
static_cast<cricket::WebRtcVideoChannel*>(engine_.CreateMediaChannel(
|
||||
call_.get(), config, VideoOptions(), webrtc::CryptoOptions(),
|
||||
video_bitrate_allocator_factory_.get())));
|
||||
channel->SetInterface(network_interface.get(),
|
||||
webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(network_interface.get());
|
||||
// Default value when DSCP is disabled should be DSCP_DEFAULT.
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
|
||||
|
||||
@ -5076,8 +5074,7 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
|
||||
static_cast<cricket::WebRtcVideoChannel*>(engine_.CreateMediaChannel(
|
||||
call_.get(), config, VideoOptions(), webrtc::CryptoOptions(),
|
||||
video_bitrate_allocator_factory_.get())));
|
||||
channel->SetInterface(network_interface.get(),
|
||||
webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(network_interface.get());
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
|
||||
|
||||
// Create a send stream to configure
|
||||
@ -5106,8 +5103,7 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
|
||||
static_cast<cricket::WebRtcVideoChannel*>(engine_.CreateMediaChannel(
|
||||
call_.get(), config, VideoOptions(), webrtc::CryptoOptions(),
|
||||
video_bitrate_allocator_factory_.get())));
|
||||
channel->SetInterface(network_interface.get(),
|
||||
webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(network_interface.get());
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
|
||||
}
|
||||
|
||||
|
||||
@ -3102,7 +3102,7 @@ TEST_P(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
|
||||
channel.reset(static_cast<cricket::WebRtcVoiceMediaChannel*>(
|
||||
engine_->CreateMediaChannel(&call_, config, cricket::AudioOptions(),
|
||||
webrtc::CryptoOptions())));
|
||||
channel->SetInterface(&network_interface, webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(&network_interface);
|
||||
// Default value when DSCP is disabled should be DSCP_DEFAULT.
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface.dscp());
|
||||
|
||||
@ -3110,7 +3110,7 @@ TEST_P(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
|
||||
channel.reset(static_cast<cricket::WebRtcVoiceMediaChannel*>(
|
||||
engine_->CreateMediaChannel(&call_, config, cricket::AudioOptions(),
|
||||
webrtc::CryptoOptions())));
|
||||
channel->SetInterface(&network_interface, webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(&network_interface);
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface.dscp());
|
||||
|
||||
// Create a send stream to configure
|
||||
@ -3138,11 +3138,11 @@ TEST_P(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
|
||||
channel.reset(static_cast<cricket::WebRtcVoiceMediaChannel*>(
|
||||
engine_->CreateMediaChannel(&call_, config, cricket::AudioOptions(),
|
||||
webrtc::CryptoOptions())));
|
||||
channel->SetInterface(&network_interface, webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(&network_interface);
|
||||
// Default value when DSCP is disabled should be DSCP_DEFAULT.
|
||||
EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface.dscp());
|
||||
|
||||
channel->SetInterface(nullptr, webrtc::MediaTransportConfig());
|
||||
channel->SetInterface(nullptr);
|
||||
}
|
||||
|
||||
TEST_P(WebRtcVoiceEngineTestFake, SetOutputVolume) {
|
||||
|
||||
@ -36,8 +36,6 @@ rtc_library("rtc_pc_base") {
|
||||
"composite_data_channel_transport.h",
|
||||
"composite_rtp_transport.cc",
|
||||
"composite_rtp_transport.h",
|
||||
"datagram_rtp_transport.cc",
|
||||
"datagram_rtp_transport.h",
|
||||
"dtls_srtp_transport.cc",
|
||||
"dtls_srtp_transport.h",
|
||||
"dtls_transport.cc",
|
||||
@ -97,7 +95,6 @@ rtc_library("rtc_pc_base") {
|
||||
"../api/crypto:options",
|
||||
"../api/rtc_event_log",
|
||||
"../api/transport:datagram_transport_interface",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
"../api/video:video_frame",
|
||||
"../api/video:video_rtp_headers",
|
||||
@ -250,7 +247,6 @@ rtc_library("peerconnection") {
|
||||
"../api/task_queue",
|
||||
"../api/transport:datagram_transport_interface",
|
||||
"../api/transport:field_trial_based_config",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/units:data_rate",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
"../api/video:video_frame",
|
||||
@ -335,14 +331,11 @@ if (rtc_include_tests) {
|
||||
":rtc_pc_base",
|
||||
"../api:array_view",
|
||||
"../api:audio_options_api",
|
||||
"../api:fake_media_transport",
|
||||
"../api:ice_transport_factory",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:loopback_media_transport",
|
||||
"../api:rtc_error",
|
||||
"../api:rtp_headers",
|
||||
"../api:rtp_parameters",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
"../api/video/test:mock_recordable_encoded_frame",
|
||||
"../call:rtp_interfaces",
|
||||
@ -574,7 +567,6 @@ if (rtc_include_tests) {
|
||||
"../api:function_view",
|
||||
"../api:libjingle_logging_api",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:loopback_media_transport",
|
||||
"../api:media_stream_interface",
|
||||
"../api:mock_rtp",
|
||||
"../api:rtc_error",
|
||||
@ -586,7 +578,6 @@ if (rtc_include_tests) {
|
||||
"../api/rtc_event_log",
|
||||
"../api/rtc_event_log:rtc_event_log_factory",
|
||||
"../api/task_queue:default_task_queue_factory",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/transport/rtp:rtp_source",
|
||||
"../api/units:time_delta",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "api/call/audio_sink.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
@ -195,24 +194,20 @@ void BaseChannel::DisconnectFromRtpTransport() {
|
||||
rtp_transport_->SignalSentPacket.disconnect(this);
|
||||
}
|
||||
|
||||
void BaseChannel::Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) {
|
||||
void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
RTC_DCHECK_RUN_ON(worker_thread_);
|
||||
media_transport_config_ = media_transport_config;
|
||||
|
||||
network_thread_->Invoke<void>(
|
||||
RTC_FROM_HERE, [this, rtp_transport] { SetRtpTransport(rtp_transport); });
|
||||
|
||||
// Both RTP and RTCP channels should be set, we can call SetInterface on
|
||||
// the media channel and it can set network options.
|
||||
media_channel_->SetInterface(this, media_transport_config);
|
||||
media_channel_->SetInterface(this);
|
||||
}
|
||||
|
||||
void BaseChannel::Deinit() {
|
||||
RTC_DCHECK(worker_thread_->IsCurrent());
|
||||
media_channel_->SetInterface(/*iface=*/nullptr,
|
||||
webrtc::MediaTransportConfig());
|
||||
media_channel_->SetInterface(/*iface=*/nullptr);
|
||||
// Packets arrive on the network thread, processing packets calls virtual
|
||||
// functions, so need to stop this process in Deinit that is called in
|
||||
// derived classes destructor.
|
||||
@ -820,10 +815,8 @@ void BaseChannel::UpdateMediaSendRecvState() {
|
||||
[this] { UpdateMediaSendRecvState_w(); });
|
||||
}
|
||||
|
||||
void VoiceChannel::Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) {
|
||||
BaseChannel::Init_w(rtp_transport, media_transport_config);
|
||||
void VoiceChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
BaseChannel::Init_w(rtp_transport);
|
||||
}
|
||||
|
||||
void VoiceChannel::UpdateMediaSendRecvState_w() {
|
||||
@ -1229,10 +1222,8 @@ RtpDataChannel::~RtpDataChannel() {
|
||||
Deinit();
|
||||
}
|
||||
|
||||
void RtpDataChannel::Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) {
|
||||
BaseChannel::Init_w(rtp_transport, media_transport_config);
|
||||
void RtpDataChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
BaseChannel::Init_w(rtp_transport);
|
||||
media_channel()->SignalDataReceived.connect(this,
|
||||
&RtpDataChannel::OnDataReceived);
|
||||
media_channel()->SignalReadyToSend.connect(
|
||||
|
||||
17
pc/channel.h
17
pc/channel.h
@ -22,7 +22,6 @@
|
||||
#include "api/function_view.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/rtp_receiver_interface.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "api/video/video_sink_interface.h"
|
||||
#include "api/video/video_source_interface.h"
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
@ -46,7 +45,6 @@
|
||||
|
||||
namespace webrtc {
|
||||
class AudioSinkInterface;
|
||||
class MediaTransportInterface;
|
||||
} // namespace webrtc
|
||||
|
||||
namespace cricket {
|
||||
@ -92,9 +90,7 @@ class BaseChannel : public ChannelInterface,
|
||||
webrtc::CryptoOptions crypto_options,
|
||||
rtc::UniqueRandomIdGenerator* ssrc_generator);
|
||||
virtual ~BaseChannel();
|
||||
virtual void Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config);
|
||||
virtual void Init_w(webrtc::RtpTransportInternal* rtp_transport);
|
||||
|
||||
// Deinit may be called multiple times and is simply ignored if it's already
|
||||
// done.
|
||||
@ -299,9 +295,6 @@ class BaseChannel : public ChannelInterface,
|
||||
|
||||
webrtc::RtpTransportInternal* rtp_transport_ = nullptr;
|
||||
|
||||
// Optional media transport configuration (experimental).
|
||||
webrtc::MediaTransportConfig media_transport_config_;
|
||||
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
|
||||
bool writable_ = false;
|
||||
@ -353,9 +346,7 @@ class VoiceChannel : public BaseChannel {
|
||||
cricket::MediaType media_type() const override {
|
||||
return cricket::MEDIA_TYPE_AUDIO;
|
||||
}
|
||||
void Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) override;
|
||||
void Init_w(webrtc::RtpTransportInternal* rtp_transport) override;
|
||||
|
||||
private:
|
||||
// overrides from BaseChannel
|
||||
@ -435,9 +426,7 @@ class RtpDataChannel : public BaseChannel {
|
||||
DtlsTransportInternal* rtcp_dtls_transport,
|
||||
rtc::PacketTransportInternal* rtp_packet_transport,
|
||||
rtc::PacketTransportInternal* rtcp_packet_transport);
|
||||
void Init_w(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config) override;
|
||||
void Init_w(webrtc::RtpTransportInternal* rtp_transport) override;
|
||||
|
||||
virtual bool SendData(const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
|
||||
@ -187,7 +187,6 @@ VoiceChannel* ChannelManager::CreateVoiceChannel(
|
||||
webrtc::Call* call,
|
||||
const cricket::MediaConfig& media_config,
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config,
|
||||
rtc::Thread* signaling_thread,
|
||||
const std::string& content_name,
|
||||
bool srtp_required,
|
||||
@ -197,9 +196,8 @@ VoiceChannel* ChannelManager::CreateVoiceChannel(
|
||||
if (!worker_thread_->IsCurrent()) {
|
||||
return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] {
|
||||
return CreateVoiceChannel(call, media_config, rtp_transport,
|
||||
media_transport_config, signaling_thread,
|
||||
content_name, srtp_required, crypto_options,
|
||||
ssrc_generator, options);
|
||||
signaling_thread, content_name, srtp_required,
|
||||
crypto_options, ssrc_generator, options);
|
||||
});
|
||||
}
|
||||
|
||||
@ -221,7 +219,7 @@ VoiceChannel* ChannelManager::CreateVoiceChannel(
|
||||
absl::WrapUnique(media_channel), content_name, srtp_required,
|
||||
crypto_options, ssrc_generator);
|
||||
|
||||
voice_channel->Init_w(rtp_transport, media_transport_config);
|
||||
voice_channel->Init_w(rtp_transport);
|
||||
|
||||
VoiceChannel* voice_channel_ptr = voice_channel.get();
|
||||
voice_channels_.push_back(std::move(voice_channel));
|
||||
@ -257,7 +255,6 @@ VideoChannel* ChannelManager::CreateVideoChannel(
|
||||
webrtc::Call* call,
|
||||
const cricket::MediaConfig& media_config,
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config,
|
||||
rtc::Thread* signaling_thread,
|
||||
const std::string& content_name,
|
||||
bool srtp_required,
|
||||
@ -267,10 +264,10 @@ VideoChannel* ChannelManager::CreateVideoChannel(
|
||||
webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) {
|
||||
if (!worker_thread_->IsCurrent()) {
|
||||
return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
|
||||
return CreateVideoChannel(
|
||||
call, media_config, rtp_transport, media_transport_config,
|
||||
signaling_thread, content_name, srtp_required, crypto_options,
|
||||
ssrc_generator, options, video_bitrate_allocator_factory);
|
||||
return CreateVideoChannel(call, media_config, rtp_transport,
|
||||
signaling_thread, content_name, srtp_required,
|
||||
crypto_options, ssrc_generator, options,
|
||||
video_bitrate_allocator_factory);
|
||||
});
|
||||
}
|
||||
|
||||
@ -293,7 +290,7 @@ VideoChannel* ChannelManager::CreateVideoChannel(
|
||||
absl::WrapUnique(media_channel), content_name, srtp_required,
|
||||
crypto_options, ssrc_generator);
|
||||
|
||||
video_channel->Init_w(rtp_transport, media_transport_config);
|
||||
video_channel->Init_w(rtp_transport);
|
||||
|
||||
VideoChannel* video_channel_ptr = video_channel.get();
|
||||
video_channels_.push_back(std::move(video_channel));
|
||||
@ -355,7 +352,7 @@ RtpDataChannel* ChannelManager::CreateRtpDataChannel(
|
||||
crypto_options, ssrc_generator);
|
||||
|
||||
// Media Transports are not supported with Rtp Data Channel.
|
||||
data_channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
|
||||
data_channel->Init_w(rtp_transport);
|
||||
|
||||
RtpDataChannel* data_channel_ptr = data_channel.get();
|
||||
data_channels_.push_back(std::move(data_channel));
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
|
||||
#include "api/audio_options.h"
|
||||
#include "api/crypto/crypto_options.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "call/call.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_channel.h"
|
||||
@ -101,7 +100,6 @@ class ChannelManager final {
|
||||
webrtc::Call* call,
|
||||
const cricket::MediaConfig& media_config,
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config,
|
||||
rtc::Thread* signaling_thread,
|
||||
const std::string& content_name,
|
||||
bool srtp_required,
|
||||
@ -118,7 +116,6 @@ class ChannelManager final {
|
||||
webrtc::Call* call,
|
||||
const cricket::MediaConfig& media_config,
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
const webrtc::MediaTransportConfig& media_transport_config,
|
||||
rtc::Thread* signaling_thread,
|
||||
const std::string& content_name,
|
||||
bool srtp_required,
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include <memory>
|
||||
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "api/video/builtin_video_bitrate_allocator_factory.h"
|
||||
#include "media/base/fake_media_engine.h"
|
||||
#include "media/base/test_utils.h"
|
||||
@ -73,20 +72,17 @@ class ChannelManagerTest : public ::testing::Test {
|
||||
return dtls_srtp_transport;
|
||||
}
|
||||
|
||||
void TestCreateDestroyChannels(
|
||||
webrtc::RtpTransportInternal* rtp_transport,
|
||||
webrtc::MediaTransportConfig media_transport_config) {
|
||||
void TestCreateDestroyChannels(webrtc::RtpTransportInternal* rtp_transport) {
|
||||
cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
|
||||
&fake_call_, cricket::MediaConfig(), rtp_transport,
|
||||
media_transport_config, rtc::Thread::Current(), cricket::CN_AUDIO,
|
||||
kDefaultSrtpRequired, webrtc::CryptoOptions(), &ssrc_generator_,
|
||||
AudioOptions());
|
||||
rtc::Thread::Current(), cricket::CN_AUDIO, kDefaultSrtpRequired,
|
||||
webrtc::CryptoOptions(), &ssrc_generator_, AudioOptions());
|
||||
EXPECT_TRUE(voice_channel != nullptr);
|
||||
cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
|
||||
&fake_call_, cricket::MediaConfig(), rtp_transport,
|
||||
media_transport_config, rtc::Thread::Current(), cricket::CN_VIDEO,
|
||||
kDefaultSrtpRequired, webrtc::CryptoOptions(), &ssrc_generator_,
|
||||
VideoOptions(), video_bitrate_allocator_factory_.get());
|
||||
rtc::Thread::Current(), cricket::CN_VIDEO, kDefaultSrtpRequired,
|
||||
webrtc::CryptoOptions(), &ssrc_generator_, VideoOptions(),
|
||||
video_bitrate_allocator_factory_.get());
|
||||
EXPECT_TRUE(video_channel != nullptr);
|
||||
cricket::RtpDataChannel* rtp_data_channel = cm_->CreateRtpDataChannel(
|
||||
cricket::MediaConfig(), rtp_transport, rtc::Thread::Current(),
|
||||
@ -183,8 +179,7 @@ TEST_F(ChannelManagerTest, SetVideoRtxEnabled) {
|
||||
TEST_F(ChannelManagerTest, CreateDestroyChannels) {
|
||||
EXPECT_TRUE(cm_->Init());
|
||||
auto rtp_transport = CreateDtlsSrtpTransport();
|
||||
TestCreateDestroyChannels(rtp_transport.get(),
|
||||
webrtc::MediaTransportConfig());
|
||||
TestCreateDestroyChannels(rtp_transport.get());
|
||||
}
|
||||
|
||||
TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) {
|
||||
@ -194,8 +189,7 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) {
|
||||
EXPECT_TRUE(cm_->set_network_thread(network_.get()));
|
||||
EXPECT_TRUE(cm_->Init());
|
||||
auto rtp_transport = CreateDtlsSrtpTransport();
|
||||
TestCreateDestroyChannels(rtp_transport.get(),
|
||||
webrtc::MediaTransportConfig());
|
||||
TestCreateDestroyChannels(rtp_transport.get());
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio_options.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/fake_media_engine.h"
|
||||
#include "media/base/fake_rtp.h"
|
||||
@ -1431,7 +1430,7 @@ std::unique_ptr<cricket::VoiceChannel> ChannelTest<VoiceTraits>::CreateChannel(
|
||||
worker_thread, network_thread, signaling_thread, std::move(ch),
|
||||
cricket::CN_AUDIO, (flags & DTLS) != 0, webrtc::CryptoOptions(),
|
||||
&ssrc_generator_);
|
||||
channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
|
||||
channel->Init_w(rtp_transport);
|
||||
return channel;
|
||||
}
|
||||
|
||||
@ -1514,7 +1513,7 @@ std::unique_ptr<cricket::VideoChannel> ChannelTest<VideoTraits>::CreateChannel(
|
||||
worker_thread, network_thread, signaling_thread, std::move(ch),
|
||||
cricket::CN_VIDEO, (flags & DTLS) != 0, webrtc::CryptoOptions(),
|
||||
&ssrc_generator_);
|
||||
channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
|
||||
channel->Init_w(rtp_transport);
|
||||
return channel;
|
||||
}
|
||||
|
||||
@ -2301,7 +2300,7 @@ std::unique_ptr<cricket::RtpDataChannel> ChannelTest<DataTraits>::CreateChannel(
|
||||
worker_thread, network_thread, signaling_thread, std::move(ch),
|
||||
cricket::CN_DATA, (flags & DTLS) != 0, webrtc::CryptoOptions(),
|
||||
&ssrc_generator_);
|
||||
channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
|
||||
channel->Init_w(rtp_transport);
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "api/data_channel_interface.h"
|
||||
#include "api/priority.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/transport/data_channel_transport_interface.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "pc/channel.h"
|
||||
#include "rtc_base/async_invoker.h"
|
||||
|
||||
@ -1,380 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 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 "pc/datagram_rtp_transport.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "p2p/base/dtls_transport_internal.h"
|
||||
#include "p2p/base/packet_transport_internal.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/dscp.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/rtc_certificate.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h"
|
||||
#include "rtc_base/stream.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Field trials.
|
||||
// Disable datagram to RTCP feedback translation and enable RTCP feedback loop
|
||||
// on top of datagram feedback loop. Note that two
|
||||
// feedback loops add unneccesary overhead, so it's preferable to use feedback
|
||||
// loop provided by datagram transport and convert datagram ACKs to RTCP ACKs,
|
||||
// but enabling RTCP feedback loop may be useful in tests and experiments.
|
||||
const char kDisableDatagramToRtcpFeebackTranslationFieldTrial[] =
|
||||
"WebRTC-kDisableDatagramToRtcpFeebackTranslation";
|
||||
|
||||
} // namespace
|
||||
|
||||
// Maximum packet size of RTCP feedback packet for allocation. We re-create RTCP
|
||||
// feedback packets when we get ACK notifications from datagram transport. Our
|
||||
// rtcp feedback packets contain only 1 ACK, so they are much smaller than 1250.
|
||||
constexpr size_t kMaxRtcpFeedbackPacketSize = 1250;
|
||||
|
||||
DatagramRtpTransport::DatagramRtpTransport(
|
||||
const std::vector<RtpExtension>& rtp_header_extensions,
|
||||
cricket::IceTransportInternal* ice_transport,
|
||||
DatagramTransportInterface* datagram_transport)
|
||||
: ice_transport_(ice_transport),
|
||||
datagram_transport_(datagram_transport),
|
||||
disable_datagram_to_rtcp_feeback_translation_(field_trial::IsEnabled(
|
||||
kDisableDatagramToRtcpFeebackTranslationFieldTrial)) {
|
||||
// Save extension map for parsing RTP packets (we only need transport
|
||||
// sequence numbers).
|
||||
const RtpExtension* transport_sequence_number_extension =
|
||||
RtpExtension::FindHeaderExtensionByUri(rtp_header_extensions,
|
||||
TransportSequenceNumber::kUri);
|
||||
|
||||
if (transport_sequence_number_extension != nullptr) {
|
||||
rtp_header_extension_map_.Register<TransportSequenceNumber>(
|
||||
transport_sequence_number_extension->id);
|
||||
} else {
|
||||
RTC_LOG(LS_ERROR) << "Transport sequence numbers are not supported in "
|
||||
"datagram transport connection";
|
||||
}
|
||||
|
||||
RTC_DCHECK(ice_transport_);
|
||||
RTC_DCHECK(datagram_transport_);
|
||||
|
||||
ice_transport_->SignalNetworkRouteChanged.connect(
|
||||
this, &DatagramRtpTransport::OnNetworkRouteChanged);
|
||||
// Subscribe to DatagramTransport to read incoming packets.
|
||||
datagram_transport_->SetDatagramSink(this);
|
||||
datagram_transport_->SetTransportStateCallback(this);
|
||||
}
|
||||
|
||||
DatagramRtpTransport::~DatagramRtpTransport() {
|
||||
// Unsubscribe from DatagramTransport sinks.
|
||||
datagram_transport_->SetDatagramSink(nullptr);
|
||||
datagram_transport_->SetTransportStateCallback(nullptr);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
// Assign and increment datagram_id.
|
||||
const DatagramId datagram_id = current_datagram_id_++;
|
||||
|
||||
// Send as is (without extracting transport sequence number) for
|
||||
// RTP packets if we are not doing datagram => RTCP feedback translation.
|
||||
if (disable_datagram_to_rtcp_feeback_translation_) {
|
||||
// Even if we are not extracting transport sequence number we need to
|
||||
// propagate "Sent" notification for both RTP and RTCP packets. For this
|
||||
// reason we need save options.packet_id in packet map.
|
||||
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
|
||||
|
||||
return SendDatagram(*packet, datagram_id);
|
||||
}
|
||||
|
||||
// Parse RTP packet.
|
||||
RtpPacket rtp_packet(&rtp_header_extension_map_);
|
||||
// TODO(mellem): Verify that this doesn't mangle something (it shouldn't).
|
||||
if (!rtp_packet.Parse(*packet)) {
|
||||
RTC_NOTREACHED() << "Failed to parse outgoing RtpPacket, len="
|
||||
<< packet->size()
|
||||
<< ", options.packet_id=" << options.packet_id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Try to get transport sequence number.
|
||||
uint16_t transport_senquence_number;
|
||||
if (!rtp_packet.GetExtension<TransportSequenceNumber>(
|
||||
&transport_senquence_number)) {
|
||||
// Save packet info without transport sequence number.
|
||||
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
|
||||
|
||||
RTC_LOG(LS_VERBOSE)
|
||||
<< "Sending rtp packet without transport sequence number, packet="
|
||||
<< rtp_packet.ToString();
|
||||
|
||||
return SendDatagram(*packet, datagram_id);
|
||||
}
|
||||
|
||||
// Save packet info with sequence number and ssrc so we could reconstruct
|
||||
// RTCP feedback packet when we receive datagram ACK.
|
||||
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(
|
||||
options.packet_id, rtp_packet.Ssrc(), transport_senquence_number);
|
||||
|
||||
// Since datagram transport provides feedback and timestamps, we do not need
|
||||
// to send transport sequence number, so we remove it from RTP packet. Later
|
||||
// when we get Ack for sent datagram, we will re-create RTCP feedback packet.
|
||||
if (!rtp_packet.RemoveExtension(TransportSequenceNumber::kId)) {
|
||||
RTC_NOTREACHED() << "Failed to remove transport sequence number, packet="
|
||||
<< rtp_packet.ToString();
|
||||
return -1;
|
||||
}
|
||||
|
||||
RTC_LOG(LS_VERBOSE) << "Removed transport_senquence_number="
|
||||
<< transport_senquence_number
|
||||
<< " from packet=" << rtp_packet.ToString()
|
||||
<< ", saved bytes=" << packet->size() - rtp_packet.size();
|
||||
|
||||
return SendDatagram(
|
||||
rtc::ArrayView<const uint8_t>(rtp_packet.data(), rtp_packet.size()),
|
||||
datagram_id);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
// Assign and increment datagram_id.
|
||||
const DatagramId datagram_id = current_datagram_id_++;
|
||||
|
||||
// Even if we are not extracting transport sequence number we need to
|
||||
// propagate "Sent" notification for both RTP and RTCP packets. For this
|
||||
// reason we need save options.packet_id in packet map.
|
||||
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
|
||||
return SendDatagram(*packet, datagram_id);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
DatagramId datagram_id) {
|
||||
return datagram_transport_->SendDatagram(data, datagram_id).ok();
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnDatagramReceived(
|
||||
rtc::ArrayView<const uint8_t> data) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
rtc::ArrayView<const char> cdata(reinterpret_cast<const char*>(data.data()),
|
||||
data.size());
|
||||
if (cricket::InferRtpPacketType(cdata) == cricket::RtpPacketType::kRtcp) {
|
||||
rtc::CopyOnWriteBuffer buffer(data.data(), data.size());
|
||||
SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(sukhanov): I am not filling out time, but on my video quality
|
||||
// test in WebRTC the time was not set either and higher layers of the stack
|
||||
// overwrite -1 with current current rtc time. Leaveing comment for now to
|
||||
// make sure it works as expected.
|
||||
RtpPacketReceived parsed_packet(&rtp_header_extension_map_);
|
||||
if (!parsed_packet.Parse(data)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to parse incoming RTP packet";
|
||||
return;
|
||||
}
|
||||
if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) {
|
||||
RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: "
|
||||
<< RtpDemuxer::DescribePacket(parsed_packet);
|
||||
}
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnDatagramSent(DatagramId datagram_id) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
// Find packet_id and propagate OnPacketSent notification.
|
||||
const auto& it = sent_rtp_packet_map_.find(datagram_id);
|
||||
if (it == sent_rtp_packet_map_.end()) {
|
||||
RTC_NOTREACHED() << "Did not find sent packet info for sent datagram_id="
|
||||
<< datagram_id;
|
||||
return;
|
||||
}
|
||||
|
||||
// Also see how DatagramRtpTransport::OnSentPacket handles OnSentPacket
|
||||
// notification from ICE in bypass mode.
|
||||
rtc::SentPacket sent_packet(/*packet_id=*/it->second.packet_id,
|
||||
rtc::TimeMillis());
|
||||
|
||||
SignalSentPacket(sent_packet);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::GetAndRemoveSentPacketInfo(
|
||||
DatagramId datagram_id,
|
||||
SentPacketInfo* sent_packet_info) {
|
||||
RTC_CHECK(sent_packet_info != nullptr);
|
||||
|
||||
const auto& it = sent_rtp_packet_map_.find(datagram_id);
|
||||
if (it == sent_rtp_packet_map_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*sent_packet_info = it->second;
|
||||
sent_rtp_packet_map_.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnDatagramAcked(const DatagramAck& ack) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
SentPacketInfo sent_packet_info;
|
||||
if (!GetAndRemoveSentPacketInfo(ack.datagram_id, &sent_packet_info)) {
|
||||
// TODO(sukhanov): If OnDatagramAck() can come after OnDatagramLost(),
|
||||
// datagram_id is already deleted and we may need to relax the CHECK below.
|
||||
// It's probably OK to ignore such datagrams, because it's been a few RTTs
|
||||
// anyway since they were sent.
|
||||
RTC_NOTREACHED() << "Did not find sent packet info for datagram_id="
|
||||
<< ack.datagram_id;
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_LOG(LS_VERBOSE) << "Datagram acked, ack.datagram_id=" << ack.datagram_id
|
||||
<< ", sent_packet_info.packet_id="
|
||||
<< sent_packet_info.packet_id
|
||||
<< ", sent_packet_info.transport_sequence_number="
|
||||
<< sent_packet_info.transport_sequence_number.value_or(-1)
|
||||
<< ", sent_packet_info.ssrc="
|
||||
<< sent_packet_info.ssrc.value_or(-1)
|
||||
<< ", receive_timestamp_ms="
|
||||
<< ack.receive_timestamp.ms();
|
||||
|
||||
// If transport sequence number was not present in RTP packet, we do not need
|
||||
// to propagate RTCP feedback.
|
||||
if (!sent_packet_info.transport_sequence_number) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(sukhanov): We noticed that datagram transport implementations can
|
||||
// return zero timestamps in the middle of the call. This is workaround to
|
||||
// avoid propagating zero timestamps, but we need to understand why we have
|
||||
// them in the first place.
|
||||
int64_t receive_timestamp_us = ack.receive_timestamp.us();
|
||||
|
||||
if (receive_timestamp_us == 0) {
|
||||
receive_timestamp_us = previous_nonzero_timestamp_us_;
|
||||
} else {
|
||||
previous_nonzero_timestamp_us_ = receive_timestamp_us;
|
||||
}
|
||||
|
||||
// Ssrc must be provided in packet info if transport sequence number is set,
|
||||
// which is guaranteed by SentPacketInfo constructor.
|
||||
RTC_CHECK(sent_packet_info.ssrc);
|
||||
|
||||
// Recreate RTCP feedback packet.
|
||||
rtcp::TransportFeedback feedback_packet;
|
||||
feedback_packet.SetMediaSsrc(*sent_packet_info.ssrc);
|
||||
|
||||
const uint16_t transport_sequence_number =
|
||||
sent_packet_info.transport_sequence_number.value();
|
||||
|
||||
feedback_packet.SetBase(transport_sequence_number, receive_timestamp_us);
|
||||
feedback_packet.AddReceivedPacket(transport_sequence_number,
|
||||
receive_timestamp_us);
|
||||
|
||||
rtc::CopyOnWriteBuffer buffer(kMaxRtcpFeedbackPacketSize);
|
||||
size_t index = 0;
|
||||
if (!feedback_packet.Create(buffer.data(), &index, buffer.capacity(),
|
||||
nullptr)) {
|
||||
RTC_NOTREACHED() << "Failed to create RTCP feedback packet";
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_CHECK_GT(index, 0);
|
||||
RTC_CHECK_LE(index, kMaxRtcpFeedbackPacketSize);
|
||||
|
||||
// Propagage created RTCP packet as normal incoming packet.
|
||||
buffer.SetSize(index);
|
||||
SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1);
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnDatagramLost(DatagramId datagram_id) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
|
||||
RTC_LOG(LS_INFO) << "Datagram lost, datagram_id=" << datagram_id;
|
||||
|
||||
SentPacketInfo sent_packet_info;
|
||||
if (!GetAndRemoveSentPacketInfo(datagram_id, &sent_packet_info)) {
|
||||
RTC_NOTREACHED() << "Did not find sent packet info for lost datagram_id="
|
||||
<< datagram_id;
|
||||
}
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnStateChanged(MediaTransportState state) {
|
||||
state_ = state;
|
||||
SignalWritableState(state_ == MediaTransportState::kWritable);
|
||||
if (state_ == MediaTransportState::kWritable) {
|
||||
SignalReadyToSend(true);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& DatagramRtpTransport::transport_name() const {
|
||||
return ice_transport_->transport_name();
|
||||
}
|
||||
|
||||
int DatagramRtpTransport::SetRtpOption(rtc::Socket::Option opt, int value) {
|
||||
return ice_transport_->SetOption(opt, value);
|
||||
}
|
||||
|
||||
int DatagramRtpTransport::SetRtcpOption(rtc::Socket::Option opt, int value) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::IsReadyToSend() const {
|
||||
return state_ == MediaTransportState::kWritable;
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::IsWritable(bool /*rtcp*/) const {
|
||||
return state_ == MediaTransportState::kWritable;
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) {
|
||||
rtp_header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::RegisterRtpDemuxerSink(
|
||||
const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) {
|
||||
rtp_demuxer_.RemoveSink(sink);
|
||||
return rtp_demuxer_.AddSink(criteria, sink);
|
||||
}
|
||||
|
||||
bool DatagramRtpTransport::UnregisterRtpDemuxerSink(
|
||||
RtpPacketSinkInterface* sink) {
|
||||
return rtp_demuxer_.RemoveSink(sink);
|
||||
}
|
||||
|
||||
void DatagramRtpTransport::OnNetworkRouteChanged(
|
||||
absl::optional<rtc::NetworkRoute> network_route) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
SignalNetworkRouteChanged(network_route);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 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 PC_DATAGRAM_RTP_TRANSPORT_H_
|
||||
#define PC_DATAGRAM_RTP_TRANSPORT_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/crypto/crypto_options.h"
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
|
||||
#include "p2p/base/ice_transport_internal.h"
|
||||
#include "p2p/base/packet_transport_internal.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/buffer_queue.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h"
|
||||
#include "rtc_base/stream.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
constexpr int kDatagramDtlsAdaptorComponent = -1;
|
||||
|
||||
// RTP transport which uses the DatagramTransportInterface to send and receive
|
||||
// packets.
|
||||
class DatagramRtpTransport : public RtpTransportInternal,
|
||||
public webrtc::DatagramSinkInterface,
|
||||
public webrtc::MediaTransportStateCallback {
|
||||
public:
|
||||
DatagramRtpTransport(
|
||||
const std::vector<webrtc::RtpExtension>& rtp_header_extensions,
|
||||
cricket::IceTransportInternal* ice_transport,
|
||||
DatagramTransportInterface* datagram_transport);
|
||||
|
||||
~DatagramRtpTransport() override;
|
||||
|
||||
// =====================================================
|
||||
// Overrides for webrtc::DatagramTransportSinkInterface
|
||||
// and MediaTransportStateCallback
|
||||
// =====================================================
|
||||
void OnDatagramReceived(rtc::ArrayView<const uint8_t> data) override;
|
||||
|
||||
void OnDatagramSent(webrtc::DatagramId datagram_id) override;
|
||||
|
||||
void OnDatagramAcked(const webrtc::DatagramAck& ack) override;
|
||||
|
||||
void OnDatagramLost(webrtc::DatagramId datagram_id) override;
|
||||
|
||||
void OnStateChanged(webrtc::MediaTransportState state) override;
|
||||
|
||||
// =====================================================
|
||||
// RtpTransportInternal overrides
|
||||
// =====================================================
|
||||
bool SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) override;
|
||||
|
||||
bool SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
|
||||
const rtc::PacketOptions& options,
|
||||
int flags) override;
|
||||
|
||||
const std::string& transport_name() const override;
|
||||
|
||||
// Datagram transport always muxes RTCP.
|
||||
bool rtcp_mux_enabled() const override { return true; }
|
||||
void SetRtcpMuxEnabled(bool enable) override {}
|
||||
|
||||
int SetRtpOption(rtc::Socket::Option opt, int value) override;
|
||||
int SetRtcpOption(rtc::Socket::Option opt, int value) override;
|
||||
|
||||
bool IsReadyToSend() const override;
|
||||
|
||||
bool IsWritable(bool rtcp) const override;
|
||||
|
||||
bool IsSrtpActive() const override { return false; }
|
||||
|
||||
void UpdateRtpHeaderExtensionMap(
|
||||
const cricket::RtpHeaderExtensions& header_extensions) override;
|
||||
|
||||
bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
|
||||
RtpPacketSinkInterface* sink) override;
|
||||
|
||||
bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override;
|
||||
|
||||
private:
|
||||
// RTP/RTCP packet info stored for each sent packet.
|
||||
struct SentPacketInfo {
|
||||
// RTP packet info with ssrc and transport sequence number.
|
||||
SentPacketInfo(int64_t packet_id,
|
||||
uint32_t ssrc,
|
||||
uint16_t transport_sequence_number)
|
||||
: ssrc(ssrc),
|
||||
transport_sequence_number(transport_sequence_number),
|
||||
packet_id(packet_id) {}
|
||||
|
||||
// Packet info without SSRC and transport sequence number used for RTCP
|
||||
// packets, RTP packets when transport sequence number is not provided or
|
||||
// when feedback translation is disabled.
|
||||
explicit SentPacketInfo(int64_t packet_id) : packet_id(packet_id) {}
|
||||
|
||||
SentPacketInfo() = default;
|
||||
|
||||
absl::optional<uint32_t> ssrc;
|
||||
|
||||
// Transport sequence number (if it was provided in outgoing RTP packet).
|
||||
// It is used to re-create RTCP feedback packets from datagram ACKs.
|
||||
absl::optional<uint16_t> transport_sequence_number;
|
||||
|
||||
// Packet id from rtc::PacketOptions. It is required to propagage sent
|
||||
// notification up the stack (SignalSentPacket).
|
||||
int64_t packet_id = 0;
|
||||
};
|
||||
|
||||
// Finds SentPacketInfo for given |datagram_id| and removes map entry.
|
||||
// Returns false if entry was not found.
|
||||
bool GetAndRemoveSentPacketInfo(webrtc::DatagramId datagram_id,
|
||||
SentPacketInfo* sent_packet_info);
|
||||
|
||||
// Sends datagram to datagram_transport.
|
||||
bool SendDatagram(rtc::ArrayView<const uint8_t> data,
|
||||
webrtc::DatagramId datagram_id);
|
||||
|
||||
// Propagates network route changes from ICE.
|
||||
void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route);
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
cricket::IceTransportInternal* ice_transport_;
|
||||
webrtc::DatagramTransportInterface* datagram_transport_;
|
||||
|
||||
RtpDemuxer rtp_demuxer_;
|
||||
|
||||
MediaTransportState state_ = MediaTransportState::kPending;
|
||||
|
||||
// Extension map for parsing transport sequence numbers.
|
||||
webrtc::RtpHeaderExtensionMap rtp_header_extension_map_;
|
||||
|
||||
// Keeps information about sent RTP packet until they are Acked or Lost.
|
||||
std::map<webrtc::DatagramId, SentPacketInfo> sent_rtp_packet_map_;
|
||||
|
||||
// Current datagram_id, incremented after each sent RTP packets.
|
||||
// Datagram id is passed to datagram transport when we send datagram and we
|
||||
// get it back in notifications about Sent, Acked and Lost datagrams.
|
||||
int64_t current_datagram_id_ = 0;
|
||||
|
||||
// TODO(sukhanov): Previous nonzero timestamp is required for workaround for
|
||||
// zero timestamps received, which sometimes are received from datagram
|
||||
// transport. Investigate if we can eliminate zero timestamps.
|
||||
int64_t previous_nonzero_timestamp_us_ = 0;
|
||||
|
||||
// Disable datagram to RTCP feedback translation and enable RTCP feedback
|
||||
// loop (note that having both RTCP and datagram feedback loops is
|
||||
// inefficient, but can be useful in tests and experiments).
|
||||
const bool disable_datagram_to_rtcp_feeback_translation_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // PC_DATAGRAM_RTP_TRANSPORT_H_
|
||||
@ -88,9 +88,7 @@ JsepTransport::JsepTransport(
|
||||
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
|
||||
std::unique_ptr<SctpTransportInternal> sctp_transport,
|
||||
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport,
|
||||
webrtc::DataChannelTransportInterface* data_channel_transport)
|
||||
std::unique_ptr<SctpTransportInternal> sctp_transport)
|
||||
: network_thread_(rtc::Thread::Current()),
|
||||
mid_(mid),
|
||||
local_certificate_(local_certificate),
|
||||
@ -115,10 +113,7 @@ JsepTransport::JsepTransport(
|
||||
sctp_transport_(sctp_transport
|
||||
? new rtc::RefCountedObject<webrtc::SctpTransport>(
|
||||
std::move(sctp_transport))
|
||||
: nullptr),
|
||||
datagram_transport_(std::move(datagram_transport)),
|
||||
datagram_rtp_transport_(std::move(datagram_rtp_transport)),
|
||||
data_channel_transport_(data_channel_transport) {
|
||||
: nullptr) {
|
||||
RTC_DCHECK(ice_transport_);
|
||||
RTC_DCHECK(rtp_dtls_transport_);
|
||||
// |rtcp_ice_transport_| must be present iff |rtcp_dtls_transport_| is
|
||||
@ -383,18 +378,6 @@ absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
|
||||
return absl::optional<rtc::SSLRole>(dtls_role);
|
||||
}
|
||||
|
||||
absl::optional<OpaqueTransportParameters>
|
||||
JsepTransport::GetTransportParameters() const {
|
||||
rtc::CritScope scope(&accessor_lock_);
|
||||
if (!datagram_transport_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
OpaqueTransportParameters params;
|
||||
params.parameters = datagram_transport_->GetTransportParameters();
|
||||
return params;
|
||||
}
|
||||
|
||||
bool JsepTransport::GetStats(TransportStats* stats) {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
rtc::CritScope scope(&accessor_lock_);
|
||||
@ -753,106 +736,10 @@ bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(nisse): Delete.
|
||||
void JsepTransport::NegotiateDatagramTransport(SdpType type) {
|
||||
RTC_DCHECK(type == SdpType::kAnswer || type == SdpType::kPrAnswer);
|
||||
rtc::CritScope lock(&accessor_lock_);
|
||||
if (!datagram_transport_) {
|
||||
return; // No need to negotiate the use of datagram transport.
|
||||
}
|
||||
|
||||
bool compatible_datagram_transport = false;
|
||||
if (datagram_transport_ &&
|
||||
local_description_->transport_desc.opaque_parameters &&
|
||||
remote_description_->transport_desc.opaque_parameters) {
|
||||
// If both descriptions have datagram transport parameters, and the remote
|
||||
// parameters are accepted by the datagram transport, then use the datagram
|
||||
// transport. Otherwise, fall back to RTP.
|
||||
compatible_datagram_transport =
|
||||
datagram_transport_
|
||||
->SetRemoteTransportParameters(remote_description_->transport_desc
|
||||
.opaque_parameters->parameters)
|
||||
.ok();
|
||||
}
|
||||
|
||||
bool use_datagram_transport_for_media =
|
||||
compatible_datagram_transport &&
|
||||
remote_description_->media_alt_protocol ==
|
||||
remote_description_->transport_desc.opaque_parameters->protocol &&
|
||||
remote_description_->media_alt_protocol ==
|
||||
local_description_->media_alt_protocol;
|
||||
|
||||
bool use_datagram_transport_for_data =
|
||||
compatible_datagram_transport &&
|
||||
remote_description_->data_alt_protocol ==
|
||||
remote_description_->transport_desc.opaque_parameters->protocol &&
|
||||
remote_description_->data_alt_protocol ==
|
||||
local_description_->data_alt_protocol;
|
||||
|
||||
RTC_LOG(LS_INFO)
|
||||
<< "Negotiating datagram transport, use_datagram_transport_for_media="
|
||||
<< use_datagram_transport_for_media
|
||||
<< ", use_datagram_transport_for_data=" << use_datagram_transport_for_data
|
||||
<< " answer type=" << (type == SdpType::kAnswer ? "answer" : "pr_answer");
|
||||
|
||||
// A provisional or full or answer lets the peer start sending on one of the
|
||||
// transports.
|
||||
if (composite_rtp_transport_) {
|
||||
composite_rtp_transport_->SetSendTransport(
|
||||
use_datagram_transport_for_media ? datagram_rtp_transport_.get()
|
||||
: default_rtp_transport());
|
||||
}
|
||||
if (composite_data_channel_transport_) {
|
||||
composite_data_channel_transport_->SetSendTransport(
|
||||
use_datagram_transport_for_data ? data_channel_transport_
|
||||
: sctp_data_channel_transport_.get());
|
||||
}
|
||||
|
||||
if (type != SdpType::kAnswer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (composite_rtp_transport_) {
|
||||
if (use_datagram_transport_for_media) {
|
||||
// Negotiated use of datagram transport for RTP, so remove the
|
||||
// non-datagram RTP transport.
|
||||
composite_rtp_transport_->RemoveTransport(default_rtp_transport());
|
||||
if (unencrypted_rtp_transport_) {
|
||||
unencrypted_rtp_transport_ = nullptr;
|
||||
} else if (sdes_transport_) {
|
||||
sdes_transport_ = nullptr;
|
||||
} else {
|
||||
dtls_srtp_transport_ = nullptr;
|
||||
}
|
||||
} else {
|
||||
composite_rtp_transport_->RemoveTransport(datagram_rtp_transport_.get());
|
||||
datagram_rtp_transport_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (composite_data_channel_transport_) {
|
||||
if (use_datagram_transport_for_data) {
|
||||
// Negotiated use of datagram transport for data channels, so remove the
|
||||
// non-datagram data channel transport.
|
||||
composite_data_channel_transport_->RemoveTransport(
|
||||
sctp_data_channel_transport_.get());
|
||||
sctp_data_channel_transport_ = nullptr;
|
||||
sctp_transport_ = nullptr;
|
||||
} else {
|
||||
composite_data_channel_transport_->RemoveTransport(
|
||||
data_channel_transport_);
|
||||
data_channel_transport_ = nullptr;
|
||||
}
|
||||
} else if (data_channel_transport_ && !use_datagram_transport_for_data) {
|
||||
// The datagram transport has been rejected without a fallback. We still
|
||||
// need to inform the application and delete it.
|
||||
SignalDataChannelTransportNegotiated(this, nullptr);
|
||||
data_channel_transport_ = nullptr;
|
||||
}
|
||||
|
||||
if (!use_datagram_transport_for_media && !use_datagram_transport_for_data) {
|
||||
// Datagram transport is not being used for anything, so clean it up.
|
||||
datagram_transport_ = nullptr;
|
||||
}
|
||||
return; // No need to negotiate the use of datagram transport.
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
#include "api/candidate.h"
|
||||
#include "api/ice_transport_interface.h"
|
||||
#include "api/jsep.h"
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "media/sctp/sctp_transport_internal.h"
|
||||
#include "p2p/base/dtls_transport.h"
|
||||
#include "p2p/base/p2p_constants.h"
|
||||
@ -103,9 +102,7 @@ class JsepTransport : public sigslot::has_slots<> {
|
||||
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
|
||||
std::unique_ptr<SctpTransportInternal> sctp_transport,
|
||||
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport,
|
||||
webrtc::DataChannelTransportInterface* data_channel_transport);
|
||||
std::unique_ptr<SctpTransportInternal> sctp_transport);
|
||||
|
||||
~JsepTransport() override;
|
||||
|
||||
@ -158,9 +155,6 @@ class JsepTransport : public sigslot::has_slots<> {
|
||||
absl::optional<rtc::SSLRole> GetDtlsRole() const
|
||||
RTC_LOCKS_EXCLUDED(accessor_lock_);
|
||||
|
||||
absl::optional<OpaqueTransportParameters> GetTransportParameters() const
|
||||
RTC_LOCKS_EXCLUDED(accessor_lock_);
|
||||
|
||||
// TODO(deadbeef): Make this const. See comment in transportcontroller.h.
|
||||
bool GetStats(TransportStats* stats) RTC_LOCKS_EXCLUDED(accessor_lock_);
|
||||
|
||||
@ -245,13 +239,6 @@ class JsepTransport : public sigslot::has_slots<> {
|
||||
return data_channel_transport_;
|
||||
}
|
||||
|
||||
// Returns datagram transport, if available.
|
||||
webrtc::DatagramTransportInterface* datagram_transport() const
|
||||
RTC_LOCKS_EXCLUDED(accessor_lock_) {
|
||||
rtc::CritScope scope(&accessor_lock_);
|
||||
return datagram_transport_.get();
|
||||
}
|
||||
|
||||
// This is signaled when RTCP-mux becomes active and
|
||||
// |rtcp_dtls_transport_| is destroyed. The JsepTransportController will
|
||||
// handle the signal and update the aggregate transport states.
|
||||
@ -407,10 +394,6 @@ class JsepTransport : public sigslot::has_slots<> {
|
||||
absl::optional<std::vector<int>> recv_extension_ids_
|
||||
RTC_GUARDED_BY(network_thread_);
|
||||
|
||||
// Optional datagram transport (experimental).
|
||||
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport_
|
||||
RTC_GUARDED_BY(accessor_lock_);
|
||||
|
||||
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport_
|
||||
RTC_GUARDED_BY(accessor_lock_);
|
||||
|
||||
|
||||
@ -15,11 +15,8 @@
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "api/ice_transport_factory.h"
|
||||
#include "api/transport/datagram_transport_interface.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "p2p/base/ice_transport_internal.h"
|
||||
#include "p2p/base/port.h"
|
||||
#include "pc/datagram_rtp_transport.h"
|
||||
#include "pc/srtp_filter.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
@ -140,26 +137,6 @@ RtpTransportInternal* JsepTransportController::GetRtpTransport(
|
||||
return jsep_transport->rtp_transport();
|
||||
}
|
||||
|
||||
MediaTransportConfig JsepTransportController::GetMediaTransportConfig(
|
||||
const std::string& mid) const {
|
||||
auto jsep_transport = GetJsepTransportForMid(mid);
|
||||
if (!jsep_transport) {
|
||||
return MediaTransportConfig();
|
||||
}
|
||||
|
||||
DatagramTransportInterface* datagram_transport = nullptr;
|
||||
if (config_.use_datagram_transport) {
|
||||
datagram_transport = jsep_transport->datagram_transport();
|
||||
}
|
||||
|
||||
if (datagram_transport) {
|
||||
return MediaTransportConfig(
|
||||
/*rtp_max_packet_size=*/datagram_transport->GetLargestDatagramSize());
|
||||
} else {
|
||||
return MediaTransportConfig();
|
||||
}
|
||||
}
|
||||
|
||||
DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
|
||||
const std::string& mid) const {
|
||||
auto jsep_transport = GetJsepTransportForMid(mid);
|
||||
@ -425,17 +402,6 @@ void JsepTransportController::SetActiveResetSrtpParams(
|
||||
}
|
||||
}
|
||||
|
||||
void JsepTransportController::SetMediaTransportSettings(
|
||||
bool use_datagram_transport,
|
||||
bool use_datagram_transport_for_data_channels,
|
||||
bool use_datagram_transport_for_data_channels_receive_only) {
|
||||
config_.use_datagram_transport = use_datagram_transport;
|
||||
config_.use_datagram_transport_for_data_channels =
|
||||
use_datagram_transport_for_data_channels;
|
||||
config_.use_datagram_transport_for_data_channels_receive_only =
|
||||
use_datagram_transport_for_data_channels_receive_only;
|
||||
}
|
||||
|
||||
void JsepTransportController::RollbackTransports() {
|
||||
if (!network_thread_->IsCurrent()) {
|
||||
network_thread_->Invoke<void>(RTC_FROM_HERE, [=] { RollbackTransports(); });
|
||||
@ -468,16 +434,12 @@ JsepTransportController::CreateIceTransport(const std::string& transport_name,
|
||||
std::unique_ptr<cricket::DtlsTransportInternal>
|
||||
JsepTransportController::CreateDtlsTransport(
|
||||
const cricket::ContentInfo& content_info,
|
||||
cricket::IceTransportInternal* ice,
|
||||
DatagramTransportInterface* datagram_transport) {
|
||||
cricket::IceTransportInternal* ice) {
|
||||
RTC_DCHECK(network_thread_->IsCurrent());
|
||||
|
||||
std::unique_ptr<cricket::DtlsTransportInternal> dtls;
|
||||
|
||||
if (datagram_transport) {
|
||||
RTC_DCHECK(config_.use_datagram_transport ||
|
||||
config_.use_datagram_transport_for_data_channels);
|
||||
} else if (config_.dtls_transport_factory) {
|
||||
if (config_.dtls_transport_factory) {
|
||||
dtls = config_.dtls_transport_factory->CreateDtlsTransport(
|
||||
ice, config_.crypto_options);
|
||||
} else {
|
||||
@ -1066,83 +1028,6 @@ cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
|
||||
return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
// TODO(sukhanov): Refactor to avoid code duplication for Media and Datagram
|
||||
// transports setup.
|
||||
std::unique_ptr<webrtc::DatagramTransportInterface>
|
||||
JsepTransportController::MaybeCreateDatagramTransport(
|
||||
const cricket::ContentInfo& content_info,
|
||||
const cricket::SessionDescription& description,
|
||||
bool local) {
|
||||
if (config_.media_transport_factory == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!(config_.use_datagram_transport ||
|
||||
config_.use_datagram_transport_for_data_channels)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Caller (offerer) datagram transport.
|
||||
if (offer_datagram_transport_) {
|
||||
RTC_DCHECK(local);
|
||||
RTC_LOG(LS_INFO) << "Offered datagram transport has now been activated.";
|
||||
return std::move(offer_datagram_transport_);
|
||||
}
|
||||
|
||||
const cricket::TransportDescription* transport_description =
|
||||
description.GetTransportDescriptionByName(content_info.mid());
|
||||
RTC_DCHECK(transport_description)
|
||||
<< "Missing transport description for mid=" << content_info.mid();
|
||||
|
||||
if (!transport_description->opaque_parameters) {
|
||||
RTC_LOG(LS_INFO)
|
||||
<< "No opaque transport parameters, not creating datagram transport";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (transport_description->opaque_parameters->protocol !=
|
||||
config_.media_transport_factory->GetTransportName()) {
|
||||
RTC_LOG(LS_INFO) << "Opaque transport parameters for protocol="
|
||||
<< transport_description->opaque_parameters->protocol
|
||||
<< ", which does not match supported protocol="
|
||||
<< config_.media_transport_factory->GetTransportName();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RTC_DCHECK(!local);
|
||||
// When bundle is enabled, two JsepTransports are created, and then
|
||||
// the second transport is destroyed (right away).
|
||||
// For datagram transport, we don't want to create the second
|
||||
// datagram transport in the first place.
|
||||
RTC_LOG(LS_INFO) << "Returning new, client datagram transport.";
|
||||
|
||||
MediaTransportSettings settings;
|
||||
settings.is_caller = local;
|
||||
settings.remote_transport_parameters =
|
||||
transport_description->opaque_parameters->parameters;
|
||||
settings.event_log = config_.event_log;
|
||||
|
||||
auto datagram_transport_result =
|
||||
config_.media_transport_factory->CreateDatagramTransport(network_thread_,
|
||||
settings);
|
||||
|
||||
if (!datagram_transport_result.ok()) {
|
||||
// Datagram transport negotiation will fail and we'll fall back to RTP.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!datagram_transport_result.value()
|
||||
->SetRemoteTransportParameters(
|
||||
transport_description->opaque_parameters->parameters)
|
||||
.ok()) {
|
||||
// Datagram transport negotiation failed (parameters are incompatible).
|
||||
// Fall back to RTP.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return datagram_transport_result.MoveValue();
|
||||
}
|
||||
|
||||
RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
bool local,
|
||||
const cricket::ContentInfo& content_info,
|
||||
@ -1164,14 +1049,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
CreateIceTransport(content_info.name, /*rtcp=*/false);
|
||||
RTC_DCHECK(ice);
|
||||
|
||||
std::unique_ptr<DatagramTransportInterface> datagram_transport =
|
||||
MaybeCreateDatagramTransport(content_info, description, local);
|
||||
if (datagram_transport) {
|
||||
datagram_transport->Connect(ice->internal());
|
||||
}
|
||||
|
||||
std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
|
||||
CreateDtlsTransport(content_info, ice->internal(), nullptr);
|
||||
CreateDtlsTransport(content_info, ice->internal());
|
||||
|
||||
std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
|
||||
std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
|
||||
@ -1183,29 +1062,9 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
if (config_.rtcp_mux_policy !=
|
||||
PeerConnectionInterface::kRtcpMuxPolicyRequire &&
|
||||
content_info.type == cricket::MediaProtocolType::kRtp) {
|
||||
RTC_DCHECK(datagram_transport == nullptr);
|
||||
rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
|
||||
rtcp_dtls_transport =
|
||||
CreateDtlsTransport(content_info, rtcp_ice->internal(),
|
||||
/*datagram_transport=*/nullptr);
|
||||
}
|
||||
|
||||
// Only create a datagram RTP transport if the datagram transport should be
|
||||
// used for RTP.
|
||||
if (datagram_transport && config_.use_datagram_transport) {
|
||||
// TODO(sukhanov): We use unencrypted RTP transport over DatagramTransport,
|
||||
// because MediaTransport encrypts. In the future we may want to
|
||||
// implement our own version of RtpTransport over MediaTransport, because
|
||||
// it will give us more control over things like:
|
||||
// - Fusing
|
||||
// - Rtp header compression
|
||||
// - Handling Rtcp feedback.
|
||||
RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram "
|
||||
"transport is used.";
|
||||
RTC_DCHECK(!rtcp_dtls_transport);
|
||||
datagram_rtp_transport = std::make_unique<DatagramRtpTransport>(
|
||||
content_info.media_description()->rtp_header_extensions(),
|
||||
ice->internal(), datagram_transport.get());
|
||||
CreateDtlsTransport(content_info, rtcp_ice->internal());
|
||||
}
|
||||
|
||||
if (config_.disable_encryption) {
|
||||
@ -1229,19 +1088,13 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
||||
config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
|
||||
}
|
||||
|
||||
DataChannelTransportInterface* data_channel_transport = nullptr;
|
||||
if (config_.use_datagram_transport_for_data_channels) {
|
||||
data_channel_transport = datagram_transport.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<cricket::JsepTransport> jsep_transport =
|
||||
std::make_unique<cricket::JsepTransport>(
|
||||
content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
|
||||
std::move(unencrypted_rtp_transport), std::move(sdes_transport),
|
||||
std::move(dtls_srtp_transport), std::move(datagram_rtp_transport),
|
||||
std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport),
|
||||
std::move(sctp_transport), std::move(datagram_transport),
|
||||
data_channel_transport);
|
||||
std::move(sctp_transport));
|
||||
|
||||
jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
|
||||
this, &JsepTransportController::OnRtcpPacketReceived_n);
|
||||
@ -1643,54 +1496,10 @@ void JsepTransportController::OnDtlsHandshakeError(
|
||||
SignalDtlsHandshakeError(error);
|
||||
}
|
||||
|
||||
// TODO(nisse): Delete
|
||||
absl::optional<cricket::OpaqueTransportParameters>
|
||||
JsepTransportController::GetTransportParameters(const std::string& mid) {
|
||||
if (!(config_.use_datagram_transport ||
|
||||
config_.use_datagram_transport_for_data_channels)) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
|
||||
if (transport) {
|
||||
absl::optional<cricket::OpaqueTransportParameters> params =
|
||||
transport->GetTransportParameters();
|
||||
if (params) {
|
||||
params->protocol = config_.media_transport_factory->GetTransportName();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
RTC_DCHECK(!local_desc_ && !remote_desc_)
|
||||
<< "JsepTransport should exist for every mid once any description is set";
|
||||
|
||||
if (config_.use_datagram_transport_for_data_channels_receive_only) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
// Need to generate a transport for the offer.
|
||||
if (!offer_datagram_transport_) {
|
||||
webrtc::MediaTransportSettings settings;
|
||||
settings.is_caller = true;
|
||||
settings.pre_shared_key = rtc::CreateRandomString(32);
|
||||
settings.event_log = config_.event_log;
|
||||
auto datagram_transport_or_error =
|
||||
config_.media_transport_factory->CreateDatagramTransport(
|
||||
network_thread_, settings);
|
||||
|
||||
if (datagram_transport_or_error.ok()) {
|
||||
offer_datagram_transport_ =
|
||||
std::move(datagram_transport_or_error.value());
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Unable to create datagram transport, error="
|
||||
<< datagram_transport_or_error.error().message();
|
||||
}
|
||||
}
|
||||
|
||||
// We have prepared a transport for the offer, and can now use its parameters.
|
||||
cricket::OpaqueTransportParameters params;
|
||||
params.parameters = offer_datagram_transport_->GetTransportParameters();
|
||||
params.protocol = config_.media_transport_factory->GetTransportName();
|
||||
return params;
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
#include "api/ice_transport_factory.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/rtc_event_log/rtc_event_log.h"
|
||||
#include "api/transport/media/media_transport_config.h"
|
||||
#include "media/sctp/sctp_transport_internal.h"
|
||||
#include "p2p/base/dtls_transport.h"
|
||||
#include "p2p/base/dtls_transport_factory.h"
|
||||
@ -103,31 +102,6 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
|
||||
// Factory for SCTP transports.
|
||||
cricket::SctpTransportInternalFactory* sctp_factory = nullptr;
|
||||
|
||||
// Whether an RtpMediaTransport should be created as default, when no
|
||||
// MediaTransportFactory is provided.
|
||||
bool use_rtp_media_transport = false;
|
||||
|
||||
// Use encrypted datagram transport to send packets.
|
||||
bool use_datagram_transport = false;
|
||||
|
||||
// Use datagram transport's implementation of data channels instead of SCTP.
|
||||
bool use_datagram_transport_for_data_channels = false;
|
||||
|
||||
// Whether |use_datagram_transport_for_data_channels| applies to outgoing
|
||||
// calls. If true, |use_datagram_transport_for_data_channels| applies only
|
||||
// to incoming calls.
|
||||
bool use_datagram_transport_for_data_channels_receive_only = false;
|
||||
|
||||
// Optional media transport factory (experimental). If provided it will be
|
||||
// used to create datagram_transport (as long as either
|
||||
// |use_datagram_transport| or
|
||||
// |use_datagram_transport_for_data_channels| is set to true). However,
|
||||
// whether it will be used to send / receive audio and video frames instead
|
||||
// of RTP is determined by |use_datagram_transport|. Note that currently
|
||||
// datagram_transport co-exists with RTP / RTCP transports and may use the
|
||||
// same underlying ICE transport.
|
||||
MediaTransportFactory* media_transport_factory = nullptr;
|
||||
};
|
||||
|
||||
// The ICE related events are signaled on the |signaling_thread|.
|
||||
@ -161,8 +135,6 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
rtc::scoped_refptr<SctpTransport> GetSctpTransport(
|
||||
const std::string& mid) const;
|
||||
|
||||
MediaTransportConfig GetMediaTransportConfig(const std::string& mid) const;
|
||||
|
||||
DataChannelTransportInterface* GetDataChannelTransport(
|
||||
const std::string& mid) const;
|
||||
|
||||
@ -215,15 +187,6 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
|
||||
void SetActiveResetSrtpParams(bool active_reset_srtp_params);
|
||||
|
||||
// Allows to overwrite the settings from config. You may set or reset the
|
||||
// media transport configuration on the jsep transport controller, as long as
|
||||
// you did not call 'GetMediaTransport' or 'MaybeCreateJsepTransport'. Once
|
||||
// Jsep transport is created, you can't change this setting.
|
||||
void SetMediaTransportSettings(
|
||||
bool use_datagram_transport,
|
||||
bool use_datagram_transport_for_data_channels,
|
||||
bool use_datagram_transport_for_data_channels_receive_only);
|
||||
|
||||
// For now the rollback only removes mid to transport mappings
|
||||
// and deletes unused transports, but doesn't consider anything more complex.
|
||||
void RollbackTransports();
|
||||
@ -347,16 +310,6 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
const cricket::ContentInfo& content_info,
|
||||
const cricket::SessionDescription& description);
|
||||
|
||||
// Creates datagram transport if config wants to use it, and a=x-mt line is
|
||||
// present for the current media transport. Returned
|
||||
// DatagramTransportInterface is not connected, and must be connected to ICE.
|
||||
// You must call |GenerateOrGetLastMediaTransportOffer| on the caller before
|
||||
// calling MaybeCreateDatagramTransport.
|
||||
std::unique_ptr<webrtc::DatagramTransportInterface>
|
||||
MaybeCreateDatagramTransport(const cricket::ContentInfo& content_info,
|
||||
const cricket::SessionDescription& description,
|
||||
bool local);
|
||||
|
||||
void MaybeDestroyJsepTransport(const std::string& mid);
|
||||
void DestroyAllJsepTransports_n();
|
||||
|
||||
@ -370,8 +323,7 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
|
||||
std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
|
||||
const cricket::ContentInfo& content_info,
|
||||
cricket::IceTransportInternal* ice,
|
||||
DatagramTransportInterface* datagram_transport);
|
||||
cricket::IceTransportInternal* ice);
|
||||
rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport(
|
||||
const std::string& transport_name,
|
||||
bool rtcp);
|
||||
@ -446,17 +398,6 @@ class JsepTransportController : public sigslot::has_slots<> {
|
||||
|
||||
Config config_;
|
||||
|
||||
// Early on in the call we don't know if datagram transport is going to be
|
||||
// used, but we need to get the server-supported parameters to add to an SDP.
|
||||
// This server datagram transport will be promoted to the used datagram
|
||||
// transport after the local description is set, and the ownership will be
|
||||
// transferred to the actual JsepTransport. This "offer" datagram transport is
|
||||
// not created if it's done on the party that provides answer. This offer
|
||||
// datagram transport is only created once at the beginning of the connection,
|
||||
// and never again.
|
||||
std::unique_ptr<DatagramTransportInterface> offer_datagram_transport_ =
|
||||
nullptr;
|
||||
|
||||
const cricket::SessionDescription* local_desc_ = nullptr;
|
||||
const cricket::SessionDescription* remote_desc_ = nullptr;
|
||||
absl::optional<bool> initial_offerer_;
|
||||
|
||||
@ -13,9 +13,6 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "api/test/fake_media_transport.h"
|
||||
#include "api/test/loopback_media_transport.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "p2p/base/dtls_transport_factory.h"
|
||||
#include "p2p/base/fake_dtls_transport.h"
|
||||
#include "p2p/base/fake_ice_transport.h"
|
||||
@ -44,20 +41,6 @@ static const char kDataMid1[] = "data1";
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Media transport factory requires crypto settings to be present in order to
|
||||
// create media transport.
|
||||
void AddCryptoSettings(cricket::SessionDescription* description) {
|
||||
for (auto& content : description->contents()) {
|
||||
content.media_description()->AddCrypto(cricket::CryptoParams(
|
||||
/*t=*/0, std::string(rtc::CS_AES_CM_128_HMAC_SHA1_80),
|
||||
"inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2", ""));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class FakeIceTransportFactory : public webrtc::IceTransportFactory {
|
||||
public:
|
||||
~FakeIceTransportFactory() override = default;
|
||||
@ -440,96 +423,6 @@ TEST_F(JsepTransportControllerTest, GetDtlsTransportWithRtcpMux) {
|
||||
EXPECT_EQ(nullptr, transport_controller_->GetRtcpDtlsTransport(kVideoMid1));
|
||||
}
|
||||
|
||||
TEST_F(JsepTransportControllerTest,
|
||||
DtlsIsStillCreatedIfDatagramTransportIsOnlyUsedForDataChannels) {
|
||||
FakeMediaTransportFactory fake_media_transport_factory("transport_params");
|
||||
JsepTransportController::Config config;
|
||||
|
||||
config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
|
||||
config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle;
|
||||
config.media_transport_factory = &fake_media_transport_factory;
|
||||
config.use_datagram_transport_for_data_channels = true;
|
||||
CreateJsepTransportController(config);
|
||||
|
||||
auto description = CreateSessionDescriptionWithBundledData();
|
||||
AddCryptoSettings(description.get());
|
||||
|
||||
absl::optional<cricket::OpaqueTransportParameters> params =
|
||||
transport_controller_->GetTransportParameters(kAudioMid1);
|
||||
for (auto& info : description->transport_infos()) {
|
||||
info.description.opaque_parameters = params;
|
||||
}
|
||||
for (cricket::ContentInfo& content_info : description->contents()) {
|
||||
if (content_info.media_description()->type() == cricket::MEDIA_TYPE_DATA) {
|
||||
content_info.media_description()->set_alt_protocol(params->protocol);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(transport_controller_
|
||||
->SetLocalDescription(SdpType::kOffer, description.get())
|
||||
.ok());
|
||||
EXPECT_TRUE(transport_controller_
|
||||
->SetRemoteDescription(SdpType::kAnswer, description.get())
|
||||
.ok());
|
||||
|
||||
FakeDatagramTransport* datagram_transport =
|
||||
static_cast<FakeDatagramTransport*>(
|
||||
transport_controller_->GetDataChannelTransport(kAudioMid1));
|
||||
|
||||
ASSERT_NE(nullptr, datagram_transport);
|
||||
|
||||
EXPECT_EQ(cricket::ICE_CANDIDATE_COMPONENT_RTP,
|
||||
transport_controller_->GetDtlsTransport(kAudioMid1)->component())
|
||||
<< "Datagram transport for media was not enabled, and so DTLS transport "
|
||||
"should be created.";
|
||||
|
||||
// Datagram transport is not used for media, so no max packet size is
|
||||
// specified.
|
||||
EXPECT_EQ(transport_controller_->GetMediaTransportConfig(kAudioMid1)
|
||||
.rtp_max_packet_size,
|
||||
absl::nullopt);
|
||||
|
||||
// Since datagram transport is not used for RTP, setting it to writable should
|
||||
// not make the RTP transport writable.
|
||||
datagram_transport->set_state(MediaTransportState::kWritable);
|
||||
EXPECT_FALSE(transport_controller_->GetRtpTransport(kAudioMid1)
|
||||
->IsWritable(/*rtcp=*/false));
|
||||
}
|
||||
|
||||
// An offer that bundles different alt-protocols should be rejected.
|
||||
TEST_F(JsepTransportControllerTest, CannotBundleDifferentAltProtocols) {
|
||||
FakeMediaTransportFactory fake_media_transport_factory("transport_params");
|
||||
JsepTransportController::Config config;
|
||||
config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
|
||||
config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle;
|
||||
config.media_transport_factory = &fake_media_transport_factory;
|
||||
config.use_datagram_transport = true;
|
||||
config.use_datagram_transport_for_data_channels = true;
|
||||
CreateJsepTransportController(config);
|
||||
|
||||
auto description = CreateSessionDescriptionWithBundledData();
|
||||
AddCryptoSettings(description.get());
|
||||
|
||||
absl::optional<cricket::OpaqueTransportParameters> params =
|
||||
transport_controller_->GetTransportParameters(kAudioMid1);
|
||||
for (auto& info : description->transport_infos()) {
|
||||
info.description.opaque_parameters = params;
|
||||
}
|
||||
|
||||
// Append a different alt-protocol to each of the sections.
|
||||
for (cricket::ContentInfo& content_info : description->contents()) {
|
||||
content_info.media_description()->set_alt_protocol(params->protocol + "-" +
|
||||
content_info.name);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(transport_controller_
|
||||
->SetLocalDescription(SdpType::kOffer, description.get())
|
||||
.ok());
|
||||
EXPECT_FALSE(transport_controller_
|
||||
->SetRemoteDescription(SdpType::kAnswer, description.get())
|
||||
.ok());
|
||||
}
|
||||
|
||||
TEST_F(JsepTransportControllerTest, SetIceConfig) {
|
||||
CreateJsepTransportController(JsepTransportController::Config());
|
||||
auto description = CreateSessionDescriptionWithoutBundle();
|
||||
@ -1650,423 +1543,4 @@ TEST_F(JsepTransportControllerTest, ChangeTaggedMediaSectionMaxBundle) {
|
||||
.ok());
|
||||
}
|
||||
|
||||
constexpr char kFakeTransportParameters[] = "fake-params";
|
||||
|
||||
// Test fixture that provides common setup and helpers for tests related to the
|
||||
// datagram transport.
|
||||
class JsepTransportControllerDatagramTest
|
||||
: public JsepTransportControllerTest,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
JsepTransportControllerDatagramTest()
|
||||
: JsepTransportControllerTest(),
|
||||
fake_media_transport_factory_(kFakeTransportParameters) {
|
||||
JsepTransportController::Config config;
|
||||
config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire;
|
||||
config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle;
|
||||
config.media_transport_factory = &fake_media_transport_factory_;
|
||||
config.use_datagram_transport = true;
|
||||
CreateJsepTransportController(config);
|
||||
}
|
||||
|
||||
// Whether the JsepTransportController under test acts as the offerer or
|
||||
// answerer in this test.
|
||||
bool IsOfferer() { return GetParam(); }
|
||||
|
||||
// Sets a description as local or remote based on type and current
|
||||
// perspective.
|
||||
RTCError SetDescription(SdpType type,
|
||||
const cricket::SessionDescription* description) {
|
||||
if (IsOfferer() == (type == SdpType::kOffer)) {
|
||||
return transport_controller_->SetLocalDescription(type, description);
|
||||
} else {
|
||||
return transport_controller_->SetRemoteDescription(type, description);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a session description with the settings necessary for datagram
|
||||
// transport (bundle + crypto) and the given |transport_params|.
|
||||
std::unique_ptr<cricket::SessionDescription>
|
||||
CreateSessionDescriptionForDatagramTransport(
|
||||
absl::optional<cricket::OpaqueTransportParameters> transport_params) {
|
||||
auto description = CreateSessionDescriptionWithBundleGroup();
|
||||
AddCryptoSettings(description.get());
|
||||
|
||||
for (auto& info : description->transport_infos()) {
|
||||
info.description.opaque_parameters = transport_params;
|
||||
}
|
||||
if (transport_params) {
|
||||
for (auto& content_info : description->contents()) {
|
||||
content_info.media_description()->set_alt_protocol(
|
||||
transport_params->protocol);
|
||||
}
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
// Creates transport parameters with |protocol| and |parameters|
|
||||
// matching what |fake_media_transport_factory_| provides.
|
||||
cricket::OpaqueTransportParameters CreateTransportParameters() {
|
||||
cricket::OpaqueTransportParameters params;
|
||||
params.protocol = fake_media_transport_factory_.GetTransportName();
|
||||
params.parameters = "fake-params";
|
||||
return params;
|
||||
}
|
||||
|
||||
protected:
|
||||
FakeMediaTransportFactory fake_media_transport_factory_;
|
||||
};
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, InitDatagramTransport) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
// Getting transport parameters is allowed before setting a description.
|
||||
// This is necessary so that the offerer can include these params.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
// Setting a description activates the datagram transport without changing
|
||||
// transport parameters.
|
||||
auto description = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok());
|
||||
|
||||
// After setting an offer with transport parameters, those parameters are
|
||||
// reflected by the controller.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest,
|
||||
OfferMissingDatagramTransportParams) {
|
||||
if (IsOfferer()) {
|
||||
// This test doesn't make sense from the offerer's perspective, as the offer
|
||||
// must contain datagram transport params if the offerer supports it.
|
||||
return;
|
||||
}
|
||||
|
||||
auto description =
|
||||
CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok());
|
||||
|
||||
// The offer didn't contain any datagram transport parameters, so the answer
|
||||
// won't either.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, OfferHasWrongTransportName) {
|
||||
if (IsOfferer()) {
|
||||
// This test doesn't make sense from the offerer's perspective, as the
|
||||
// offerer cannot offer itself the wrong transport.
|
||||
return;
|
||||
}
|
||||
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
fake_params.protocol = "wrong-name";
|
||||
|
||||
auto description = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok());
|
||||
|
||||
// The offerer and answerer support different datagram transports, so the
|
||||
// answerer rejects the offered parameters.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, IncompatibleAnswer) {
|
||||
// Transport will claim that no parameters are compatible, even if they match
|
||||
// exactly.
|
||||
fake_media_transport_factory_.set_transport_parameters_comparison(
|
||||
[](absl::string_view, absl::string_view) { return false; });
|
||||
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
// The offerer and answerer have incompatible parameters, so the answerer
|
||||
// rejects the offered parameters.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, CompatibleAnswer) {
|
||||
// Transport will claim that no parameters are compatible, even if they are
|
||||
// completely different.
|
||||
fake_media_transport_factory_.set_transport_parameters_comparison(
|
||||
[](absl::string_view, absl::string_view) { return true; });
|
||||
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
cricket::OpaqueTransportParameters answer_params;
|
||||
answer_params.protocol = fake_params.protocol;
|
||||
answer_params.parameters = "something different from offer";
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(answer_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
// The offerer and answerer have compatible parameters, so the answerer
|
||||
// accepts the offered parameters.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, AnswerRejectsDatagram) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
// The answer rejected datagram transport, so its parameters are empty.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, AnswerAcceptsDatagram) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
// The answer accepted datagram transport, so it is present.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, PrAnswerRejectsDatagram) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kPrAnswer, answer.get()).ok());
|
||||
|
||||
// The answer rejected datagram transport, but it's provisional, so the
|
||||
// transport is kept around for now.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, PrAnswerAcceptsDatagram) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kPrAnswer, answer.get()).ok());
|
||||
|
||||
// The answer provisionally accepted datagram transport, so it's kept.
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, RenegotiationCannotAddDatagram) {
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
|
||||
// Attempting to add a datagram transport on a re-offer does not cause an
|
||||
// error, but also does not add a datagram transport.
|
||||
auto reoffer =
|
||||
CreateSessionDescriptionForDatagramTransport(CreateTransportParameters());
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest, RenegotiationCannotRemoveDatagram) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
// Attempting to remove a datagram transport on a re-offer does not cause an
|
||||
// error, but also does not remove the datagram transport.
|
||||
auto reoffer = CreateSessionDescriptionForDatagramTransport(absl::nullopt);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
TEST_P(JsepTransportControllerDatagramTest,
|
||||
RenegotiationKeepsDatagramTransport) {
|
||||
cricket::OpaqueTransportParameters fake_params = CreateTransportParameters();
|
||||
if (IsOfferer()) {
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
auto offer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto answer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
// Attempting to remove a datagram transport on a re-offer does not cause an
|
||||
// error, but also does not remove the datagram transport.
|
||||
auto reoffer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
|
||||
auto reanswer = CreateSessionDescriptionForDatagramTransport(fake_params);
|
||||
EXPECT_TRUE(SetDescription(SdpType::kAnswer, reanswer.get()).ok());
|
||||
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1),
|
||||
fake_params);
|
||||
EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1),
|
||||
fake_params);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
JsepTransportControllerDatagramTests,
|
||||
JsepTransportControllerDatagramTest,
|
||||
testing::Values(true, false),
|
||||
// The parameter value is the local perspective (offerer or answerer).
|
||||
[](const testing::TestParamInfo<bool>& info) {
|
||||
return info.param ? "Offerer" : "Answerer";
|
||||
});
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -120,9 +120,7 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
|
||||
std::move(sdes_transport), std::move(dtls_srtp_transport),
|
||||
/*datagram_rtp_transport=*/nullptr, std::move(rtp_dtls_transport),
|
||||
std::move(rtcp_dtls_transport),
|
||||
/*sctp_transport=*/nullptr,
|
||||
/*datagram_transport=*/nullptr,
|
||||
/*data_channel_transport=*/nullptr);
|
||||
/*sctp_transport=*/nullptr);
|
||||
|
||||
signal_rtcp_mux_active_received_ = false;
|
||||
jsep_transport->SignalRtcpMuxActive.connect(
|
||||
|
||||
@ -107,13 +107,6 @@ const char kDtlsSrtpSetupFailureRtcp[] =
|
||||
|
||||
namespace {
|
||||
|
||||
// Field trials.
|
||||
// Controls datagram transport support.
|
||||
const char kDatagramTransportFieldTrial[] = "WebRTC-DatagramTransport";
|
||||
// Controls datagram transport data channel support.
|
||||
const char kDatagramTransportDataChannelFieldTrial[] =
|
||||
"WebRTC-DatagramTransportDataChannels";
|
||||
|
||||
// UMA metric names.
|
||||
const char kSimulcastVersionApplyLocalDescription[] =
|
||||
"WebRTC.PeerConnection.Simulcast.ApplyLocalDescription";
|
||||
@ -916,11 +909,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
|
||||
SdpSemantics sdp_semantics;
|
||||
absl::optional<rtc::AdapterType> network_preference;
|
||||
bool active_reset_srtp_params;
|
||||
bool use_media_transport;
|
||||
bool use_media_transport_for_data_channels;
|
||||
absl::optional<bool> use_datagram_transport;
|
||||
absl::optional<bool> use_datagram_transport_for_data_channels;
|
||||
absl::optional<bool> use_datagram_transport_for_data_channels_receive_only;
|
||||
absl::optional<CryptoOptions> crypto_options;
|
||||
bool offer_extmap_allow_mixed;
|
||||
std::string turn_logging_id;
|
||||
@ -981,14 +969,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator==(
|
||||
sdp_semantics == o.sdp_semantics &&
|
||||
network_preference == o.network_preference &&
|
||||
active_reset_srtp_params == o.active_reset_srtp_params &&
|
||||
use_media_transport == o.use_media_transport &&
|
||||
use_media_transport_for_data_channels ==
|
||||
o.use_media_transport_for_data_channels &&
|
||||
use_datagram_transport == o.use_datagram_transport &&
|
||||
use_datagram_transport_for_data_channels ==
|
||||
o.use_datagram_transport_for_data_channels &&
|
||||
use_datagram_transport_for_data_channels_receive_only ==
|
||||
o.use_datagram_transport_for_data_channels_receive_only &&
|
||||
crypto_options == o.crypto_options &&
|
||||
offer_extmap_allow_mixed == o.offer_extmap_allow_mixed &&
|
||||
turn_logging_id == o.turn_logging_id &&
|
||||
@ -1057,10 +1037,6 @@ PeerConnection::PeerConnection(PeerConnectionFactory* factory,
|
||||
event_log_(std::move(event_log)),
|
||||
event_log_ptr_(event_log_.get()),
|
||||
operations_chain_(rtc::OperationsChain::Create()),
|
||||
datagram_transport_config_(
|
||||
field_trial::FindFullName(kDatagramTransportFieldTrial)),
|
||||
datagram_transport_data_channel_config_(
|
||||
field_trial::FindFullName(kDatagramTransportDataChannelFieldTrial)),
|
||||
rtcp_cname_(GenerateRtcpCname()),
|
||||
local_streams_(StreamCollection::Create()),
|
||||
remote_streams_(StreamCollection::Create()),
|
||||
@ -1265,33 +1241,6 @@ bool PeerConnection::Initialize(
|
||||
#endif
|
||||
config.active_reset_srtp_params = configuration.active_reset_srtp_params;
|
||||
|
||||
use_datagram_transport_ = datagram_transport_config_.enabled &&
|
||||
configuration.use_datagram_transport.value_or(
|
||||
datagram_transport_config_.default_value);
|
||||
use_datagram_transport_for_data_channels_ =
|
||||
datagram_transport_data_channel_config_.enabled &&
|
||||
configuration.use_datagram_transport_for_data_channels.value_or(
|
||||
datagram_transport_data_channel_config_.default_value);
|
||||
use_datagram_transport_for_data_channels_receive_only_ =
|
||||
configuration.use_datagram_transport_for_data_channels_receive_only
|
||||
.value_or(datagram_transport_data_channel_config_.receive_only);
|
||||
if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) {
|
||||
if (!factory_->media_transport_factory()) {
|
||||
RTC_DCHECK(false)
|
||||
<< "PeerConnecton is initialized with use_datagram_transport = true "
|
||||
"or use_datagram_transport_for_data_channels = true "
|
||||
"but media transport factory is not set in PeerConnectionFactory";
|
||||
return false;
|
||||
}
|
||||
|
||||
config.use_datagram_transport = use_datagram_transport_;
|
||||
config.use_datagram_transport_for_data_channels =
|
||||
use_datagram_transport_for_data_channels_;
|
||||
config.use_datagram_transport_for_data_channels_receive_only =
|
||||
use_datagram_transport_for_data_channels_receive_only_;
|
||||
config.media_transport_factory = factory_->media_transport_factory();
|
||||
}
|
||||
|
||||
// Obtain a certificate from RTCConfiguration if any were provided (optional).
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||
if (!configuration.certificates.empty()) {
|
||||
@ -1314,24 +1263,7 @@ bool PeerConnection::Initialize(
|
||||
|
||||
sctp_factory_ = factory_->CreateSctpTransportInternalFactory();
|
||||
|
||||
if (use_datagram_transport_for_data_channels_) {
|
||||
if (configuration.enable_rtp_data_channel) {
|
||||
RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and "
|
||||
"use_datagram_transport_for_data_channels are "
|
||||
"incompatible and cannot both be set to true";
|
||||
return false;
|
||||
}
|
||||
if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) {
|
||||
RTC_LOG(LS_INFO) << "Using data channel transport with no fallback";
|
||||
data_channel_controller_.set_data_channel_type(
|
||||
cricket::DCT_DATA_CHANNEL_TRANSPORT);
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP";
|
||||
data_channel_controller_.set_data_channel_type(
|
||||
cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
|
||||
config.sctp_factory = sctp_factory_.get();
|
||||
}
|
||||
} else if (configuration.enable_rtp_data_channel) {
|
||||
if (configuration.enable_rtp_data_channel) {
|
||||
// Enable creation of RTP data channels if the kEnableRtpDataChannels is
|
||||
// set. It takes precendence over the disable_sctp_data_channels
|
||||
// PeerConnectionFactoryInterface::Options.
|
||||
@ -3956,66 +3888,6 @@ RTCError PeerConnection::SetConfiguration(
|
||||
"SetLocalDescription.");
|
||||
}
|
||||
|
||||
if (local_description() && configuration.use_datagram_transport !=
|
||||
configuration_.use_datagram_transport) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport "
|
||||
"after calling SetLocalDescription.");
|
||||
}
|
||||
|
||||
if (remote_description() && configuration.use_datagram_transport !=
|
||||
configuration_.use_datagram_transport) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport "
|
||||
"after calling SetRemoteDescription.");
|
||||
}
|
||||
|
||||
if (local_description() &&
|
||||
configuration.use_datagram_transport_for_data_channels !=
|
||||
configuration_.use_datagram_transport_for_data_channels) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport_for_data_channels "
|
||||
"after calling SetLocalDescription.");
|
||||
}
|
||||
|
||||
if (remote_description() &&
|
||||
configuration.use_datagram_transport_for_data_channels !=
|
||||
configuration_.use_datagram_transport_for_data_channels) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport_for_data_channels "
|
||||
"after calling SetRemoteDescription.");
|
||||
}
|
||||
|
||||
if (local_description() &&
|
||||
configuration.use_datagram_transport_for_data_channels_receive_only !=
|
||||
configuration_
|
||||
.use_datagram_transport_for_data_channels_receive_only) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport_for_data_channels_receive_only "
|
||||
"after calling SetLocalDescription.");
|
||||
}
|
||||
|
||||
if (remote_description() &&
|
||||
configuration.use_datagram_transport_for_data_channels_receive_only !=
|
||||
configuration_
|
||||
.use_datagram_transport_for_data_channels_receive_only) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
RTCErrorType::INVALID_MODIFICATION,
|
||||
"Can't change use_datagram_transport_for_data_channels_receive_only "
|
||||
"after calling SetRemoteDescription.");
|
||||
}
|
||||
|
||||
if ((configuration.use_datagram_transport &&
|
||||
*configuration.use_datagram_transport) ||
|
||||
(configuration.use_datagram_transport_for_data_channels &&
|
||||
*configuration.use_datagram_transport_for_data_channels)) {
|
||||
RTC_CHECK(configuration.bundle_policy == kBundlePolicyMaxBundle)
|
||||
<< "Media transport requires MaxBundle policy.";
|
||||
}
|
||||
|
||||
// The simplest (and most future-compatible) way to tell if the config was
|
||||
// modified in an invalid way is to copy each property we do support
|
||||
// modifying, then use operator==. There are far more properties we don't
|
||||
@ -4044,11 +3916,6 @@ RTCError PeerConnection::SetConfiguration(
|
||||
modified_config.network_preference = configuration.network_preference;
|
||||
modified_config.active_reset_srtp_params =
|
||||
configuration.active_reset_srtp_params;
|
||||
modified_config.use_datagram_transport = configuration.use_datagram_transport;
|
||||
modified_config.use_datagram_transport_for_data_channels =
|
||||
configuration.use_datagram_transport_for_data_channels;
|
||||
modified_config.use_datagram_transport_for_data_channels_receive_only =
|
||||
configuration.use_datagram_transport_for_data_channels_receive_only;
|
||||
modified_config.turn_logging_id = configuration.turn_logging_id;
|
||||
modified_config.allow_codec_switching = configuration.allow_codec_switching;
|
||||
if (configuration != modified_config) {
|
||||
@ -4118,20 +3985,6 @@ RTCError PeerConnection::SetConfiguration(
|
||||
|
||||
transport_controller_->SetIceConfig(ParseIceConfig(modified_config));
|
||||
|
||||
use_datagram_transport_ = datagram_transport_config_.enabled &&
|
||||
modified_config.use_datagram_transport.value_or(
|
||||
datagram_transport_config_.default_value);
|
||||
use_datagram_transport_for_data_channels_ =
|
||||
datagram_transport_data_channel_config_.enabled &&
|
||||
modified_config.use_datagram_transport_for_data_channels.value_or(
|
||||
datagram_transport_data_channel_config_.default_value);
|
||||
use_datagram_transport_for_data_channels_receive_only_ =
|
||||
modified_config.use_datagram_transport_for_data_channels_receive_only
|
||||
.value_or(datagram_transport_data_channel_config_.receive_only);
|
||||
transport_controller_->SetMediaTransportSettings(
|
||||
use_datagram_transport_, use_datagram_transport_for_data_channels_,
|
||||
use_datagram_transport_for_data_channels_receive_only_);
|
||||
|
||||
if (configuration_.active_reset_srtp_params !=
|
||||
modified_config.active_reset_srtp_params) {
|
||||
transport_controller_->SetActiveResetSrtpParams(
|
||||
@ -4946,25 +4799,6 @@ void PeerConnection::GetOptionsForOffer(
|
||||
session_options->offer_extmap_allow_mixed =
|
||||
configuration_.offer_extmap_allow_mixed;
|
||||
|
||||
// If datagram transport is in use, add opaque transport parameters.
|
||||
if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) {
|
||||
for (auto& options : session_options->media_description_options) {
|
||||
absl::optional<cricket::OpaqueTransportParameters> params =
|
||||
transport_controller_->GetTransportParameters(options.mid);
|
||||
if (!params) {
|
||||
continue;
|
||||
}
|
||||
options.transport_options.opaque_parameters = params;
|
||||
if ((use_datagram_transport_ &&
|
||||
(options.type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
options.type == cricket::MEDIA_TYPE_VIDEO)) ||
|
||||
(use_datagram_transport_for_data_channels_ &&
|
||||
options.type == cricket::MEDIA_TYPE_DATA)) {
|
||||
options.alt_protocol = params->protocol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow fallback for using obsolete SCTP syntax.
|
||||
// Note that the default in |session_options| is true, while
|
||||
// the default in |options| is false.
|
||||
@ -5270,25 +5104,6 @@ void PeerConnection::GetOptionsForAnswer(
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&cricket::PortAllocator::GetPooledIceCredentials,
|
||||
port_allocator_.get()));
|
||||
|
||||
// If datagram transport is in use, add opaque transport parameters.
|
||||
if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) {
|
||||
for (auto& options : session_options->media_description_options) {
|
||||
absl::optional<cricket::OpaqueTransportParameters> params =
|
||||
transport_controller_->GetTransportParameters(options.mid);
|
||||
if (!params) {
|
||||
continue;
|
||||
}
|
||||
options.transport_options.opaque_parameters = params;
|
||||
if ((use_datagram_transport_ &&
|
||||
(options.type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
options.type == cricket::MEDIA_TYPE_VIDEO)) ||
|
||||
(use_datagram_transport_for_data_channels_ &&
|
||||
options.type == cricket::MEDIA_TYPE_DATA)) {
|
||||
options.alt_protocol = params->protocol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::GetOptionsForPlanBAnswer(
|
||||
@ -6653,13 +6468,11 @@ RTCError PeerConnection::CreateChannels(const SessionDescription& desc) {
|
||||
cricket::VoiceChannel* PeerConnection::CreateVoiceChannel(
|
||||
const std::string& mid) {
|
||||
RtpTransportInternal* rtp_transport = GetRtpTransport(mid);
|
||||
MediaTransportConfig media_transport_config =
|
||||
transport_controller_->GetMediaTransportConfig(mid);
|
||||
|
||||
cricket::VoiceChannel* voice_channel = channel_manager()->CreateVoiceChannel(
|
||||
call_ptr_, configuration_.media_config, rtp_transport,
|
||||
media_transport_config, signaling_thread(), mid, SrtpRequired(),
|
||||
GetCryptoOptions(), &ssrc_generator_, audio_options_);
|
||||
call_ptr_, configuration_.media_config, rtp_transport, signaling_thread(),
|
||||
mid, SrtpRequired(), GetCryptoOptions(), &ssrc_generator_,
|
||||
audio_options_);
|
||||
if (!voice_channel) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -6676,13 +6489,10 @@ cricket::VoiceChannel* PeerConnection::CreateVoiceChannel(
|
||||
cricket::VideoChannel* PeerConnection::CreateVideoChannel(
|
||||
const std::string& mid) {
|
||||
RtpTransportInternal* rtp_transport = GetRtpTransport(mid);
|
||||
MediaTransportConfig media_transport_config =
|
||||
transport_controller_->GetMediaTransportConfig(mid);
|
||||
|
||||
cricket::VideoChannel* video_channel = channel_manager()->CreateVideoChannel(
|
||||
call_ptr_, configuration_.media_config, rtp_transport,
|
||||
media_transport_config, signaling_thread(), mid, SrtpRequired(),
|
||||
GetCryptoOptions(), &ssrc_generator_, video_options_,
|
||||
call_ptr_, configuration_.media_config, rtp_transport, signaling_thread(),
|
||||
mid, SrtpRequired(), GetCryptoOptions(), &ssrc_generator_, video_options_,
|
||||
video_bitrate_allocator_factory_.get());
|
||||
if (!video_channel) {
|
||||
return nullptr;
|
||||
@ -7127,8 +6937,7 @@ bool PeerConnection::ReadyToUseRemoteCandidate(
|
||||
}
|
||||
|
||||
bool PeerConnection::SrtpRequired() const {
|
||||
return !use_datagram_transport_ &&
|
||||
(dtls_enabled_ ||
|
||||
return (dtls_enabled_ ||
|
||||
webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED);
|
||||
}
|
||||
|
||||
|
||||
@ -358,57 +358,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
uint32_t first_ssrc;
|
||||
};
|
||||
|
||||
// Field-trial based configuration for datagram transport.
|
||||
struct DatagramTransportConfig {
|
||||
explicit DatagramTransportConfig(const std::string& field_trial)
|
||||
: enabled("enabled", true), default_value("default_value", false) {
|
||||
ParseFieldTrial({&enabled, &default_value}, field_trial);
|
||||
}
|
||||
|
||||
// Whether datagram transport support is enabled at all. Defaults to true,
|
||||
// allowing datagram transport to be used if (a) the application provides a
|
||||
// factory for it and (b) the configuration specifies its use. This flag
|
||||
// provides a kill-switch to force-disable datagram transport across all
|
||||
// applications, without code changes.
|
||||
FieldTrialFlag enabled;
|
||||
|
||||
// Whether the datagram transport is enabled or disabled by default.
|
||||
// Defaults to false, meaning that applications must configure use of
|
||||
// datagram transport through RTCConfiguration. If set to true,
|
||||
// applications will use the datagram transport by default (but may still
|
||||
// explicitly configure themselves not to use it through RTCConfiguration).
|
||||
FieldTrialFlag default_value;
|
||||
};
|
||||
|
||||
// Field-trial based configuration for datagram transport data channels.
|
||||
struct DatagramTransportDataChannelConfig {
|
||||
explicit DatagramTransportDataChannelConfig(const std::string& field_trial)
|
||||
: enabled("enabled", true),
|
||||
default_value("default_value", false),
|
||||
receive_only("receive_only", false) {
|
||||
ParseFieldTrial({&enabled, &default_value, &receive_only}, field_trial);
|
||||
}
|
||||
|
||||
// Whether datagram transport data channel support is enabled at all.
|
||||
// Defaults to true, allowing datagram transport to be used if (a) the
|
||||
// application provides a factory for it and (b) the configuration specifies
|
||||
// its use. This flag provides a kill-switch to force-disable datagram
|
||||
// transport across all applications, without code changes.
|
||||
FieldTrialFlag enabled;
|
||||
|
||||
// Whether the datagram transport data channels are enabled or disabled by
|
||||
// default. Defaults to false, meaning that applications must configure use
|
||||
// of datagram transport through RTCConfiguration. If set to true,
|
||||
// applications will use the datagram transport by default (but may still
|
||||
// explicitly configure themselves not to use it through RTCConfiguration).
|
||||
FieldTrialFlag default_value;
|
||||
|
||||
// Whether the datagram transport is enabled in receive-only mode. If true,
|
||||
// and if the datagram transport is enabled, it will only be used when
|
||||
// receiving incoming calls, not when placing outgoing calls.
|
||||
FieldTrialFlag receive_only;
|
||||
};
|
||||
|
||||
// Captures partial state to be used for rollback. Applicable only in
|
||||
// Unified Plan.
|
||||
class TransceiverStableState {
|
||||
@ -1212,25 +1161,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
PeerConnectionInterface::RTCConfiguration configuration_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
|
||||
// Field-trial based configuration for datagram transport.
|
||||
const DatagramTransportConfig datagram_transport_config_;
|
||||
|
||||
// Field-trial based configuration for datagram transport data channels.
|
||||
const DatagramTransportDataChannelConfig
|
||||
datagram_transport_data_channel_config_;
|
||||
|
||||
// Final, resolved value for whether datagram transport is in use.
|
||||
bool use_datagram_transport_ RTC_GUARDED_BY(signaling_thread()) = false;
|
||||
|
||||
// Equivalent of |use_datagram_transport_|, but for its use with data
|
||||
// channels.
|
||||
bool use_datagram_transport_for_data_channels_
|
||||
RTC_GUARDED_BY(signaling_thread()) = false;
|
||||
|
||||
// Resolved value of whether to use data channels only for incoming calls.
|
||||
bool use_datagram_transport_for_data_channels_receive_only_
|
||||
RTC_GUARDED_BY(signaling_thread()) = false;
|
||||
|
||||
// TODO(zstein): |async_resolver_factory_| can currently be nullptr if it
|
||||
// is not injected. It should be required once chromium supplies it.
|
||||
std::unique_ptr<AsyncResolverFactory> async_resolver_factory_
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#include "api/peer_connection_proxy.h"
|
||||
#include "api/rtc_event_log/rtc_event_log.h"
|
||||
#include "api/transport/field_trial_based_config.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/turn_customizer.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "api/video_track_source_proxy.h"
|
||||
@ -82,7 +81,6 @@ PeerConnectionFactory::PeerConnectionFactory(
|
||||
std::move(dependencies.network_state_predictor_factory)),
|
||||
injected_network_controller_factory_(
|
||||
std::move(dependencies.network_controller_factory)),
|
||||
media_transport_factory_(std::move(dependencies.media_transport_factory)),
|
||||
neteq_factory_(std::move(dependencies.neteq_factory)),
|
||||
trials_(dependencies.trials ? std::move(dependencies.trials)
|
||||
: std::make_unique<FieldTrialBasedConfig>()) {
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "media/sctp/sctp_transport_internal.h"
|
||||
#include "pc/channel_manager.h"
|
||||
#include "rtc_base/rtc_certificate_generator.h"
|
||||
@ -87,10 +86,6 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface {
|
||||
|
||||
const Options& options() const { return options_; }
|
||||
|
||||
MediaTransportFactory* media_transport_factory() {
|
||||
return media_transport_factory_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
// This structure allows simple management of all new dependencies being added
|
||||
// to the PeerConnectionFactory.
|
||||
@ -128,7 +123,6 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface {
|
||||
network_state_predictor_factory_;
|
||||
std::unique_ptr<NetworkControllerFactoryInterface>
|
||||
injected_network_controller_factory_;
|
||||
std::unique_ptr<MediaTransportFactory> media_transport_factory_;
|
||||
std::unique_ptr<NetEqFactory> neteq_factory_;
|
||||
const std::unique_ptr<WebRtcKeyValueConfig> trials_;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1421,15 +1421,11 @@ TEST_P(PeerConnectionInterfaceTest, GetConfigurationAfterSetConfiguration) {
|
||||
|
||||
PeerConnectionInterface::RTCConfiguration config = pc_->GetConfiguration();
|
||||
config.type = PeerConnectionInterface::kRelay;
|
||||
config.use_datagram_transport = true;
|
||||
config.use_datagram_transport_for_data_channels = true;
|
||||
EXPECT_TRUE(pc_->SetConfiguration(config).ok());
|
||||
|
||||
PeerConnectionInterface::RTCConfiguration returned_config =
|
||||
pc_->GetConfiguration();
|
||||
EXPECT_EQ(PeerConnectionInterface::kRelay, returned_config.type);
|
||||
EXPECT_TRUE(returned_config.use_datagram_transport);
|
||||
EXPECT_TRUE(returned_config.use_datagram_transport_for_data_channels);
|
||||
}
|
||||
|
||||
TEST_P(PeerConnectionInterfaceTest, SetConfigurationFailsAfterClose) {
|
||||
|
||||
@ -123,14 +123,13 @@ class RtpSenderReceiverTest
|
||||
|
||||
voice_channel_ = channel_manager_.CreateVoiceChannel(
|
||||
&fake_call_, cricket::MediaConfig(), rtp_transport_.get(),
|
||||
MediaTransportConfig(), rtc::Thread::Current(), cricket::CN_AUDIO,
|
||||
srtp_required, webrtc::CryptoOptions(), &ssrc_generator_,
|
||||
cricket::AudioOptions());
|
||||
rtc::Thread::Current(), cricket::CN_AUDIO, srtp_required,
|
||||
webrtc::CryptoOptions(), &ssrc_generator_, cricket::AudioOptions());
|
||||
video_channel_ = channel_manager_.CreateVideoChannel(
|
||||
&fake_call_, cricket::MediaConfig(), rtp_transport_.get(),
|
||||
MediaTransportConfig(), rtc::Thread::Current(), cricket::CN_VIDEO,
|
||||
srtp_required, webrtc::CryptoOptions(), &ssrc_generator_,
|
||||
cricket::VideoOptions(), video_bitrate_allocator_factory_.get());
|
||||
rtc::Thread::Current(), cricket::CN_VIDEO, srtp_required,
|
||||
webrtc::CryptoOptions(), &ssrc_generator_, cricket::VideoOptions(),
|
||||
video_bitrate_allocator_factory_.get());
|
||||
voice_channel_->Enable(true);
|
||||
video_channel_->Enable(true);
|
||||
voice_media_channel_ = media_engine_->GetVoiceChannel(0);
|
||||
|
||||
@ -58,7 +58,6 @@ if (!build_with_chromium) {
|
||||
"../../../api/rtc_event_log",
|
||||
"../../../api/task_queue",
|
||||
"../../../api/transport:network_control",
|
||||
"../../../api/transport/media:media_transport_interface",
|
||||
"../../../api/video_codecs:video_codecs_api",
|
||||
"../../../rtc_base",
|
||||
]
|
||||
@ -322,7 +321,6 @@ if (!build_with_chromium) {
|
||||
"../../../api/rtc_event_log",
|
||||
"../../../api/task_queue",
|
||||
"../../../api/transport:network_control",
|
||||
"../../../api/transport/media:media_transport_interface",
|
||||
"../../../api/video_codecs:video_codecs_api",
|
||||
"../../../rtc_base",
|
||||
]
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/test/create_peer_connection_quality_test_frame_generator.h"
|
||||
#include "api/test/peerconnection_quality_test_fixture.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/video_codecs/video_decoder_factory.h"
|
||||
#include "api/video_codecs/video_encoder_factory.h"
|
||||
@ -86,12 +85,6 @@ class PeerConfigurerImpl final
|
||||
std::move(network_controller_factory);
|
||||
return this;
|
||||
}
|
||||
PeerConfigurer* SetMediaTransportFactory(
|
||||
std::unique_ptr<MediaTransportFactory> media_transport_factory) override {
|
||||
components_->pcf_dependencies->media_transport_factory =
|
||||
std::move(media_transport_factory);
|
||||
return this;
|
||||
}
|
||||
PeerConfigurer* SetVideoEncoderFactory(
|
||||
std::unique_ptr<VideoEncoderFactory> video_encoder_factory) override {
|
||||
components_->pcf_dependencies->video_encoder_factory =
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
#include "api/rtc_event_log/rtc_event_log_factory_interface.h"
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/test/peerconnection_quality_test_fixture.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "api/video_codecs/video_decoder_factory.h"
|
||||
#include "api/video_codecs/video_encoder_factory.h"
|
||||
@ -47,7 +46,6 @@ struct PeerConnectionFactoryComponents {
|
||||
std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory;
|
||||
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory;
|
||||
std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory;
|
||||
std::unique_ptr<MediaTransportFactory> media_transport_factory;
|
||||
std::unique_ptr<NetEqFactory> neteq_factory;
|
||||
|
||||
// Will be passed to MediaEngineInterface, that will be used in
|
||||
|
||||
@ -229,10 +229,6 @@ PeerConnectionFactoryDependencies CreatePCFDependencies(
|
||||
pcf_deps.network_controller_factory =
|
||||
std::move(pcf_dependencies->network_controller_factory);
|
||||
}
|
||||
if (pcf_dependencies->media_transport_factory != nullptr) {
|
||||
pcf_deps.media_transport_factory =
|
||||
std::move(pcf_dependencies->media_transport_factory);
|
||||
}
|
||||
if (pcf_dependencies->neteq_factory != nullptr) {
|
||||
pcf_deps.neteq_factory = std::move(pcf_dependencies->neteq_factory);
|
||||
}
|
||||
|
||||
@ -79,7 +79,6 @@ rtc_library("video") {
|
||||
"../api/crypto:options",
|
||||
"../api/rtc_event_log",
|
||||
"../api/task_queue",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/units:timestamp",
|
||||
"../api/video:encoded_image",
|
||||
"../api/video:recordable_encoded_frame",
|
||||
@ -299,7 +298,6 @@ if (rtc_include_tests) {
|
||||
"../api/rtc_event_log:rtc_event_log_factory",
|
||||
"../api/task_queue",
|
||||
"../api/task_queue:default_task_queue_factory",
|
||||
"../api/transport/media:media_transport_interface",
|
||||
"../api/video:builtin_video_bitrate_allocator_factory",
|
||||
"../api/video:video_bitrate_allocator_factory",
|
||||
"../api/video:video_frame",
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/video/recordable_encoded_frame.h"
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
#include "call/syncable.h"
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/transport/media/media_transport_interface.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/video/recordable_encoded_frame.h"
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user