frame_sender_impl.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/cast/sender/frame_sender_impl.h"
  5. #include <algorithm>
  6. #include <limits>
  7. #include <memory>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/feature_list.h"
  12. #include "base/logging.h"
  13. #include "base/numerics/safe_conversions.h"
  14. #include "base/trace_event/trace_event.h"
  15. #include "media/cast/common/openscreen_conversion_helpers.h"
  16. #include "media/cast/common/sender_encoded_frame.h"
  17. #include "media/cast/constants.h"
  18. namespace media::cast {
  19. namespace {
  20. constexpr int kNumAggressiveReportsSentAtStart = 100;
  21. constexpr base::TimeDelta kMinSchedulingDelay = base::Milliseconds(1);
  22. constexpr base::TimeDelta kReceiverProcessTime = base::Milliseconds(250);
  23. // The additional number of frames that can be in-flight when input exceeds the
  24. // maximum frame rate.
  25. constexpr int kMaxFrameBurst = 5;
  26. } // namespace
  27. // static
  28. std::unique_ptr<FrameSender> FrameSender::Create(
  29. scoped_refptr<CastEnvironment> cast_environment,
  30. const FrameSenderConfig& config,
  31. CastTransport* const transport_sender,
  32. Client& client) {
  33. return std::make_unique<FrameSenderImpl>(cast_environment, config,
  34. transport_sender, client);
  35. }
  36. // Convenience macro used in logging statements throughout this file.
  37. #define SENDER_SSRC \
  38. (is_audio_ ? "AUDIO[" : "VIDEO[") << config_.sender_ssrc << "] "
  39. FrameSenderImpl::Client::~Client() = default;
  40. FrameSenderImpl::RtcpClient::RtcpClient(
  41. base::WeakPtr<FrameSenderImpl> frame_sender)
  42. : frame_sender_(frame_sender) {}
  43. FrameSenderImpl::RtcpClient::~RtcpClient() = default;
  44. void FrameSenderImpl::RtcpClient::OnReceivedCastMessage(
  45. const RtcpCastMessage& cast_message) {
  46. if (frame_sender_)
  47. frame_sender_->OnReceivedCastFeedback(cast_message);
  48. }
  49. void FrameSenderImpl::RtcpClient::OnReceivedRtt(
  50. base::TimeDelta round_trip_time) {
  51. if (frame_sender_)
  52. frame_sender_->OnMeasuredRoundTripTime(round_trip_time);
  53. }
  54. void FrameSenderImpl::RtcpClient::OnReceivedPli() {
  55. if (frame_sender_)
  56. frame_sender_->OnReceivedPli();
  57. }
  58. FrameSenderImpl::FrameSenderImpl(
  59. scoped_refptr<CastEnvironment> cast_environment,
  60. const FrameSenderConfig& config,
  61. CastTransport* const transport_sender,
  62. Client& client)
  63. : cast_environment_(cast_environment),
  64. config_(config),
  65. target_playout_delay_(config.max_playout_delay),
  66. max_frame_rate_(config.max_frame_rate),
  67. transport_sender_(transport_sender),
  68. client_(client),
  69. is_audio_(config.rtp_payload_type <= RtpPayloadType::AUDIO_LAST),
  70. // We only use the adaptive control for software video encoding.
  71. congestion_control_(
  72. (!config.use_external_encoder && !is_audio_)
  73. ? NewAdaptiveCongestionControl(cast_environment->Clock(),
  74. config.max_bitrate,
  75. config.min_bitrate,
  76. max_frame_rate_)
  77. : NewFixedCongestionControl(
  78. (config.min_bitrate + config.max_bitrate) / 2)
  79. ),
  80. max_ack_delay_(config_.max_playout_delay) {
  81. DCHECK(transport_sender_);
  82. DCHECK_GT(config_.rtp_timebase, 0);
  83. DCHECK(congestion_control_);
  84. // We assume animated content to begin with since that is the common use
  85. // case today.
  86. VLOG(1) << SENDER_SSRC << "min latency "
  87. << config_.min_playout_delay.InMilliseconds() << "max latency "
  88. << config_.max_playout_delay.InMilliseconds() << "animated latency "
  89. << config_.animated_playout_delay.InMilliseconds();
  90. SetTargetPlayoutDelay(config_.animated_playout_delay);
  91. CastTransportRtpConfig transport_config;
  92. transport_config.ssrc = config.sender_ssrc;
  93. transport_config.feedback_ssrc = config.receiver_ssrc;
  94. transport_config.rtp_payload_type = config.rtp_payload_type;
  95. transport_config.aes_key = config.aes_key;
  96. transport_config.aes_iv_mask = config.aes_iv_mask;
  97. transport_sender_->InitializeStream(
  98. transport_config, std::make_unique<FrameSenderImpl::RtcpClient>(
  99. weak_factory_.GetWeakPtr()));
  100. }
  101. FrameSenderImpl::~FrameSenderImpl() = default;
  102. bool FrameSenderImpl::NeedsKeyFrame() const {
  103. return picture_lost_at_receiver_;
  104. }
  105. base::TimeTicks FrameSenderImpl::GetRecordedReferenceTime(
  106. FrameId frame_id) const {
  107. return frame_reference_times_[frame_id.lower_8_bits()];
  108. }
  109. void FrameSenderImpl::ScheduleNextRtcpReport() {
  110. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  111. cast_environment_->PostDelayedTask(
  112. CastEnvironment::MAIN, FROM_HERE,
  113. base::BindOnce(&FrameSenderImpl::SendRtcpReport,
  114. weak_factory_.GetWeakPtr(), true),
  115. kRtcpReportInterval);
  116. }
  117. void FrameSenderImpl::SendRtcpReport(bool schedule_future_reports) {
  118. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  119. // Sanity-check: We should have sent at least the first frame by this point.
  120. DCHECK(!last_send_time_.is_null());
  121. // Create lip-sync info for the sender report. The last sent frame's
  122. // reference time and RTP timestamp are used to estimate an RTP timestamp in
  123. // terms of "now." Note that |now| is never likely to be precise to an exact
  124. // frame boundary; and so the computation here will result in a
  125. // |now_as_rtp_timestamp| value that is rarely equal to any one emitted by the
  126. // encoder.
  127. const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
  128. const base::TimeDelta time_delta =
  129. now - GetRecordedReferenceTime(last_sent_frame_id_);
  130. const RtpTimeDelta rtp_delta =
  131. ToRtpTimeDelta(time_delta, config_.rtp_timebase);
  132. const RtpTimeTicks now_as_rtp_timestamp =
  133. GetRecordedRtpTimestamp(last_sent_frame_id_) + rtp_delta;
  134. transport_sender_->SendSenderReport(config_.sender_ssrc, now,
  135. now_as_rtp_timestamp);
  136. if (schedule_future_reports)
  137. ScheduleNextRtcpReport();
  138. }
  139. void FrameSenderImpl::OnMeasuredRoundTripTime(base::TimeDelta round_trip_time) {
  140. DCHECK_GT(round_trip_time, base::TimeDelta());
  141. current_round_trip_time_ = round_trip_time;
  142. max_ack_delay_ = 2 * std::max(current_round_trip_time_, base::TimeDelta()) +
  143. kReceiverProcessTime;
  144. max_ack_delay_ = std::min(max_ack_delay_, target_playout_delay_);
  145. }
  146. void FrameSenderImpl::SetTargetPlayoutDelay(
  147. base::TimeDelta new_target_playout_delay) {
  148. if (send_target_playout_delay_ &&
  149. target_playout_delay_ == new_target_playout_delay) {
  150. return;
  151. }
  152. new_target_playout_delay =
  153. std::max(new_target_playout_delay, config_.min_playout_delay);
  154. new_target_playout_delay =
  155. std::min(new_target_playout_delay, config_.max_playout_delay);
  156. VLOG(2) << SENDER_SSRC << "Target playout delay changing from "
  157. << target_playout_delay_.InMilliseconds() << " ms to "
  158. << new_target_playout_delay.InMilliseconds() << " ms.";
  159. target_playout_delay_ = new_target_playout_delay;
  160. max_ack_delay_ = std::min(max_ack_delay_, target_playout_delay_);
  161. send_target_playout_delay_ = true;
  162. congestion_control_->UpdateTargetPlayoutDelay(target_playout_delay_);
  163. }
  164. base::TimeDelta FrameSenderImpl::GetTargetPlayoutDelay() const {
  165. return target_playout_delay_;
  166. }
  167. void FrameSenderImpl::ResendCheck() {
  168. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  169. DCHECK(!last_send_time_.is_null());
  170. const base::TimeDelta time_since_last_send =
  171. cast_environment_->Clock()->NowTicks() - last_send_time_;
  172. if (time_since_last_send > max_ack_delay_) {
  173. if (latest_acked_frame_id_ == last_sent_frame_id_) {
  174. // Last frame acked, no point in doing anything
  175. } else {
  176. VLOG(1) << SENDER_SSRC
  177. << "ACK timeout; last acked frame: " << latest_acked_frame_id_;
  178. ResendForKickstart();
  179. }
  180. }
  181. ScheduleNextResendCheck();
  182. }
  183. void FrameSenderImpl::ScheduleNextResendCheck() {
  184. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  185. DCHECK(!last_send_time_.is_null());
  186. base::TimeDelta time_to_next =
  187. last_send_time_ - cast_environment_->Clock()->NowTicks() + max_ack_delay_;
  188. time_to_next = std::max(time_to_next, kMinSchedulingDelay);
  189. cast_environment_->PostDelayedTask(
  190. CastEnvironment::MAIN, FROM_HERE,
  191. base::BindOnce(&FrameSenderImpl::ResendCheck, weak_factory_.GetWeakPtr()),
  192. time_to_next);
  193. }
  194. void FrameSenderImpl::ResendForKickstart() {
  195. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  196. DCHECK(!last_send_time_.is_null());
  197. VLOG(1) << SENDER_SSRC << "Resending last packet of frame "
  198. << last_sent_frame_id_ << " to kick-start.";
  199. last_send_time_ = cast_environment_->Clock()->NowTicks();
  200. transport_sender_->ResendFrameForKickstart(config_.sender_ssrc,
  201. last_sent_frame_id_);
  202. }
  203. void FrameSenderImpl::RecordLatestFrameTimestamps(
  204. FrameId frame_id,
  205. base::TimeTicks reference_time,
  206. RtpTimeTicks rtp_timestamp) {
  207. DCHECK(!reference_time.is_null());
  208. frame_reference_times_[frame_id.lower_8_bits()] = reference_time;
  209. frame_rtp_timestamps_[frame_id.lower_8_bits()] = rtp_timestamp;
  210. }
  211. base::TimeDelta FrameSenderImpl::GetInFlightMediaDuration() const {
  212. const base::TimeDelta encoder_duration = client_.GetEncoderBacklogDuration();
  213. // No frames are in flight, so only look at the encoder duration.
  214. if (last_sent_frame_id_ == latest_acked_frame_id_) {
  215. return encoder_duration;
  216. }
  217. const RtpTimeTicks oldest_acked_timestamp =
  218. GetRecordedRtpTimestamp(latest_acked_frame_id_);
  219. const RtpTimeTicks newest_acked_timestamp =
  220. GetRecordedRtpTimestamp(last_sent_frame_id_);
  221. return ToTimeDelta(newest_acked_timestamp - oldest_acked_timestamp,
  222. config_.rtp_timebase) +
  223. encoder_duration;
  224. }
  225. RtpTimeTicks FrameSenderImpl::GetRecordedRtpTimestamp(FrameId frame_id) const {
  226. return frame_rtp_timestamps_[frame_id.lower_8_bits()];
  227. }
  228. int FrameSenderImpl::GetUnacknowledgedFrameCount() const {
  229. if (last_send_time_.is_null())
  230. return 0;
  231. const int count = last_sent_frame_id_ - latest_acked_frame_id_;
  232. DCHECK_GE(count, 0);
  233. return count;
  234. }
  235. int FrameSenderImpl::GetSuggestedBitrate(base::TimeTicks playout_time,
  236. base::TimeDelta playout_delay) {
  237. return congestion_control_->GetBitrate(playout_time, playout_delay);
  238. }
  239. double FrameSenderImpl::MaxFrameRate() const {
  240. return max_frame_rate_;
  241. }
  242. void FrameSenderImpl::SetMaxFrameRate(double max_frame_rate) {
  243. max_frame_rate_ = max_frame_rate;
  244. }
  245. base::TimeDelta FrameSenderImpl::TargetPlayoutDelay() const {
  246. return target_playout_delay_;
  247. }
  248. base::TimeDelta FrameSenderImpl::CurrentRoundTripTime() const {
  249. return current_round_trip_time_;
  250. }
  251. base::TimeTicks FrameSenderImpl::LastSendTime() const {
  252. return last_send_time_;
  253. }
  254. FrameId FrameSenderImpl::LatestAckedFrameId() const {
  255. return latest_acked_frame_id_;
  256. }
  257. base::TimeDelta FrameSenderImpl::GetAllowedInFlightMediaDuration() const {
  258. // The total amount allowed in-flight media should equal the amount that fits
  259. // within the entire playout delay window, plus the amount of time it takes to
  260. // receive an ACK from the receiver.
  261. return target_playout_delay_ + (current_round_trip_time_ / 2);
  262. }
  263. void FrameSenderImpl::EnqueueFrame(
  264. std::unique_ptr<SenderEncodedFrame> encoded_frame) {
  265. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  266. VLOG(2) << SENDER_SSRC
  267. << "About to send another frame: last_sent=" << last_sent_frame_id_
  268. << ", latest_acked=" << latest_acked_frame_id_;
  269. const FrameId frame_id = encoded_frame->frame_id;
  270. const bool is_first_frame_to_be_sent = last_send_time_.is_null();
  271. if (picture_lost_at_receiver_ &&
  272. (encoded_frame->dependency == EncodedFrame::KEY)) {
  273. picture_lost_at_receiver_ = false;
  274. DCHECK(frame_id > latest_acked_frame_id_);
  275. // Cancel sending remaining frames.
  276. std::vector<FrameId> cancel_sending_frames;
  277. for (FrameId id = latest_acked_frame_id_ + 1; id < frame_id; ++id) {
  278. cancel_sending_frames.push_back(id);
  279. client_.OnFrameCanceled(id);
  280. }
  281. transport_sender_->CancelSendingFrames(config_.sender_ssrc,
  282. cancel_sending_frames);
  283. }
  284. last_send_time_ = cast_environment_->Clock()->NowTicks();
  285. DCHECK(frame_id > last_sent_frame_id_) << "enqueued frames out of order.";
  286. last_sent_frame_id_ = frame_id;
  287. // If this is the first frame about to be sent, fake the value of
  288. // |latest_acked_frame_id_| to indicate the receiver starts out all
  289. // caught up. Also, schedule the periodic frame re-send checks.
  290. if (is_first_frame_to_be_sent) {
  291. latest_acked_frame_id_ = frame_id - 1;
  292. ScheduleNextResendCheck();
  293. }
  294. VLOG_IF(1, !is_audio_ && encoded_frame->dependency == EncodedFrame::KEY)
  295. << SENDER_SSRC << "Sending encoded key frame, id=" << frame_id;
  296. std::unique_ptr<FrameEvent> encode_event(new FrameEvent());
  297. encode_event->timestamp = encoded_frame->encode_completion_time;
  298. encode_event->type = FRAME_ENCODED;
  299. encode_event->media_type = is_audio_ ? AUDIO_EVENT : VIDEO_EVENT;
  300. encode_event->rtp_timestamp = encoded_frame->rtp_timestamp;
  301. encode_event->frame_id = frame_id;
  302. encode_event->size = base::checked_cast<uint32_t>(encoded_frame->data.size());
  303. encode_event->key_frame = encoded_frame->dependency == EncodedFrame::KEY;
  304. encode_event->target_bitrate = encoded_frame->encoder_bitrate;
  305. encode_event->encoder_cpu_utilization = encoded_frame->encoder_utilization;
  306. encode_event->idealized_bitrate_utilization = encoded_frame->lossiness;
  307. cast_environment_->logger()->DispatchFrameEvent(std::move(encode_event));
  308. RecordLatestFrameTimestamps(frame_id, encoded_frame->reference_time,
  309. encoded_frame->rtp_timestamp);
  310. if (!is_audio_) {
  311. // Used by chrome/browser/media/cast_mirroring_performance_browsertest.cc
  312. TRACE_EVENT_INSTANT1("cast_perf_test", "VideoFrameEncoded",
  313. TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp",
  314. encoded_frame->rtp_timestamp.lower_32_bits());
  315. }
  316. // At the start of the session, it's important to send reports before each
  317. // frame so that the receiver can properly compute playout times. The reason
  318. // more than one report is sent is because transmission is not guaranteed,
  319. // only best effort, so send enough that one should almost certainly get
  320. // through.
  321. if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
  322. // SendRtcpReport() will schedule future reports to be made if this is the
  323. // last "aggressive report."
  324. ++num_aggressive_rtcp_reports_sent_;
  325. const bool is_last_aggressive_report =
  326. (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart);
  327. VLOG_IF(1, is_last_aggressive_report)
  328. << SENDER_SSRC << "Sending last aggressive report.";
  329. SendRtcpReport(is_last_aggressive_report);
  330. }
  331. congestion_control_->WillSendFrameToTransport(
  332. frame_id, encoded_frame->data.size(), last_send_time_);
  333. if (send_target_playout_delay_) {
  334. encoded_frame->new_playout_delay_ms =
  335. target_playout_delay_.InMilliseconds();
  336. }
  337. const char* name = is_audio_ ? "Audio Transport" : "Video Transport";
  338. TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
  339. "cast.stream", name, TRACE_ID_WITH_SCOPE(name, frame_id.lower_32_bits()),
  340. "rtp_timestamp", encoded_frame->rtp_timestamp.lower_32_bits());
  341. transport_sender_->InsertFrame(config_.sender_ssrc, *encoded_frame);
  342. }
  343. void FrameSenderImpl::OnReceivedCastFeedback(
  344. const RtcpCastMessage& cast_feedback) {
  345. DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
  346. const bool have_valid_rtt = current_round_trip_time_.is_positive();
  347. if (have_valid_rtt) {
  348. congestion_control_->UpdateRtt(current_round_trip_time_);
  349. // Having the RTT value implies the receiver sent back a receiver report
  350. // based on it having received a report from here. Therefore, ensure this
  351. // sender stops aggressively sending reports.
  352. if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
  353. VLOG(1) << SENDER_SSRC
  354. << "No longer a need to send reports aggressively (sent "
  355. << num_aggressive_rtcp_reports_sent_ << ").";
  356. num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart;
  357. ScheduleNextRtcpReport();
  358. }
  359. }
  360. if (last_send_time_.is_null())
  361. return; // Cannot get an ACK without having first sent a frame.
  362. if (cast_feedback.missing_frames_and_packets.empty() &&
  363. cast_feedback.received_later_frames.empty()) {
  364. if (latest_acked_frame_id_ == cast_feedback.ack_frame_id) {
  365. VLOG(1) << SENDER_SSRC << "Received duplicate ACK for frame "
  366. << latest_acked_frame_id_;
  367. TRACE_EVENT_INSTANT2(
  368. "cast.stream", "Duplicate ACK", TRACE_EVENT_SCOPE_THREAD,
  369. "ack_frame_id", cast_feedback.ack_frame_id.lower_32_bits(),
  370. "last_sent_frame_id", last_sent_frame_id_.lower_32_bits());
  371. }
  372. // We only count duplicate ACKs when we have sent newer frames.
  373. if (latest_acked_frame_id_ == cast_feedback.ack_frame_id &&
  374. latest_acked_frame_id_ != last_sent_frame_id_) {
  375. duplicate_ack_counter_++;
  376. } else {
  377. duplicate_ack_counter_ = 0;
  378. }
  379. if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) {
  380. ResendForKickstart();
  381. }
  382. } else {
  383. // Only count duplicated ACKs if there is no NACK request in between.
  384. // This is to avoid aggressive resend.
  385. duplicate_ack_counter_ = 0;
  386. }
  387. base::TimeTicks now = cast_environment_->Clock()->NowTicks();
  388. congestion_control_->AckFrame(cast_feedback.ack_frame_id, now);
  389. if (!cast_feedback.received_later_frames.empty()) {
  390. // Ack the received frames.
  391. congestion_control_->AckLaterFrames(cast_feedback.received_later_frames,
  392. now);
  393. }
  394. std::unique_ptr<FrameEvent> ack_event(new FrameEvent());
  395. ack_event->timestamp = now;
  396. ack_event->type = FRAME_ACK_RECEIVED;
  397. ack_event->media_type = is_audio_ ? AUDIO_EVENT : VIDEO_EVENT;
  398. ack_event->rtp_timestamp =
  399. GetRecordedRtpTimestamp(cast_feedback.ack_frame_id);
  400. ack_event->frame_id = cast_feedback.ack_frame_id;
  401. cast_environment_->logger()->DispatchFrameEvent(std::move(ack_event));
  402. const bool is_acked_out_of_order =
  403. cast_feedback.ack_frame_id < latest_acked_frame_id_;
  404. VLOG(2) << SENDER_SSRC << "Received ACK"
  405. << (is_acked_out_of_order ? " out-of-order" : "") << " for frame "
  406. << cast_feedback.ack_frame_id;
  407. if (is_acked_out_of_order) {
  408. TRACE_EVENT_INSTANT2(
  409. "cast.stream", "ACK out of order", TRACE_EVENT_SCOPE_THREAD,
  410. "ack_frame_id", cast_feedback.ack_frame_id.lower_32_bits(),
  411. "latest_acked_frame_id", latest_acked_frame_id_.lower_32_bits());
  412. } else if (latest_acked_frame_id_ < cast_feedback.ack_frame_id) {
  413. // Cancel resends of acked frames.
  414. std::vector<FrameId> frames_to_cancel;
  415. frames_to_cancel.reserve(cast_feedback.ack_frame_id -
  416. latest_acked_frame_id_);
  417. do {
  418. ++latest_acked_frame_id_;
  419. frames_to_cancel.push_back(latest_acked_frame_id_);
  420. client_.OnFrameCanceled(latest_acked_frame_id_);
  421. // This is a good place to match the trace for frame ids
  422. // since this ensures we not only track frame ids that are
  423. // implicitly ACKed, but also handles duplicate ACKs
  424. const char* name = is_audio_ ? "Audio Transport" : "Video Transport";
  425. TRACE_EVENT_NESTABLE_ASYNC_END1(
  426. "cast.stream", name,
  427. TRACE_ID_WITH_SCOPE(name, latest_acked_frame_id_.lower_32_bits()),
  428. "RTT_usecs", current_round_trip_time_.InMicroseconds());
  429. } while (latest_acked_frame_id_ < cast_feedback.ack_frame_id);
  430. transport_sender_->CancelSendingFrames(config_.sender_ssrc,
  431. frames_to_cancel);
  432. }
  433. }
  434. void FrameSenderImpl::OnReceivedPli() {
  435. picture_lost_at_receiver_ = true;
  436. }
  437. bool FrameSenderImpl::ShouldDropNextFrame(
  438. base::TimeDelta frame_duration) const {
  439. // Check that accepting the next frame won't cause more frames to become
  440. // in-flight than the system's design limit.
  441. const int count_frames_in_flight =
  442. GetUnacknowledgedFrameCount() + client_.GetNumberOfFramesInEncoder();
  443. if (count_frames_in_flight >= kMaxUnackedFrames) {
  444. VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight.";
  445. return true;
  446. }
  447. // Check that accepting the next frame won't exceed the configured maximum
  448. // frame rate, allowing for short-term bursts.
  449. const base::TimeDelta duration_in_flight = GetInFlightMediaDuration();
  450. const double max_frames_in_flight =
  451. max_frame_rate_ * duration_in_flight.InSecondsF();
  452. if (count_frames_in_flight >= max_frames_in_flight + kMaxFrameBurst) {
  453. VLOG(1) << SENDER_SSRC << "Dropping: Burst threshold would be exceeded.";
  454. return true;
  455. }
  456. // Check that accepting the next frame won't exceed the allowed in-flight
  457. // media duration.
  458. const base::TimeDelta duration_would_be_in_flight =
  459. duration_in_flight + frame_duration;
  460. const base::TimeDelta allowed_in_flight = GetAllowedInFlightMediaDuration();
  461. if (VLOG_IS_ON(1)) {
  462. const int64_t percent =
  463. allowed_in_flight.is_positive()
  464. ? base::ClampRound<int64_t>(duration_would_be_in_flight /
  465. allowed_in_flight * 100)
  466. : std::numeric_limits<int64_t>::max();
  467. VLOG_IF(1, percent > 50)
  468. << SENDER_SSRC << duration_in_flight.InMicroseconds()
  469. << " usec in-flight + " << frame_duration.InMicroseconds()
  470. << " usec for next frame --> " << percent << "% of allowed in-flight.";
  471. }
  472. if (duration_would_be_in_flight > allowed_in_flight) {
  473. VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high.";
  474. return true;
  475. }
  476. // Next frame is accepted.
  477. return false;
  478. }
  479. } // namespace media::cast