blob: 77b10ca052d9864993fda1beae4ade0c71b22346 [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 Chapovalova32d7102017-12-14 17:28:27 +010049void RtcpTransceiver::AddMediaReceiverRtcpObserver(
50 uint32_t remote_ssrc,
51 MediaReceiverRtcpObserver* observer) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020052 RTC_CHECK(rtcp_transceiver_);
53 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalova32d7102017-12-14 17:28:27 +010054 task_queue_->PostTask([ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020055 ptr->AddMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010056 });
57}
58
59void RtcpTransceiver::RemoveMediaReceiverRtcpObserver(
60 uint32_t remote_ssrc,
61 MediaReceiverRtcpObserver* observer,
62 std::unique_ptr<rtc::QueuedTask> on_removed) {
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 auto remove = [ptr, remote_ssrc, observer] {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020066 ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
Danil Chapovalova32d7102017-12-14 17:28:27 +010067 };
68 task_queue_->PostTaskAndReply(std::move(remove), std::move(on_removed));
69}
70
Danil Chapovalove3927c52018-03-06 14:33:20 +010071void RtcpTransceiver::SetReadyToSend(bool ready) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020072 RTC_CHECK(rtcp_transceiver_);
73 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalove3927c52018-03-06 14:33:20 +010074 task_queue_->PostTask([ptr, ready] {
Danil Chapovalove3927c52018-03-06 14:33:20 +010075 ptr->SetReadyToSend(ready);
76 });
77}
78
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010079void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020080 RTC_CHECK(rtcp_transceiver_);
81 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010082 int64_t now_us = rtc::TimeMicros();
83 task_queue_->PostTask([ptr, packet, now_us] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010084 ptr->ReceivePacket(packet, now_us);
85 });
86}
87
88void RtcpTransceiver::SendCompoundPacket() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020089 RTC_CHECK(rtcp_transceiver_);
90 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010091 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010092 ptr->SendCompoundPacket();
93 });
94}
95
Danil Chapovalov1de4b622017-12-13 13:35:10 +010096void RtcpTransceiver::SetRemb(int64_t bitrate_bps,
97 std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +020098 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010099 // TODO(danilchap): Replace with lambda with move capture when available.
100 struct SetRembClosure {
101 void operator()() {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100102 ptr->SetRemb(bitrate_bps, std::move(ssrcs));
103 }
104
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200105 RtcpTransceiverImpl* ptr;
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100106 int64_t bitrate_bps;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100107 std::vector<uint32_t> ssrcs;
108 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200109 task_queue_->PostTask(
110 SetRembClosure{rtcp_transceiver_.get(), bitrate_bps, std::move(ssrcs)});
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100111}
112
113void RtcpTransceiver::UnsetRemb() {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200114 RTC_CHECK(rtcp_transceiver_);
115 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100116 task_queue_->PostTask([ptr] {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100117 ptr->UnsetRemb();
118 });
119}
120
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100121uint32_t RtcpTransceiver::SSRC() const {
122 return rtcp_transceiver_->sender_ssrc();
123}
124
125bool RtcpTransceiver::SendFeedbackPacket(
126 const rtcp::TransportFeedback& packet) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200127 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100128 struct Closure {
129 void operator()() {
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100130 ptr->SendRawPacket(raw_packet);
131 }
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200132 RtcpTransceiverImpl* ptr;
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100133 rtc::Buffer raw_packet;
134 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200135 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), packet.Build()});
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100136 return true;
137}
138
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100139void RtcpTransceiver::SendNack(uint32_t ssrc,
140 std::vector<uint16_t> sequence_numbers) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200141 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100142 // TODO(danilchap): Replace with lambda with move capture when available.
143 struct Closure {
144 void operator()() {
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100145 ptr->SendNack(ssrc, std::move(sequence_numbers));
146 }
147
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200148 RtcpTransceiverImpl* ptr;
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100149 uint32_t ssrc;
150 std::vector<uint16_t> sequence_numbers;
151 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200152 task_queue_->PostTask(
153 Closure{rtcp_transceiver_.get(), ssrc, std::move(sequence_numbers)});
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100154}
155
Danil Chapovalov8d19e032017-11-28 19:53:33 +0100156void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200157 RTC_CHECK(rtcp_transceiver_);
158 RtcpTransceiverImpl* ptr = rtcp_transceiver_.get();
159 task_queue_->PostTask([ptr, ssrc] { ptr->SendPictureLossIndication(ssrc); });
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100160}
161
162void RtcpTransceiver::SendFullIntraRequest(std::vector<uint32_t> ssrcs) {
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200163 RTC_CHECK(rtcp_transceiver_);
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100164 // TODO(danilchap): Replace with lambda with move capture when available.
165 struct Closure {
166 void operator()() {
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100167 ptr->SendFullIntraRequest(ssrcs);
168 }
169
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200170 RtcpTransceiverImpl* ptr;
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100171 std::vector<uint32_t> ssrcs;
172 };
Danil Chapovalovf0076d32018-09-05 16:46:40 +0200173 task_queue_->PostTask(Closure{rtcp_transceiver_.get(), std::move(ssrcs)});
Danil Chapovalova7e418c2017-11-21 11:08:53 +0100174}
175
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100176} // namespace webrtc