Fix RTCP Receiver Report reception code
Craft user-friendly rtcp_receiver_report struct from the raw message which can be fetched using SSRC
This commit is contained in:
		
							parent
							
								
									ea8f1d2039
								
							
						
					
					
						commit
						fc117e6eba
					
				|  | @ -9,6 +9,7 @@ | |||
| #endif | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "util.hh" | ||||
| 
 | ||||
|  | @ -115,6 +116,12 @@ namespace uvg_rtp { | |||
|             struct rtcp_report_block blocks[1]; | ||||
|         }; | ||||
| 
 | ||||
|         struct rtcp_receiver_report { | ||||
|             struct rtcp_header header; | ||||
|             uint32_t ssrc; | ||||
|             std::vector<rtcp_report_block> report_blocks; | ||||
|         }; | ||||
| 
 | ||||
|         PACKED_STRUCT(rtcp_receiver_frame) { | ||||
|             struct rtcp_header header; | ||||
|             uint32_t sender_ssrc; | ||||
|  |  | |||
|  | @ -64,10 +64,10 @@ namespace uvg_rtp { | |||
| 
 | ||||
|         /* Save the latest RTCP packets received from this participant
 | ||||
|          * Users can query these packets using the SSRC of participant */ | ||||
|         uvg_rtp::frame::rtcp_sender_frame   *s_frame; | ||||
|         uvg_rtp::frame::rtcp_receiver_frame *r_frame; | ||||
|         uvg_rtp::frame::rtcp_sdes_frame     *sdes_frame; | ||||
|         uvg_rtp::frame::rtcp_app_frame      *app_frame; | ||||
|         uvg_rtp::frame::rtcp_sender_frame    *s_frame; | ||||
|         uvg_rtp::frame::rtcp_receiver_report *r_frame; | ||||
|         uvg_rtp::frame::rtcp_sdes_frame      *sdes_frame; | ||||
|         uvg_rtp::frame::rtcp_app_frame       *app_frame; | ||||
|     }; | ||||
| 
 | ||||
|     class rtcp : public runner { | ||||
|  | @ -127,10 +127,10 @@ namespace uvg_rtp { | |||
|              * Return nullptr if we haven't received this kind of packet or if "ssrc" doesn't exist | ||||
|              * | ||||
|              * NOTE: Caller is responsible for deallocating the memory */ | ||||
|             uvg_rtp::frame::rtcp_sender_frame   *get_sender_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_receiver_frame *get_receiver_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_sdes_frame     *get_sdes_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_app_frame      *get_app_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_sender_frame    *get_sender_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_receiver_report *get_receiver_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_sdes_frame      *get_sdes_packet(uint32_t ssrc); | ||||
|             uvg_rtp::frame::rtcp_app_frame       *get_app_packet(uint32_t ssrc); | ||||
| 
 | ||||
|             /* create RTCP BYE packet using our own SSRC and send it to all participants */ | ||||
|             rtp_error_t terminate_self(); | ||||
|  | @ -189,7 +189,7 @@ namespace uvg_rtp { | |||
|              * polling an RTCP packet, user can install a function that is called when | ||||
|              * a specific RTCP packet is received. */ | ||||
|             rtp_error_t install_sender_hook(void (*hook)(uvg_rtp::frame::rtcp_sender_frame *)); | ||||
|             rtp_error_t install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_frame *)); | ||||
|             rtp_error_t install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_report *)); | ||||
|             rtp_error_t install_sdes_hook(void (*hook)(uvg_rtp::frame::rtcp_sdes_frame *)); | ||||
|             rtp_error_t install_app_hook(void (*hook)(uvg_rtp::frame::rtcp_app_frame *)); | ||||
| 
 | ||||
|  | @ -324,7 +324,7 @@ namespace uvg_rtp { | |||
|             std::vector<uvg_rtp::socket> sockets_; | ||||
| 
 | ||||
|             void (*sender_hook_)(uvg_rtp::frame::rtcp_sender_frame *); | ||||
|             void (*receiver_hook_)(uvg_rtp::frame::rtcp_receiver_frame *); | ||||
|             void (*receiver_hook_)(uvg_rtp::frame::rtcp_receiver_report *); | ||||
|             void (*sdes_hook_)(uvg_rtp::frame::rtcp_sdes_frame *); | ||||
|             void (*app_hook_)(uvg_rtp::frame::rtcp_app_frame *); | ||||
|     }; | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 
 | ||||
| #define SET_NEXT_FIELD_32(a, p, v) do { *(uint32_t *)&(a)[p] = (v); ptr += 4; } while (0) | ||||
| 
 | ||||
| uvg_rtp::frame::rtcp_receiver_frame *uvg_rtp::rtcp::get_receiver_packet(uint32_t ssrc) | ||||
| uvg_rtp::frame::rtcp_receiver_report *uvg_rtp::rtcp::get_receiver_packet(uint32_t ssrc) | ||||
| { | ||||
|     if (participants_.find(ssrc) == participants_.end()) | ||||
|         return nullptr; | ||||
|  | @ -17,7 +17,7 @@ uvg_rtp::frame::rtcp_receiver_frame *uvg_rtp::rtcp::get_receiver_packet(uint32_t | |||
|     return frame; | ||||
| } | ||||
| 
 | ||||
| rtp_error_t uvg_rtp::rtcp::install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_frame *)) | ||||
| rtp_error_t uvg_rtp::rtcp::install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_report *)) | ||||
| { | ||||
|     if (!hook) | ||||
|         return RTP_INVALID_VALUE; | ||||
|  | @ -31,53 +31,50 @@ rtp_error_t uvg_rtp::rtcp::handle_receiver_report_packet(uint8_t *packet, size_t | |||
|     if (!packet || !size) | ||||
|         return RTP_INVALID_VALUE; | ||||
| 
 | ||||
|     frame->header.length = ntohs(frame->header.length); | ||||
|     frame->sender_ssrc   = ntohl(frame->sender_ssrc); | ||||
|     auto frame = new uvg_rtp::frame::rtcp_receiver_report; | ||||
| 
 | ||||
|     frame->header.version = (packet[0] >> 6) & 0x3f; | ||||
|     frame->header.padding = (packet[0] >> 5) & 0x1; | ||||
|     frame->header.count   = packet[0] & 0x1f; | ||||
|     frame->header.length  = ntohs(*(uint16_t *)&packet[2]); | ||||
|     frame->ssrc           = ntohl(*(uint32_t *)&packet[4]); | ||||
| 
 | ||||
|     /* Receiver Reports are sent from participant that don't send RTP packets
 | ||||
|      * This means that the sender of this report is not in the participants_ map | ||||
|      * but rather in the initial_participants_ vector | ||||
|      * | ||||
|      * Check if that's the case and if so, move the entry from initial_participants_ to participants_ */ | ||||
|     if (!is_participant(frame->sender_ssrc)) { | ||||
|         /* TODO: this is not correct way to do it! fix before multicast */ | ||||
|         add_participant(frame->sender_ssrc); | ||||
|     if (!is_participant(frame->ssrc)) { | ||||
|         LOG_WARN("Got a Receiver Report from an unknown participant"); | ||||
|         add_participant(frame->ssrc); | ||||
|     } | ||||
| 
 | ||||
|     if (frame->header.count == 0) { | ||||
|     if (!frame->header.count) { | ||||
|         LOG_ERROR("Receiver Report cannot have 0 report blocks!"); | ||||
|         return RTP_INVALID_VALUE; | ||||
|     } | ||||
| 
 | ||||
|     /* We need to make a copy of the frame because right now frame points to RTCP recv buffer
 | ||||
|      * Deallocate previous frame if it exists */ | ||||
|     if (participants_[frame->sender_ssrc]->r_frame != nullptr) | ||||
|         (void)uvg_rtp::frame::dealloc_frame(participants_[frame->sender_ssrc]->r_frame); | ||||
|     /* Deallocate previous frame from the buffer if it exists, it's going to get overwritten */ | ||||
|     if (participants_[frame->ssrc]->r_frame) | ||||
|         delete participants_[frame->ssrc]->r_frame; | ||||
| 
 | ||||
|     auto cpy_frame = uvg_rtp::frame::alloc_rtcp_receiver_frame(frame->header.count); | ||||
|     memcpy(cpy_frame, frame, size); | ||||
| 
 | ||||
|     fprintf(stderr, "Receiver report:\n"); | ||||
|     for (int i = 0; i < frame->header.count; ++i) { | ||||
|         cpy_frame->blocks[i].lost     = ntohl(frame->blocks[i].lost); | ||||
|         cpy_frame->blocks[i].last_seq = ntohl(frame->blocks[i].last_seq); | ||||
|         cpy_frame->blocks[i].jitter   = ntohl(frame->blocks[i].jitter); | ||||
|         cpy_frame->blocks[i].lsr      = ntohl(frame->blocks[i].lsr); | ||||
|         cpy_frame->blocks[i].dlsr     = ntohl(frame->blocks[i].dlsr); | ||||
|         uvg_rtp::frame::rtcp_report_block report; | ||||
| 
 | ||||
|         fprintf(stderr, "-------\n"); | ||||
|         fprintf(stderr, "lost:     %d\n", cpy_frame->blocks[i].lost); | ||||
|         fprintf(stderr, "last_seq: %u\n", cpy_frame->blocks[i].last_seq); | ||||
|         fprintf(stderr, "jitter:   %u\n", cpy_frame->blocks[i].jitter); | ||||
|         fprintf(stderr, "last sr:  %u\n", cpy_frame->blocks[i].lsr); | ||||
|         fprintf(stderr, "dlsr:     %u\n", cpy_frame->blocks[i].dlsr); | ||||
|         fprintf(stderr, "-------\n"); | ||||
|         report.ssrc     = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 0]); | ||||
|         report.lost     = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 4]); | ||||
|         report.last_seq = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 8]); | ||||
|         report.jitter   = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 12]); | ||||
|         report.lsr      = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 16]); | ||||
|         report.dlsr     = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 20]); | ||||
| 
 | ||||
|         frame->report_blocks.push_back(report); | ||||
|     } | ||||
| 
 | ||||
|     if (receiver_hook_) | ||||
|         receiver_hook_(cpy_frame); | ||||
|         receiver_hook_(frame); | ||||
|     else | ||||
|         participants_[frame->sender_ssrc]->r_frame = cpy_frame; | ||||
|         participants_[frame->ssrc]->r_frame = frame; | ||||
| 
 | ||||
|     return RTP_OK; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue