Skip to content

Commit

Permalink
Add a new algorithm to allocate better bandwidth in Single PC (#1296)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcague authored Sep 18, 2018
1 parent 12f8713 commit 460f384
Show file tree
Hide file tree
Showing 13 changed files with 729 additions and 19 deletions.
14 changes: 13 additions & 1 deletion erizo/src/erizo/MediaStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ MediaStream::MediaStream(std::shared_ptr<Worker> worker,
worker_{std::move(worker)},
audio_muted_{false}, video_muted_{false},
pipeline_initialized_{false},
is_publisher_{is_publisher} {
is_publisher_{is_publisher},
simulcast_{false},
bitrate_from_max_quality_layer_{0} {
setVideoSinkSSRC(kDefaultVideoSinkSSRC);
setAudioSinkSSRC(kDefaultAudioSinkSSRC);
ELOG_INFO("%s message: constructor, id: %s",
Expand Down Expand Up @@ -95,6 +97,16 @@ uint32_t MediaStream::getMaxVideoBW() {
return bitrate;
}

uint32_t MediaStream::getBitrateSent() {
uint32_t bitrate = 0;
std::string video_ssrc = std::to_string(is_publisher_ ? getVideoSourceSSRC() : getVideoSinkSSRC());
if (stats_->getNode().hasChild(video_ssrc) &&
stats_->getNode()[video_ssrc].hasChild("bitrateCalculated")) {
bitrate = stats_->getNode()[video_ssrc]["bitrateCalculated"].value();
}
return bitrate;
}

void MediaStream::setMaxVideoBW(uint32_t max_video_bw) {
asyncTask([max_video_bw] (std::shared_ptr<MediaStream> stream) {
if (stream->rtcp_processor_) {
Expand Down
12 changes: 11 additions & 1 deletion erizo/src/erizo/MediaStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <boost/thread/mutex.hpp>

#include <atomic>
#include <string>
#include <map>
#include <vector>
Expand Down Expand Up @@ -69,6 +70,8 @@ class MediaStream: public MediaSink, public MediaSource, public FeedbackSink,
bool init();
void close() override;
virtual uint32_t getMaxVideoBW();
virtual uint32_t getBitrateFromMaxQualityLayer() { return bitrate_from_max_quality_layer_; }
virtual uint32_t getBitrateSent();
void setMaxVideoBW(uint32_t max_video_bw);
void syncClose();
bool setRemoteSdp(std::shared_ptr<SdpInfo> sdp);
Expand Down Expand Up @@ -134,7 +137,10 @@ class MediaStream: public MediaSink, public MediaSource, public FeedbackSink,

SdpInfo* getRemoteSdpInfo() { return remote_sdp_.get(); }

bool isSlideShowModeEnabled() { return slide_show_mode_; }
virtual bool isSlideShowModeEnabled() { return slide_show_mode_; }

virtual bool isSimulcast() { return simulcast_; }
void setSimulcast(bool simulcast) { simulcast_ = simulcast; }

RtpExtensionProcessor& getRtpExtensionProcessor() { return connection_->getRtpExtensionProcessor(); }
std::shared_ptr<Worker> getWorker() { return worker_; }
Expand All @@ -150,6 +156,7 @@ class MediaStream: public MediaSink, public MediaSource, public FeedbackSink,
bool isRunning() { return pipeline_initialized_ && sending_; }
Pipeline::Ptr getPipeline() { return pipeline_; }
bool isPublisher() { return is_publisher_; }
void setBitrateFromMaxQualityLayer(uint64_t bitrate) { bitrate_from_max_quality_layer_ = bitrate; }

inline std::string toLog() {
return "id: " + stream_id_ + ", role:" + (is_publisher_ ? "publisher" : "subscriber") + ", " + printLogContext();
Expand Down Expand Up @@ -202,6 +209,9 @@ class MediaStream: public MediaSink, public MediaSource, public FeedbackSink,
bool pipeline_initialized_;

bool is_publisher_;

std::atomic_bool simulcast_;
std::atomic<uint64_t> bitrate_from_max_quality_layer_;
protected:
std::shared_ptr<SdpInfo> remote_sdp_;
std::shared_ptr<SdpInfo> local_sdp_;
Expand Down
21 changes: 4 additions & 17 deletions erizo/src/erizo/WebRtcConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "MediaStream.h"
#include "DtlsTransport.h"
#include "SdpInfo.h"
#include "bandwidth/MaxVideoBWDistributor.h"
#include "bandwidth/TargetVideoBWDistributor.h"
#include "rtp/RtpHeaders.h"
#include "rtp/RtpVP8Parser.h"
#include "rtp/RtcpAggregator.h"
Expand Down Expand Up @@ -52,6 +54,7 @@ WebRtcConnection::WebRtcConnection(std::shared_ptr<Worker> worker, std::shared_p
ELOG_INFO("%s message: constructor, stunserver: %s, stunPort: %d, minPort: %d, maxPort: %d",
toLog(), ice_config.stun_server.c_str(), ice_config.stun_port, ice_config.min_port, ice_config.max_port);
stats_ = std::make_shared<Stats>();
distributor_ = std::unique_ptr<BandwidthDistributionAlgorithm>(new TargetVideoBWDistributor());
global_state_ = CONN_INITIAL;

trickle_enabled_ = ice_config_.should_trickle;
Expand Down Expand Up @@ -498,23 +501,7 @@ void WebRtcConnection::onREMBFromTransport(RtcpHeader *chead, Transport *transpo
});
}

std::sort(streams.begin(), streams.end(),
[](const std::shared_ptr<MediaStream> &i, const std::shared_ptr<MediaStream> &j) {
return i->getMaxVideoBW() < j->getMaxVideoBW();
});

uint8_t remaining_streams = streams.size();
uint32_t remaining_bitrate = chead->getREMBBitRate();
std::for_each(streams.begin(), streams.end(),
[&remaining_bitrate, &remaining_streams, transport, chead](const std::shared_ptr<MediaStream> &stream) {
uint32_t max_bitrate = stream->getMaxVideoBW();
uint32_t remaining_avg_bitrate = remaining_bitrate / remaining_streams;
uint32_t bitrate = std::min(max_bitrate, remaining_avg_bitrate);
auto generated_remb = RtpUtils::createREMB(chead->getSSRC(), {stream->getVideoSinkSSRC()}, bitrate);
stream->onTransportData(generated_remb, transport);
remaining_bitrate -= bitrate;
remaining_streams--;
});
distributor_->distribute(chead->getREMBBitRate(), chead->getSSRC(), streams, transport);
}

void WebRtcConnection::onRtcpFromTransport(std::shared_ptr<DataPacket> packet, Transport *transport) {
Expand Down
3 changes: 3 additions & 0 deletions erizo/src/erizo/WebRtcConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "./MediaDefinitions.h"
#include "./Transport.h"
#include "./Stats.h"
#include "bandwidth/BandwidthDistributionAlgorithm.h"
#include "pipeline/Pipeline.h"
#include "thread/Worker.h"
#include "thread/IOWorker.h"
Expand Down Expand Up @@ -192,6 +193,8 @@ class WebRtcConnection: public TransportListener, public LogContext,
bool audio_muted_;
bool video_muted_;
bool first_remote_sdp_processed_;

std::unique_ptr<BandwidthDistributionAlgorithm> distributor_;
};

} // namespace erizo
Expand Down
22 changes: 22 additions & 0 deletions erizo/src/erizo/bandwidth/BandwidthDistributionAlgorithm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef ERIZO_SRC_ERIZO_BANDWIDTH_BANDWIDTHDISTRIBUTIONALGORITHM_H_
#define ERIZO_SRC_ERIZO_BANDWIDTH_BANDWIDTHDISTRIBUTIONALGORITHM_H_

#include <memory>
#include <vector>

namespace erizo {

class MediaStream;
class Transport;

class BandwidthDistributionAlgorithm {
public:
BandwidthDistributionAlgorithm() {}
virtual ~BandwidthDistributionAlgorithm() {}
virtual void distribute(uint32_t remb, uint32_t ssrc, std::vector<std::shared_ptr<MediaStream>> streams,
Transport *transport) = 0;
};

} // namespace erizo

#endif // ERIZO_SRC_ERIZO_BANDWIDTH_BANDWIDTHDISTRIBUTIONALGORITHM_H_
35 changes: 35 additions & 0 deletions erizo/src/erizo/bandwidth/MaxVideoBWDistributor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* MaxVideoBWDistributor.cpp
*/

#include <algorithm>

#include "MaxVideoBWDistributor.h"
#include "MediaStream.h"
#include "Transport.h"
#include "rtp/RtpUtils.h"

namespace erizo {

void MaxVideoBWDistributor::distribute(uint32_t remb, uint32_t ssrc,
std::vector<std::shared_ptr<MediaStream>> streams, Transport *transport) {
std::sort(streams.begin(), streams.end(),
[](const std::shared_ptr<MediaStream> &i, const std::shared_ptr<MediaStream> &j) {
return i->getMaxVideoBW() < j->getMaxVideoBW();
});

uint8_t remaining_streams = streams.size();
uint32_t remaining_bitrate = remb;
std::for_each(streams.begin(), streams.end(),
[&remaining_bitrate, &remaining_streams, transport, ssrc](const std::shared_ptr<MediaStream> &stream) {
uint32_t max_bitrate = stream->getMaxVideoBW();
uint32_t remaining_avg_bitrate = remaining_bitrate / remaining_streams;
uint32_t bitrate = std::min(max_bitrate, remaining_avg_bitrate);
auto generated_remb = RtpUtils::createREMB(ssrc, {stream->getVideoSinkSSRC()}, bitrate);
stream->onTransportData(generated_remb, transport);
remaining_bitrate -= bitrate;
remaining_streams--;
});
}

} // namespace erizo
18 changes: 18 additions & 0 deletions erizo/src/erizo/bandwidth/MaxVideoBWDistributor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef ERIZO_SRC_ERIZO_BANDWIDTH_MAXVIDEOBWDISTRIBUTOR_H_
#define ERIZO_SRC_ERIZO_BANDWIDTH_MAXVIDEOBWDISTRIBUTOR_H_

#include "bandwidth/BandwidthDistributionAlgorithm.h"

namespace erizo {

class MaxVideoBWDistributor : public BandwidthDistributionAlgorithm {
public:
MaxVideoBWDistributor() {}
virtual ~MaxVideoBWDistributor() {}
void distribute(uint32_t remb, uint32_t ssrc, std::vector<std::shared_ptr<MediaStream>> streams,
Transport *transport) override;
};

} // namespace erizo

#endif // ERIZO_SRC_ERIZO_BANDWIDTH_MAXVIDEOBWDISTRIBUTOR_H_
55 changes: 55 additions & 0 deletions erizo/src/erizo/bandwidth/TargetVideoBWDistributor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* TargetVideoBWDistributor.cpp
*/

#include <algorithm>

#include "TargetVideoBWDistributor.h"
#include "MediaStream.h"
#include "Transport.h"
#include "rtp/RtpUtils.h"

namespace erizo {

void TargetVideoBWDistributor::distribute(uint32_t remb, uint32_t ssrc,
std::vector<std::shared_ptr<MediaStream>> streams, Transport *transport) {
std::sort(streams.begin(), streams.end(),
[this](const std::shared_ptr<MediaStream> &i, const std::shared_ptr<MediaStream> &j) {
return getTargetVideoBW(i) < getTargetVideoBW(j);
});
uint8_t remaining_streams = streams.size();
uint32_t remaining_bitrate = remb;
std::for_each(streams.begin(), streams.end(),
[&remaining_bitrate, &remaining_streams, transport, ssrc, this](const std::shared_ptr<MediaStream> &stream) {
uint32_t max_bitrate = stream->getMaxVideoBW();

uint32_t target_bitrate = getTargetVideoBW(stream);

uint32_t remaining_avg_bitrate = remaining_bitrate / remaining_streams;
uint32_t bitrate = std::min(target_bitrate, remaining_avg_bitrate);
uint32_t remb = std::min(max_bitrate, remaining_avg_bitrate);
auto generated_remb = RtpUtils::createREMB(ssrc, {stream->getVideoSinkSSRC()}, remb);
stream->onTransportData(generated_remb, transport);

remaining_bitrate -= bitrate;
remaining_streams--;
});
}

uint32_t TargetVideoBWDistributor::getTargetVideoBW(const std::shared_ptr<MediaStream> &stream) {
bool slide_show_mode = stream->isSlideShowModeEnabled();
bool is_simulcast = stream->isSimulcast();
uint32_t bitrate_sent = stream->getBitrateSent();
uint32_t max_bitrate = stream->getMaxVideoBW();

uint32_t target_bitrate = max_bitrate;
if (is_simulcast) {
target_bitrate = std::min(stream->getBitrateFromMaxQualityLayer(), max_bitrate);
}
if (slide_show_mode) {
target_bitrate = std::min(bitrate_sent, max_bitrate);
}
return target_bitrate;
}

} // namespace erizo
22 changes: 22 additions & 0 deletions erizo/src/erizo/bandwidth/TargetVideoBWDistributor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef ERIZO_SRC_ERIZO_BANDWIDTH_TARGETVIDEOBWDISTRIBUTOR_H_
#define ERIZO_SRC_ERIZO_BANDWIDTH_TARGETVIDEOBWDISTRIBUTOR_H_

#include "bandwidth/BandwidthDistributionAlgorithm.h"

namespace erizo {

class MediaStream;

class TargetVideoBWDistributor : public BandwidthDistributionAlgorithm {
public:
TargetVideoBWDistributor() {}
virtual ~TargetVideoBWDistributor() {}
void distribute(uint32_t remb, uint32_t ssrc, std::vector<std::shared_ptr<MediaStream>> streams,
Transport *transport) override;
private:
uint32_t getTargetVideoBW(const std::shared_ptr<MediaStream> &stream);
};

} // namespace erizo

#endif // ERIZO_SRC_ERIZO_BANDWIDTH_TARGETVIDEOBWDISTRIBUTOR_H_
3 changes: 3 additions & 0 deletions erizo/src/erizo/rtp/QualityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ void QualityManager::selectLayer(bool try_higher_layers) {
if (!initialized_ || !stats_->getNode().hasChild("qualityLayers")) {
return;
}
stream_->setSimulcast(true);
last_quality_check_ = clock_->now();
int min_valid_spatial_layer = std::min(min_desired_spatial_layer_, max_active_spatial_layer_);
int aux_temporal_layer = 0;
Expand Down Expand Up @@ -223,6 +224,8 @@ void QualityManager::calculateMaxActiveLayer() {

max_active_spatial_layer_ = max_active_spatial_layer;
max_active_temporal_layer_ = max_active_temporal_layer;

stream_->setBitrateFromMaxQualityLayer(getInstantLayerBitrate(max_active_spatial_layer, max_active_temporal_layer));
}

uint64_t QualityManager::getInstantLayerBitrate(int spatial_layer, int temporal_layer) {
Expand Down
Loading

0 comments on commit 460f384

Please sign in to comment.