Skip to content
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

Add Stream Switch Handler #1724

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion erizo/generateProject.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ EOF
}


usage()
{
cat << EOF
usage: $0 options

Generate Erizo projects. It will generate all builds if no option is passed.

OPTIONS:
-h Show this message
-d Generate debug
-r Generate release
EOF
}

generateVersion() {
echo "generating $1"
BIN_DIR="$BASE_BIN_DIR/$1"
Expand Down Expand Up @@ -58,4 +72,28 @@ while getopts “hdr” OPTION
done
fi

generateVersion release
if [ "$#" -eq 0 ]
then
generateVersion debug
generateVersion release
else
while getopts “hdr” OPTION
do
case $OPTION in
h)
usage
exit 1
;;
d)
generateVersion debug
;;
r)
generateVersion release
;;
?)
usage
exit
;;
esac
done
fi
8 changes: 8 additions & 0 deletions erizo/src/erizo/MediaStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "rtp/PliPriorityHandler.h"
#include "rtp/PliPacerHandler.h"
#include "rtp/RtpPaddingGeneratorHandler.h"
#include "rtp/StreamSwitchHandler.h"
#include "rtp/RtpUtils.h"
#include "rtp/PacketCodecParser.h"

Expand Down Expand Up @@ -462,6 +463,7 @@ void MediaStream::initializePipeline() {
addHandlerInPosition(AFTER_READER, handler_pointer_dic, handler_order);
pipeline_->addFront(std::make_shared<RtcpProcessorHandler>());
pipeline_->addFront(std::make_shared<FecReceiverHandler>());
pipeline_->addFront(std::make_shared<StreamSwitchHandler>());
pipeline_->addFront(std::make_shared<LayerBitrateCalculationHandler>());
pipeline_->addFront(std::make_shared<QualityFilterHandler>());
pipeline_->addFront(std::make_shared<IncomingStatsHandler>());
Expand Down Expand Up @@ -574,6 +576,12 @@ void MediaStream::onTransportData(std::shared_ptr<DataPacket> incoming_packet, T
char* buf = packet->data;
RtpHeader *head = reinterpret_cast<RtpHeader*> (buf);
RtcpHeader *chead = reinterpret_cast<RtcpHeader*> (buf);

if (chead->isFeedback()) {
if (RtpUtils::isPLI(packet)) {
ELOG_WARN("Received PLI from subscriber%s", stream_ptr->getLabel());
}
}
if (!chead->isFeedback()) {
uint32_t recv_ssrc;
if (chead->isRtcp()) {
Expand Down
14 changes: 14 additions & 0 deletions erizo/src/erizo/MediaStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@

namespace erizo {

class MediaStreamSwitchEvent : public MediaEvent {
public:
MediaStreamSwitchEvent(bool is_connected, bool has_audio, bool has_video)
: is_connected{is_connected}, has_audio{has_audio}, has_video{has_video} {}

std::string getType() const override {
return "MediaStreamSwitchEvent";
}

bool is_connected;
bool has_audio;
bool has_video;
};

class MediaStreamStatsListener {
public:
virtual ~MediaStreamStatsListener() {
Expand Down
12 changes: 10 additions & 2 deletions erizo/src/erizo/OneToManyProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ namespace erizo {
const std::string& peer_id) {
ELOG_DEBUG("Adding subscriber");
boost::mutex::scoped_lock lock(monitor_mutex_);
if (!subscriber_stream) {
return;
}
ELOG_DEBUG("From %u, %u ", publisher_->getAudioSourceSSRC(), publisher_->getVideoSourceSSRC());
ELOG_DEBUG("Subscribers ssrcs: Audio %u, video, %u from %u, %u ",
ELOG_WARN("Subscribers ssrcs: Audio %u, video, %u from %u, %u ",
subscriber_stream->getAudioSinkSSRC(), subscriber_stream->getVideoSinkSSRC(),
publisher_->getAudioSourceSSRC() , publisher_->getVideoSourceSSRC());
std::shared_ptr<FeedbackSource> fbsource = subscriber_stream->getFeedbackSource().lock();
Expand All @@ -166,6 +169,9 @@ namespace erizo {
subscribers_.erase(peer_id);
}
subscribers_[peer_id] = subscriber_stream;
bool has_audio = publisher_->getAudioSourceSSRC() != kDefaultAudioSinkSSRC;
bool has_video = publisher_->getVideoSourceSSRC() != kDefaultVideoSinkSSRC;
subscriber_stream->deliverEvent(std::make_shared<MediaStreamSwitchEvent>(true, has_audio, has_video));
}

std::shared_ptr<MediaSink> OneToManyProcessor::getSubscriber(const std::string& peer_id) {
Expand All @@ -179,7 +185,9 @@ namespace erizo {
void OneToManyProcessor::removeSubscriber(const std::string& peer_id) {
ELOG_DEBUG("Remove subscriber %s", peer_id.c_str());
boost::mutex::scoped_lock lock(monitor_mutex_);
if (subscribers_.find(peer_id) != subscribers_.end()) {
auto subscriber_it = subscribers_.find(peer_id);
if (subscriber_it != subscribers_.end()) {
subscriber_it->second->deliverEvent(std::make_shared<MediaStreamSwitchEvent>(false, false, false));
subscribers_.erase(peer_id);
}
}
Expand Down
16 changes: 13 additions & 3 deletions erizo/src/erizo/SdpInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,17 @@ namespace erizo {
return nullptr;
}

RtpMap *SdpInfo::getCodecByName(const std::string codecName, const unsigned int clockRate) {
RtpMap *SdpInfo::getCodecByName(const std::string codecName) {
for (unsigned int it = 0; it < internalPayloadVector_.size(); it++) {
RtpMap& rtp = internalPayloadVector_[it];
if (rtp.encoding_name == codecName) {
return &rtp;
}
}
return NULL;
}

RtpMap *SdpInfo::getCodecByNameAndClockRate(const std::string codecName, const unsigned int clockRate) {
for (unsigned int it = 0; it < internalPayloadVector_.size(); it++) {
RtpMap& rtp = internalPayloadVector_[it];
if (rtp.encoding_name == codecName && rtp.clock_rate == clockRate) {
Expand All @@ -117,7 +127,7 @@ namespace erizo {
}

bool SdpInfo::supportCodecByName(const std::string codecName, const unsigned int clockRate) {
RtpMap *rtp = getCodecByName(codecName, clockRate);
RtpMap *rtp = getCodecByNameAndClockRate(codecName, clockRate);
if (rtp != NULL) {
return supportPayloadType(rtp->payload_type);
}
Expand All @@ -128,7 +138,7 @@ namespace erizo {
if (inOutPTMap.count(payloadType) > 0) {
for (unsigned int it = 0; it < payloadVector.size(); it++) {
const RtpMap& rtp = payloadVector[it];
if (inOutPTMap[rtp.payload_type] == payloadType) {
if (inOutPTMap[payloadType] == rtp.payload_type) {
return true;
}
}
Expand Down
4 changes: 3 additions & 1 deletion erizo/src/erizo/SdpInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ class SdpInfo {

std::string getPassword(MediaType media) const;

RtpMap* getCodecByName(const std::string codecName, const unsigned int clockRate);
RtpMap* getCodecByName(const std::string codecName);

RtpMap* getCodecByNameAndClockRate(const std::string codecName, const unsigned int clockRate);

bool supportCodecByName(const std::string codecName, const unsigned int clockRate);

Expand Down
9 changes: 9 additions & 0 deletions erizo/src/erizo/WebRtcConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,15 @@ void WebRtcConnection::write(std::shared_ptr<DataPacket> packet) {
if (transport == nullptr) {
return;
}
if (packet->type == VIDEO_PACKET && packet->is_keyframe) {
ELOG_WARN("Sending keyframe!");
}

RtcpHeader *chead = reinterpret_cast<RtcpHeader*> (packet->data);
if (chead->isRtcp() && chead->getPacketType() == RTCP_PS_Feedback_PT && chead->getBlockCount() == RTCP_PLI_FMT) {
ELOG_WARN("Sending PLI!");
}

extension_processor_.processRtpExtensions(packet);
transport->write(packet->data, packet->length);
}
Expand Down
3 changes: 3 additions & 0 deletions erizo/src/erizo/rtp/BandwidthEstimationHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ void BandwidthEstimationHandler::updateExtensionMap(bool is_video, std::array<RT
switch (extension) {
case RTP_ID:
case MID:
case VIDEO_CONTENT_TYPE:
case VIDEO_TIMING:
case COLOR_SPACE:
case UNKNOWN:
continue;
break;
Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/FakeKeyframeGeneratorHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void FakeKeyframeGeneratorHandler::maybeSendAndSchedulePLIs() {
}

void FakeKeyframeGeneratorHandler::sendPLI() {
ELOG_WARN("Sending PLI from FakeKeyframeGenerator");
getContext()->fireRead(RtpUtils::createPLI(video_sink_ssrc_, video_source_ssrc_));
}

Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/PeriodicPliHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void PeriodicPliHandler::write(Context *ctx, std::shared_ptr<DataPacket> packet)
}

void PeriodicPliHandler::sendPLI() {
ELOG_WARN("Sending PLI from PeriodicPliHandler");
getContext()->fireWrite(RtpUtils::createPLI(video_source_ssrc_, video_sink_ssrc_, HIGH_PRIORITY));
}

Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/PliPacerHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void PliPacerHandler::read(Context *ctx, std::shared_ptr<DataPacket> packet) {
}

void PliPacerHandler::sendPLI() {
ELOG_WARN("Sending PLI in PliPacerHandler");
getContext()->fireWrite(RtpUtils::createPLI(video_source_ssrc_, video_sink_ssrc_));
scheduleNextPLI();
}
Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/PliPriorityHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ void PliPriorityHandler::write(Context *ctx, std::shared_ptr<DataPacket> packet)
}

void PliPriorityHandler::sendPLI() {
ELOG_WARN("Sending PLI from PliPriorityHandler");
getContext()->fireWrite(RtpUtils::createPLI(video_source_ssrc_, video_sink_ssrc_, LOW_PRIORITY));
}

Expand Down
10 changes: 9 additions & 1 deletion erizo/src/erizo/rtp/QualityFilterHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void QualityFilterHandler::handleFeedbackPackets(const std::shared_ptr<DataPacke
(chead->getBlockCount() == RTCP_PLI_FMT ||
chead->getBlockCount() == RTCP_SLI_FMT ||
chead->getBlockCount() == RTCP_FIR_FMT)) {
ELOG_WARN("Handling PLI");
sendPLI();
}
});
Expand All @@ -57,6 +58,7 @@ 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_) {
ELOG_WARN("Change spatial layer %d -> %d", target_spatial_layer_, new_spatial_layer);
if (new_spatial_layer > target_spatial_layer_) {
sendPLI(LOW_PRIORITY);
} else {
Expand All @@ -80,6 +82,7 @@ bool QualityFilterHandler::checkSSRCChange(uint32_t ssrc) {
}

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

Expand All @@ -97,6 +100,7 @@ void QualityFilterHandler::changeSpatialLayerOnKeyframeReceived(const std::share
future_spatial_layer_ = -1;
changing_spatial_layer_ = false;
} else if (now - time_change_started_ > kSwitchTimeout) {
ELOG_WARN("Timeout when changing spatial layer");
sendPLI();
target_spatial_layer_ = future_spatial_layer_;
future_spatial_layer_ = -1;
Expand All @@ -122,6 +126,7 @@ void QualityFilterHandler::updatePictureID(const std::shared_ptr<DataPacket> &pa
RtpHeader *rtp_header = reinterpret_cast<RtpHeader*>(packet->data);
unsigned char* start_buffer = reinterpret_cast<unsigned char*> (packet->data);
start_buffer = start_buffer + rtp_header->getHeaderLength();
packet->picture_id = new_picture_id;
RtpVP8Parser::setVP8PictureID(start_buffer, packet->length - rtp_header->getHeaderLength(), new_picture_id);
}
}
Expand All @@ -131,6 +136,7 @@ void QualityFilterHandler::updateTL0PicIdx(const std::shared_ptr<DataPacket> &pa
RtpHeader *rtp_header = reinterpret_cast<RtpHeader*>(packet->data);
unsigned char* start_buffer = reinterpret_cast<unsigned char*> (packet->data);
start_buffer = start_buffer + rtp_header->getHeaderLength();
packet->tl0_pic_idx = new_tl0_pic_idx;
RtpVP8Parser::setVP8TL0PicIdx(start_buffer, packet->length - rtp_header->getHeaderLength(), new_tl0_pic_idx);
}
}
Expand Down Expand Up @@ -233,8 +239,10 @@ void QualityFilterHandler::write(Context *ctx, std::shared_ptr<DataPacket> packe
chead->setTimestamp(sr_timestamp + timestamp_offset_);
}
*/
ELOG_DEBUG(" packet, ssrc: %u, sn: %u, ts: %u, pid: %d, tl0pic: %d, keyframe: %d",
ssrc, sequence_number_info.output, last_timestamp_sent_, picture_id_info.output, tl0_pic_idx_sent,
packet->is_keyframe);
}

ctx->fireWrite(packet);
}

Expand Down
5 changes: 3 additions & 2 deletions erizo/src/erizo/rtp/QualityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,9 @@ void QualityManager::selectLayer(bool try_higher_layers) {
}

if (next_temporal_layer != temporal_layer_ || next_spatial_layer != spatial_layer_) {
ELOG_DEBUG("message: Layer Switch, current_layer: %d/%d, new_layer: %d/%d",
spatial_layer_, temporal_layer_, next_spatial_layer, next_temporal_layer);
ELOG_WARN("message: Layer Switch, current_layer: %d/%d, new_layer: %d/%d, max_layer: %d/%d",
spatial_layer_, temporal_layer_, next_spatial_layer, next_temporal_layer,
max_active_spatial_layer_, max_active_temporal_layer_);
setTemporalLayer(next_temporal_layer);
setSpatialLayer(next_spatial_layer);

Expand Down
5 changes: 4 additions & 1 deletion erizo/src/erizo/rtp/RtpExtensionProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ enum RTPExtensions {
TRANSPORT_CC, // https://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
PLAYBACK_TIME, // https:// www.webrtc.org/experiments/rtp-hdrext/playout-delay
RTP_ID, // urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
MID // urn:ietf:params:rtp-hdrext:sdes:mid
MID, // urn:ietf:params:rtp-hdrext:sdes:mid
VIDEO_CONTENT_TYPE, // https://www.webrtc.org/experiments/rtp-hdrext/video-content-type
VIDEO_TIMING, // https://www.webrtc.org/experiments/rtp-hdrext/video-timing
COLOR_SPACE // https://www.webrtc.org/experiments/rtp-hdrext/color-space
};

class RtpExtensionProcessor{
Expand Down
36 changes: 32 additions & 4 deletions erizo/src/erizo/rtp/RtpUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include <cmath>
#include <memory>

#include "RtpExtensionProcessor.h"
#include "rtp/RtpHeaders.h"

namespace erizo {


Expand Down Expand Up @@ -179,10 +182,23 @@ std::shared_ptr<DataPacket> RtpUtils::makePaddingPacket(std::shared_ptr<DataPack
return padding_packet;
}

std::shared_ptr<DataPacket> RtpUtils::makeVP8BlackKeyframePacket(std::shared_ptr<DataPacket> packet) {
uint8_t vp8_keyframe[] = {
(uint8_t) 0x90, (uint8_t) 0xe0, (uint8_t) 0x80, (uint8_t) 0x01, // payload header 1
(uint8_t) 0x00, (uint8_t) 0x20, (uint8_t) 0x10, (uint8_t) 0x0f, // payload header 2
uint8_t vp8_keyframe[] = {
// PAYLOAD DESCRIPTOR
// X=1, N=0, S=1, PID=0
(uint8_t) 0x90,
// X: I=1, L=1, T=1, K=0
(uint8_t) 0xe0,
// I: M=1, PictureID (1st part)=0
(uint8_t) 0x80,
// I: PictureID (2nd part)=1
(uint8_t) 0x01,
// L: TL0PICIDX=0
(uint8_t) 0x00,
// T: TID=1, Y=0, KEYIDX=0 (ignore)
(uint8_t) 0x20,
// PAYLOAD HEADER
// P=0 (keyframe)
(uint8_t) 0x10, (uint8_t) 0x0f,
(uint8_t) 0x00, (uint8_t) 0x9d, (uint8_t) 0x01, (uint8_t) 0x2a,
(uint8_t) 0x40, (uint8_t) 0x01, (uint8_t) 0xb4, (uint8_t) 0x00,
(uint8_t) 0x07, (uint8_t) 0x07, (uint8_t) 0x09, (uint8_t) 0x03,
Expand Down Expand Up @@ -218,6 +234,7 @@ std::shared_ptr<DataPacket> RtpUtils::makeVP8BlackKeyframePacket(std::shared_ptr
(uint8_t) 0xfe, (uint8_t) 0xef, (uint8_t) 0xb9, (uint8_t) 0x00
};

std::shared_ptr<DataPacket> RtpUtils::makeVP8BlackKeyframePacket(std::shared_ptr<DataPacket> packet) {
uint16_t keyframe_length = sizeof(vp8_keyframe)/sizeof(vp8_keyframe[0]);
erizo::RtpHeader *header = reinterpret_cast<RtpHeader*>(packet->data);
const uint16_t packet_length = header->getHeaderLength() + keyframe_length;
Expand All @@ -231,8 +248,19 @@ std::shared_ptr<DataPacket> RtpUtils::makeVP8BlackKeyframePacket(std::shared_ptr
std::shared_ptr<DataPacket> keyframe_packet =
std::make_shared<DataPacket>(packet->comp, packet_buffer, packet_length, packet->type);
keyframe_packet->is_keyframe = true;

keyframe_packet->picture_id = packet->picture_id;
keyframe_packet->tl0_pic_idx = packet->tl0_pic_idx;
keyframe_packet->rid = packet->rid;
keyframe_packet->mid = packet->mid;
keyframe_packet->priority = packet->priority;
keyframe_packet->received_time_ms = packet->received_time_ms;
keyframe_packet->compatible_spatial_layers = packet->compatible_spatial_layers;
keyframe_packet->compatible_temporal_layers = packet->compatible_spatial_layers;
keyframe_packet->ending_of_layer_frame = true;
keyframe_packet->codec = packet->codec;
keyframe_packet->clock_rate = packet->clock_rate;
keyframe_packet->is_padding = packet->is_padding;

return keyframe_packet;
}
Expand Down
Loading