rtcp: Combine generation of sender and receiver reports
This reduces the amount of duplicate code in rtcp.
This commit is contained in:
		
							parent
							
								
									4abd24bd02
								
							
						
					
					
						commit
						55dad012a1
					
				|  | @ -341,13 +341,6 @@ namespace uvgrtp { | |||
|              * should be increased before calculating the new average */ | ||||
|             void update_rtcp_bandwidth(size_t pkt_size); | ||||
| 
 | ||||
|             /* Functions for generating different kinds of reports.
 | ||||
|              * These functions will both generate the report and send it | ||||
|              * | ||||
|              * Return RTP_OK on success and RTP_ERROR on error */ | ||||
|             rtp_error_t generate_sender_report(); | ||||
|             rtp_error_t generate_receiver_report(); | ||||
| 
 | ||||
|             /* Because struct statistics contains uvgRTP clock object we cannot
 | ||||
|              * zero it out without compiler complaining about it so all the fields | ||||
|              * must be set to zero manually */ | ||||
|  |  | |||
							
								
								
									
										183
									
								
								src/rtcp.cc
								
								
								
								
							
							
						
						
									
										183
									
								
								src/rtcp.cc
								
								
								
								
							|  | @ -523,8 +523,6 @@ void uvgrtp::rtcp::update_session_statistics(uvgrtp::frame::rtp_frame *frame) | |||
|     int dropped = expected - p->stats.received_pkts; | ||||
|     p->stats.dropped_pkts = dropped >= 0 ? dropped : 0; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     uint64_t arrival = | ||||
|         p->stats.initial_rtp + | ||||
|         + uvgrtp::clock::ntp::diff_now(p->stats.initial_ntp) | ||||
|  | @ -653,7 +651,6 @@ rtp_error_t uvgrtp::rtcp::handle_incoming_packet(uint8_t *buffer, size_t size) | |||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| rtp_error_t uvgrtp::rtcp::handle_sdes_packet(uint8_t* packet, size_t size) | ||||
| { | ||||
|     if (!packet || !size) | ||||
|  | @ -919,9 +916,75 @@ rtp_error_t uvgrtp::rtcp::generate_report() | |||
| { | ||||
|     rtcp_pkt_sent_count_++; | ||||
| 
 | ||||
|     if (our_role_ == RECEIVER) | ||||
|         return generate_receiver_report(); | ||||
|     return generate_sender_report(); | ||||
|     LOG_DEBUG("Generating RTCP Sender Report"); | ||||
| 
 | ||||
|     if (!senders_) { | ||||
|         LOG_DEBUG("Session does not have any RTP senders!"); | ||||
|         return RTP_NOT_READY; | ||||
|     } | ||||
| 
 | ||||
|     rtp_error_t ret = RTP_OK; | ||||
|     uint8_t* frame = nullptr; | ||||
|     int ptr = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE; | ||||
| 
 | ||||
|     size_t frame_size = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE + (size_t)num_receivers_ * REPORT_BLOCK_SIZE; | ||||
| 
 | ||||
|     if (flags_ & RCE_SRTP) | ||||
|         frame_size += UVG_SRTCP_INDEX_LENGTH + UVG_AUTH_TAG_LENGTH; | ||||
| 
 | ||||
|     if (our_role_ == SENDER) | ||||
|     { | ||||
|         // sender reports have sender information in addition compared to receiver reports
 | ||||
|         frame_size += SENDER_INFO_SIZE; | ||||
|         construct_rtcp_header(frame_size, frame, num_receivers_, uvgrtp::frame::RTCP_FT_SR, true); | ||||
|     } | ||||
|     else // RECEIVER
 | ||||
|     { | ||||
|         construct_rtcp_header(frame_size, frame, num_receivers_, uvgrtp::frame::RTCP_FT_RR, true); | ||||
|     } | ||||
| 
 | ||||
|     if (our_role_ == SENDER) | ||||
|     { | ||||
|         /* Sender infoormation */ | ||||
|         uint64_t ntp_ts = uvgrtp::clock::ntp::now(); | ||||
|         uint64_t rtp_ts = rtp_ts_start_ + (uvgrtp::clock::ntp::diff(ntp_ts, clock_start_)) * clock_rate_ / 1000; | ||||
| 
 | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts >> 32)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts & 0xffffffff)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl((u_long)rtp_ts)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_pkts)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_bytes)); | ||||
|     } | ||||
| 
 | ||||
|     // the report blocks for sender or receiver report. Both have same reports.
 | ||||
| 
 | ||||
|     LOG_DEBUG("Report from 0x%x has %zu blocks", ssrc_, num_receivers_); | ||||
| 
 | ||||
|     for (auto& p : participants_) { | ||||
|         int dropped = p.second->stats.dropped_pkts; | ||||
|         uint8_t frac = dropped ? p.second->stats.received_bytes / dropped : 0; | ||||
| 
 | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.first)); /* ssrc */ | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl((frac << 24) | p.second->stats.dropped_pkts)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.max_seq)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.jitter)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.lsr)); | ||||
| 
 | ||||
|         /* calculate delay of last SR only if SR has been received at least once */ | ||||
|         if (p.second->stats.lsr) { | ||||
|             uint64_t diff = (u_long)uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts); | ||||
|             SET_NEXT_FIELD_32(frame, ptr, (uint32_t)htonl((u_long)uvgrtp::clock::ms_to_jiffies(diff))); | ||||
|         } | ||||
|         ptr += p.second->stats.lsr ? 0 : 4; | ||||
|     } | ||||
| 
 | ||||
|     if (srtcp_ && (ret = srtcp_->handle_rtcp_encryption(flags_, rtcp_pkt_sent_count_, ssrc_, frame, frame_size)) != RTP_OK) | ||||
|     { | ||||
|         delete[] frame; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     return send_rtcp_packet_to_participants(frame, frame_size); | ||||
| } | ||||
| 
 | ||||
| rtp_error_t uvgrtp::rtcp::send_sdes_packet(std::vector<uvgrtp::frame::rtcp_sdes_item>& items) | ||||
|  | @ -1008,111 +1071,3 @@ rtp_error_t uvgrtp::rtcp::send_app_packet(char* name, uint8_t subtype, | |||
|     return send_rtcp_packet_to_participants(frame, frame_size); | ||||
| } | ||||
| 
 | ||||
| rtp_error_t uvgrtp::rtcp::generate_receiver_report() | ||||
| { | ||||
|     if (!senders_) { | ||||
|         LOG_WARN("Session doesn't have any participants!"); | ||||
|         return RTP_NOT_READY; | ||||
|     } | ||||
| 
 | ||||
|     rtp_error_t ret = RTP_OK; | ||||
|     uint8_t* frame = nullptr; | ||||
| 
 | ||||
|     size_t frame_size = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE + (size_t)num_receivers_ * REPORT_BLOCK_SIZE; | ||||
|     int report_ptr = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE; | ||||
| 
 | ||||
|     if (flags_ & RCE_SRTP) | ||||
|         frame_size += UVG_SRTCP_INDEX_LENGTH + UVG_AUTH_TAG_LENGTH; | ||||
| 
 | ||||
|     construct_rtcp_header(frame_size, frame, num_receivers_, uvgrtp::frame::RTCP_FT_RR, true); | ||||
| 
 | ||||
|     LOG_DEBUG("Receiver Report from 0x%x has %zu blocks", ssrc_, num_receivers_); | ||||
| 
 | ||||
|     for (auto& p : participants_) { | ||||
|         int dropped = p.second->stats.dropped_pkts; | ||||
| 
 | ||||
|         // TODO: Shouldn't this be number of packets received no bytes?
 | ||||
|         uint8_t frac = dropped ? p.second->stats.received_bytes / dropped : 0; | ||||
| 
 | ||||
|         SET_NEXT_FIELD_32(frame, report_ptr, htonl(p.first)); /* ssrc */ | ||||
|         SET_NEXT_FIELD_32(frame, report_ptr, htonl((frac << 24) | p.second->stats.dropped_pkts)); | ||||
|         SET_NEXT_FIELD_32(frame, report_ptr, htonl(p.second->stats.max_seq)); | ||||
|         SET_NEXT_FIELD_32(frame, report_ptr, htonl(p.second->stats.jitter)); | ||||
|         SET_NEXT_FIELD_32(frame, report_ptr, htonl(p.second->stats.lsr)); | ||||
| 
 | ||||
|         /* calculate delay of last SR only if SR has been received at least once */ | ||||
|         if (p.second->stats.lsr) { | ||||
|             uint64_t diff = uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts); | ||||
|             SET_NEXT_FIELD_32(frame, report_ptr, (uint32_t)htonl((u_long)uvgrtp::clock::ms_to_jiffies(diff))); | ||||
|         } | ||||
|         report_ptr += p.second->stats.lsr ? 0 : 4; | ||||
|     } | ||||
| 
 | ||||
|     if (srtcp_ && (ret = srtcp_->handle_rtcp_encryption(flags_, rtcp_pkt_sent_count_, ssrc_, frame, frame_size)) != RTP_OK) | ||||
|     { | ||||
|         delete[] frame; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     return send_rtcp_packet_to_participants(frame, frame_size); | ||||
| } | ||||
| 
 | ||||
| rtp_error_t uvgrtp::rtcp::generate_sender_report() | ||||
| { | ||||
|     LOG_DEBUG("Generating RTCP Sender Report"); | ||||
| 
 | ||||
|     if (!senders_) { | ||||
|         LOG_DEBUG("Session does not have any RTP senders!"); | ||||
|         return RTP_NOT_READY; | ||||
|     } | ||||
|      | ||||
|     rtp_error_t ret = RTP_OK; | ||||
|     uint8_t* frame = nullptr; | ||||
|     int ptr = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE; | ||||
| 
 | ||||
|     size_t frame_size = RTCP_HEADER_SIZE + SSRC_CSRC_SIZE + SENDER_INFO_SIZE; | ||||
|     frame_size += num_receivers_ * REPORT_BLOCK_SIZE; /* report blocks */ | ||||
| 
 | ||||
|     if (flags_ & RCE_SRTP) | ||||
|         frame_size += UVG_SRTCP_INDEX_LENGTH + UVG_AUTH_TAG_LENGTH; | ||||
| 
 | ||||
|     construct_rtcp_header(frame_size, frame, num_receivers_, uvgrtp::frame::RTCP_FT_SR, true); | ||||
| 
 | ||||
|     /* Sender information */ | ||||
|     uint64_t ntp_ts = uvgrtp::clock::ntp::now(); | ||||
|     uint64_t rtp_ts = rtp_ts_start_ + (uvgrtp::clock::ntp::diff(ntp_ts, clock_start_)) * clock_rate_ / 1000; | ||||
| 
 | ||||
|     SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts >> 32)); | ||||
|     SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts & 0xffffffff)); | ||||
|     SET_NEXT_FIELD_32(frame, ptr, htonl((u_long)rtp_ts)); | ||||
|     SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_pkts)); | ||||
|     SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_bytes)); | ||||
| 
 | ||||
|     LOG_DEBUG("Sender Report from 0x%x has %zu blocks", ssrc_, num_receivers_); | ||||
| 
 | ||||
|     for (auto& p : participants_) { | ||||
|         int dropped = p.second->stats.dropped_pkts; | ||||
|         uint8_t frac = dropped ? p.second->stats.received_bytes / dropped : 0; | ||||
| 
 | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.first)); /* ssrc */ | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl((frac << 24) | p.second->stats.dropped_pkts)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.max_seq)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.jitter)); | ||||
|         SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.lsr)); | ||||
| 
 | ||||
|         /* calculate delay of last SR only if SR has been received at least once */ | ||||
|         if (p.second->stats.lsr) { | ||||
|             uint64_t diff = (u_long)uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts); | ||||
|             SET_NEXT_FIELD_32(frame, ptr, (uint32_t)htonl((u_long)uvgrtp::clock::ms_to_jiffies(diff))); | ||||
|         } | ||||
|         ptr += p.second->stats.lsr ? 0 : 4; | ||||
|     } | ||||
| 
 | ||||
|     if (srtcp_ && (ret = srtcp_->handle_rtcp_encryption(flags_, rtcp_pkt_sent_count_, ssrc_, frame, frame_size)) != RTP_OK) | ||||
|     { | ||||
|         delete[] frame; | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     return send_rtcp_packet_to_participants(frame, frame_size); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue