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

FakeKeyframeGeneratorHandler only acts if transport is ready #1335

Merged
merged 3 commits into from
Nov 15, 2018
Merged
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
2 changes: 1 addition & 1 deletion erizo/src/erizo/WebRtcConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ void WebRtcConnection::updateState(TransportState state, Transport * transport)

global_state_ = temp;

ELOG_INFO("%s newGlobalState: %d", toLog(), global_state_);
ELOG_INFO("%s newGlobalState: %d", toLog(), temp);
maybeNotifyWebRtcConnectionEvent(global_state_, msg);
}

Expand Down
4 changes: 3 additions & 1 deletion erizo/src/erizo/WebRtcConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ class WebRtcConnection: public TransportListener, public LogContext,
void maybeNotifyWebRtcConnectionEvent(const WebRTCEvent& event, const std::string& message,
const std::string& stream_id = "");

protected:
std::atomic<WebRTCEvent> global_state_;

private:
std::string connection_id_;
bool audio_enabled_;
Expand All @@ -180,7 +183,6 @@ class WebRtcConnection: public TransportListener, public LogContext,
std::shared_ptr<Transport> video_transport_, audio_transport_;

std::shared_ptr<Stats> stats_;
WebRTCEvent global_state_;

boost::mutex update_state_mutex_;
boost::mutex event_listener_mutex_;
Expand Down
67 changes: 40 additions & 27 deletions erizo/src/erizo/rtp/FakeKeyframeGeneratorHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ constexpr uint64_t kPliPeriodMs = 300;
FakeKeyframeGeneratorHandler::FakeKeyframeGeneratorHandler() :
stream_{nullptr}, enabled_{true}, first_keyframe_received_{false}, plis_scheduled_{false},
video_source_ssrc_{0}, video_sink_ssrc_{0} {
}
}

void FakeKeyframeGeneratorHandler::enable() {
enabled_ = true;
Expand All @@ -43,15 +43,15 @@ void FakeKeyframeGeneratorHandler::read(Context *ctx, std::shared_ptr<DataPacket

void FakeKeyframeGeneratorHandler::write(Context *ctx, std::shared_ptr<DataPacket> packet) {
RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data);
if (enabled_) {
if (!first_keyframe_received_ && packet->type == VIDEO_PACKET && !chead->isRtcp()) {
if (!enabled_) {
ctx->fireWrite(std::move(packet));
return;
}

if (!first_keyframe_received_ && packet->type == VIDEO_PACKET && !chead->isRtcp()) {
if (stream_->getCurrentState() == CONN_READY) { // TODO(pedro): Find a solution for this in all handlers
if (!packet->is_keyframe) {
if (!plis_scheduled_) {
plis_scheduled_ = true;
ELOG_DEBUG("Scheduling PLIs");
sendPLI();
schedulePLI();
}
maybeSendAndSchedulePLIs();
ELOG_DEBUG("Building a black keyframe from packet");
auto keyframe_packet = transformIntoKeyframePacket(packet);
ctx->fireWrite(keyframe_packet);
Expand All @@ -60,38 +60,51 @@ void FakeKeyframeGeneratorHandler::write(Context *ctx, std::shared_ptr<DataPacke
ELOG_DEBUG("First part of a keyframe received, stop rewriting packets");
first_keyframe_received_ = true;
}
} else {
ELOG_DEBUG("Transport is not ready - not transforming packet");
}
}
ctx->fireWrite(std::move(packet));
}

std::shared_ptr<DataPacket> FakeKeyframeGeneratorHandler::transformIntoKeyframePacket
(std::shared_ptr<DataPacket> packet) {
if (packet->codec == "VP8") {
auto keyframe_packet = RtpUtils::makeVP8BlackKeyframePacket(packet);
return keyframe_packet;
} else {
ELOG_DEBUG("Generate keyframe packet is not available for codec %s", packet->codec);
return packet;
(std::shared_ptr<DataPacket> packet) {
if (packet->codec == "VP8") {
auto keyframe_packet = RtpUtils::makeVP8BlackKeyframePacket(packet);
return keyframe_packet;
} else {
ELOG_DEBUG("Generate keyframe packet is not available for codec %s", packet->codec);
return packet;
}
}

void FakeKeyframeGeneratorHandler::maybeSendAndSchedulePLIs() {
if (!plis_scheduled_) {
plis_scheduled_ = true;
ELOG_DEBUG("Scheduling PLIs");
sendPLI();
schedulePLI();
}
}

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

void FakeKeyframeGeneratorHandler::schedulePLI() {
std::weak_ptr<FakeKeyframeGeneratorHandler> weak_this = shared_from_this();
stream_->getWorker()->scheduleEvery([weak_this] {
if (auto this_ptr = weak_this.lock()) {
if (!this_ptr->first_keyframe_received_) {
ELOG_DEBUG("Sending PLI in FakeGenerator, scheduling another");
this_ptr->sendPLI();
return true;
} else {
ELOG_DEBUG("Stop sending scheduled PLI packets");
return false;
}
if (auto this_ptr = weak_this.lock()) {
if (!this_ptr->first_keyframe_received_) {
ELOG_DEBUG("Sending PLI in FakeGenerator, scheduling another");
this_ptr->sendPLI();
return true;
} else {
ELOG_DEBUG("Stop sending scheduled PLI packets");
return false;
}
return false;
}, std::chrono::milliseconds(kPliPeriodMs));
}
return false;
}, std::chrono::milliseconds(kPliPeriodMs));
}
} // namespace erizo
1 change: 1 addition & 0 deletions erizo/src/erizo/rtp/FakeKeyframeGeneratorHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class FakeKeyframeGeneratorHandler: public Handler, public std::enable_shared_fr

private:
std::shared_ptr<DataPacket> transformIntoKeyframePacket(std::shared_ptr<DataPacket> packet);
void maybeSendAndSchedulePLIs();
void sendPLI();
void schedulePLI();

Expand Down
1 change: 1 addition & 0 deletions erizo/src/test/log4cxx.properties
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ log4j.logger.rtp.RtpPacketQueue=ERROR
log4j.logger.rtp.RtpRetransmissionHandler=ERROR
log4j.logger.rtp.RtpVP8Fragmenter=ERROR
log4j.logger.rtp.RtpVP8Parser=ERROR
log4j.logger.rtp.FakeKeyframeGeneratorHandler=ERROR
log4j.logger.rtp.RtpSlideShowHandler=ERROR
log4j.logger.rtp.RtpTrackMuteHandler=ERROR
log4j.logger.rtp.RtpSink=ERROR
Expand Down
4 changes: 3 additions & 1 deletion erizo/src/test/utils/Mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ class MockWebRtcConnection: public WebRtcConnection {
public:
MockWebRtcConnection(std::shared_ptr<Worker> worker, std::shared_ptr<IOWorker> io_worker, const IceConfig &ice_config,
const std::vector<RtpMap> rtp_mappings) :
WebRtcConnection(worker, io_worker, "", ice_config, rtp_mappings, std::vector<erizo::ExtMap>(), nullptr) {}
WebRtcConnection(worker, io_worker, "", ice_config, rtp_mappings, std::vector<erizo::ExtMap>(), nullptr) {
global_state_ = CONN_READY;
}

virtual ~MockWebRtcConnection() {
}
Expand Down