blob: e5ad3bae95d4c7024bfd870690233aab57392889 [file] [log] [blame]
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +01001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "modules/rtp_rtcp/source/rtcp_transceiver.h"
12
13#include <utility>
14
Karl Wiberg918f50c2018-07-05 11:40:33 +020015#include "absl/memory/memory.h"
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010016#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010017#include "rtc_base/checks.h"
18#include "rtc_base/event.h"
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010019#include "rtc_base/timeutils.h"
20
21namespace webrtc {
22
23RtcpTransceiver::RtcpTransceiver(const RtcpTransceiverConfig& config)
24 : task_queue_(config.task_queue),
Danil Chapovalovf0076d32018-09-05 16:46:40 +020025 rtcp_transceiver_(absl::make_unique<RtcpTransceiverImpl>(config)) {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010026 RTC_DCHECK(task_queue_);
27}
28
29RtcpTransceiver::~RtcpTransceiver() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020030 if (!rtcp_transceiver_)
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010031 return;
Danil Chapovalovf0076d32018-09-05 16:46:40 +020032 RTC_CHECK(!task_queue_->IsCurrent());
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010033
34 rtc::Event done(false, false);
35 // TODO(danilchap): Merge cleanup into main closure when task queue does not
36 // silently drop tasks.
37 task_queue_->PostTask(rtc::NewClosure(
38 [this] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020039 // Destructor steps that better run on the task_queue_.
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010040 rtcp_transceiver_.reset();
41 },
42 /*cleanup=*/[&done] { done.Set(); }));
Danil Chapovalovf0076d32018-09-05 16:46:40 +020043 // Wait until destruction is complete to guarantee callbacks are not used
44 // after destructor returns.
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010045 done.Wait(rtc::Event::kForever);
46 RTC_CHECK(!rtcp_transceiver_) << "Task queue is too busy to handle rtcp";
47}
48
Danil Chapovalovf0076d32018-09-05 16:46:40 +020049void RtcpTransceiver::Stop(std::unique_ptr<rtc::QueuedTask> on_destroyed) {
50 RTC_DCHECK(rtcp_transceiver_);
51 struct Destructor {
52 void operator()() { rtcp_transceiver = nullptr; }
53 std::unique_ptr<RtcpTransceiverImpl> rtcp_transceiver;
54 };
55 task_queue_->PostTaskAndReply(Destructor{std::move(rtcp_transceiver_)},
56 std::move(on_destroyed));
57 RTC_DCHECK(!rtcp_transceiver_);
58}
59
Danil Chapovalova32d7102017-12-14 17:28:27 +010060void RtcpTransceiver::AddMediaReceiverRtcpObserver(
61 uint32_t remote_ssrc,
62 MediaReceiverRtcpObserver* observer) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020063 RTC_CHECK(rtcp_transceiver_);
64 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalova32d7102017-12-14 17:28:27 +010065 task_queue_->PostTask([ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020066 ptr->AddMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010067 });
68}
69
70void RtcpTransceiver::RemoveMediaReceiverRtcpObserver(
71 uint32_t remote_ssrc,
72 MediaReceiverRtcpObserver* observer,
73 std::unique_ptr<rtc::QueuedTask> on_removed) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020074 RTC_CHECK(rtcp_transceiver_);
75 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalova32d7102017-12-14 17:28:27 +010076 auto remove = [ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020077 ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010078 };
79 task_queue_->PostTaskAndReply(std::move(remove), std::move(on_removed));
80}
81
Danil Chapovalove3927c52018-03-06 14:33:20 +010082void RtcpTransceiver::SetReadyToSend(bool ready) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020083 RTC_CHECK(rtcp_transceiver_);
84 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalove3927c52018-03-06 14:33:20 +010085 task_queue_->PostTask([ptr, ready] {
Danil Chapovalove3927c52018-03-06 14:33:20 +010086 ptr->SetReadyToSend(ready);
87 });
88}
89
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010090void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020091 RTC_CHECK(rtcp_transceiver_);
92 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010093 int64_t now_us = rtc::TimeMicros();
94 task_queue_->PostTask([ptr, packet, now_us] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010095 ptr->ReceivePacket(packet, now_us);
96 });
97}
98
99void RtcpTransceiver::SendCompoundPacket() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200100 RTC_CHECK(rtcp_transceiver_);
101 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100102 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100103 ptr->SendCompoundPacket();
104 });
105}
106
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100107void RtcpTransceiver::SetRemb(int64_t bitrate_bps,
108 std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200109 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100110 // TODO(danilchap): Replace with lambda with move capture when available.
111 struct SetRembClosure {
112 void operator()() {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100113 ptr->SetRemb(bitrate_bps, std::move(ssrcs));
114 }
115
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200116 RtcpTransceiverImpl* ptr;
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100117 int64_t bitrate_bps;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100118 std::vector<uint32_t> ssrcs;
119 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200120 task_queue_->PostTask(
121 SetRembClosure{rtcp_transceiver_.get(), bitrate_bps, std::move(ssrcs)});
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100122}
123
124void RtcpTransceiver::UnsetRemb() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200125 RTC_CHECK(rtcp_transceiver_);
126 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100127 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100128 ptr->UnsetRemb();
129 });
130}
131
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100132uint32_t RtcpTransceiver::SSRC() const {
133 return rtcp_transceiver_->sender_ssrc();
134}
135
136bool RtcpTransceiver::SendFeedbackPacket(
137 const rtcp::TransportFeedback& packet) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200138 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100139 struct Closure {
140 void operator()() {
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100141 ptr->SendRawPacket(raw_packet);
142 }
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200143 RtcpTransceiverImpl* ptr;
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100144 rtc::Buffer raw_packet;
145 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200146 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), packet.Build()});
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100147 return true;
148}
149
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100150void RtcpTransceiver::SendNack(uint32_t ssrc,
151 std::vector<uint16_t> sequence_numbers) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200152 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100153 // TODO(danilchap): Replace with lambda with move capture when available.
154 struct Closure {
155 void operator()() {
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100156 ptr->SendNack(ssrc, std::move(sequence_numbers));
157 }
158
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200159 RtcpTransceiverImpl* ptr;
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100160 uint32_t ssrc;
161 std::vector<uint16_t> sequence_numbers;
162 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200163 task_queue_->PostTask(
164 Closure{rtcp_transceiver_.get(), ssrc, std::move(sequence_numbers)});
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100165}
166
Danil Chapovalov8d19e032017-11-28 19:53:33 +0100167void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200168 RTC_CHECK(rtcp_transceiver_);
169 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
170 task_queue_->PostTask([ptr, ssrc] { ptr->SendPictureLossIndication(ssrc); });
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100171}
172
173void RtcpTransceiver::SendFullIntraRequest(std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200174 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100175 // TODO(danilchap): Replace with lambda with move capture when available.
176 struct Closure {
177 void operator()() {
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100178 ptr->SendFullIntraRequest(ssrcs);
179 }
180
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200181 RtcpTransceiverImpl* ptr;
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100182 std::vector<uint32_t> ssrcs;
183 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200184 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), std::move(ssrcs)});
Danil Chapovalova7e418c2017-11-21 11:08:53 +0100185}
186
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100187} // namespace webrtc