1233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang/* 2233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * 4233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * Use of this source code is governed by a BSD-style license 5233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * that can be found in the LICENSE file in the root of the source 6233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * tree. An additional intellectual property rights grant can be found 7233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * in the file PATENTS. All contributing project authors may 8233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang * be found in the AUTHORS file in the root of the source tree. 9233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang */ 10233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 11233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang#include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h" 12233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 13233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang#include "webrtc/base/checks.h" 14233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang#include "webrtc/base/logging.h" 1598f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/clock.h" 160b9e29c87da2d9c1a3792d2c87197b0688b68e4eHenrik Kjellander#include "webrtc/modules/pacing/packet_router.h" 17233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" 18ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" 19233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 20233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangnamespace webrtc { 21233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 22233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang// TODO(sprang): Tune these! 2313f6b8f7f4afe2316fa853f02732293d604a473fstefanconst int RemoteEstimatorProxy::kDefaultProcessIntervalMs = 50; 24233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangconst int RemoteEstimatorProxy::kBackWindowMs = 500; 25233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 26233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangRemoteEstimatorProxy::RemoteEstimatorProxy(Clock* clock, 27233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang PacketRouter* packet_router) 28233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang : clock_(clock), 29233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang packet_router_(packet_router), 30233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang last_process_time_ms_(-1), 31233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang media_ssrc_(0), 32233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang feedback_sequence_(0), 33233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang window_start_seq_(-1) {} 34233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 35233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangRemoteEstimatorProxy::~RemoteEstimatorProxy() {} 36233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 37233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangvoid RemoteEstimatorProxy::IncomingPacketFeedbackVector( 38233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang const std::vector<PacketInfo>& packet_feedback_vector) { 39233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang rtc::CritScope cs(&lock_); 40233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang for (PacketInfo info : packet_feedback_vector) 41233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang OnPacketArrival(info.sequence_number, info.arrival_time_ms); 42233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 43233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 44233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangvoid RemoteEstimatorProxy::IncomingPacket(int64_t arrival_time_ms, 45233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang size_t payload_size, 46233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang const RTPHeader& header, 47233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang bool was_paced) { 48bbe876f0d30ec806c7c4a12629eb1f19ab45fb86stefan if (!header.extension.hasTransportSequenceNumber) { 49bbe876f0d30ec806c7c4a12629eb1f19ab45fb86stefan LOG(LS_WARNING) << "RemoteEstimatorProxy: Incoming packet " 50bbe876f0d30ec806c7c4a12629eb1f19ab45fb86stefan "is missing the transport sequence number extension!"; 51bbe876f0d30ec806c7c4a12629eb1f19ab45fb86stefan return; 52bbe876f0d30ec806c7c4a12629eb1f19ab45fb86stefan } 53233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang rtc::CritScope cs(&lock_); 54233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang media_ssrc_ = header.ssrc; 55233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang OnPacketArrival(header.extension.transportSequenceNumber, arrival_time_ms); 56233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 57233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 58233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangvoid RemoteEstimatorProxy::RemoveStream(unsigned int ssrc) {} 59233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 60233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangbool RemoteEstimatorProxy::LatestEstimate(std::vector<unsigned int>* ssrcs, 61233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang unsigned int* bitrate_bps) const { 62233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return false; 63233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 64233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 65233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangbool RemoteEstimatorProxy::GetStats( 66233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang ReceiveBandwidthEstimatorStats* output) const { 67233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return false; 68233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 69233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 70233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 71233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangint64_t RemoteEstimatorProxy::TimeUntilNextProcess() { 72233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang int64_t now = clock_->TimeInMilliseconds(); 73233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang int64_t time_until_next = 0; 74233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (last_process_time_ms_ != -1 && 75233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang now - last_process_time_ms_ < kDefaultProcessIntervalMs) { 76233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang time_until_next = (last_process_time_ms_ + kDefaultProcessIntervalMs - now); 77233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 78233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return time_until_next; 79233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 80233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 81233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangint32_t RemoteEstimatorProxy::Process() { 82233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // TODO(sprang): Perhaps we need a dedicated thread here instead? 83233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 84233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (TimeUntilNextProcess() > 0) 85233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return 0; 86233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang last_process_time_ms_ = clock_->TimeInMilliseconds(); 87233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 88233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang bool more_to_build = true; 89233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang while (more_to_build) { 90233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang rtcp::TransportFeedback feedback_packet; 91233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (BuildFeedbackPacket(&feedback_packet)) { 9291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(packet_router_ != nullptr); 93233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang packet_router_->SendFeedback(&feedback_packet); 94233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } else { 95233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang more_to_build = false; 96233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 97233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 98233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 99233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return 0; 100233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 101233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 102233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangvoid RemoteEstimatorProxy::OnPacketArrival(uint16_t sequence_number, 103233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang int64_t arrival_time) { 104233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang int64_t seq = unwrapper_.Unwrap(sequence_number); 105233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 106233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (window_start_seq_ == -1) { 107233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang window_start_seq_ = seq; 108233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // Start new feedback packet, cull old packets. 109233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang for (auto it = packet_arrival_times_.begin(); 110233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang it != packet_arrival_times_.end() && it->first < seq && 111233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang arrival_time - it->second >= kBackWindowMs;) { 112233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang auto delete_it = it; 113233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang ++it; 114233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang packet_arrival_times_.erase(delete_it); 115233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 116233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } else if (seq < window_start_seq_) { 117233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang window_start_seq_ = seq; 118233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 119233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 12091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(packet_arrival_times_.end() == packet_arrival_times_.find(seq)); 121233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang packet_arrival_times_[seq] = arrival_time; 122233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 123233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 124233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangbool RemoteEstimatorProxy::BuildFeedbackPacket( 125233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang rtcp::TransportFeedback* feedback_packet) { 126233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang rtc::CritScope cs(&lock_); 127233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (window_start_seq_ == -1) 128233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return false; 129233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 130233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // window_start_seq_ is the first sequence number to include in the current 131233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // feedback packet. Some older may still be in the map, in case a reordering 132233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // happens and we need to retransmit them. 133233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang auto it = packet_arrival_times_.find(window_start_seq_); 13491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(it != packet_arrival_times_.end()); 135233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 136233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // TODO(sprang): Measure receive times in microseconds and remove the 137233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // conversions below. 138233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang feedback_packet->WithMediaSourceSsrc(media_ssrc_); 139233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang feedback_packet->WithBase(static_cast<uint16_t>(it->first & 0xFFFF), 140233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang it->second * 1000); 141233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang feedback_packet->WithFeedbackSequenceNumber(feedback_sequence_++); 142233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang for (; it != packet_arrival_times_.end(); ++it) { 143233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (!feedback_packet->WithReceivedPacket( 144233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang static_cast<uint16_t>(it->first & 0xFFFF), it->second * 1000)) { 145233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // If we can't even add the first seq to the feedback packet, we won't be 146233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // able to build it at all. 14791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_CHECK_NE(window_start_seq_, it->first); 148233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 149233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // Could not add timestamp, feedback packet might be full. Return and 150233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // try again with a fresh packet. 151233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang window_start_seq_ = it->first; 152233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang break; 153233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 154233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // Note: Don't erase items from packet_arrival_times_ after sending, in case 155233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // they need to be re-sent after a reordering. Removal will be handled 156233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang // by OnPacketArrival once packets are too old. 157233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang } 158233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang if (it == packet_arrival_times_.end()) 159233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang window_start_seq_ = -1; 160233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 161233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang return true; 162233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} 163233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang 164233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang} // namespace webrtc 165