2020-08-14 16:58:22 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 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 "media/base/media_channel.h"
|
|
|
|
|
2021-06-25 00:43:10 +00:00
|
|
|
#include "media/base/rtp_utils.h"
|
|
|
|
#include "rtc_base/task_utils/to_queued_task.h"
|
|
|
|
|
2020-08-14 16:58:22 +00:00
|
|
|
namespace cricket {
|
2021-06-25 00:43:10 +00:00
|
|
|
using webrtc::FrameDecryptorInterface;
|
|
|
|
using webrtc::FrameEncryptorInterface;
|
|
|
|
using webrtc::FrameTransformerInterface;
|
|
|
|
using webrtc::PendingTaskSafetyFlag;
|
|
|
|
using webrtc::TaskQueueBase;
|
|
|
|
using webrtc::ToQueuedTask;
|
|
|
|
using webrtc::VideoTrackInterface;
|
2020-08-14 16:58:22 +00:00
|
|
|
|
|
|
|
VideoOptions::VideoOptions()
|
2021-06-25 00:43:10 +00:00
|
|
|
: content_hint(VideoTrackInterface::ContentHint::kNone) {}
|
2020-08-14 16:58:22 +00:00
|
|
|
VideoOptions::~VideoOptions() = default;
|
|
|
|
|
2022-03-11 16:49:54 +00:00
|
|
|
MediaChannel::MediaChannel(TaskQueueBase* network_thread, bool enable_dscp)
|
|
|
|
: enable_dscp_(enable_dscp),
|
2021-06-25 00:43:10 +00:00
|
|
|
network_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()),
|
|
|
|
network_thread_(network_thread) {}
|
2020-08-14 16:58:22 +00:00
|
|
|
|
2021-06-25 00:43:10 +00:00
|
|
|
MediaChannel::~MediaChannel() {
|
|
|
|
RTC_DCHECK(!network_interface_);
|
|
|
|
}
|
2020-08-14 16:58:22 +00:00
|
|
|
|
|
|
|
void MediaChannel::SetInterface(NetworkInterface* iface) {
|
2021-06-25 00:43:10 +00:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
iface ? network_safety_->SetAlive() : network_safety_->SetNotAlive();
|
2020-08-14 16:58:22 +00:00
|
|
|
network_interface_ = iface;
|
|
|
|
UpdateDscp();
|
|
|
|
}
|
|
|
|
|
|
|
|
int MediaChannel::GetRtpSendTimeExtnId() const {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SetFrameEncryptor(
|
|
|
|
uint32_t ssrc,
|
2021-06-25 00:43:10 +00:00
|
|
|
rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
|
2020-08-14 16:58:22 +00:00
|
|
|
// Placeholder should be pure virtual once internal supports it.
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SetFrameDecryptor(
|
|
|
|
uint32_t ssrc,
|
2021-06-25 00:43:10 +00:00
|
|
|
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
|
2020-08-14 16:58:22 +00:00
|
|
|
// Placeholder should be pure virtual once internal supports it.
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SetVideoCodecSwitchingEnabled(bool enabled) {}
|
|
|
|
|
2021-06-25 00:43:10 +00:00
|
|
|
bool MediaChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
|
|
|
|
const rtc::PacketOptions& options) {
|
|
|
|
return DoSendPacket(packet, false, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MediaChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
|
|
|
|
const rtc::PacketOptions& options) {
|
|
|
|
return DoSendPacket(packet, true, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
int MediaChannel::SetOption(NetworkInterface::SocketType type,
|
|
|
|
rtc::Socket::Option opt,
|
|
|
|
int option) {
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
return SetOptionLocked(type, opt, option);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
// worker_thread.
|
|
|
|
void MediaChannel::SetExtmapAllowMixed(bool extmap_allow_mixed) {
|
|
|
|
extmap_allow_mixed_ = extmap_allow_mixed;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MediaChannel::ExtmapAllowMixed() const {
|
|
|
|
return extmap_allow_mixed_;
|
|
|
|
}
|
|
|
|
|
2022-03-11 16:49:54 +00:00
|
|
|
bool MediaChannel::HasNetworkInterface() const {
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
return network_interface_ != nullptr;
|
|
|
|
}
|
|
|
|
|
2020-08-14 16:58:22 +00:00
|
|
|
void MediaChannel::SetEncoderToPacketizerFrameTransformer(
|
|
|
|
uint32_t ssrc,
|
2021-06-25 00:43:10 +00:00
|
|
|
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {}
|
|
|
|
|
2020-08-14 16:58:22 +00:00
|
|
|
void MediaChannel::SetDepacketizerToDecoderFrameTransformer(
|
|
|
|
uint32_t ssrc,
|
2021-06-25 00:43:10 +00:00
|
|
|
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {}
|
|
|
|
|
|
|
|
int MediaChannel::SetOptionLocked(NetworkInterface::SocketType type,
|
|
|
|
rtc::Socket::Option opt,
|
|
|
|
int option) {
|
|
|
|
if (!network_interface_)
|
|
|
|
return -1;
|
|
|
|
return network_interface_->SetOption(type, opt, option);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MediaChannel::DscpEnabled() const {
|
|
|
|
return enable_dscp_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is the DSCP value used for both RTP and RTCP channels if DSCP is
|
2022-03-11 16:49:54 +00:00
|
|
|
// enabled. It can be changed at any time via `SetPreferredDscp`.
|
2021-06-25 00:43:10 +00:00
|
|
|
rtc::DiffServCodePoint MediaChannel::PreferredDscp() const {
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
return preferred_dscp_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SetPreferredDscp(rtc::DiffServCodePoint new_dscp) {
|
|
|
|
if (!network_thread_->IsCurrent()) {
|
|
|
|
// This is currently the common path as the derived channel classes
|
|
|
|
// get called on the worker thread. There are still some tests though
|
|
|
|
// that call directly on the network thread.
|
|
|
|
network_thread_->PostTask(ToQueuedTask(
|
|
|
|
network_safety_, [this, new_dscp]() { SetPreferredDscp(new_dscp); }));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
if (new_dscp == preferred_dscp_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
preferred_dscp_ = new_dscp;
|
|
|
|
UpdateDscp();
|
|
|
|
}
|
|
|
|
|
|
|
|
rtc::scoped_refptr<PendingTaskSafetyFlag> MediaChannel::network_safety() {
|
|
|
|
return network_safety_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::UpdateDscp() {
|
|
|
|
rtc::DiffServCodePoint value =
|
|
|
|
enable_dscp_ ? preferred_dscp_ : rtc::DSCP_DEFAULT;
|
|
|
|
int ret =
|
|
|
|
SetOptionLocked(NetworkInterface::ST_RTP, rtc::Socket::OPT_DSCP, value);
|
|
|
|
if (ret == 0)
|
|
|
|
SetOptionLocked(NetworkInterface::ST_RTCP, rtc::Socket::OPT_DSCP, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MediaChannel::DoSendPacket(rtc::CopyOnWriteBuffer* packet,
|
|
|
|
bool rtcp,
|
|
|
|
const rtc::PacketOptions& options) {
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
|
|
if (!network_interface_)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (!rtcp) ? network_interface_->SendPacket(packet, options)
|
|
|
|
: network_interface_->SendRtcp(packet, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SendRtp(const uint8_t* data,
|
|
|
|
size_t len,
|
|
|
|
const webrtc::PacketOptions& options) {
|
|
|
|
auto send =
|
|
|
|
[this, packet_id = options.packet_id,
|
|
|
|
included_in_feedback = options.included_in_feedback,
|
|
|
|
included_in_allocation = options.included_in_allocation,
|
|
|
|
packet = rtc::CopyOnWriteBuffer(data, len, kMaxRtpPacketLen)]() mutable {
|
|
|
|
rtc::PacketOptions rtc_options;
|
|
|
|
rtc_options.packet_id = packet_id;
|
|
|
|
if (DscpEnabled()) {
|
|
|
|
rtc_options.dscp = PreferredDscp();
|
|
|
|
}
|
|
|
|
rtc_options.info_signaled_after_sent.included_in_feedback =
|
|
|
|
included_in_feedback;
|
|
|
|
rtc_options.info_signaled_after_sent.included_in_allocation =
|
|
|
|
included_in_allocation;
|
|
|
|
SendPacket(&packet, rtc_options);
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO(bugs.webrtc.org/11993): ModuleRtpRtcpImpl2 and related classes (e.g.
|
|
|
|
// RTCPSender) aren't aware of the network thread and may trigger calls to
|
|
|
|
// this function from different threads. Update those classes to keep
|
|
|
|
// network traffic on the network thread.
|
|
|
|
if (network_thread_->IsCurrent()) {
|
|
|
|
send();
|
|
|
|
} else {
|
|
|
|
network_thread_->PostTask(ToQueuedTask(network_safety_, std::move(send)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaChannel::SendRtcp(const uint8_t* data, size_t len) {
|
|
|
|
auto send = [this, packet = rtc::CopyOnWriteBuffer(
|
|
|
|
data, len, kMaxRtpPacketLen)]() mutable {
|
|
|
|
rtc::PacketOptions rtc_options;
|
|
|
|
if (DscpEnabled()) {
|
|
|
|
rtc_options.dscp = PreferredDscp();
|
|
|
|
}
|
|
|
|
SendRtcp(&packet, rtc_options);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (network_thread_->IsCurrent()) {
|
|
|
|
send();
|
|
|
|
} else {
|
|
|
|
network_thread_->PostTask(ToQueuedTask(network_safety_, std::move(send)));
|
|
|
|
}
|
|
|
|
}
|
2020-08-14 16:58:22 +00:00
|
|
|
|
|
|
|
MediaSenderInfo::MediaSenderInfo() = default;
|
|
|
|
MediaSenderInfo::~MediaSenderInfo() = default;
|
|
|
|
|
|
|
|
MediaReceiverInfo::MediaReceiverInfo() = default;
|
|
|
|
MediaReceiverInfo::~MediaReceiverInfo() = default;
|
|
|
|
|
|
|
|
VoiceSenderInfo::VoiceSenderInfo() = default;
|
|
|
|
VoiceSenderInfo::~VoiceSenderInfo() = default;
|
|
|
|
|
|
|
|
VoiceReceiverInfo::VoiceReceiverInfo() = default;
|
|
|
|
VoiceReceiverInfo::~VoiceReceiverInfo() = default;
|
|
|
|
|
|
|
|
VideoSenderInfo::VideoSenderInfo() = default;
|
|
|
|
VideoSenderInfo::~VideoSenderInfo() = default;
|
|
|
|
|
|
|
|
VideoReceiverInfo::VideoReceiverInfo() = default;
|
|
|
|
VideoReceiverInfo::~VideoReceiverInfo() = default;
|
|
|
|
|
|
|
|
VoiceMediaInfo::VoiceMediaInfo() = default;
|
|
|
|
VoiceMediaInfo::~VoiceMediaInfo() = default;
|
|
|
|
|
|
|
|
VideoMediaInfo::VideoMediaInfo() = default;
|
|
|
|
VideoMediaInfo::~VideoMediaInfo() = default;
|
|
|
|
|
|
|
|
AudioSendParameters::AudioSendParameters() = default;
|
|
|
|
AudioSendParameters::~AudioSendParameters() = default;
|
|
|
|
|
|
|
|
std::map<std::string, std::string> AudioSendParameters::ToStringMap() const {
|
|
|
|
auto params = RtpSendParameters<AudioCodec>::ToStringMap();
|
|
|
|
params["options"] = options.ToString();
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
|
|
|
cricket::MediaType VoiceMediaChannel::media_type() const {
|
|
|
|
return cricket::MediaType::MEDIA_TYPE_AUDIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
VideoSendParameters::VideoSendParameters() = default;
|
|
|
|
VideoSendParameters::~VideoSendParameters() = default;
|
|
|
|
|
|
|
|
std::map<std::string, std::string> VideoSendParameters::ToStringMap() const {
|
|
|
|
auto params = RtpSendParameters<VideoCodec>::ToStringMap();
|
|
|
|
params["conference_mode"] = (conference_mode ? "yes" : "no");
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
|
|
|
cricket::MediaType VideoMediaChannel::media_type() const {
|
|
|
|
return cricket::MediaType::MEDIA_TYPE_VIDEO;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace cricket
|