-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Estimate bandwidth in connection and don't limit by REMBs #1726
Changes from 16 commits
7dd7945
ba1dc0b
4c02f93
1fe25ae
deddd2f
28251cf
dcb0e41
d5cda13
967c495
7afa19b
d126ff8
304608d
b98b2f7
7d36acc
659de0e
eb1f0ac
b3929a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
#include <vector> | ||
|
||
#include "./WebRtcConnection.h" | ||
#include "./MediaStream.h" | ||
#include "lib/Clock.h" | ||
#include "lib/ClockUtils.h" | ||
|
@@ -39,12 +40,12 @@ std::unique_ptr<RemoteBitrateEstimator> RemoteBitrateEstimatorPicker::pickEstima | |
} | ||
|
||
BandwidthEstimationHandler::BandwidthEstimationHandler(std::shared_ptr<RemoteBitrateEstimatorPicker> picker) : | ||
stream_{nullptr}, clock_{webrtc::Clock::GetRealTimeClock()}, | ||
connection_{nullptr}, clock_{webrtc::Clock::GetRealTimeClock()}, | ||
picker_{picker}, | ||
using_absolute_send_time_{false}, packets_since_absolute_send_time_{0}, | ||
min_bitrate_bps_{kMinBitRateAllowed}, | ||
bitrate_{0}, last_send_bitrate_{0}, max_video_bw_{kDefaultMaxVideoBWInKbps}, last_remb_time_{0}, | ||
running_{false}, active_{true}, initialized_{false} { | ||
bitrate_{0}, last_send_bitrate_{0}, last_remb_time_{0}, | ||
sink_ssrc_{0}, running_{false}, active_{true}, initialized_{false} { | ||
rtc::LogMessage::SetLogToStderr(false); | ||
} | ||
|
||
|
@@ -57,32 +58,25 @@ void BandwidthEstimationHandler::disable() { | |
} | ||
|
||
void BandwidthEstimationHandler::notifyUpdate() { | ||
ELOG_DEBUG("NotifyUPDATE"); | ||
auto pipeline = getContext()->getPipelineShared(); | ||
|
||
if (pipeline) { | ||
auto rtcp_processor = pipeline->getService<RtcpProcessor>(); | ||
if (rtcp_processor) { | ||
max_video_bw_ = rtcp_processor->getMaxVideoBW(); | ||
} | ||
if (pipeline && !connection_) { | ||
connection_ = pipeline->getService<WebRtcConnection>().get(); | ||
} | ||
|
||
if (initialized_) { | ||
if (!connection_) { | ||
ELOG_ERROR("Returning because there is no connection"); | ||
return; | ||
} | ||
|
||
if (pipeline && !stream_) { | ||
stream_ = pipeline->getService<MediaStream>().get(); | ||
} | ||
if (!stream_) { | ||
RtpExtensionProcessor& ext_processor = connection_->getRtpExtensionProcessor(); | ||
updateExtensionMaps(ext_processor.getVideoExtensionMap(), ext_processor.getAudioExtensionMap()); | ||
|
||
if (initialized_) { | ||
return; | ||
} | ||
worker_ = stream_->getWorker(); | ||
worker_ = connection_->getWorker(); | ||
stats_ = pipeline->getService<Stats>(); | ||
RtpExtensionProcessor& ext_processor = stream_->getRtpExtensionProcessor(); | ||
if (ext_processor.getVideoExtensionMap().size() == 0) { | ||
return; | ||
} | ||
updateExtensionMaps(ext_processor.getVideoExtensionMap(), ext_processor.getAudioExtensionMap()); | ||
|
||
pickEstimator(); | ||
initialized_ = true; | ||
|
@@ -229,19 +223,39 @@ void BandwidthEstimationHandler::pickEstimator() { | |
} | ||
|
||
void BandwidthEstimationHandler::sendREMBPacket() { | ||
sink_ssrc_ = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need to use a class variable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are right. I kept if for consistency but it does make more sense to have it as a local variable. |
||
source_ssrcs_.clear(); | ||
ELOG_DEBUG("Update MediaStream SSRCs"); | ||
connection_->forEachMediaStream([this] (const std::shared_ptr<MediaStream> &media_stream) { | ||
ELOG_DEBUG("MediaStream %s, publisher %u, sink %u, source %u", media_stream->getId().c_str(), | ||
media_stream->isPublisher(), media_stream->getVideoSinkSSRC(), media_stream->getVideoSourceSSRC()); | ||
if (media_stream->isReady() && media_stream->isPublisher()) { | ||
sink_ssrc_ = media_stream->getVideoSinkSSRC(); | ||
} | ||
source_ssrcs_.push_back(media_stream->getVideoSourceSSRC()); | ||
}); | ||
|
||
if (sink_ssrc_ == 0) { | ||
ELOG_WARN("No SSRC available to send REMB"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if there could be cases where we should not notify with a warning here. |
||
return; | ||
} | ||
remb_packet_.setPacketType(RTCP_PS_Feedback_PT); | ||
remb_packet_.setBlockCount(RTCP_AFB); | ||
memcpy(&remb_packet_.report.rembPacket.uniqueid, "REMB", 4); | ||
|
||
remb_packet_.setSSRC(stream_->getVideoSinkSSRC()); | ||
// todo(pedro) figure out which sourceSSRC to use here | ||
remb_packet_.setSourceSSRC(stream_->getVideoSourceSSRC()); | ||
remb_packet_.setLength(5); | ||
uint32_t capped_bitrate = max_video_bw_ > 0 ? std::min(max_video_bw_, bitrate_) : bitrate_; | ||
ELOG_DEBUG("Bitrates min(%u,%u) = %u", bitrate_, max_video_bw_, capped_bitrate); | ||
remb_packet_.setSSRC(sink_ssrc_); | ||
remb_packet_.setSourceSSRC(0); | ||
remb_packet_.setLength(4 + source_ssrcs_.size()); | ||
uint32_t capped_bitrate = bitrate_; | ||
ELOG_DEBUG("Bitrates min(%u) = %u", bitrate_, capped_bitrate); | ||
remb_packet_.setREMBBitRate(capped_bitrate); | ||
remb_packet_.setREMBNumSSRC(1); | ||
remb_packet_.setREMBFeedSSRC(0, stream_->getVideoSourceSSRC()); | ||
remb_packet_.setREMBNumSSRC(source_ssrcs_.size()); | ||
|
||
for (std::size_t i = 0; i < source_ssrcs_.size(); i++) { | ||
ELOG_DEBUG("Setting REMBFeedSSRC %u to ssrc %u, size %u", i, source_ssrcs_[i], source_ssrcs_.size()); | ||
remb_packet_.setREMBFeedSSRC(i, source_ssrcs_[i]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 |
||
} | ||
|
||
int remb_length = (remb_packet_.getLength() + 1) * 4; | ||
if (active_) { | ||
ELOG_DEBUG("BWE Estimation is %d", last_send_bitrate_); | ||
|
@@ -252,6 +266,7 @@ void BandwidthEstimationHandler::sendREMBPacket() { | |
|
||
void BandwidthEstimationHandler::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs, | ||
uint32_t bitrate) { | ||
ELOG_WARN("Onreceive bitrate %lu", bitrate); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider using ELOG_DEBUG here |
||
if (last_send_bitrate_ > 0) { | ||
unsigned int new_remb_bitrate = last_send_bitrate_ - bitrate_ + bitrate; | ||
if (new_remb_bitrate < kSendThresholdPercent * last_send_bitrate_ / 100) { | ||
|
@@ -274,8 +289,7 @@ void BandwidthEstimationHandler::OnReceiveBitrateChanged(const std::vector<uint3 | |
} | ||
last_remb_time_ = now; | ||
last_send_bitrate_ = bitrate_; | ||
stats_->getNode() | ||
[stream_->getVideoSourceSSRC()].insertStat("erizoBandwidth", CumulativeStat{last_send_bitrate_}); | ||
stats_->getNode().insertStat("erizoBandwidth", CumulativeStat{last_send_bitrate_}); | ||
sendREMBPacket(); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we use a more descriptive message?