blob: 9c48b993ac8b72058f7ba90a297083c3f10ae107 [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 {
Danil Chapovalov792df6b2018-09-07 13:03:32 +020022namespace {
23struct Destructor {
24 void operator()() { rtcp_transceiver = nullptr; }
25 std::unique_ptr<RtcpTransceiverImpl> rtcp_transceiver;
26};
27} // namespace
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010028
29RtcpTransceiver::RtcpTransceiver(const RtcpTransceiverConfig& config)
30 : task_queue_(config.task_queue),
Danil Chapovalovf0076d32018-09-05 16:46:40 +020031 rtcp_transceiver_(absl::make_unique<RtcpTransceiverImpl>(config)) {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010032 RTC_DCHECK(task_queue_);
33}
34
35RtcpTransceiver::~RtcpTransceiver() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020036 if (!rtcp_transceiver_)
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010037 return;
Danil Chapovalov792df6b2018-09-07 13:03:32 +020038 task_queue_->PostTask(Destructor{std::move(rtcp_transceiver_)});
39 RTC_DCHECK(!rtcp_transceiver_);
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010040}
41
Danil Chapovalovf0076d32018-09-05 16:46:40 +020042void RtcpTransceiver::Stop(std::unique_ptr<rtc::QueuedTask> on_destroyed) {
43 RTC_DCHECK(rtcp_transceiver_);
Danil Chapovalovf0076d32018-09-05 16:46:40 +020044 task_queue_->PostTaskAndReply(Destructor{std::move(rtcp_transceiver_)},
45 std::move(on_destroyed));
46 RTC_DCHECK(!rtcp_transceiver_);
47}
48
Danil Chapovalov98f5f6c2018-10-22 14:22:31 +020049void RtcpTransceiver::Stop(std::function<void()> on_destroyed) {
50 RTC_DCHECK(rtcp_transceiver_);
51 task_queue_->PostTask(rtc::NewClosure(
52 Destructor{std::move(rtcp_transceiver_)}, std::move(on_destroyed)));
53 RTC_DCHECK(!rtcp_transceiver_);
54}
55
Danil Chapovalova32d7102017-12-14 17:28:27 +010056void RtcpTransceiver::AddMediaReceiverRtcpObserver(
57 uint32_t remote_ssrc,
58 MediaReceiverRtcpObserver* observer) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020059 RTC_CHECK(rtcp_transceiver_);
60 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalova32d7102017-12-14 17:28:27 +010061 task_queue_->PostTask([ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020062 ptr->AddMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010063 });
64}
65
66void RtcpTransceiver::RemoveMediaReceiverRtcpObserver(
67 uint32_t remote_ssrc,
68 MediaReceiverRtcpObserver* observer,
69 std::unique_ptr<rtc::QueuedTask> on_removed) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020070 RTC_CHECK(rtcp_transceiver_);
71 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalova32d7102017-12-14 17:28:27 +010072 auto remove = [ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020073 ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010074 };
75 task_queue_->PostTaskAndReply(std::move(remove), std::move(on_removed));
76}
77
Danil Chapovalov98f5f6c2018-10-22 14:22:31 +020078void RtcpTransceiver::RemoveMediaReceiverRtcpObserver(
79 uint32_t remote_ssrc,
80 MediaReceiverRtcpObserver* observer,
81 std::function<void()> on_removed) {
82 RTC_CHECK(rtcp_transceiver_);
83 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
84 auto remove = [ptr, remote_ssrc, observer] {
85 ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
86 };
87 task_queue_->PostTask(
88 rtc::NewClosure(std::move(remove), std::move(on_removed)));
89}
90
Danil Chapovalove3927c52018-03-06 14:33:20 +010091void RtcpTransceiver::SetReadyToSend(bool ready) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020092 RTC_CHECK(rtcp_transceiver_);
93 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalove3927c52018-03-06 14:33:20 +010094 task_queue_->PostTask([ptr, ready] {
Danil Chapovalove3927c52018-03-06 14:33:20 +010095 ptr->SetReadyToSend(ready);
96 });
97}
98
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010099void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) {
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 int64_t now_us = rtc::TimeMicros();
103 task_queue_->PostTask([ptr, packet, now_us] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100104 ptr->ReceivePacket(packet, now_us);
105 });
106}
107
108void RtcpTransceiver::SendCompoundPacket() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200109 RTC_CHECK(rtcp_transceiver_);
110 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100111 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100112 ptr->SendCompoundPacket();
113 });
114}
115
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100116void RtcpTransceiver::SetRemb(int64_t bitrate_bps,
117 std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200118 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100119 // TODO(danilchap): Replace with lambda with move capture when available.
120 struct SetRembClosure {
121 void operator()() {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100122 ptr->SetRemb(bitrate_bps, std::move(ssrcs));
123 }
124
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200125 RtcpTransceiverImpl* ptr;
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100126 int64_t bitrate_bps;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100127 std::vector<uint32_t> ssrcs;
128 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200129 task_queue_->PostTask(
130 SetRembClosure{rtcp_transceiver_.get(), bitrate_bps, std::move(ssrcs)});
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100131}
132
133void RtcpTransceiver::UnsetRemb() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200134 RTC_CHECK(rtcp_transceiver_);
135 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100136 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100137 ptr->UnsetRemb();
138 });
139}
140
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100141uint32_t RtcpTransceiver::SSRC() const {
142 return rtcp_transceiver_->sender_ssrc();
143}
144
145bool RtcpTransceiver::SendFeedbackPacket(
146 const rtcp::TransportFeedback& packet) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200147 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100148 struct Closure {
149 void operator()() {
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100150 ptr->SendRawPacket(raw_packet);
151 }
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200152 RtcpTransceiverImpl* ptr;
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100153 rtc::Buffer raw_packet;
154 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200155 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), packet.Build()});
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100156 return true;
157}
158
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100159void RtcpTransceiver::SendNack(uint32_t ssrc,
160 std::vector<uint16_t> sequence_numbers) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200161 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100162 // TODO(danilchap): Replace with lambda with move capture when available.
163 struct Closure {
164 void operator()() {
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100165 ptr->SendNack(ssrc, std::move(sequence_numbers));
166 }
167
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200168 RtcpTransceiverImpl* ptr;
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100169 uint32_t ssrc;
170 std::vector<uint16_t> sequence_numbers;
171 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200172 task_queue_->PostTask(
173 Closure{rtcp_transceiver_.get(), ssrc, std::move(sequence_numbers)});
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100174}
175
Danil Chapovalov8d19e032017-11-28 19:53:33 +0100176void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200177 RTC_CHECK(rtcp_transceiver_);
178 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
179 task_queue_->PostTask([ptr, ssrc] { ptr->SendPictureLossIndication(ssrc); });
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100180}
181
182void RtcpTransceiver::SendFullIntraRequest(std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200183 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100184 // TODO(danilchap): Replace with lambda with move capture when available.
185 struct Closure {
186 void operator()() {
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100187 ptr->SendFullIntraRequest(ssrcs);
188 }
189
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200190 RtcpTransceiverImpl* ptr;
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100191 std::vector<uint32_t> ssrcs;
192 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200193 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), std::move(ssrcs)});
Danil Chapovalova7e418c2017-11-21 11:08:53 +0100194}
195
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100196} // namespace webrtc