diff --git a/srtcore/common.cpp b/srtcore/common.cpp index 27dbe89d1..5236df454 100644 --- a/srtcore/common.cpp +++ b/srtcore/common.cpp @@ -438,7 +438,8 @@ std::string TransmissionEventStr(ETransmissionEvent ev) "checktimer", "send", "receive", - "custom" + "custom", + "sync" }; size_t vals_size = Size(vals); diff --git a/srtcore/common.h b/srtcore/common.h index 60a884f5c..13fee4a84 100644 --- a/srtcore/common.h +++ b/srtcore/common.h @@ -290,6 +290,7 @@ enum ETransmissionEvent TEV_SEND, // --> When the packet is scheduled for sending - older CCC::onPktSent TEV_RECEIVE, // --> When a data packet was received - older CCC::onPktReceived TEV_CUSTOM, // --> probably dead call - older CCC::processCustomMsg + TEV_SYNC, // --> Backup group. When rate estimation is derived from an active member, and update is needed. TEV_E_SIZE }; diff --git a/srtcore/core.cpp b/srtcore/core.cpp index 7ec8cb767..135744d8a 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -7551,7 +7551,7 @@ bool srt::CUDT::updateCC(ETransmissionEvent evt, const EventVariant arg) // This part is also required only by LiveCC, however not // moved there due to that it needs access to CSndBuffer. - if (evt == TEV_ACK || evt == TEV_LOSSREPORT || evt == TEV_CHECKTIMER) + if (evt == TEV_ACK || evt == TEV_LOSSREPORT || evt == TEV_CHECKTIMER || evt == TEV_SYNC) { // Specific part done when MaxBW is set to 0 (auto) and InputBW is 0. // This requests internal input rate sampling. diff --git a/srtcore/core.h b/srtcore/core.h index 7c2532560..8fc1b8f62 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -728,6 +728,22 @@ class CUDT static loss_seqs_t defaultPacketArrival(void* vself, CPacket& pkt); static loss_seqs_t groupPacketArrival(void* vself, CPacket& pkt); + CRateEstimator getRateEstimator() const + { + if (!m_pSndBuffer) + return CRateEstimator(); + return m_pSndBuffer->getRateEstimator(); + } + + void setRateEstimator(const CRateEstimator& rate) + { + if (!m_pSndBuffer) + return; + + m_pSndBuffer->setRateEstimator(rate); + updateCC(TEV_SYNC, EventVariant(0)); + } + private: // Identification CUDTSocket* const m_parent; // Temporary, until the CUDTSocket class is merged with CUDT diff --git a/srtcore/group.cpp b/srtcore/group.cpp index aa562da5c..db50b3ec2 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -3525,8 +3525,8 @@ size_t CUDTGroup::sendBackup_TryActivateStandbyIfNeeded( return 0; } - const unsigned num_stable = w_sendBackupCtx.countMembersByState(BKUPST_ACTIVE_FRESH); - const unsigned num_fresh = w_sendBackupCtx.countMembersByState(BKUPST_ACTIVE_STABLE); + const unsigned num_stable = w_sendBackupCtx.countMembersByState(BKUPST_ACTIVE_STABLE); + const unsigned num_fresh = w_sendBackupCtx.countMembersByState(BKUPST_ACTIVE_FRESH); if (num_stable + num_fresh == 0) { @@ -3571,6 +3571,10 @@ size_t CUDTGroup::sendBackup_TryActivateStandbyIfNeeded( try { + CUDT& cudt = d->ps->core(); + // Take source rate estimation from an active member (needed for the input rate estimation mode). + cudt.setRateEstimator(w_sendBackupCtx.getRateEstimate()); + // TODO: At this point all packets that could be sent // are located in m_SenderBuffer. So maybe just use sendBackupRexmit()? if (w_curseq == SRT_SEQNO_NONE) @@ -3582,7 +3586,7 @@ size_t CUDTGroup::sendBackup_TryActivateStandbyIfNeeded( HLOGC(gslog.Debug, log << "grp/sendBackup: ... trying @" << d->id << " - sending the VERY FIRST message"); - stat = d->ps->core().sendmsg2(buf, len, (w_mc)); + stat = cudt.sendmsg2(buf, len, (w_mc)); if (stat != -1) { // This will be no longer used, but let it stay here. @@ -3599,7 +3603,7 @@ size_t CUDTGroup::sendBackup_TryActivateStandbyIfNeeded( << " collected messages..."); // Note: this will set the currently required packet // because it has been just freshly added to the sender buffer - stat = sendBackupRexmit(d->ps->core(), (w_mc)); + stat = sendBackupRexmit(cudt, (w_mc)); } ++num_activated; } @@ -4384,6 +4388,9 @@ int CUDTGroup::sendBackup_SendOverActive(const char* buf, int len, SRT_MSGCTRL& { ++w_nsuccessful; w_maxActiveWeight = max(w_maxActiveWeight, d->weight); + + if (u.m_pSndBuffer) + w_sendBackupCtx.setRateEstimate(u.m_pSndBuffer->getRateEstimator()); } else if (erc == SRT_EASYNCSND) { diff --git a/srtcore/group_backup.h b/srtcore/group_backup.h index 760ccfbe4..790cf55ed 100644 --- a/srtcore/group_backup.h +++ b/srtcore/group_backup.h @@ -110,11 +110,16 @@ namespace groups std::string printMembers() const; + void setRateEstimate(const CRateEstimator& rate) { m_rateEstimate = rate; } + + const CRateEstimator& getRateEstimate() const { return m_rateEstimate; } + private: std::vector m_memberStates; // TODO: consider std::map here? unsigned m_stateCounter[BKUPST_E_SIZE]; uint16_t m_activeMaxWeight; uint16_t m_standbyMaxWeight; + CRateEstimator m_rateEstimate; // The rate estimator state of the active link to copy to a backup on activation. }; } // namespace groups