bool RtcpRrGenerator::isRetransmitOfOldPacket(std::shared_ptr<dataPacket> packet) { RtpHeader *head = reinterpret_cast<RtpHeader*>(packet->data); if (!RtpUtils::sequenceNumberLessThan(head->getSeqNumber(), rr_info_.max_seq) || rr_info_.jitter.jitter == 0) { return false; } int64_t time_diff_ms = static_cast<uint32_t>(packet->received_time_ms) - rr_info_.last_recv_ts; int64_t timestamp_diff = static_cast<int32_t>(head->getTimestamp() - rr_info_.last_rtp_ts); uint16_t clock_rate = type_ == VIDEO_PACKET ? getVideoClockRate(head->getPayloadType()) : getAudioClockRate(head->getPayloadType()); int64_t rtp_time_stamp_diff_ms = timestamp_diff / clock_rate; int64_t max_delay_ms = ((2 * rr_info_.jitter.jitter) / clock_rate); return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms; }
void RRGenerationHandler::handleRtpPacket(std::shared_ptr<dataPacket> packet) { RtpHeader *head = reinterpret_cast<RtpHeader*>(packet->data); auto rr_packet_pair = rr_info_map_.find(head->getSSRC()); if (rr_packet_pair == rr_info_map_.end()) { ELOG_DEBUG("%s message: handleRtpPacket ssrc not found, ssrc: %u", connection_->toLog(), head->getSSRC()); return; } std::shared_ptr<RRPackets> selected_packet_info = rr_packet_pair->second; uint16_t seq_num = head->getSeqNumber(); selected_packet_info->packets_received++; if (selected_packet_info->base_seq == -1) { selected_packet_info->ssrc = head->getSSRC(); selected_packet_info->base_seq = head->getSeqNumber(); } if (selected_packet_info->max_seq == -1) { selected_packet_info->max_seq = seq_num; } else if (!rtpSequenceLessThan(seq_num, selected_packet_info->max_seq)) { if (seq_num < selected_packet_info->max_seq) { selected_packet_info->cycle++; } selected_packet_info->max_seq = seq_num; } selected_packet_info->extended_seq = (selected_packet_info->cycle << 16) | selected_packet_info->max_seq; uint16_t clock_rate = selected_packet_info->type == VIDEO_PACKET ? getVideoClockRate(head->getPayloadType()) : getAudioClockRate(head->getPayloadType()); if (head->getTimestamp() != selected_packet_info->last_rtp_ts && !isRetransmitOfOldPacket(packet, selected_packet_info)) { int transit_time = static_cast<int>((packet->received_time_ms * clock_rate) - head->getTimestamp()); int delta = abs(transit_time - selected_packet_info->jitter.transit_time); if (selected_packet_info->jitter.transit_time != 0 && delta < MAX_DELAY) { selected_packet_info->jitter.jitter += (1. / 16.) * (static_cast<double>(delta) - selected_packet_info->jitter.jitter); } selected_packet_info->jitter.transit_time = transit_time; } selected_packet_info->last_rtp_ts = head->getTimestamp(); selected_packet_info->last_recv_ts = static_cast<uint32_t>(packet->received_time_ms); uint64_t now = ClockUtils::timePointToMs(clock::now()); if (selected_packet_info->next_packet_ms == 0) { // Schedule the first packet uint16_t selected_interval = selectInterval(selected_packet_info); selected_packet_info->next_packet_ms = now + selected_interval; return; } if (now >= selected_packet_info->next_packet_ms) { sendRR(selected_packet_info); } }
bool RtcpRrGenerator::handleRtpPacket(std::shared_ptr<dataPacket> packet) { RtpHeader *head = reinterpret_cast<RtpHeader*>(packet->data); if (ssrc_ != head->getSSRC()) { ELOG_DEBUG("message: handleRtpPacket ssrc not found, ssrc: %u", head->getSSRC()); return false; } uint16_t seq_num = head->getSeqNumber(); rr_info_.packets_received++; if (rr_info_.base_seq == -1) { rr_info_.base_seq = head->getSeqNumber(); } if (rr_info_.max_seq == -1) { rr_info_.max_seq = seq_num; } else if (!RtpUtils::sequenceNumberLessThan(seq_num, rr_info_.max_seq)) { if (seq_num < rr_info_.max_seq) { rr_info_.cycle++; } rr_info_.max_seq = seq_num; } rr_info_.extended_seq = (rr_info_.cycle << 16) | rr_info_.max_seq; uint16_t clock_rate = type_ == VIDEO_PACKET ? getVideoClockRate(head->getPayloadType()) : getAudioClockRate(head->getPayloadType()); if (head->getTimestamp() != rr_info_.last_rtp_ts && !isRetransmitOfOldPacket(packet)) { int transit_time = static_cast<int>((packet->received_time_ms * clock_rate) - head->getTimestamp()); int delta = abs(transit_time - rr_info_.jitter.transit_time); if (rr_info_.jitter.transit_time != 0 && delta < MAX_DELAY) { rr_info_.jitter.jitter += (1. / 16.) * (static_cast<double>(delta) - rr_info_.jitter.jitter); } rr_info_.jitter.transit_time = transit_time; } rr_info_.last_rtp_ts = head->getTimestamp(); rr_info_.last_recv_ts = static_cast<uint32_t>(packet->received_time_ms); uint64_t now = ClockUtils::timePointToMs(clock_->now()); if (rr_info_.next_packet_ms == 0) { // Schedule the first packet uint16_t selected_interval = selectInterval(); rr_info_.next_packet_ms = now + selected_interval; return false; } if (now >= rr_info_.next_packet_ms) { ELOG_DEBUG("message: should send packet, ssrc: %u", ssrc_); return true; } return false; }