Skip to content

Commit

Permalink
Implement Pli Priority Handler (#1480)
Browse files Browse the repository at this point in the history
  • Loading branch information
lodoyun authored Oct 18, 2019
1 parent 458edbc commit 59c19c9
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 17 deletions.
20 changes: 14 additions & 6 deletions erizo/src/erizo/MediaDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,31 @@ enum packetType {
OTHER_PACKET
};

enum packetPriority {
HIGH_PRIORITY,
LOW_PRIORITY
};

struct DataPacket {
DataPacket() = default;

DataPacket(int comp_, const char *data_, int length_, packetType type_, uint64_t received_time_ms_) :
comp{comp_}, length{length_}, type{type_}, received_time_ms{received_time_ms_}, is_keyframe{false},
ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
comp{comp_}, length{length_}, type{type_}, priority{HIGH_PRIORITY}, received_time_ms{received_time_ms_},
is_keyframe{false}, ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
memcpy(data, data_, length_);
}

DataPacket(int comp_, const char *data_, int length_, packetType type_) :
comp{comp_}, length{length_}, type{type_}, received_time_ms{ClockUtils::timePointToMs(clock::now())},
is_keyframe{false}, ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
comp{comp_}, length{length_}, type{type_}, priority{HIGH_PRIORITY},
received_time_ms{ClockUtils::timePointToMs(clock::now())}, is_keyframe{false},
ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
memcpy(data, data_, length_);
}

DataPacket(int comp_, const unsigned char *data_, int length_) :
comp{comp_}, length{length_}, type{VIDEO_PACKET}, received_time_ms{ClockUtils::timePointToMs(clock::now())},
is_keyframe{false}, ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
comp{comp_}, length{length_}, type{VIDEO_PACKET}, priority{HIGH_PRIORITY},
received_time_ms{ClockUtils::timePointToMs(clock::now())}, is_keyframe{false},
ending_of_layer_frame{false}, picture_id{-1}, tl0_pic_idx{-1}, is_padding{false} {
memcpy(data, data_, length_);
}

Expand All @@ -62,6 +69,7 @@ struct DataPacket {
char data[1500];
int length;
packetType type;
packetPriority priority;
uint64_t received_time_ms;
std::vector<int> compatible_spatial_layers;
std::vector<int> compatible_temporal_layers;
Expand Down
2 changes: 2 additions & 0 deletions erizo/src/erizo/MediaStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "rtp/LayerBitrateCalculationHandler.h"
#include "rtp/QualityFilterHandler.h"
#include "rtp/QualityManager.h"
#include "rtp/PliPriorityHandler.h"
#include "rtp/PliPacerHandler.h"
#include "rtp/RtpPaddingGeneratorHandler.h"
#include "rtp/RtpUtils.h"
Expand Down Expand Up @@ -398,6 +399,7 @@ void MediaStream::initializePipeline() {
pipeline_->addFront(std::make_shared<RtpTrackMuteHandler>());
pipeline_->addFront(std::make_shared<RtpSlideShowHandler>());
pipeline_->addFront(std::make_shared<RtpPaddingGeneratorHandler>());
pipeline_->addFront(std::make_shared<PliPriorityHandler>());
pipeline_->addFront(std::make_shared<PliPacerHandler>());
pipeline_->addFront(std::make_shared<RtpPaddingRemovalHandler>());
pipeline_->addFront(std::make_shared<BandwidthEstimationHandler>());
Expand Down
2 changes: 2 additions & 0 deletions erizo/src/erizo/rtp/PliPacerHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ void PliPacerHandler::scheduleNextPLI() {
void PliPacerHandler::write(Context *ctx, std::shared_ptr<DataPacket> packet) {
if (enabled_ && RtpUtils::isPLI(packet)) {
if (waiting_for_keyframe_) {
ELOG_DEBUG("%s, message: Discarding PLI - waiting for keyframe %d", stream_->toLog(), packet->priority);
return;
}
ELOG_DEBUG("%s, message: Sending and scheduling PLI, priority %d", stream_->toLog(), packet->priority);
waiting_for_keyframe_ = true;
scheduleNextPLI();
}
Expand Down
89 changes: 89 additions & 0 deletions erizo/src/erizo/rtp/PliPriorityHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "rtp/PliPriorityHandler.h"

#include "rtp/RtpUtils.h"
#include "./MediaDefinitions.h"
#include "./MediaStream.h"

namespace erizo {

DEFINE_LOGGER(PliPriorityHandler, "rtp.PliPriorityHandler");

constexpr duration PliPriorityHandler::kLowPriorityPliPeriod;

PliPriorityHandler::PliPriorityHandler(std::shared_ptr<erizo::Clock> the_clock)
: enabled_{true}, stream_{nullptr}, clock_{the_clock},
video_sink_ssrc_{0}, video_source_ssrc_{0}, plis_received_in_interval_{0}, first_received_{false} {}

void PliPriorityHandler::enable() {
enabled_ = true;
}

void PliPriorityHandler::disable() {
enabled_ = false;
}

void PliPriorityHandler::notifyUpdate() {
auto pipeline = getContext()->getPipelineShared();
if (pipeline && !stream_) {
stream_ = pipeline->getService<MediaStream>().get();
video_sink_ssrc_ = stream_->getVideoSinkSSRC();
video_source_ssrc_ = stream_->getVideoSourceSSRC();
}
}

void PliPriorityHandler::read(Context *ctx, std::shared_ptr<DataPacket> packet) {
if (enabled_ && packet->is_keyframe) {
ELOG_DEBUG("%s, message: Received Keyframe, resetting plis", stream_->toLog());
plis_received_in_interval_ = 0; // reset the pli counter because we have keyframe
}
ctx->fireRead(std::move(packet));
}

void PliPriorityHandler::write(Context *ctx, std::shared_ptr<DataPacket> packet) {
if (enabled_ && RtpUtils::isPLI(packet) && packet->priority == LOW_PRIORITY) {
if (!first_received_) {
ELOG_DEBUG("%s, message: First PLI received - sending it, %d", stream_->toLog(), packet->priority);
first_received_ = true;
sendPLI();
schedulePeriodicPlis();
return;
}
plis_received_in_interval_++;
ELOG_DEBUG("%s, message: Accounting received PLI, priority %d, total %u",
stream_->toLog(), packet->priority, plis_received_in_interval_);
return;
}
ctx->fireWrite(std::move(packet));
}

void PliPriorityHandler::sendPLI() {
getContext()->fireWrite(RtpUtils::createPLI(video_source_ssrc_, video_sink_ssrc_, LOW_PRIORITY));
}

void PliPriorityHandler::schedulePeriodicPlis() {
if (!enabled_) {
return;
}
ELOG_INFO("%s, message: Starting low priority plis scheduler, plis_received_in_interval_: %u",
stream_->toLog(), plis_received_in_interval_);
std::weak_ptr<PliPriorityHandler> weak_this = shared_from_this();
stream_->getWorker()->scheduleEvery([weak_this] {
if (auto this_ptr = weak_this.lock()) {
if (this_ptr->plis_received_in_interval_ > 0) {
ELOG_DEBUG("%s, message: Sending Low priority PLI, plis_received_in_interval_: %u",
this_ptr->stream_->toLog(), this_ptr->plis_received_in_interval_);
this_ptr->plis_received_in_interval_ = 0;
this_ptr->sendPLI();
return true;
} else {
// we could stop the periodic task here and restart it when a PLI is requested
ELOG_DEBUG("%s, message: No Low priority Plis to send, plis_received_in_interval_: %u",
this_ptr->stream_->toLog(), this_ptr->plis_received_in_interval_);
return true;
}
}
return false;
}, kLowPriorityPliPeriod);
}
} // namespace erizo

52 changes: 52 additions & 0 deletions erizo/src/erizo/rtp/PliPriorityHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef ERIZO_SRC_ERIZO_RTP_PLIPRIORITYHANDLER_H_
#define ERIZO_SRC_ERIZO_RTP_PLIPRIORITYHANDLER_H_

#include <string>

#include "./logger.h"
#include "pipeline/Handler.h"
#include "thread/Worker.h"
#include "lib/Clock.h"

namespace erizo {

class MediaStream;

class PliPriorityHandler: public Handler, public std::enable_shared_from_this<PliPriorityHandler> {
DECLARE_LOGGER();

public:
static constexpr duration kLowPriorityPliPeriod = std::chrono::seconds(3);

public:
explicit PliPriorityHandler(std::shared_ptr<erizo::Clock> the_clock = std::make_shared<SteadyClock>());

void enable() override;
void disable() override;

std::string getName() override {
return "pli-priority";
}

void read(Context *ctx, std::shared_ptr<DataPacket> packet) override;
void write(Context *ctx, std::shared_ptr<DataPacket> packet) override;
void notifyUpdate() override;

private:
void schedulePeriodicPlis();
void sendPLI();

private:
bool enabled_;
MediaStream* stream_;
std::shared_ptr<erizo::Clock> clock_;
uint32_t video_sink_ssrc_;
uint32_t video_source_ssrc_;
uint32_t plis_received_in_interval_;
bool first_received_;
};

} // namespace erizo

#endif // ERIZO_SRC_ERIZO_RTP_PLIPRIORITYHANDLER_H_

12 changes: 8 additions & 4 deletions erizo/src/erizo/rtp/QualityFilterHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace erizo {

DEFINE_LOGGER(QualityFilterHandler, "rtp.QualityFilterHandler");

constexpr duration kSwitchTimeout = std::chrono::seconds(3);
constexpr duration kSwitchTimeout = std::chrono::seconds(4);

QualityFilterHandler::QualityFilterHandler()
: picture_id_translator_{511, 250, 15}, stream_{nullptr}, enabled_{true}, initialized_{false},
Expand Down Expand Up @@ -57,7 +57,11 @@ void QualityFilterHandler::read(Context *ctx, std::shared_ptr<DataPacket> packet
void QualityFilterHandler::checkLayers() {
int new_spatial_layer = quality_manager_->getSpatialLayer();
if (new_spatial_layer != target_spatial_layer_ && !changing_spatial_layer_) {
sendPLI();
if (new_spatial_layer > target_spatial_layer_) {
sendPLI(LOW_PRIORITY);
} else {
sendPLI();
}
future_spatial_layer_ = new_spatial_layer;
changing_spatial_layer_ = true;
time_change_started_ = clock::now();
Expand All @@ -75,8 +79,8 @@ bool QualityFilterHandler::checkSSRCChange(uint32_t ssrc) {
return changed;
}

void QualityFilterHandler::sendPLI() {
getContext()->fireRead(RtpUtils::createPLI(video_sink_ssrc_, video_source_ssrc_));
void QualityFilterHandler::sendPLI(packetPriority priority) {
getContext()->fireRead(RtpUtils::createPLI(video_sink_ssrc_, video_source_ssrc_, priority));
}

void QualityFilterHandler::changeSpatialLayerOnKeyframeReceived(const std::shared_ptr<DataPacket> &packet) {
Expand Down
2 changes: 1 addition & 1 deletion erizo/src/erizo/rtp/QualityFilterHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class QualityFilterHandler: public Handler, public std::enable_shared_from_this<
void notifyUpdate() override;

private:
void sendPLI();
void sendPLI(packetPriority priority = HIGH_PRIORITY);
void checkLayers();
void handleFeedbackPackets(const std::shared_ptr<DataPacket> &packet);
bool checkSSRCChange(uint32_t ssrc);
Expand Down
7 changes: 5 additions & 2 deletions erizo/src/erizo/rtp/RtpUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ bool RtpUtils::isFIR(std::shared_ptr<DataPacket> packet) {
return is_fir;
}

std::shared_ptr<DataPacket> RtpUtils::createPLI(uint32_t source_ssrc, uint32_t sink_ssrc) {
std::shared_ptr<DataPacket> RtpUtils::createPLI(uint32_t source_ssrc, uint32_t sink_ssrc,
packetPriority priority) {
RtcpHeader pli;
pli.setPacketType(RTCP_PS_Feedback_PT);
pli.setBlockCount(RTCP_PLI_FMT);
Expand All @@ -76,7 +77,9 @@ std::shared_ptr<DataPacket> RtpUtils::createPLI(uint32_t source_ssrc, uint32_t s
pli.setLength(2);
char *buf = reinterpret_cast<char*>(&pli);
int len = (pli.getLength() + 1) * 4;
return std::make_shared<DataPacket>(0, buf, len, VIDEO_PACKET);
auto packet = std::make_shared<DataPacket>(0, buf, len, VIDEO_PACKET);
packet->priority = priority;
return packet;
}

std::shared_ptr<DataPacket> RtpUtils::createFIR(uint32_t source_ssrc, uint32_t sink_ssrc, uint8_t seq_number) {
Expand Down
3 changes: 2 additions & 1 deletion erizo/src/erizo/rtp/RtpUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class RtpUtils {

static void forEachNack(RtcpHeader *chead, std::function<void(uint16_t, uint16_t, RtcpHeader*)> f);

static std::shared_ptr<DataPacket> createPLI(uint32_t source_ssrc, uint32_t sink_ssrc);
static std::shared_ptr<DataPacket> createPLI(uint32_t source_ssrc, uint32_t sink_ssrc,
packetPriority priority = HIGH_PRIORITY);

static std::shared_ptr<DataPacket> createFIR(uint32_t source_ssrc, uint32_t sink_ssrc, uint8_t seq_number);
static std::shared_ptr<DataPacket> createREMB(uint32_t ssrc, std::vector<uint32_t> ssrc_list, uint32_t bitrate);
Expand Down
Loading

0 comments on commit 59c19c9

Please sign in to comment.