blob: 9a179295b29839b1c70690f3fd5a70b5bb4cc3b1 [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),
Karl Wiberg918f50c2018-07-05 11:40:33 +020025 rtcp_transceiver_(absl::make_unique<RtcpTransceiverImpl>(config)),
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010026 ptr_factory_(rtcp_transceiver_.get()),
27 // Creating first weak ptr can be done on any thread, but is not
28 // thread-safe, thus do it at construction. Creating second (e.g. making a
29 // copy) is thread-safe.
30 ptr_(ptr_factory_.GetWeakPtr()) {
31 RTC_DCHECK(task_queue_);
32}
33
34RtcpTransceiver::~RtcpTransceiver() {
35 if (task_queue_->IsCurrent())
36 return;
37
38 rtc::Event done(false, false);
39 // TODO(danilchap): Merge cleanup into main closure when task queue does not
40 // silently drop tasks.
41 task_queue_->PostTask(rtc::NewClosure(
42 [this] {
43 // Destructor steps that has to run on the task_queue_.
44 ptr_factory_.InvalidateWeakPtrs();
45 rtcp_transceiver_.reset();
46 },
47 /*cleanup=*/[&done] { done.Set(); }));
48 // Wait until destruction is complete to be sure weak pointers invalidated and
49 // rtcp_transceiver destroyed on the queue while |this| still valid.
50 done.Wait(rtc::Event::kForever);
51 RTC_CHECK(!rtcp_transceiver_) << "Task queue is too busy to handle rtcp";
52}
53
Danil Chapovalova32d7102017-12-14 17:28:27 +010054void RtcpTransceiver::AddMediaReceiverRtcpObserver(
55 uint32_t remote_ssrc,
56 MediaReceiverRtcpObserver* observer) {
57 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
58 task_queue_->PostTask([ptr, remote_ssrc, observer] {
59 if (ptr)
60 ptr->AddMediaReceiverRtcpObserver(remote_ssrc, observer);
61 });
62}
63
64void RtcpTransceiver::RemoveMediaReceiverRtcpObserver(
65 uint32_t remote_ssrc,
66 MediaReceiverRtcpObserver* observer,
67 std::unique_ptr<rtc::QueuedTask> on_removed) {
68 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
69 auto remove = [ptr, remote_ssrc, observer] {
70 if (ptr)
71 ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
72 };
73 task_queue_->PostTaskAndReply(std::move(remove), std::move(on_removed));
74}
75
Danil Chapovalove3927c52018-03-06 14:33:20 +010076void RtcpTransceiver::SetReadyToSend(bool ready) {
77 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
78 task_queue_->PostTask([ptr, ready] {
79 if (ptr)
80 ptr->SetReadyToSend(ready);
81 });
82}
83
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010084void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) {
85 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
86 int64_t now_us = rtc::TimeMicros();
87 task_queue_->PostTask([ptr, packet, now_us] {
88 if (ptr)
89 ptr->ReceivePacket(packet, now_us);
90 });
91}
92
93void RtcpTransceiver::SendCompoundPacket() {
94 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
95 task_queue_->PostTask([ptr] {
96 if (ptr)
97 ptr->SendCompoundPacket();
98 });
99}
100
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100101void RtcpTransceiver::SetRemb(int64_t bitrate_bps,
102 std::vector<uint32_t> ssrcs) {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100103 // TODO(danilchap): Replace with lambda with move capture when available.
104 struct SetRembClosure {
105 void operator()() {
106 if (ptr)
107 ptr->SetRemb(bitrate_bps, std::move(ssrcs));
108 }
109
110 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100111 int64_t bitrate_bps;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100112 std::vector<uint32_t> ssrcs;
113 };
114 task_queue_->PostTask(SetRembClosure{ptr_, bitrate_bps, std::move(ssrcs)});
115}
116
117void RtcpTransceiver::UnsetRemb() {
118 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
119 task_queue_->PostTask([ptr] {
120 if (ptr)
121 ptr->UnsetRemb();
122 });
123}
124
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100125uint32_t RtcpTransceiver::SSRC() const {
126 return rtcp_transceiver_->sender_ssrc();
127}
128
129bool RtcpTransceiver::SendFeedbackPacket(
130 const rtcp::TransportFeedback& packet) {
131 struct Closure {
132 void operator()() {
133 if (ptr)
134 ptr->SendRawPacket(raw_packet);
135 }
136 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
137 rtc::Buffer raw_packet;
138 };
139 task_queue_->PostTask(Closure{ptr_, packet.Build()});
140 return true;
141}
142
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100143void RtcpTransceiver::SendNack(uint32_t ssrc,
144 std::vector<uint16_t> sequence_numbers) {
145 // TODO(danilchap): Replace with lambda with move capture when available.
146 struct Closure {
147 void operator()() {
148 if (ptr)
149 ptr->SendNack(ssrc, std::move(sequence_numbers));
150 }
151
152 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
153 uint32_t ssrc;
154 std::vector<uint16_t> sequence_numbers;
155 };
156 task_queue_->PostTask(Closure{ptr_, ssrc, std::move(sequence_numbers)});
157}
158
Danil Chapovalov8d19e032017-11-28 19:53:33 +0100159void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) {
160 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
161 task_queue_->PostTask([ptr, ssrc] {
162 if (ptr)
163 ptr->SendPictureLossIndication(ssrc);
164 });
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100165}
166
167void RtcpTransceiver::SendFullIntraRequest(std::vector<uint32_t> ssrcs) {
168 // TODO(danilchap): Replace with lambda with move capture when available.
169 struct Closure {
170 void operator()() {
171 if (ptr)
172 ptr->SendFullIntraRequest(ssrcs);
173 }
174
175 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
176 std::vector<uint32_t> ssrcs;
177 };
178 task_queue_->PostTask(Closure{ptr_, std::move(ssrcs)});
Danil Chapovalova7e418c2017-11-21 11:08:53 +0100179}
180
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100181} // namespace webrtc