Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc |
| index 638922cdcc189e1ec4c8388dcd532945fec6bfe1..41c8adc67606a9f6b77b33f18cc84aaeabb1aaac 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc |
| @@ -14,8 +14,10 @@ |
| #include <string.h> |
| #include <limits> |
| +#include <map> |
| #include <memory> |
| #include <utility> |
| +#include <vector> |
| #include "webrtc/base/checks.h" |
| #include "webrtc/base/logging.h" |
| @@ -47,7 +49,6 @@ namespace { |
| using rtcp::CommonHeader; |
| using rtcp::ReportBlock; |
| -using RTCPHelp::RTCPReceiveInformation; |
| using RTCPHelp::RTCPReportBlockInformation; |
| // The number of RTCP time intervals needed to trigger a timeout. |
| @@ -70,6 +71,23 @@ struct RTCPReceiver::PacketInformation { |
| std::unique_ptr<rtcp::TransportFeedback> transport_feedback; |
| }; |
| +struct RTCPReceiver::ReceiveInformation { |
| + struct TimedTmmbrItem { |
| + rtcp::TmmbItem tmmbr_item; |
| + int64_t last_updated_ms; |
| + }; |
| + |
| + int64_t last_time_received_ms = 0; |
| + |
| + int64_t last_fir_request_ms = 0; |
| + int32_t last_fir_sequence_number = -1; |
| + |
| + bool ready_for_delete = false; |
| + |
| + std::vector<rtcp::TmmbItem> tmmbn; |
| + std::map<uint32_t, TimedTmmbrItem> tmmbr; |
| +}; |
| + |
| RTCPReceiver::RTCPReceiver( |
| Clock* clock, |
| bool receiver_only, |
| @@ -93,7 +111,6 @@ RTCPReceiver::RTCPReceiver( |
| _lastReceivedXRNTPfrac(0), |
| xr_rrtr_status_(false), |
| xr_rr_rtt_ms_(0), |
| - _receivedInfoMap(), |
| _lastReceivedRrMs(0), |
| _lastIncreasedSequenceNumberMs(0), |
| stats_callback_(NULL), |
| @@ -113,12 +130,6 @@ RTCPReceiver::~RTCPReceiver() { |
| info_map->erase(it_info); |
| } |
| } |
| - while (!_receivedInfoMap.empty()) { |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator first = |
| - _receivedInfoMap.begin(); |
| - delete first->second; |
| - _receivedInfoMap.erase(first); |
| - } |
| } |
| bool RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) { |
| @@ -137,12 +148,9 @@ bool RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) { |
| int64_t RTCPReceiver::LastReceivedReceiverReport() const { |
| rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| int64_t last_received_rr = -1; |
|
philipel
2016/09/29 11:39:21
Maybe make |last_received_rr| a member variable an
danilchap
2016/09/29 13:00:58
It totaly make sense, thank you, but it turn out t
philipel
2016/09/29 14:43:38
Lets do it in another CL then.
|
| - for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin(); |
| - it != _receivedInfoMap.end(); ++it) { |
| - if (it->second->last_time_received_ms > last_received_rr) { |
| - last_received_rr = it->second->last_time_received_ms; |
| - } |
| - } |
| + for (const auto& kv : received_infos_) |
| + if (kv.second.last_time_received_ms > last_received_rr) |
| + last_received_rr = kv.second.last_time_received_ms; |
| return last_received_rr; |
| } |
| @@ -420,9 +428,7 @@ void RTCPReceiver::HandleSenderReport(const CommonHeader& rtcp_block, |
| packet_information->remote_ssrc = remoteSSRC; |
| - RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC); |
| - if (!ptrReceiveInfo) |
| - return; |
| + CreateReceiveInformation(remoteSSRC); |
| TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR", |
| "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_); |
| @@ -445,8 +451,6 @@ void RTCPReceiver::HandleSenderReport(const CommonHeader& rtcp_block, |
| // we will store all the receive blocks. |
| packet_information->packet_type_flags |= kRtcpRr; |
| } |
| - // Update that this remote is alive. |
| - ptrReceiveInfo->last_time_received_ms = _clock->TimeInMilliseconds(); |
| for (const rtcp::ReportBlock report_block : sender_report.report_blocks()) |
| HandleReportBlock(report_block, packet_information, remoteSSRC); |
| @@ -464,18 +468,13 @@ void RTCPReceiver::HandleReceiverReport(const CommonHeader& rtcp_block, |
| packet_information->remote_ssrc = remoteSSRC; |
| - RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC); |
| - if (!ptrReceiveInfo) |
| - return; |
| + CreateReceiveInformation(remoteSSRC); |
| TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR", |
| "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_); |
| packet_information->packet_type_flags |= kRtcpRr; |
| - // Update that this remote is alive. |
| - ptrReceiveInfo->last_time_received_ms = _clock->TimeInMilliseconds(); |
| - |
| for (const ReportBlock& report_block : receiver_report.report_blocks()) |
| HandleReportBlock(report_block, packet_information, remoteSSRC); |
| } |
| @@ -602,31 +601,19 @@ RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation( |
| return it_info->second; |
| } |
| -RTCPReceiveInformation* RTCPReceiver::CreateReceiveInformation( |
| - uint32_t remoteSSRC) { |
| - rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| - |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator it = |
| - _receivedInfoMap.find(remoteSSRC); |
| - |
| - if (it != _receivedInfoMap.end()) { |
| - return it->second; |
| - } |
| - RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation; |
| - _receivedInfoMap[remoteSSRC] = receiveInfo; |
| - return receiveInfo; |
| +void RTCPReceiver::CreateReceiveInformation(uint32_t remote_ssrc) { |
| + // Create or find receive information. |
| + ReceiveInformation* receive_info = &received_infos_[remote_ssrc]; |
| + // Update that this remote is alive. |
| + receive_info->last_time_received_ms = _clock->TimeInMilliseconds(); |
| } |
| -RTCPReceiveInformation* RTCPReceiver::GetReceiveInformation( |
| - uint32_t remoteSSRC) { |
| - rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| - |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator it = |
| - _receivedInfoMap.find(remoteSSRC); |
| - if (it == _receivedInfoMap.end()) { |
| - return NULL; |
| - } |
| - return it->second; |
| +RTCPReceiver::ReceiveInformation* RTCPReceiver::GetReceiveInformation( |
| + uint32_t remote_ssrc) { |
| + auto it = received_infos_.find(remote_ssrc); |
| + if (it == received_infos_.end()) |
| + return nullptr; |
| + return &it->second; |
| } |
| bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) { |
| @@ -661,61 +648,43 @@ bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) { |
| bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() { |
| rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| - bool updateBoundingSet = false; |
| - int64_t timeNow = _clock->TimeInMilliseconds(); |
| - |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt = |
| - _receivedInfoMap.begin(); |
| - |
| - while (receiveInfoIt != _receivedInfoMap.end()) { |
| - RTCPReceiveInformation* receiveInfo = receiveInfoIt->second; |
| - if (receiveInfo == NULL) { |
| - return updateBoundingSet; |
| - } |
| - // time since last received rtcp packet |
| - // when we dont have a lastTimeReceived and the object is marked |
| - // readyForDelete it's removed from the map |
| - if (receiveInfo->last_time_received_ms > 0) { |
| - /// use audio define since we don't know what interval the remote peer is |
| - // using |
| - if ((timeNow - receiveInfo->last_time_received_ms) > |
| - 5 * RTCP_INTERVAL_AUDIO_MS) { |
| - // no rtcp packet for the last five regular intervals, reset limitations |
| - receiveInfo->ClearTmmbr(); |
| - // prevent that we call this over and over again |
| - receiveInfo->last_time_received_ms = 0; |
| - // send new TMMBN to all channels using the default codec |
| - updateBoundingSet = true; |
| + bool update_bounding_set = false; |
| + int64_t now_ms = _clock->TimeInMilliseconds(); |
| + // Use audio define since we don't know what interval the remote peer use. |
| + int64_t timeouted_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS; |
| + |
| + for (auto receive_info_it = received_infos_.begin(); |
| + receive_info_it != received_infos_.end();) { |
| + ReceiveInformation* receive_info = &receive_info_it->second; |
| + if (receive_info->last_time_received_ms > 0) { |
| + if (receive_info->last_time_received_ms < timeouted_ms) { |
| + // No rtcp packet for the last 5 regular intervals, reset limitations. |
| + receive_info->tmmbr.clear(); |
| + // Prevent that we call this over and over again. |
| + receive_info->last_time_received_ms = 0; |
| + // Send new TMMBN to all channels using the default codec. |
| + update_bounding_set = true; |
| } |
| - receiveInfoIt++; |
| - } else if (receiveInfo->ready_for_delete) { |
| - // store our current receiveInfoItem |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator |
| - receiveInfoItemToBeErased = receiveInfoIt; |
| - receiveInfoIt++; |
| - delete receiveInfoItemToBeErased->second; |
| - _receivedInfoMap.erase(receiveInfoItemToBeErased); |
| + ++receive_info_it; |
| + } else if (receive_info->ready_for_delete) { |
|
philipel
2016/09/29 11:39:21
Should a ReceiveInfo that is ready for deletion ev
danilchap
2016/09/29 13:00:58
Comment (not mine, I just moved it) explicitly say
philipel
2016/09/29 14:43:38
Oops, missed that comment :)
|
| + // When we dont have a last_time_received_ms and the object is marked |
| + // ready_for_delete it's removed from the map. |
| + receive_info_it = received_infos_.erase(receive_info_it); |
| } else { |
| - receiveInfoIt++; |
| + ++receive_info_it; |
| } |
| } |
| - return updateBoundingSet; |
| + return update_bounding_set; |
| } |
| std::vector<rtcp::TmmbItem> RTCPReceiver::BoundingSet(bool* tmmbr_owner) { |
| rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| - |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt = |
| - _receivedInfoMap.find(_remoteSSRC); |
| - |
| - if (receiveInfoIt == _receivedInfoMap.end()) { |
| + ReceiveInformation* receive_info = GetReceiveInformation(_remoteSSRC); |
| + if (!receive_info) |
| return std::vector<rtcp::TmmbItem>(); |
| - } |
| - RTCPReceiveInformation* receiveInfo = receiveInfoIt->second; |
| - RTC_DCHECK(receiveInfo); |
| - *tmmbr_owner = TMMBRHelp::IsOwner(receiveInfo->tmmbn, main_ssrc_); |
| - return receiveInfo->tmmbn; |
| + *tmmbr_owner = TMMBRHelp::IsOwner(receive_info->tmmbn, main_ssrc_); |
| + return receive_info->tmmbn; |
| } |
| void RTCPReceiver::HandleSDES(const CommonHeader& rtcp_block, |
| @@ -778,12 +747,10 @@ void RTCPReceiver::HandleBYE(const CommonHeader& rtcp_block) { |
| } |
| } |
| - // we can't delete it due to TMMBR |
| - std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt = |
| - _receivedInfoMap.find(bye.sender_ssrc()); |
| - |
| - if (receiveInfoIt != _receivedInfoMap.end()) |
| - receiveInfoIt->second->ready_for_delete = true; |
| + // We can't delete it due to TMMBR. |
| + ReceiveInformation* receive_info = GetReceiveInformation(bye.sender_ssrc()); |
| + if (receive_info) |
| + receive_info->ready_for_delete = true; |
| received_cnames_.erase(bye.sender_ssrc()); |
| xr_rr_rtt_ms_ = 0; |
| @@ -861,21 +828,25 @@ void RTCPReceiver::HandleTMMBR(const CommonHeader& rtcp_block, |
| return; |
| } |
| - uint32_t senderSSRC = tmmbr.sender_ssrc(); |
| - RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC); |
| - if (!ptrReceiveInfo) // This remote SSRC must be saved before. |
| + uint32_t sender_ssrc = tmmbr.sender_ssrc(); |
| + ReceiveInformation* receive_info = GetReceiveInformation(sender_ssrc); |
| + if (!receive_info) // This remote SSRC must be saved before. |
| return; |
| if (tmmbr.media_ssrc()) { |
| // media_ssrc() SHOULD be 0 if same as SenderSSRC. |
| // In relay mode this is a valid number. |
| - senderSSRC = tmmbr.media_ssrc(); |
| + sender_ssrc = tmmbr.media_ssrc(); |
| } |
| for (const rtcp::TmmbItem& request : tmmbr.requests()) { |
| if (main_ssrc_ == request.ssrc() && request.bitrate_bps()) { |
| - ptrReceiveInfo->InsertTmmbrItem(senderSSRC, request, |
| - _clock->TimeInMilliseconds()); |
| + auto* entry = &receive_info->tmmbr[sender_ssrc]; |
| + entry->tmmbr_item = rtcp::TmmbItem(sender_ssrc, |
| + request.bitrate_bps(), |
| + request.packet_overhead()); |
| + entry->last_updated_ms = _clock->TimeInMilliseconds(); |
| + |
| packet_information->packet_type_flags |= kRtcpTmmbr; |
| } |
| } |
| @@ -889,15 +860,14 @@ void RTCPReceiver::HandleTMMBN(const CommonHeader& rtcp_block, |
| return; |
| } |
| - RTCPReceiveInformation* ptrReceiveInfo = |
| - GetReceiveInformation(tmmbn.sender_ssrc()); |
| - if (!ptrReceiveInfo) // This remote SSRC must be saved before. |
| + ReceiveInformation* receive_info = GetReceiveInformation(tmmbn.sender_ssrc()); |
| + if (!receive_info) // This remote SSRC must be saved before. |
| return; |
| packet_information->packet_type_flags |= kRtcpTmmbn; |
| for (const auto& item : tmmbn.items()) |
| - ptrReceiveInfo->tmmbn.push_back(item); |
| + receive_info->tmmbn.push_back(item); |
| } |
| void RTCPReceiver::HandleSR_REQ(const CommonHeader& rtcp_block, |
| @@ -960,8 +930,7 @@ void RTCPReceiver::HandleFIR(const CommonHeader& rtcp_block, |
| return; |
| } |
| - RTCPReceiveInformation* ptrReceiveInfo = |
| - GetReceiveInformation(fir.sender_ssrc()); |
| + ReceiveInformation* receive_info = GetReceiveInformation(fir.sender_ssrc()); |
| for (const rtcp::Fir::Request& fir_request : fir.requests()) { |
| // Is it our sender that is requested to generate a new keyframe |
| @@ -970,25 +939,21 @@ void RTCPReceiver::HandleFIR(const CommonHeader& rtcp_block, |
| ++packet_type_counter_.fir_packets; |
| - // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it |
| - // we don't know who this originate from |
| - if (ptrReceiveInfo) { |
| - // check if we have reported this FIRSequenceNumber before |
| - if (fir_request.seq_nr != ptrReceiveInfo->last_fir_sequence_number) { |
| - int64_t now = _clock->TimeInMilliseconds(); |
| - // sanity; don't go crazy with the callbacks |
| - if ((now - ptrReceiveInfo->last_fir_request_ms) > |
| - RTCP_MIN_FRAME_LENGTH_MS) { |
| - ptrReceiveInfo->last_fir_request_ms = now; |
| - ptrReceiveInfo->last_fir_sequence_number = fir_request.seq_nr; |
| - // received signal that we need to send a new key frame |
| - packet_information->packet_type_flags |= kRtcpFir; |
| - } |
| - } |
| - } else { |
| - // received signal that we need to send a new key frame |
| - packet_information->packet_type_flags |= kRtcpFir; |
| + if (receive_info) { |
| + // Check if we have reported this FIRSequenceNumber before. |
| + if (fir_request.seq_nr == receive_info->last_fir_sequence_number) |
| + continue; |
| + |
| + int64_t now_ms = _clock->TimeInMilliseconds(); |
| + // Sanity: don't go crazy with the callbacks. |
| + if (now_ms - receive_info->last_fir_request_ms < RTCP_MIN_FRAME_LENGTH_MS) |
| + continue; |
| + |
| + receive_info->last_fir_request_ms = now_ms; |
| + receive_info->last_fir_sequence_number = fir_request.seq_nr; |
| } |
| + // Received signal that we need to send a new key frame. |
| + packet_information->packet_type_flags |= kRtcpFir; |
| } |
| } |
| @@ -1150,16 +1115,24 @@ int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC, |
| return 0; |
| } |
| -std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() const { |
| +std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() { |
| rtc::CritScope lock(&_criticalSectionRTCPReceiver); |
| std::vector<rtcp::TmmbItem> candidates; |
| int64_t now_ms = _clock->TimeInMilliseconds(); |
| - |
| - for (const auto& kv : _receivedInfoMap) { |
| - RTCPReceiveInformation* receive_info = kv.second; |
| - RTC_DCHECK(receive_info); |
| - receive_info->GetTmmbrSet(now_ms, &candidates); |
| + // Use audio define since we don't know what interval the remote peer use. |
| + int64_t timeouted_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS; |
| + |
| + for (auto& kv : received_infos_) { |
| + for (auto it = kv.second.tmmbr.begin(); it != kv.second.tmmbr.end();) { |
| + if (it->second.last_updated_ms < timeouted_ms) { |
| + // Erase timeout entries. |
| + it = kv.second.tmmbr.erase(it); |
| + } else { |
| + candidates.push_back(it->second.tmmbr_item); |
| + ++it; |
| + } |
| + } |
| } |
| return candidates; |
| } |