Replaces OverheadObserver with simple getter.
This interface has a couple of issues. Primarily for me, it makes it difficult work with the paced sender as we need to either temporarily release a lock or force a thread-handover in order to avoid a cyclic lock order. For video in particular, its behavior is also falky since header sizes can vary not only form frame to frame, but from packet to packet within a frame (e.g. TimingInfo extension is only on the last packet, if set). On bitrate allocation, the last reported value is picked, leading to timing issues affecting the bitrate set. This CL removes the callback interface and instead we simply poll the RTP module for a packet overhead. This consists of an expected overhead based on which non-volatile header extensions are registered (so for instance AbsoluteCaptureTime is disregarded since it's only populated once per second). The overhead estimation is a little less accurate but instead simpler and deterministic. Bug: webrtc:10809 Change-Id: I2c3d3fcca6ad35704c4c1b6b9e0a39227aada1ea Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/173704 Commit-Queue: Erik Språng <sprang@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Reviewed-by: Ali Tofigh <alito@webrtc.org> Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31185}
This commit is contained in:
parent
03fade52da
commit
04e1bab1b3
@ -29,7 +29,6 @@
|
|||||||
#include "api/transport/media/video_transport.h"
|
#include "api/transport/media/video_transport.h"
|
||||||
#include "api/transport/network_control.h"
|
#include "api/transport/network_control.h"
|
||||||
#include "api/units/data_rate.h"
|
#include "api/units/data_rate.h"
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
|
||||||
#include "rtc_base/copy_on_write_buffer.h"
|
#include "rtc_base/copy_on_write_buffer.h"
|
||||||
#include "rtc_base/network_route.h"
|
#include "rtc_base/network_route.h"
|
||||||
|
|
||||||
@ -238,13 +237,6 @@ class MediaTransportInterface : public DataChannelTransportInterface {
|
|||||||
// Corresponding observers for audio and video overhead. Before destruction,
|
// Corresponding observers for audio and video overhead. Before destruction,
|
||||||
// the observers must be unregistered by setting nullptr.
|
// the observers must be unregistered by setting nullptr.
|
||||||
|
|
||||||
// TODO(nisse): Should move to per-stream objects, since packetization
|
|
||||||
// overhead can vary per stream, e.g., depending on negotiated extensions. In
|
|
||||||
// addition, we should move towards reporting total overhead including all
|
|
||||||
// layers. Currently, overhead of the lower layers is reported elsewhere,
|
|
||||||
// e.g., on route change between IPv4 and IPv6.
|
|
||||||
virtual void SetAudioOverheadObserver(OverheadObserver* observer) {}
|
|
||||||
|
|
||||||
// Registers an observer for network change events. If the network route is
|
// Registers an observer for network change events. If the network route is
|
||||||
// already established when the callback is added, |callback| will be called
|
// already established when the callback is added, |callback| will be called
|
||||||
// immediately with the current network route. Before media transport is
|
// immediately with the current network route. Before media transport is
|
||||||
|
|||||||
@ -118,7 +118,6 @@ AudioSendStream::AudioSendStream(
|
|||||||
voe::CreateChannelSend(clock,
|
voe::CreateChannelSend(clock,
|
||||||
task_queue_factory,
|
task_queue_factory,
|
||||||
module_process_thread,
|
module_process_thread,
|
||||||
/*overhead_observer=*/this,
|
|
||||||
config.send_transport,
|
config.send_transport,
|
||||||
rtcp_rtt_stats,
|
rtcp_rtt_stats,
|
||||||
event_log,
|
event_log,
|
||||||
@ -343,6 +342,12 @@ void AudioSendStream::ConfigureStream(
|
|||||||
RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
|
RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set currently known overhead (used in ANA, opus only).
|
||||||
|
{
|
||||||
|
rtc::CritScope cs(&overhead_per_packet_lock_);
|
||||||
|
UpdateOverheadForEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
channel_send_->CallEncoder([this](AudioEncoder* encoder) {
|
channel_send_->CallEncoder([this](AudioEncoder* encoder) {
|
||||||
if (!encoder) {
|
if (!encoder) {
|
||||||
return;
|
return;
|
||||||
@ -505,10 +510,17 @@ void AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
|||||||
// thread. Then this check can be enabled.
|
// thread. Then this check can be enabled.
|
||||||
// RTC_DCHECK(!worker_thread_checker_.IsCurrent());
|
// RTC_DCHECK(!worker_thread_checker_.IsCurrent());
|
||||||
channel_send_->ReceivedRTCPPacket(packet, length);
|
channel_send_->ReceivedRTCPPacket(packet, length);
|
||||||
|
worker_queue_->PostTask([&]() {
|
||||||
|
// Poll if overhead has changed, which it can do if ack triggers us to stop
|
||||||
|
// sending mid/rid.
|
||||||
|
rtc::CritScope cs(&overhead_per_packet_lock_);
|
||||||
|
UpdateOverheadForEncoder();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
|
uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
|
|
||||||
// Pick a target bitrate between the constraints. Overrules the allocator if
|
// Pick a target bitrate between the constraints. Overrules the allocator if
|
||||||
// it 1) allocated a bitrate of zero to disable the stream or 2) allocated a
|
// it 1) allocated a bitrate of zero to disable the stream or 2) allocated a
|
||||||
// higher than max to allow for e.g. extra FEC.
|
// higher than max to allow for e.g. extra FEC.
|
||||||
@ -531,13 +543,6 @@ void AudioSendStream::SetTransportOverhead(
|
|||||||
UpdateOverheadForEncoder();
|
UpdateOverheadForEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSendStream::OnOverheadChanged(
|
|
||||||
size_t overhead_bytes_per_packet_bytes) {
|
|
||||||
rtc::CritScope cs(&overhead_per_packet_lock_);
|
|
||||||
audio_overhead_per_packet_bytes_ = overhead_bytes_per_packet_bytes;
|
|
||||||
UpdateOverheadForEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioSendStream::UpdateOverheadForEncoder() {
|
void AudioSendStream::UpdateOverheadForEncoder() {
|
||||||
const size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
|
const size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
|
||||||
if (overhead_per_packet_bytes == 0) {
|
if (overhead_per_packet_bytes == 0) {
|
||||||
@ -546,7 +551,7 @@ void AudioSendStream::UpdateOverheadForEncoder() {
|
|||||||
channel_send_->CallEncoder([&](AudioEncoder* encoder) {
|
channel_send_->CallEncoder([&](AudioEncoder* encoder) {
|
||||||
encoder->OnReceivedOverhead(overhead_per_packet_bytes);
|
encoder->OnReceivedOverhead(overhead_per_packet_bytes);
|
||||||
});
|
});
|
||||||
worker_queue_->PostTask([this, overhead_per_packet_bytes] {
|
auto update_task = [this, overhead_per_packet_bytes] {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
if (total_packet_overhead_bytes_ != overhead_per_packet_bytes) {
|
if (total_packet_overhead_bytes_ != overhead_per_packet_bytes) {
|
||||||
total_packet_overhead_bytes_ = overhead_per_packet_bytes;
|
total_packet_overhead_bytes_ = overhead_per_packet_bytes;
|
||||||
@ -554,7 +559,12 @@ void AudioSendStream::UpdateOverheadForEncoder() {
|
|||||||
ConfigureBitrateObserver();
|
ConfigureBitrateObserver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
if (worker_queue_->IsCurrent()) {
|
||||||
|
update_task();
|
||||||
|
} else {
|
||||||
|
worker_queue_->PostTask(update_task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
|
size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
|
||||||
@ -564,7 +574,7 @@ size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
|
|||||||
|
|
||||||
size_t AudioSendStream::GetPerPacketOverheadBytes() const {
|
size_t AudioSendStream::GetPerPacketOverheadBytes() const {
|
||||||
return transport_overhead_per_packet_bytes_ +
|
return transport_overhead_per_packet_bytes_ +
|
||||||
audio_overhead_per_packet_bytes_;
|
rtp_rtcp_module_->ExpectedPerPacketOverhead();
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpState AudioSendStream::GetRtpState() const {
|
RtpState AudioSendStream::GetRtpState() const {
|
||||||
@ -651,8 +661,9 @@ bool AudioSendStream::SetupSendCodec(const Config& new_config) {
|
|||||||
// If overhead changes later, it will be updated in UpdateOverheadForEncoder.
|
// If overhead changes later, it will be updated in UpdateOverheadForEncoder.
|
||||||
{
|
{
|
||||||
rtc::CritScope cs(&overhead_per_packet_lock_);
|
rtc::CritScope cs(&overhead_per_packet_lock_);
|
||||||
if (GetPerPacketOverheadBytes() > 0) {
|
size_t overhead = GetPerPacketOverheadBytes();
|
||||||
encoder->OnReceivedOverhead(GetPerPacketOverheadBytes());
|
if (overhead > 0) {
|
||||||
|
encoder->OnReceivedOverhead(overhead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,12 +715,6 @@ bool AudioSendStream::ReconfigureSendCodec(const Config& new_config) {
|
|||||||
ReconfigureANA(new_config);
|
ReconfigureANA(new_config);
|
||||||
ReconfigureCNG(new_config);
|
ReconfigureCNG(new_config);
|
||||||
|
|
||||||
// Set currently known overhead (used in ANA, opus only).
|
|
||||||
{
|
|
||||||
rtc::CritScope cs(&overhead_per_packet_lock_);
|
|
||||||
UpdateOverheadForEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,9 +841,9 @@ void AudioSendStream::ConfigureBitrateObserver() {
|
|||||||
priority_bitrate += max_overhead;
|
priority_bitrate += max_overhead;
|
||||||
} else {
|
} else {
|
||||||
RTC_DCHECK(frame_length_range_);
|
RTC_DCHECK(frame_length_range_);
|
||||||
const DataSize kOverheadPerPacket =
|
const DataSize overhead_per_packet =
|
||||||
DataSize::Bytes(total_packet_overhead_bytes_);
|
DataSize::Bytes(total_packet_overhead_bytes_);
|
||||||
DataRate min_overhead = kOverheadPerPacket / frame_length_range_->second;
|
DataRate min_overhead = overhead_per_packet / frame_length_range_->second;
|
||||||
priority_bitrate += min_overhead;
|
priority_bitrate += min_overhead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,8 +52,7 @@ namespace internal {
|
|||||||
class AudioState;
|
class AudioState;
|
||||||
|
|
||||||
class AudioSendStream final : public webrtc::AudioSendStream,
|
class AudioSendStream final : public webrtc::AudioSendStream,
|
||||||
public webrtc::BitrateAllocatorObserver,
|
public webrtc::BitrateAllocatorObserver {
|
||||||
public webrtc::OverheadObserver {
|
|
||||||
public:
|
public:
|
||||||
AudioSendStream(Clock* clock,
|
AudioSendStream(Clock* clock,
|
||||||
const webrtc::AudioSendStream::Config& config,
|
const webrtc::AudioSendStream::Config& config,
|
||||||
@ -99,10 +98,6 @@ class AudioSendStream final : public webrtc::AudioSendStream,
|
|||||||
|
|
||||||
void SetTransportOverhead(int transport_overhead_per_packet_bytes);
|
void SetTransportOverhead(int transport_overhead_per_packet_bytes);
|
||||||
|
|
||||||
// OverheadObserver override reports audio packetization overhead from
|
|
||||||
// RTP/RTCP module or Media Transport.
|
|
||||||
void OnOverheadChanged(size_t overhead_bytes_per_packet_bytes) override;
|
|
||||||
|
|
||||||
RtpState GetRtpState() const;
|
RtpState GetRtpState() const;
|
||||||
const voe::ChannelSendInterface* GetChannel() const;
|
const voe::ChannelSendInterface* GetChannel() const;
|
||||||
|
|
||||||
@ -205,10 +200,6 @@ class AudioSendStream final : public webrtc::AudioSendStream,
|
|||||||
size_t transport_overhead_per_packet_bytes_
|
size_t transport_overhead_per_packet_bytes_
|
||||||
RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
|
RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
|
||||||
|
|
||||||
// Current audio packetization overhead (RTP or Media Transport).
|
|
||||||
size_t audio_overhead_per_packet_bytes_
|
|
||||||
RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
|
|
||||||
|
|
||||||
bool registered_with_allocator_ RTC_GUARDED_BY(worker_queue_) = false;
|
bool registered_with_allocator_ RTC_GUARDED_BY(worker_queue_) = false;
|
||||||
size_t total_packet_overhead_bytes_ RTC_GUARDED_BY(worker_queue_) = 0;
|
size_t total_packet_overhead_bytes_ RTC_GUARDED_BY(worker_queue_) = 0;
|
||||||
absl::optional<std::pair<TimeDelta, TimeDelta>> frame_length_range_
|
absl::optional<std::pair<TimeDelta, TimeDelta>> frame_length_range_
|
||||||
|
|||||||
@ -660,9 +660,9 @@ TEST(AudioSendStreamTest, SSBweWithOverhead) {
|
|||||||
"WebRTC-Audio-LegacyOverhead/Disabled/");
|
"WebRTC-Audio-LegacyOverhead/Disabled/");
|
||||||
for (bool use_null_audio_processing : {false, true}) {
|
for (bool use_null_audio_processing : {false, true}) {
|
||||||
ConfigHelper helper(true, true, use_null_audio_processing);
|
ConfigHelper helper(true, true, use_null_audio_processing);
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
|
||||||
auto send_stream = helper.CreateAudioSendStream();
|
auto send_stream = helper.CreateAudioSendStream();
|
||||||
EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
|
|
||||||
send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
|
|
||||||
const DataRate bitrate =
|
const DataRate bitrate =
|
||||||
DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
|
DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
|
||||||
kMaxOverheadRate;
|
kMaxOverheadRate;
|
||||||
@ -684,9 +684,9 @@ TEST(AudioSendStreamTest, SSBweWithOverheadMinRespected) {
|
|||||||
"WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
|
"WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
|
||||||
for (bool use_null_audio_processing : {false, true}) {
|
for (bool use_null_audio_processing : {false, true}) {
|
||||||
ConfigHelper helper(true, true, use_null_audio_processing);
|
ConfigHelper helper(true, true, use_null_audio_processing);
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
|
||||||
auto send_stream = helper.CreateAudioSendStream();
|
auto send_stream = helper.CreateAudioSendStream();
|
||||||
EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
|
|
||||||
send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
|
|
||||||
const DataRate bitrate = DataRate::KilobitsPerSec(6) + kMinOverheadRate;
|
const DataRate bitrate = DataRate::KilobitsPerSec(6) + kMinOverheadRate;
|
||||||
EXPECT_CALL(*helper.channel_send(),
|
EXPECT_CALL(*helper.channel_send(),
|
||||||
OnBitrateAllocation(Field(
|
OnBitrateAllocation(Field(
|
||||||
@ -706,9 +706,9 @@ TEST(AudioSendStreamTest, SSBweWithOverheadMaxRespected) {
|
|||||||
"WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
|
"WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
|
||||||
for (bool use_null_audio_processing : {false, true}) {
|
for (bool use_null_audio_processing : {false, true}) {
|
||||||
ConfigHelper helper(true, true, use_null_audio_processing);
|
ConfigHelper helper(true, true, use_null_audio_processing);
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
|
||||||
auto send_stream = helper.CreateAudioSendStream();
|
auto send_stream = helper.CreateAudioSendStream();
|
||||||
EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
|
|
||||||
send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
|
|
||||||
const DataRate bitrate = DataRate::KilobitsPerSec(64) + kMaxOverheadRate;
|
const DataRate bitrate = DataRate::KilobitsPerSec(64) + kMaxOverheadRate;
|
||||||
EXPECT_CALL(*helper.channel_send(),
|
EXPECT_CALL(*helper.channel_send(),
|
||||||
OnBitrateAllocation(Field(
|
OnBitrateAllocation(Field(
|
||||||
@ -804,36 +804,56 @@ TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioSendStreamTest, OnAudioOverheadChanged) {
|
TEST(AudioSendStreamTest, AudioOverheadChanged) {
|
||||||
for (bool use_null_audio_processing : {false, true}) {
|
for (bool use_null_audio_processing : {false, true}) {
|
||||||
ConfigHelper helper(false, true, use_null_audio_processing);
|
ConfigHelper helper(false, true, use_null_audio_processing);
|
||||||
|
const size_t audio_overhead_per_packet_bytes = 555;
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(audio_overhead_per_packet_bytes));
|
||||||
auto send_stream = helper.CreateAudioSendStream();
|
auto send_stream = helper.CreateAudioSendStream();
|
||||||
auto new_config = helper.config();
|
auto new_config = helper.config();
|
||||||
|
|
||||||
// CallEncoder will be called on overhead change.
|
BitrateAllocationUpdate update;
|
||||||
EXPECT_CALL(*helper.channel_send(), CallEncoder(::testing::_)).Times(1);
|
update.target_bitrate =
|
||||||
|
DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
|
||||||
|
kMaxOverheadRate;
|
||||||
|
EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
|
||||||
|
helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
|
||||||
|
RTC_FROM_HERE);
|
||||||
|
|
||||||
const size_t audio_overhead_per_packet_bytes = 555;
|
|
||||||
send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
|
|
||||||
EXPECT_EQ(audio_overhead_per_packet_bytes,
|
EXPECT_EQ(audio_overhead_per_packet_bytes,
|
||||||
send_stream->TestOnlyGetPerPacketOverheadBytes());
|
send_stream->TestOnlyGetPerPacketOverheadBytes());
|
||||||
|
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(audio_overhead_per_packet_bytes + 20));
|
||||||
|
EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
|
||||||
|
helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
|
||||||
|
RTC_FROM_HERE);
|
||||||
|
|
||||||
|
EXPECT_EQ(audio_overhead_per_packet_bytes + 20,
|
||||||
|
send_stream->TestOnlyGetPerPacketOverheadBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
|
TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
|
||||||
for (bool use_null_audio_processing : {false, true}) {
|
for (bool use_null_audio_processing : {false, true}) {
|
||||||
ConfigHelper helper(false, true, use_null_audio_processing);
|
ConfigHelper helper(false, true, use_null_audio_processing);
|
||||||
|
const size_t audio_overhead_per_packet_bytes = 555;
|
||||||
|
EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
|
||||||
|
.WillRepeatedly(Return(audio_overhead_per_packet_bytes));
|
||||||
auto send_stream = helper.CreateAudioSendStream();
|
auto send_stream = helper.CreateAudioSendStream();
|
||||||
auto new_config = helper.config();
|
auto new_config = helper.config();
|
||||||
|
|
||||||
// CallEncoder will be called when each of overhead changes.
|
|
||||||
EXPECT_CALL(*helper.channel_send(), CallEncoder(::testing::_)).Times(2);
|
|
||||||
|
|
||||||
const size_t transport_overhead_per_packet_bytes = 333;
|
const size_t transport_overhead_per_packet_bytes = 333;
|
||||||
send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
|
send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
|
||||||
|
|
||||||
const size_t audio_overhead_per_packet_bytes = 555;
|
BitrateAllocationUpdate update;
|
||||||
send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
|
update.target_bitrate =
|
||||||
|
DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
|
||||||
|
kMaxOverheadRate;
|
||||||
|
EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
|
||||||
|
helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
|
||||||
|
RTC_FROM_HERE);
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
|
transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
|
||||||
|
|||||||
@ -69,7 +69,6 @@ class ChannelSend : public ChannelSendInterface,
|
|||||||
ChannelSend(Clock* clock,
|
ChannelSend(Clock* clock,
|
||||||
TaskQueueFactory* task_queue_factory,
|
TaskQueueFactory* task_queue_factory,
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
OverheadObserver* overhead_observer,
|
|
||||||
Transport* rtp_transport,
|
Transport* rtp_transport,
|
||||||
RtcpRttStats* rtcp_rtt_stats,
|
RtcpRttStats* rtcp_rtt_stats,
|
||||||
RtcEventLog* rtc_event_log,
|
RtcEventLog* rtc_event_log,
|
||||||
@ -482,7 +481,6 @@ ChannelSend::ChannelSend(
|
|||||||
Clock* clock,
|
Clock* clock,
|
||||||
TaskQueueFactory* task_queue_factory,
|
TaskQueueFactory* task_queue_factory,
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
OverheadObserver* overhead_observer,
|
|
||||||
Transport* rtp_transport,
|
Transport* rtp_transport,
|
||||||
RtcpRttStats* rtcp_rtt_stats,
|
RtcpRttStats* rtcp_rtt_stats,
|
||||||
RtcEventLog* rtc_event_log,
|
RtcEventLog* rtc_event_log,
|
||||||
@ -515,7 +513,6 @@ ChannelSend::ChannelSend(
|
|||||||
audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
|
audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
|
||||||
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
configuration.overhead_observer = overhead_observer;
|
|
||||||
configuration.bandwidth_callback = rtcp_observer_.get();
|
configuration.bandwidth_callback = rtcp_observer_.get();
|
||||||
configuration.transport_feedback_callback = feedback_observer_proxy_.get();
|
configuration.transport_feedback_callback = feedback_observer_proxy_.get();
|
||||||
configuration.clock = (clock ? clock : Clock::GetRealTimeClock());
|
configuration.clock = (clock ? clock : Clock::GetRealTimeClock());
|
||||||
@ -980,7 +977,6 @@ std::unique_ptr<ChannelSendInterface> CreateChannelSend(
|
|||||||
Clock* clock,
|
Clock* clock,
|
||||||
TaskQueueFactory* task_queue_factory,
|
TaskQueueFactory* task_queue_factory,
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
OverheadObserver* overhead_observer,
|
|
||||||
Transport* rtp_transport,
|
Transport* rtp_transport,
|
||||||
RtcpRttStats* rtcp_rtt_stats,
|
RtcpRttStats* rtcp_rtt_stats,
|
||||||
RtcEventLog* rtc_event_log,
|
RtcEventLog* rtc_event_log,
|
||||||
@ -991,9 +987,9 @@ std::unique_ptr<ChannelSendInterface> CreateChannelSend(
|
|||||||
uint32_t ssrc,
|
uint32_t ssrc,
|
||||||
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
|
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
|
||||||
return std::make_unique<ChannelSend>(
|
return std::make_unique<ChannelSend>(
|
||||||
clock, task_queue_factory, module_process_thread, overhead_observer,
|
clock, task_queue_factory, module_process_thread, rtp_transport,
|
||||||
rtp_transport, rtcp_rtt_stats, rtc_event_log, frame_encryptor,
|
rtcp_rtt_stats, rtc_event_log, frame_encryptor, crypto_options,
|
||||||
crypto_options, extmap_allow_mixed, rtcp_report_interval_ms, ssrc,
|
extmap_allow_mixed, rtcp_report_interval_ms, ssrc,
|
||||||
std::move(frame_transformer));
|
std::move(frame_transformer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -128,7 +128,6 @@ std::unique_ptr<ChannelSendInterface> CreateChannelSend(
|
|||||||
Clock* clock,
|
Clock* clock,
|
||||||
TaskQueueFactory* task_queue_factory,
|
TaskQueueFactory* task_queue_factory,
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
OverheadObserver* overhead_observer,
|
|
||||||
Transport* rtp_transport,
|
Transport* rtp_transport,
|
||||||
RtcpRttStats* rtcp_rtt_stats,
|
RtcpRttStats* rtcp_rtt_stats,
|
||||||
RtcEventLog* rtc_event_log,
|
RtcEventLog* rtc_event_log,
|
||||||
|
|||||||
@ -193,7 +193,6 @@ std::vector<RtpStreamSender> CreateRtpStreamSenders(
|
|||||||
const std::map<uint32_t, RtpState>& suspended_ssrcs,
|
const std::map<uint32_t, RtpState>& suspended_ssrcs,
|
||||||
RtcEventLog* event_log,
|
RtcEventLog* event_log,
|
||||||
RateLimiter* retransmission_rate_limiter,
|
RateLimiter* retransmission_rate_limiter,
|
||||||
OverheadObserver* overhead_observer,
|
|
||||||
FrameEncryptorInterface* frame_encryptor,
|
FrameEncryptorInterface* frame_encryptor,
|
||||||
const CryptoOptions& crypto_options,
|
const CryptoOptions& crypto_options,
|
||||||
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
|
rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
|
||||||
@ -225,7 +224,6 @@ std::vector<RtpStreamSender> CreateRtpStreamSenders(
|
|||||||
configuration.send_packet_observer = observers.send_packet_observer;
|
configuration.send_packet_observer = observers.send_packet_observer;
|
||||||
configuration.event_log = event_log;
|
configuration.event_log = event_log;
|
||||||
configuration.retransmission_rate_limiter = retransmission_rate_limiter;
|
configuration.retransmission_rate_limiter = retransmission_rate_limiter;
|
||||||
configuration.overhead_observer = overhead_observer;
|
|
||||||
configuration.rtp_stats_callback = observers.rtp_stats;
|
configuration.rtp_stats_callback = observers.rtp_stats;
|
||||||
configuration.frame_encryptor = frame_encryptor;
|
configuration.frame_encryptor = frame_encryptor;
|
||||||
configuration.require_frame_encryption =
|
configuration.require_frame_encryption =
|
||||||
@ -352,7 +350,6 @@ RtpVideoSender::RtpVideoSender(
|
|||||||
suspended_ssrcs_,
|
suspended_ssrcs_,
|
||||||
event_log,
|
event_log,
|
||||||
retransmission_limiter,
|
retransmission_limiter,
|
||||||
this,
|
|
||||||
frame_encryptor,
|
frame_encryptor,
|
||||||
crypto_options,
|
crypto_options,
|
||||||
std::move(frame_transformer),
|
std::move(frame_transformer),
|
||||||
@ -361,7 +358,6 @@ RtpVideoSender::RtpVideoSender(
|
|||||||
codec_type_(GetVideoCodecType(rtp_config)),
|
codec_type_(GetVideoCodecType(rtp_config)),
|
||||||
transport_(transport),
|
transport_(transport),
|
||||||
transport_overhead_bytes_per_packet_(0),
|
transport_overhead_bytes_per_packet_(0),
|
||||||
overhead_bytes_per_packet_(0),
|
|
||||||
encoder_target_rate_bps_(0),
|
encoder_target_rate_bps_(0),
|
||||||
frame_counts_(rtp_config.ssrcs.size()),
|
frame_counts_(rtp_config.ssrcs.size()),
|
||||||
frame_count_observer_(observers.frame_count_observer) {
|
frame_count_observer_(observers.frame_count_observer) {
|
||||||
@ -733,17 +729,24 @@ void RtpVideoSender::OnTransportOverheadChanged(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoSender::OnOverheadChanged(size_t overhead_bytes_per_packet) {
|
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
overhead_bytes_per_packet_ = overhead_bytes_per_packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtpVideoSender::OnBitrateUpdated(BitrateAllocationUpdate update,
|
void RtpVideoSender::OnBitrateUpdated(BitrateAllocationUpdate update,
|
||||||
int framerate) {
|
int framerate) {
|
||||||
// Substract overhead from bitrate.
|
// Substract overhead from bitrate.
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
|
size_t num_active_streams = 0;
|
||||||
|
size_t overhead_bytes_per_packet = 0;
|
||||||
|
for (const auto& stream : rtp_streams_) {
|
||||||
|
if (stream.rtp_rtcp->SendingMedia()) {
|
||||||
|
overhead_bytes_per_packet += stream.rtp_rtcp->ExpectedPerPacketOverhead();
|
||||||
|
++num_active_streams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_active_streams > 1) {
|
||||||
|
overhead_bytes_per_packet /= num_active_streams;
|
||||||
|
}
|
||||||
|
|
||||||
DataSize packet_overhead = DataSize::Bytes(
|
DataSize packet_overhead = DataSize::Bytes(
|
||||||
overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_);
|
overhead_bytes_per_packet + transport_overhead_bytes_per_packet_);
|
||||||
DataSize max_total_packet_size = DataSize::Bytes(
|
DataSize max_total_packet_size = DataSize::Bytes(
|
||||||
rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_);
|
rtp_config_.max_packet_size + transport_overhead_bytes_per_packet_);
|
||||||
uint32_t payload_bitrate_bps = update.target_bitrate.bps();
|
uint32_t payload_bitrate_bps = update.target_bitrate.bps();
|
||||||
@ -790,7 +793,7 @@ void RtpVideoSender::OnBitrateUpdated(BitrateAllocationUpdate update,
|
|||||||
// calculations.
|
// calculations.
|
||||||
DataRate encoder_overhead_rate = CalculateOverheadRate(
|
DataRate encoder_overhead_rate = CalculateOverheadRate(
|
||||||
DataRate::BitsPerSec(encoder_target_rate_bps_),
|
DataRate::BitsPerSec(encoder_target_rate_bps_),
|
||||||
max_total_packet_size - DataSize::Bytes(overhead_bytes_per_packet_),
|
max_total_packet_size - DataSize::Bytes(overhead_bytes_per_packet),
|
||||||
packet_overhead);
|
packet_overhead);
|
||||||
encoder_overhead_rate_bps = std::min(
|
encoder_overhead_rate_bps = std::min(
|
||||||
encoder_overhead_rate.bps<uint32_t>(),
|
encoder_overhead_rate.bps<uint32_t>(),
|
||||||
|
|||||||
@ -70,7 +70,6 @@ struct RtpStreamSender {
|
|||||||
// RtpVideoSender routes outgoing data to the correct sending RTP module, based
|
// RtpVideoSender routes outgoing data to the correct sending RTP module, based
|
||||||
// on the simulcast layer in RTPVideoHeader.
|
// on the simulcast layer in RTPVideoHeader.
|
||||||
class RtpVideoSender : public RtpVideoSenderInterface,
|
class RtpVideoSender : public RtpVideoSenderInterface,
|
||||||
public OverheadObserver,
|
|
||||||
public VCMProtectionCallback,
|
public VCMProtectionCallback,
|
||||||
public StreamFeedbackObserver {
|
public StreamFeedbackObserver {
|
||||||
public:
|
public:
|
||||||
@ -136,8 +135,6 @@ class RtpVideoSender : public RtpVideoSenderInterface,
|
|||||||
|
|
||||||
void OnTransportOverheadChanged(
|
void OnTransportOverheadChanged(
|
||||||
size_t transport_overhead_bytes_per_packet) override;
|
size_t transport_overhead_bytes_per_packet) override;
|
||||||
// Implements OverheadObserver.
|
|
||||||
void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
|
|
||||||
void OnBitrateUpdated(BitrateAllocationUpdate update, int framerate) override;
|
void OnBitrateUpdated(BitrateAllocationUpdate update, int framerate) override;
|
||||||
uint32_t GetPayloadBitrateBps() const override;
|
uint32_t GetPayloadBitrateBps() const override;
|
||||||
uint32_t GetProtectionBitrateBps() const override;
|
uint32_t GetProtectionBitrateBps() const override;
|
||||||
@ -194,7 +191,6 @@ class RtpVideoSender : public RtpVideoSenderInterface,
|
|||||||
std::vector<RtpPayloadParams> params_ RTC_GUARDED_BY(crit_);
|
std::vector<RtpPayloadParams> params_ RTC_GUARDED_BY(crit_);
|
||||||
|
|
||||||
size_t transport_overhead_bytes_per_packet_ RTC_GUARDED_BY(crit_);
|
size_t transport_overhead_bytes_per_packet_ RTC_GUARDED_BY(crit_);
|
||||||
size_t overhead_bytes_per_packet_ RTC_GUARDED_BY(crit_);
|
|
||||||
uint32_t protection_bitrate_bps_;
|
uint32_t protection_bitrate_bps_;
|
||||||
uint32_t encoder_target_rate_bps_;
|
uint32_t encoder_target_rate_bps_;
|
||||||
|
|
||||||
|
|||||||
@ -31,14 +31,6 @@ class FrameCountObserver {
|
|||||||
uint32_t ssrc) = 0;
|
uint32_t ssrc) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback, used to notify an observer when the overhead per packet
|
|
||||||
// has changed.
|
|
||||||
class OverheadObserver {
|
|
||||||
public:
|
|
||||||
virtual ~OverheadObserver() = default;
|
|
||||||
virtual void OnOverheadChanged(size_t overhead_bytes_per_packet) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
// Video specific types
|
// Video specific types
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
|
|||||||
@ -38,7 +38,6 @@ namespace webrtc {
|
|||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
class FrameEncryptorInterface;
|
class FrameEncryptorInterface;
|
||||||
class OverheadObserver;
|
|
||||||
class RateLimiter;
|
class RateLimiter;
|
||||||
class ReceiveStatisticsProvider;
|
class ReceiveStatisticsProvider;
|
||||||
class RemoteBitrateEstimator;
|
class RemoteBitrateEstimator;
|
||||||
@ -113,7 +112,6 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
|
|||||||
RtcEventLog* event_log = nullptr;
|
RtcEventLog* event_log = nullptr;
|
||||||
SendPacketObserver* send_packet_observer = nullptr;
|
SendPacketObserver* send_packet_observer = nullptr;
|
||||||
RateLimiter* retransmission_rate_limiter = nullptr;
|
RateLimiter* retransmission_rate_limiter = nullptr;
|
||||||
OverheadObserver* overhead_observer = nullptr;
|
|
||||||
StreamDataCountersCallback* rtp_stats_callback = nullptr;
|
StreamDataCountersCallback* rtp_stats_callback = nullptr;
|
||||||
|
|
||||||
int rtcp_report_interval_ms = 0;
|
int rtcp_report_interval_ms = 0;
|
||||||
@ -318,6 +316,13 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
|
|||||||
virtual std::vector<RtpSequenceNumberMap::Info> GetSentRtpPacketInfos(
|
virtual std::vector<RtpSequenceNumberMap::Info> GetSentRtpPacketInfos(
|
||||||
rtc::ArrayView<const uint16_t> sequence_numbers) const = 0;
|
rtc::ArrayView<const uint16_t> sequence_numbers) const = 0;
|
||||||
|
|
||||||
|
// Returns an expected per packet overhead representing the main RTP header,
|
||||||
|
// any CSRCs, and the registered header extensions that are expected on all
|
||||||
|
// packets (i.e. disregarding things like abs capture time which is only
|
||||||
|
// populated on a subset of packets, but counting MID/RID type extensions
|
||||||
|
// when we expect to send them).
|
||||||
|
virtual size_t ExpectedPerPacketOverhead() const = 0;
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RTCP
|
// RTCP
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|||||||
@ -97,6 +97,7 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
MOCK_CONST_METHOD1(GetSentRtpPacketInfos,
|
MOCK_CONST_METHOD1(GetSentRtpPacketInfos,
|
||||||
std::vector<RtpSequenceNumberMap::Info>(
|
std::vector<RtpSequenceNumberMap::Info>(
|
||||||
rtc::ArrayView<const uint16_t> sequence_numbers));
|
rtc::ArrayView<const uint16_t> sequence_numbers));
|
||||||
|
MOCK_CONST_METHOD0(ExpectedPerPacketOverhead, size_t(void));
|
||||||
MOCK_METHOD2(RegisterRtcpObservers,
|
MOCK_METHOD2(RegisterRtcpObservers,
|
||||||
void(RtcpIntraFrameObserver* intra_frame_callback,
|
void(RtcpIntraFrameObserver* intra_frame_callback,
|
||||||
RtcpBandwidthObserver* bandwidth_callback));
|
RtcpBandwidthObserver* bandwidth_callback));
|
||||||
|
|||||||
@ -401,6 +401,13 @@ ModuleRtpRtcpImpl::GetSentRtpPacketInfos(
|
|||||||
return rtp_sender_->packet_sender.GetSentRtpPacketInfos(sequence_numbers);
|
return rtp_sender_->packet_sender.GetSentRtpPacketInfos(sequence_numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ModuleRtpRtcpImpl::ExpectedPerPacketOverhead() const {
|
||||||
|
if (!rtp_sender_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rtp_sender_->packet_generator.ExpectedPerPacketOverhead();
|
||||||
|
}
|
||||||
|
|
||||||
size_t ModuleRtpRtcpImpl::MaxRtpPacketSize() const {
|
size_t ModuleRtpRtcpImpl::MaxRtpPacketSize() const {
|
||||||
RTC_DCHECK(rtp_sender_);
|
RTC_DCHECK(rtp_sender_);
|
||||||
return rtp_sender_->packet_generator.MaxRtpPacketSize();
|
return rtp_sender_->packet_generator.MaxRtpPacketSize();
|
||||||
|
|||||||
@ -146,6 +146,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
|
|||||||
std::vector<RtpSequenceNumberMap::Info> GetSentRtpPacketInfos(
|
std::vector<RtpSequenceNumberMap::Info> GetSentRtpPacketInfos(
|
||||||
rtc::ArrayView<const uint16_t> sequence_numbers) const override;
|
rtc::ArrayView<const uint16_t> sequence_numbers) const override;
|
||||||
|
|
||||||
|
size_t ExpectedPerPacketOverhead() const override;
|
||||||
|
|
||||||
// RTCP part.
|
// RTCP part.
|
||||||
|
|
||||||
// Get RTCP status.
|
// Get RTCP status.
|
||||||
|
|||||||
@ -84,6 +84,52 @@ constexpr RtpExtensionSize kVideoExtensionSizes[] = {
|
|||||||
RtpGenericFrameDescriptorExtension00::kMaxSizeBytes},
|
RtpGenericFrameDescriptorExtension00::kMaxSizeBytes},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Size info for header extensions that might be used in audio packets.
|
||||||
|
constexpr RtpExtensionSize kAudioExtensionSizes[] = {
|
||||||
|
CreateExtensionSize<AbsoluteSendTime>(),
|
||||||
|
CreateExtensionSize<AbsoluteCaptureTimeExtension>(),
|
||||||
|
CreateExtensionSize<AudioLevel>(),
|
||||||
|
CreateExtensionSize<InbandComfortNoiseExtension>(),
|
||||||
|
CreateExtensionSize<TransmissionOffset>(),
|
||||||
|
CreateExtensionSize<TransportSequenceNumber>(),
|
||||||
|
CreateMaxExtensionSize<RtpStreamId>(),
|
||||||
|
CreateMaxExtensionSize<RepairedRtpStreamId>(),
|
||||||
|
CreateMaxExtensionSize<RtpMid>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-volatile extensions can be expected on all packets, if registered.
|
||||||
|
// Volatile ones, such as VideoContentTypeExtension which is only set on
|
||||||
|
// key-frames, are removed to simplify overhead calculations at the expense of
|
||||||
|
// some accuracy.
|
||||||
|
bool IsNonVolatile(RTPExtensionType type) {
|
||||||
|
switch (type) {
|
||||||
|
case kRtpExtensionTransmissionTimeOffset:
|
||||||
|
case kRtpExtensionAudioLevel:
|
||||||
|
case kRtpExtensionAbsoluteSendTime:
|
||||||
|
case kRtpExtensionTransportSequenceNumber:
|
||||||
|
case kRtpExtensionTransportSequenceNumber02:
|
||||||
|
case kRtpExtensionFrameMarking:
|
||||||
|
case kRtpExtensionRtpStreamId:
|
||||||
|
case kRtpExtensionRepairedRtpStreamId:
|
||||||
|
case kRtpExtensionMid:
|
||||||
|
case kRtpExtensionGenericFrameDescriptor00:
|
||||||
|
case kRtpExtensionGenericFrameDescriptor02:
|
||||||
|
return true;
|
||||||
|
case kRtpExtensionInbandComfortNoise:
|
||||||
|
case kRtpExtensionAbsoluteCaptureTime:
|
||||||
|
case kRtpExtensionVideoRotation:
|
||||||
|
case kRtpExtensionPlayoutDelay:
|
||||||
|
case kRtpExtensionVideoContentType:
|
||||||
|
case kRtpExtensionVideoTiming:
|
||||||
|
case kRtpExtensionColorSpace:
|
||||||
|
return false;
|
||||||
|
case kRtpExtensionNone:
|
||||||
|
case kRtpExtensionNumberOfExtensions:
|
||||||
|
RTC_NOTREACHED();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool HasBweExtension(const RtpHeaderExtensionMap& extensions_map) {
|
bool HasBweExtension(const RtpHeaderExtensionMap& extensions_map) {
|
||||||
return extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber) ||
|
return extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber) ||
|
||||||
extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber02) ||
|
extensions_map.IsRegistered(kRtpExtensionTransportSequenceNumber02) ||
|
||||||
@ -125,6 +171,8 @@ RTPSender::RTPSender(const RtpRtcp::Configuration& config,
|
|||||||
max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
|
max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
|
||||||
last_payload_type_(-1),
|
last_payload_type_(-1),
|
||||||
rtp_header_extension_map_(config.extmap_allow_mixed),
|
rtp_header_extension_map_(config.extmap_allow_mixed),
|
||||||
|
max_media_packet_header_(kRtpHeaderSize),
|
||||||
|
max_padding_fec_packet_header_(kRtpHeaderSize),
|
||||||
// RTP variables
|
// RTP variables
|
||||||
sequence_number_forced_(false),
|
sequence_number_forced_(false),
|
||||||
always_send_mid_and_rid_(config.always_send_mid_and_rid),
|
always_send_mid_and_rid_(config.always_send_mid_and_rid),
|
||||||
@ -170,6 +218,11 @@ rtc::ArrayView<const RtpExtensionSize> RTPSender::VideoExtensionSizes() {
|
|||||||
arraysize(kVideoExtensionSizes));
|
arraysize(kVideoExtensionSizes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::ArrayView<const RtpExtensionSize> RTPSender::AudioExtensionSizes() {
|
||||||
|
return rtc::MakeArrayView(kAudioExtensionSizes,
|
||||||
|
arraysize(kAudioExtensionSizes));
|
||||||
|
}
|
||||||
|
|
||||||
void RTPSender::SetExtmapAllowMixed(bool extmap_allow_mixed) {
|
void RTPSender::SetExtmapAllowMixed(bool extmap_allow_mixed) {
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
rtp_header_extension_map_.SetExtmapAllowMixed(extmap_allow_mixed);
|
rtp_header_extension_map_.SetExtmapAllowMixed(extmap_allow_mixed);
|
||||||
@ -180,6 +233,7 @@ int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type,
|
|||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
bool registered = rtp_header_extension_map_.RegisterByType(id, type);
|
bool registered = rtp_header_extension_map_.RegisterByType(id, type);
|
||||||
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
||||||
|
UpdateHeaderSizes();
|
||||||
return registered ? 0 : -1;
|
return registered ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +241,7 @@ bool RTPSender::RegisterRtpHeaderExtension(absl::string_view uri, int id) {
|
|||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
bool registered = rtp_header_extension_map_.RegisterByUri(id, uri);
|
bool registered = rtp_header_extension_map_.RegisterByUri(id, uri);
|
||||||
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
||||||
|
UpdateHeaderSizes();
|
||||||
return registered;
|
return registered;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,15 +252,17 @@ bool RTPSender::IsRtpHeaderExtensionRegistered(RTPExtensionType type) const {
|
|||||||
|
|
||||||
int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) {
|
int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) {
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
int32_t deregistered = rtp_header_extension_map_.Deregister(type);
|
rtp_header_extension_map_.Deregister(type);
|
||||||
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
||||||
return deregistered;
|
UpdateHeaderSizes();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::DeregisterRtpHeaderExtension(absl::string_view uri) {
|
void RTPSender::DeregisterRtpHeaderExtension(absl::string_view uri) {
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
rtp_header_extension_map_.Deregister(uri);
|
rtp_header_extension_map_.Deregister(uri);
|
||||||
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
supports_bwe_extension_ = HasBweExtension(rtp_header_extension_map_);
|
||||||
|
UpdateHeaderSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
|
void RTPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
|
||||||
@ -291,7 +348,11 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id) {
|
|||||||
|
|
||||||
void RTPSender::OnReceivedAckOnSsrc(int64_t extended_highest_sequence_number) {
|
void RTPSender::OnReceivedAckOnSsrc(int64_t extended_highest_sequence_number) {
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
|
bool update_required = !ssrc_has_acked_;
|
||||||
ssrc_has_acked_ = true;
|
ssrc_has_acked_ = true;
|
||||||
|
if (update_required) {
|
||||||
|
UpdateHeaderSizes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::OnReceivedAckOnRtxSsrc(
|
void RTPSender::OnReceivedAckOnRtxSsrc(
|
||||||
@ -369,7 +430,8 @@ std::vector<std::unique_ptr<RtpPacketToSend>> RTPSender::GeneratePadding(
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t padding_bytes_in_packet;
|
size_t padding_bytes_in_packet;
|
||||||
const size_t max_payload_size = max_packet_size_ - RtpHeaderLength();
|
const size_t max_payload_size =
|
||||||
|
max_packet_size_ - FecOrPaddingPacketMaxRtpHeaderLength();
|
||||||
if (audio_configured_) {
|
if (audio_configured_) {
|
||||||
// Allow smaller padding packets for audio.
|
// Allow smaller padding packets for audio.
|
||||||
padding_bytes_in_packet = rtc::SafeClamp<size_t>(
|
padding_bytes_in_packet = rtc::SafeClamp<size_t>(
|
||||||
@ -484,13 +546,14 @@ void RTPSender::EnqueuePackets(
|
|||||||
paced_sender_->EnqueuePackets(std::move(packets));
|
paced_sender_->EnqueuePackets(std::move(packets));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RTPSender::RtpHeaderLength() const {
|
size_t RTPSender::FecOrPaddingPacketMaxRtpHeaderLength() const {
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
size_t rtp_header_length = kRtpHeaderLength;
|
return max_padding_fec_packet_header_;
|
||||||
rtp_header_length += sizeof(uint32_t) * csrcs_.size();
|
}
|
||||||
rtp_header_length += RtpHeaderExtensionSize(kFecOrPaddingExtensionSizes,
|
|
||||||
rtp_header_extension_map_);
|
size_t RTPSender::ExpectedPerPacketOverhead() const {
|
||||||
return rtp_header_length;
|
rtc::CritScope lock(&send_critsect_);
|
||||||
|
return max_media_packet_header_;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t RTPSender::AllocateSequenceNumber(uint16_t packets_to_send) {
|
uint16_t RTPSender::AllocateSequenceNumber(uint16_t packets_to_send) {
|
||||||
@ -590,6 +653,7 @@ void RTPSender::SetRid(const std::string& rid) {
|
|||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
RTC_DCHECK_LE(rid.length(), RtpStreamId::kMaxValueSizeBytes);
|
RTC_DCHECK_LE(rid.length(), RtpStreamId::kMaxValueSizeBytes);
|
||||||
rid_ = rid;
|
rid_ = rid;
|
||||||
|
UpdateHeaderSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::SetMid(const std::string& mid) {
|
void RTPSender::SetMid(const std::string& mid) {
|
||||||
@ -597,12 +661,14 @@ void RTPSender::SetMid(const std::string& mid) {
|
|||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
RTC_DCHECK_LE(mid.length(), RtpMid::kMaxValueSizeBytes);
|
RTC_DCHECK_LE(mid.length(), RtpMid::kMaxValueSizeBytes);
|
||||||
mid_ = mid;
|
mid_ = mid;
|
||||||
|
UpdateHeaderSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
|
void RTPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
|
||||||
RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
|
RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
|
||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
csrcs_ = csrcs;
|
csrcs_ = csrcs;
|
||||||
|
UpdateHeaderSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::SetSequenceNumber(uint16_t seq) {
|
void RTPSender::SetSequenceNumber(uint16_t seq) {
|
||||||
@ -756,6 +822,7 @@ void RTPSender::SetRtpState(const RtpState& rtp_state) {
|
|||||||
capture_time_ms_ = rtp_state.capture_time_ms;
|
capture_time_ms_ = rtp_state.capture_time_ms;
|
||||||
last_timestamp_time_ms_ = rtp_state.last_timestamp_time_ms;
|
last_timestamp_time_ms_ = rtp_state.last_timestamp_time_ms;
|
||||||
ssrc_has_acked_ = rtp_state.ssrc_has_acked;
|
ssrc_has_acked_ = rtp_state.ssrc_has_acked;
|
||||||
|
UpdateHeaderSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpState RTPSender::GetRtpState() const {
|
RtpState RTPSender::GetRtpState() const {
|
||||||
@ -792,4 +859,42 @@ int64_t RTPSender::LastTimestampTimeMs() const {
|
|||||||
rtc::CritScope lock(&send_critsect_);
|
rtc::CritScope lock(&send_critsect_);
|
||||||
return last_timestamp_time_ms_;
|
return last_timestamp_time_ms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTPSender::UpdateHeaderSizes() {
|
||||||
|
const size_t rtp_header_length =
|
||||||
|
kRtpHeaderLength + sizeof(uint32_t) * csrcs_.size();
|
||||||
|
|
||||||
|
max_padding_fec_packet_header_ =
|
||||||
|
rtp_header_length + RtpHeaderExtensionSize(kFecOrPaddingExtensionSizes,
|
||||||
|
rtp_header_extension_map_);
|
||||||
|
|
||||||
|
// RtpStreamId and Mid are treated specially in that we check if they
|
||||||
|
// currently are being sent. RepairedRtpStreamId is still ignored since we
|
||||||
|
// assume RTX will not make up large enough bitrate to treat overhead
|
||||||
|
// differently.
|
||||||
|
const bool send_mid_rid = always_send_mid_and_rid_ || !ssrc_has_acked_;
|
||||||
|
std::vector<RtpExtensionSize> non_volatile_extensions;
|
||||||
|
for (auto& extension :
|
||||||
|
audio_configured_ ? AudioExtensionSizes() : VideoExtensionSizes()) {
|
||||||
|
if (IsNonVolatile(extension.type)) {
|
||||||
|
switch (extension.type) {
|
||||||
|
case RTPExtensionType::kRtpExtensionMid:
|
||||||
|
if (send_mid_rid && !mid_.empty()) {
|
||||||
|
non_volatile_extensions.push_back(extension);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTPExtensionType::kRtpExtensionRtpStreamId:
|
||||||
|
if (send_mid_rid && !rid_.empty()) {
|
||||||
|
non_volatile_extensions.push_back(extension);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
non_volatile_extensions.push_back(extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
max_media_packet_header_ =
|
||||||
|
rtp_header_length + RtpHeaderExtensionSize(non_volatile_extensions,
|
||||||
|
rtp_header_extension_map_);
|
||||||
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -39,7 +39,6 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class FrameEncryptorInterface;
|
class FrameEncryptorInterface;
|
||||||
class OverheadObserver;
|
|
||||||
class RateLimiter;
|
class RateLimiter;
|
||||||
class RtcEventLog;
|
class RtcEventLog;
|
||||||
class RtpPacketToSend;
|
class RtpPacketToSend;
|
||||||
@ -109,6 +108,9 @@ class RTPSender {
|
|||||||
// Size info for header extensions used by video packets.
|
// Size info for header extensions used by video packets.
|
||||||
static rtc::ArrayView<const RtpExtensionSize> VideoExtensionSizes();
|
static rtc::ArrayView<const RtpExtensionSize> VideoExtensionSizes();
|
||||||
|
|
||||||
|
// Size info for header extensions used by audio packets.
|
||||||
|
static rtc::ArrayView<const RtpExtensionSize> AudioExtensionSizes();
|
||||||
|
|
||||||
// Create empty packet, fills ssrc, csrcs and reserve place for header
|
// Create empty packet, fills ssrc, csrcs and reserve place for header
|
||||||
// extensions RtpSender updates before sending.
|
// extensions RtpSender updates before sending.
|
||||||
std::unique_ptr<RtpPacketToSend> AllocatePacket() const;
|
std::unique_ptr<RtpPacketToSend> AllocatePacket() const;
|
||||||
@ -116,9 +118,10 @@ class RTPSender {
|
|||||||
// Save packet's fields to generate padding that doesn't break media stream.
|
// Save packet's fields to generate padding that doesn't break media stream.
|
||||||
// Return false if sending was turned off.
|
// Return false if sending was turned off.
|
||||||
bool AssignSequenceNumber(RtpPacketToSend* packet);
|
bool AssignSequenceNumber(RtpPacketToSend* packet);
|
||||||
|
// Maximum header overhead per fec/padding packet.
|
||||||
// Used for padding and FEC packets only.
|
size_t FecOrPaddingPacketMaxRtpHeaderLength() const;
|
||||||
size_t RtpHeaderLength() const;
|
// Expected header overhead per media packet.
|
||||||
|
size_t ExpectedPerPacketOverhead() const;
|
||||||
uint16_t AllocateSequenceNumber(uint16_t packets_to_send);
|
uint16_t AllocateSequenceNumber(uint16_t packets_to_send);
|
||||||
// Including RTP headers.
|
// Including RTP headers.
|
||||||
size_t MaxRtpPacketSize() const;
|
size_t MaxRtpPacketSize() const;
|
||||||
@ -148,6 +151,8 @@ class RTPSender {
|
|||||||
|
|
||||||
bool IsFecPacket(const RtpPacketToSend& packet) const;
|
bool IsFecPacket(const RtpPacketToSend& packet) const;
|
||||||
|
|
||||||
|
void UpdateHeaderSizes() RTC_EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||||
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
Random random_ RTC_GUARDED_BY(send_critsect_);
|
Random random_ RTC_GUARDED_BY(send_critsect_);
|
||||||
|
|
||||||
@ -172,6 +177,8 @@ class RTPSender {
|
|||||||
|
|
||||||
RtpHeaderExtensionMap rtp_header_extension_map_
|
RtpHeaderExtensionMap rtp_header_extension_map_
|
||||||
RTC_GUARDED_BY(send_critsect_);
|
RTC_GUARDED_BY(send_critsect_);
|
||||||
|
size_t max_media_packet_header_ RTC_GUARDED_BY(send_critsect_);
|
||||||
|
size_t max_padding_fec_packet_header_ RTC_GUARDED_BY(send_critsect_);
|
||||||
|
|
||||||
// RTP variables
|
// RTP variables
|
||||||
uint32_t timestamp_offset_ RTC_GUARDED_BY(send_critsect_);
|
uint32_t timestamp_offset_ RTC_GUARDED_BY(send_critsect_);
|
||||||
|
|||||||
@ -71,7 +71,6 @@ RtpSenderEgress::RtpSenderEgress(const RtpRtcp::Configuration& config,
|
|||||||
transport_feedback_observer_(config.transport_feedback_callback),
|
transport_feedback_observer_(config.transport_feedback_callback),
|
||||||
send_side_delay_observer_(config.send_side_delay_observer),
|
send_side_delay_observer_(config.send_side_delay_observer),
|
||||||
send_packet_observer_(config.send_packet_observer),
|
send_packet_observer_(config.send_packet_observer),
|
||||||
overhead_observer_(config.overhead_observer),
|
|
||||||
rtp_stats_callback_(config.rtp_stats_callback),
|
rtp_stats_callback_(config.rtp_stats_callback),
|
||||||
bitrate_callback_(config.send_bitrate_observer),
|
bitrate_callback_(config.send_bitrate_observer),
|
||||||
media_has_been_sent_(false),
|
media_has_been_sent_(false),
|
||||||
@ -80,7 +79,6 @@ RtpSenderEgress::RtpSenderEgress(const RtpRtcp::Configuration& config,
|
|||||||
max_delay_it_(send_delays_.end()),
|
max_delay_it_(send_delays_.end()),
|
||||||
sum_delays_ms_(0),
|
sum_delays_ms_(0),
|
||||||
total_packet_send_delay_ms_(0),
|
total_packet_send_delay_ms_(0),
|
||||||
rtp_overhead_bytes_per_packet_(0),
|
|
||||||
total_bitrate_sent_(kBitrateStatisticsWindowMs,
|
total_bitrate_sent_(kBitrateStatisticsWindowMs,
|
||||||
RateStatistics::kBpsScale),
|
RateStatistics::kBpsScale),
|
||||||
nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
|
nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
|
||||||
@ -412,7 +410,6 @@ bool RtpSenderEgress::SendPacketToNetwork(const RtpPacketToSend& packet,
|
|||||||
const PacedPacketInfo& pacing_info) {
|
const PacedPacketInfo& pacing_info) {
|
||||||
int bytes_sent = -1;
|
int bytes_sent = -1;
|
||||||
if (transport_) {
|
if (transport_) {
|
||||||
UpdateRtpOverhead(packet);
|
|
||||||
bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options)
|
bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options)
|
||||||
? static_cast<int>(packet.size())
|
? static_cast<int>(packet.size())
|
||||||
: -1;
|
: -1;
|
||||||
@ -429,21 +426,6 @@ bool RtpSenderEgress::SendPacketToNetwork(const RtpPacketToSend& packet,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpSenderEgress::UpdateRtpOverhead(const RtpPacketToSend& packet) {
|
|
||||||
if (!overhead_observer_)
|
|
||||||
return;
|
|
||||||
size_t overhead_bytes_per_packet;
|
|
||||||
{
|
|
||||||
rtc::CritScope lock(&lock_);
|
|
||||||
if (rtp_overhead_bytes_per_packet_ == packet.headers_size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rtp_overhead_bytes_per_packet_ = packet.headers_size();
|
|
||||||
overhead_bytes_per_packet = rtp_overhead_bytes_per_packet_;
|
|
||||||
}
|
|
||||||
overhead_observer_->OnOverheadChanged(overhead_bytes_per_packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtpSenderEgress::UpdateRtpStats(const RtpPacketToSend& packet) {
|
void RtpSenderEgress::UpdateRtpStats(const RtpPacketToSend& packet) {
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,6 @@ class RtpSenderEgress {
|
|||||||
bool SendPacketToNetwork(const RtpPacketToSend& packet,
|
bool SendPacketToNetwork(const RtpPacketToSend& packet,
|
||||||
const PacketOptions& options,
|
const PacketOptions& options,
|
||||||
const PacedPacketInfo& pacing_info);
|
const PacedPacketInfo& pacing_info);
|
||||||
void UpdateRtpOverhead(const RtpPacketToSend& packet);
|
|
||||||
void UpdateRtpStats(const RtpPacketToSend& packet)
|
void UpdateRtpStats(const RtpPacketToSend& packet)
|
||||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||||
|
|
||||||
@ -115,7 +114,6 @@ class RtpSenderEgress {
|
|||||||
TransportFeedbackObserver* const transport_feedback_observer_;
|
TransportFeedbackObserver* const transport_feedback_observer_;
|
||||||
SendSideDelayObserver* const send_side_delay_observer_;
|
SendSideDelayObserver* const send_side_delay_observer_;
|
||||||
SendPacketObserver* const send_packet_observer_;
|
SendPacketObserver* const send_packet_observer_;
|
||||||
OverheadObserver* const overhead_observer_;
|
|
||||||
StreamDataCountersCallback* const rtp_stats_callback_;
|
StreamDataCountersCallback* const rtp_stats_callback_;
|
||||||
BitrateStatisticsObserver* const bitrate_callback_;
|
BitrateStatisticsObserver* const bitrate_callback_;
|
||||||
|
|
||||||
@ -129,7 +127,6 @@ class RtpSenderEgress {
|
|||||||
// The sum of delays over a kSendSideDelayWindowMs sliding window.
|
// The sum of delays over a kSendSideDelayWindowMs sliding window.
|
||||||
int64_t sum_delays_ms_ RTC_GUARDED_BY(lock_);
|
int64_t sum_delays_ms_ RTC_GUARDED_BY(lock_);
|
||||||
uint64_t total_packet_send_delay_ms_ RTC_GUARDED_BY(lock_);
|
uint64_t total_packet_send_delay_ms_ RTC_GUARDED_BY(lock_);
|
||||||
size_t rtp_overhead_bytes_per_packet_ RTC_GUARDED_BY(lock_);
|
|
||||||
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(lock_);
|
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(lock_);
|
||||||
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(lock_);
|
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(lock_);
|
||||||
RateStatistics total_bitrate_sent_ RTC_GUARDED_BY(lock_);
|
RateStatistics total_bitrate_sent_ RTC_GUARDED_BY(lock_);
|
||||||
|
|||||||
@ -178,11 +178,6 @@ class MockTransportFeedbackObserver : public TransportFeedbackObserver {
|
|||||||
MOCK_METHOD1(OnTransportFeedback, void(const rtcp::TransportFeedback&));
|
MOCK_METHOD1(OnTransportFeedback, void(const rtcp::TransportFeedback&));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockOverheadObserver : public OverheadObserver {
|
|
||||||
public:
|
|
||||||
MOCK_METHOD1(OnOverheadChanged, void(size_t overhead_bytes_per_packet));
|
|
||||||
};
|
|
||||||
|
|
||||||
class StreamDataTestCallback : public StreamDataCountersCallback {
|
class StreamDataTestCallback : public StreamDataCountersCallback {
|
||||||
public:
|
public:
|
||||||
StreamDataTestCallback()
|
StreamDataTestCallback()
|
||||||
@ -535,8 +530,7 @@ TEST_P(RtpSenderTestWithoutPacer, AssignSequenceNumberSetPaddingTimestamps) {
|
|||||||
|
|
||||||
TEST_P(RtpSenderTestWithoutPacer,
|
TEST_P(RtpSenderTestWithoutPacer,
|
||||||
TransportFeedbackObserverGetsCorrectByteCount) {
|
TransportFeedbackObserverGetsCorrectByteCount) {
|
||||||
constexpr int kRtpOverheadBytesPerPacket = 12 + 8;
|
constexpr size_t kRtpOverheadBytesPerPacket = 12 + 8;
|
||||||
NiceMock<MockOverheadObserver> mock_overhead_observer;
|
|
||||||
|
|
||||||
RtpRtcp::Configuration config;
|
RtpRtcp::Configuration config;
|
||||||
config.clock = &fake_clock_;
|
config.clock = &fake_clock_;
|
||||||
@ -545,7 +539,6 @@ TEST_P(RtpSenderTestWithoutPacer,
|
|||||||
config.transport_feedback_callback = &feedback_observer_;
|
config.transport_feedback_callback = &feedback_observer_;
|
||||||
config.event_log = &mock_rtc_event_log_;
|
config.event_log = &mock_rtc_event_log_;
|
||||||
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
config.overhead_observer = &mock_overhead_observer;
|
|
||||||
config.field_trials = &field_trials_;
|
config.field_trials = &field_trials_;
|
||||||
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
||||||
|
|
||||||
@ -568,9 +561,8 @@ TEST_P(RtpSenderTestWithoutPacer,
|
|||||||
Field(&RtpPacketSendInfo::length, expected_bytes),
|
Field(&RtpPacketSendInfo::length, expected_bytes),
|
||||||
Field(&RtpPacketSendInfo::pacing_info, PacedPacketInfo()))))
|
Field(&RtpPacketSendInfo::pacing_info, PacedPacketInfo()))))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
EXPECT_CALL(mock_overhead_observer,
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(),
|
||||||
OnOverheadChanged(kRtpOverheadBytesPerPacket))
|
kRtpOverheadBytesPerPacket);
|
||||||
.Times(1);
|
|
||||||
SendGenericPacket();
|
SendGenericPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1978,42 +1970,66 @@ TEST_P(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) {
|
|||||||
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent());
|
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(RtpSenderTest, OnOverheadChanged) {
|
TEST_P(RtpSenderTest, UpdatingCsrcsUpdatedOverhead) {
|
||||||
MockOverheadObserver mock_overhead_observer;
|
|
||||||
RtpRtcp::Configuration config;
|
RtpRtcp::Configuration config;
|
||||||
config.clock = &fake_clock_;
|
config.clock = &fake_clock_;
|
||||||
config.outgoing_transport = &transport_;
|
config.outgoing_transport = &transport_;
|
||||||
config.local_media_ssrc = kSsrc;
|
config.local_media_ssrc = kSsrc;
|
||||||
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
config.overhead_observer = &mock_overhead_observer;
|
|
||||||
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
||||||
|
|
||||||
// RTP overhead is 12B.
|
// Base RTP overhead is 12B.
|
||||||
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(12)).Times(1);
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 12u);
|
||||||
SendGenericPacket();
|
|
||||||
|
// Adding two csrcs adds 2*4 bytes to the header.
|
||||||
|
rtp_sender()->SetCsrcs({1, 2});
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(RtpSenderTest, OnOverheadChanged) {
|
||||||
|
RtpRtcp::Configuration config;
|
||||||
|
config.clock = &fake_clock_;
|
||||||
|
config.outgoing_transport = &transport_;
|
||||||
|
config.local_media_ssrc = kSsrc;
|
||||||
|
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
|
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
||||||
|
|
||||||
|
// Base RTP overhead is 12B.
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 12u);
|
||||||
|
|
||||||
rtp_sender()->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
|
rtp_sender()->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
|
||||||
kTransmissionTimeOffsetExtensionId);
|
kTransmissionTimeOffsetExtensionId);
|
||||||
|
|
||||||
// TransmissionTimeOffset extension has a size of 8B.
|
// TransmissionTimeOffset extension has a size of 3B, but with the addition
|
||||||
// 12B + 8B = 20B
|
// of header index and rounding to 4 byte boundary we end up with 20B total.
|
||||||
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(20)).Times(1);
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 20u);
|
||||||
SendGenericPacket();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(RtpSenderTest, DoesNotUpdateOverheadOnEqualSize) {
|
TEST_P(RtpSenderTest, CountMidOnlyUntilAcked) {
|
||||||
MockOverheadObserver mock_overhead_observer;
|
|
||||||
RtpRtcp::Configuration config;
|
RtpRtcp::Configuration config;
|
||||||
config.clock = &fake_clock_;
|
config.clock = &fake_clock_;
|
||||||
config.outgoing_transport = &transport_;
|
config.outgoing_transport = &transport_;
|
||||||
config.local_media_ssrc = kSsrc;
|
config.local_media_ssrc = kSsrc;
|
||||||
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
config.overhead_observer = &mock_overhead_observer;
|
|
||||||
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
rtp_sender_context_ = std::make_unique<RtpSenderContext>(config);
|
||||||
|
|
||||||
EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(_)).Times(1);
|
// Base RTP overhead is 12B.
|
||||||
SendGenericPacket();
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 12u);
|
||||||
SendGenericPacket();
|
|
||||||
|
rtp_sender()->RegisterRtpHeaderExtension(kRtpExtensionMid, kMidExtensionId);
|
||||||
|
rtp_sender()->RegisterRtpHeaderExtension(kRtpExtensionRtpStreamId,
|
||||||
|
kRidExtensionId);
|
||||||
|
|
||||||
|
// Counted only if set.
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 12u);
|
||||||
|
rtp_sender()->SetMid("foo");
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 36u);
|
||||||
|
rtp_sender()->SetRid("bar");
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 52u);
|
||||||
|
|
||||||
|
// Ack received, mid/rid no longer sent.
|
||||||
|
rtp_sender()->OnReceivedAckOnSsrc(0);
|
||||||
|
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(), 12u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(RtpSenderTest, SendPacketMatchesVideo) {
|
TEST_P(RtpSenderTest, SendPacketMatchesVideo) {
|
||||||
|
|||||||
@ -206,7 +206,8 @@ size_t RTPSenderVideo::FecPacketOverhead() const {
|
|||||||
// This reason for the header extensions to be included here is that
|
// This reason for the header extensions to be included here is that
|
||||||
// from an FEC viewpoint, they are part of the payload to be protected.
|
// from an FEC viewpoint, they are part of the payload to be protected.
|
||||||
// (The base RTP header is already protected by the FEC header.)
|
// (The base RTP header is already protected by the FEC header.)
|
||||||
overhead += rtp_sender_->RtpHeaderLength() - kRtpHeaderSize;
|
overhead +=
|
||||||
|
rtp_sender_->FecOrPaddingPacketMaxRtpHeaderLength() - kRtpHeaderSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return overhead;
|
return overhead;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user