blob: 28b95c020252025dc618673faeefb03422c8141d [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
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010015#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010016#include "rtc_base/checks.h"
17#include "rtc_base/event.h"
18#include "rtc_base/ptr_util.h"
19#include "rtc_base/timeutils.h"
20
21namespace webrtc {
22
23RtcpTransceiver::RtcpTransceiver(const RtcpTransceiverConfig& config)
24 : task_queue_(config.task_queue),
25 rtcp_transceiver_(rtc::MakeUnique<RtcpTransceiverImpl>(config)),
26 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
54void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) {
55 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
56 int64_t now_us = rtc::TimeMicros();
57 task_queue_->PostTask([ptr, packet, now_us] {
58 if (ptr)
59 ptr->ReceivePacket(packet, now_us);
60 });
61}
62
63void RtcpTransceiver::SendCompoundPacket() {
64 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
65 task_queue_->PostTask([ptr] {
66 if (ptr)
67 ptr->SendCompoundPacket();
68 });
69}
70
Danil Chapovalov1de4b622017-12-13 13:35:10 +010071void RtcpTransceiver::SetRemb(int64_t bitrate_bps,
72 std::vector<uint32_t> ssrcs) {
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010073 // TODO(danilchap): Replace with lambda with move capture when available.
74 struct SetRembClosure {
75 void operator()() {
76 if (ptr)
77 ptr->SetRemb(bitrate_bps, std::move(ssrcs));
78 }
79
80 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
Danil Chapovalov1de4b622017-12-13 13:35:10 +010081 int64_t bitrate_bps;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010082 std::vector<uint32_t> ssrcs;
83 };
84 task_queue_->PostTask(SetRembClosure{ptr_, bitrate_bps, std::move(ssrcs)});
85}
86
87void RtcpTransceiver::UnsetRemb() {
88 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
89 task_queue_->PostTask([ptr] {
90 if (ptr)
91 ptr->UnsetRemb();
92 });
93}
94
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010095uint32_t RtcpTransceiver::SSRC() const {
96 return rtcp_transceiver_->sender_ssrc();
97}
98
99bool RtcpTransceiver::SendFeedbackPacket(
100 const rtcp::TransportFeedback& packet) {
101 struct Closure {
102 void operator()() {
103 if (ptr)
104 ptr->SendRawPacket(raw_packet);
105 }
106 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
107 rtc::Buffer raw_packet;
108 };
109 task_queue_->PostTask(Closure{ptr_, packet.Build()});
110 return true;
111}
112
Danil Chapovalov327c43c2017-11-27 17:23:04 +0100113void RtcpTransceiver::SendNack(uint32_t ssrc,
114 std::vector<uint16_t> sequence_numbers) {
115 // TODO(danilchap): Replace with lambda with move capture when available.
116 struct Closure {
117 void operator()() {
118 if (ptr)
119 ptr->SendNack(ssrc, std::move(sequence_numbers));
120 }
121
122 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
123 uint32_t ssrc;
124 std::vector<uint16_t> sequence_numbers;
125 };
126 task_queue_->PostTask(Closure{ptr_, ssrc, std::move(sequence_numbers)});
127}
128
Danil Chapovalov8d19e032017-11-28 19:53:33 +0100129void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) {
130 rtc::WeakPtr<RtcpTransceiverImpl> ptr = ptr_;
131 task_queue_->PostTask([ptr, ssrc] {
132 if (ptr)
133 ptr->SendPictureLossIndication(ssrc);
134 });
Danil Chapovalov2ddf98d2017-11-22 14:00:41 +0100135}
136
137void RtcpTransceiver::SendFullIntraRequest(std::vector<uint32_t> ssrcs) {
138 // TODO(danilchap): Replace with lambda with move capture when available.
139 struct Closure {
140 void operator()() {
141 if (ptr)
142 ptr->SendFullIntraRequest(ssrcs);
143 }
144
145 rtc::WeakPtr<RtcpTransceiverImpl> ptr;
146 std::vector<uint32_t> ssrcs;
147 };
148 task_queue_->PostTask(Closure{ptr_, std::move(ssrcs)});
Danil Chapovalova7e418c2017-11-21 11:08:53 +0100149}
150
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100151} // namespace webrtc