#ifdef _WIN32 #else #endif #include "rtcp.hh" uvg_rtp::frame::rtcp_sdes_packet *uvg_rtp::rtcp::get_sdes_packet(uint32_t ssrc) { if (participants_.find(ssrc) == participants_.end()) return nullptr; auto frame = participants_[ssrc]->sdes_frame; participants_[ssrc]->sdes_frame = nullptr; return frame; } rtp_error_t uvg_rtp::rtcp::install_sdes_hook(void (*hook)(uvg_rtp::frame::rtcp_sdes_packet *)) { if (!hook) return RTP_INVALID_VALUE; sdes_hook_ = hook; return RTP_OK; } rtp_error_t uvg_rtp::rtcp::handle_sdes_packet(uint8_t *packet, size_t size) { if (!packet || !size) return RTP_INVALID_VALUE; auto frame = new uvg_rtp::frame::rtcp_sdes_packet; frame->header.version = (packet[0] >> 6) & 0x3; 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]); /* Deallocate previous frame from the buffer if it exists, it's going to get overwritten */ if (participants_[frame->ssrc]->sdes_frame) { for (auto& item : participants_[frame->ssrc]->sdes_frame->items) delete[] (uint8_t *)item.data; delete participants_[frame->ssrc]->sdes_frame; } for (int ptr = 8; ptr < frame->header.length; ) { uvg_rtp::frame::rtcp_sdes_item item; item.type = packet[ptr++]; item.length = packet[ptr++]; item.data = (void *)new uint8_t[item.length]; memcpy(item.data, &packet[ptr], item.length); ptr += item.length; } if (sdes_hook_) sdes_hook_(frame); else participants_[frame->ssrc]->sdes_frame = frame; return RTP_OK; } rtp_error_t uvg_rtp::rtcp::send_sdes_packet(std::vector& items) { if (items.empty()) { LOG_ERROR("Cannot send an empty SDES packet!"); return RTP_INVALID_VALUE; } int ptr = 8; uint8_t *frame; rtp_error_t ret; size_t frame_size; frame_size = 4 + 4; /* rtcp header + ssrc */ frame_size += items.size() * 2; /* sdes item type + length */ for (auto& item : items) frame_size += item.length; if (!(frame = new uint8_t[frame_size])) { LOG_ERROR("Failed to allocate space for RTCP Receiver Report"); return RTP_MEMORY_ERROR; } memset(frame, 0, frame_size); frame[0] = (2 << 6) | (0 << 5) | num_receivers_; frame[1] = uvg_rtp::frame::RTCP_FT_SDES; *(uint16_t *)&frame[2] = htons(frame_size); *(uint32_t *)&frame[4] = htonl(ssrc_); for (auto& item : items) { frame[ptr++] = item.type; frame[ptr++] = item.length; memcpy(frame + ptr, item.data, item.length); ptr += item.length; } for (auto& p : participants_) { if ((ret = p.second->socket->sendto(p.second->address, frame, frame_size, 0)) != RTP_OK) { LOG_ERROR("sendto() failed!"); goto end; } update_rtcp_bandwidth(frame_size); } end: delete[] frame; return ret; }