void SenderBandwidthEstimationHandler::write(Context *ctx, std::shared_ptr<dataPacket> packet) { RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data); if (!chead->isRtcp() && packet->type == VIDEO_PACKET) { period_packets_sent_++; } else if (chead->getPacketType() == RTCP_Sender_PT && chead->getSSRC() == connection_->getVideoSinkSSRC()) { analyzeSr(chead); } ctx->fireWrite(packet); }
void RtcpFeedbackGenerationHandler::read(Context *ctx, std::shared_ptr<DataPacket> packet) { // Pass packets to RR and NACK Generator RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data); if (!initialized_) { ctx->fireRead(std::move(packet)); return; } if (chead->getPacketType() == RTCP_Sender_PT) { uint32_t ssrc = chead->getSSRC(); auto generator_it = generators_map_.find(ssrc); if (generator_it != generators_map_.end()) { generator_it->second->rr_generator->handleSr(packet); } else { ELOG_DEBUG("message: no RrGenerator found, ssrc: %u", ssrc); } ctx->fireRead(std::move(packet)); return; } bool should_send_rr = false; bool should_send_nack = false; if (!chead->isRtcp()) { RtpHeader *head = reinterpret_cast<RtpHeader*>(packet->data); uint32_t ssrc = head->getSSRC(); auto generator_it = generators_map_.find(ssrc); if (generator_it != generators_map_.end()) { should_send_rr = generator_it->second->rr_generator->handleRtpPacket(packet); if (nacks_enabled_) { should_send_nack = generator_it->second->nack_generator->handleRtpPacket(packet); } } else { ELOG_DEBUG("message: no Generator found, ssrc: %u", ssrc); } if (should_send_rr || should_send_nack) { ELOG_DEBUG("message: Should send Rtcp, ssrc %u", ssrc); std::shared_ptr<DataPacket> rtcp_packet = generator_it->second->rr_generator->generateReceiverReport(); if (nacks_enabled_ && generator_it->second->nack_generator != nullptr) { generator_it->second->nack_generator->addNackPacketToRr(rtcp_packet); } ctx->fireWrite(std::move(rtcp_packet)); } } ctx->fireRead(std::move(packet)); }
void SenderBandwidthEstimationHandler::read(Context *ctx, std::shared_ptr<dataPacket> packet) { RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data); if (chead->isFeedback() && chead->getSourceSSRC() == connection_->getVideoSinkSSRC()) { char* packet_pointer = packet->data; int rtcp_length = 0; int total_length = 0; int current_block = 0; do { packet_pointer+=rtcp_length; chead = reinterpret_cast<RtcpHeader*>(packet_pointer); rtcp_length = (ntohs(chead->length) + 1) * 4; total_length += rtcp_length; ELOG_DEBUG("%s ssrc %u, sourceSSRC %u, PacketType %u", connection_->toLog(), chead->getSSRC(), chead->getSourceSSRC(), chead->getPacketType()); switch (chead->packettype) { case RTCP_Receiver_PT: { ELOG_DEBUG("%s, Analyzing Video RR: PacketLost %u, Ratio %u, current_block %d, blocks %d" ", sourceSSRC %u, ssrc %u", connection_->toLog(), chead->getLostPackets(), chead->getFractionLost(), current_block, chead->getBlockCount(), chead->getSourceSSRC(), chead->getSSRC()); // calculate RTT + Update receiver block uint32_t delay_since_last_ms = (chead->getDelaySinceLastSr() * 1000) / 65536; int64_t now_ms = ClockUtils::timePointToMs(clock::now()); uint32_t last_sr = chead->getLastSr(); auto value = std::find_if(sr_delay_data_.begin(), sr_delay_data_.end(), [last_sr](const std::shared_ptr<SrDelayData> sr_info) { return sr_info->sr_ntp == last_sr; }); if (value != sr_delay_data_.end()) { uint32_t delay = now_ms - (*value)->sr_send_time - delay_since_last_ms; sender_bwe_->UpdateReceiverBlock(chead->getFractionLost(), delay, period_packets_sent_, now_ms); period_packets_sent_ = 0; updateEstimate(); } } break; case RTCP_PS_Feedback_PT: { if (chead->getBlockCount() == RTCP_AFB) { char *uniqueId = reinterpret_cast<char*>(&chead->report.rembPacket.uniqueid); if (!strncmp(uniqueId, "REMB", 4)) { int64_t now_ms = ClockUtils::timePointToMs(clock::now()); uint64_t bitrate = chead->getBrMantis() << chead->getBrExp(); ELOG_DEBUG("%s message: Updating Estimate with REMB, bitrate %llu", connection_->toLog(), bitrate); sender_bwe_->UpdateReceiverEstimate(now_ms, bitrate); sender_bwe_->UpdateEstimate(now_ms); updateEstimate(); } else { ELOG_DEBUG("%s message: Unsupported AFB Packet not REMB", connection_->toLog()); } } } break; default: break; } current_block++; } while (total_length < packet->length); } ctx->fireRead(packet); }