blob: a2ba3cb959f8cc23967f0f895b083d85683318d1 [file] [log] [blame]
Ruslan Burakov501bfba2019-02-11 10:29:19 +01001/*
2 * Copyright 2019 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 "pc/video_rtp_receiver.h"
12
13#include <stddef.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Ruslan Burakov501bfba2019-02-11 10:29:19 +010015#include <utility>
16#include <vector>
17
18#include "api/media_stream_proxy.h"
19#include "api/media_stream_track_proxy.h"
20#include "api/video_track_source_proxy.h"
Ruslan Burakov428dcb22019-04-18 17:49:49 +020021#include "pc/jitter_buffer_delay.h"
22#include "pc/jitter_buffer_delay_proxy.h"
Ruslan Burakov501bfba2019-02-11 10:29:19 +010023#include "pc/media_stream.h"
24#include "pc/video_track.h"
25#include "rtc_base/checks.h"
26#include "rtc_base/location.h"
27#include "rtc_base/logging.h"
28#include "rtc_base/trace_event.h"
29
30namespace webrtc {
31
32VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
33 std::string receiver_id,
34 std::vector<std::string> stream_ids)
35 : VideoRtpReceiver(worker_thread,
36 receiver_id,
37 CreateStreamsFromIds(std::move(stream_ids))) {}
38
39VideoRtpReceiver::VideoRtpReceiver(
40 rtc::Thread* worker_thread,
41 const std::string& receiver_id,
42 const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
43 : worker_thread_(worker_thread),
44 id_(receiver_id),
Ruslan Burakov428dcb22019-04-18 17:49:49 +020045 source_(new RefCountedObject<VideoRtpTrackSource>()),
Ruslan Burakov501bfba2019-02-11 10:29:19 +010046 track_(VideoTrackProxy::Create(
47 rtc::Thread::Current(),
48 worker_thread,
49 VideoTrack::Create(
50 receiver_id,
51 VideoTrackSourceProxy::Create(rtc::Thread::Current(),
52 worker_thread,
53 source_),
54 worker_thread))),
Ruslan Burakov428dcb22019-04-18 17:49:49 +020055 attachment_id_(GenerateUniqueId()),
56 delay_(JitterBufferDelayProxy::Create(
57 rtc::Thread::Current(),
58 worker_thread,
59 new rtc::RefCountedObject<JitterBufferDelay>(worker_thread))) {
Ruslan Burakov501bfba2019-02-11 10:29:19 +010060 RTC_DCHECK(worker_thread_);
61 SetStreams(streams);
62 source_->SetState(MediaSourceInterface::kLive);
63}
64
65VideoRtpReceiver::~VideoRtpReceiver() {
66 // Since cricket::VideoRenderer is not reference counted,
67 // we need to remove it from the channel before we are deleted.
68 Stop();
69}
70
71std::vector<std::string> VideoRtpReceiver::stream_ids() const {
72 std::vector<std::string> stream_ids(streams_.size());
73 for (size_t i = 0; i < streams_.size(); ++i)
74 stream_ids[i] = streams_[i]->id();
75 return stream_ids;
76}
77
78bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
79 RTC_DCHECK(media_channel_);
80 RTC_DCHECK(ssrc_);
81 return worker_thread_->Invoke<bool>(
82 RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); });
83}
84
85RtpParameters VideoRtpReceiver::GetParameters() const {
86 if (!media_channel_ || !ssrc_ || stopped_) {
87 return RtpParameters();
88 }
89 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
90 return media_channel_->GetRtpReceiveParameters(*ssrc_);
91 });
92}
93
94bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
95 TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
96 if (!media_channel_ || !ssrc_ || stopped_) {
97 return false;
98 }
99 return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
100 return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters);
101 });
102}
103
104void VideoRtpReceiver::SetFrameDecryptor(
105 rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
106 frame_decryptor_ = std::move(frame_decryptor);
107 // Special Case: Set the frame decryptor to any value on any existing channel.
108 if (media_channel_ && ssrc_.has_value() && !stopped_) {
109 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
110 media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
111 });
112 }
113}
114
115rtc::scoped_refptr<FrameDecryptorInterface>
116VideoRtpReceiver::GetFrameDecryptor() const {
117 return frame_decryptor_;
118}
119
120void VideoRtpReceiver::Stop() {
121 // TODO(deadbeef): Need to do more here to fully stop receiving packets.
122 if (stopped_) {
123 return;
124 }
125 source_->SetState(MediaSourceInterface::kEnded);
126 if (!media_channel_ || !ssrc_) {
127 RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
128 } else {
129 // Allow that SetSink fail. This is the normal case when the underlying
130 // media channel has already been deleted.
131 SetSink(nullptr);
132 }
Ruslan Burakov428dcb22019-04-18 17:49:49 +0200133 delay_->OnStop();
Ruslan Burakov501bfba2019-02-11 10:29:19 +0100134 stopped_ = true;
135}
136
137void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
138 if (!media_channel_) {
139 RTC_LOG(LS_ERROR)
140 << "VideoRtpReceiver::SetupMediaChannel: No video channel exists.";
141 }
142 if (ssrc_ == ssrc) {
143 return;
144 }
145 if (ssrc_) {
146 SetSink(nullptr);
147 }
148 ssrc_ = ssrc;
149 SetSink(source_->sink());
150 // Attach any existing frame decryptor to the media channel.
151 MaybeAttachFrameDecryptorToMediaChannel(
152 ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
Ruslan Burakov493a6502019-02-27 15:32:48 +0100153
Ruslan Burakov428dcb22019-04-18 17:49:49 +0200154 delay_->OnStart(media_channel_, ssrc);
Ruslan Burakov501bfba2019-02-11 10:29:19 +0100155}
156
157void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
158 SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
159}
160
161void VideoRtpReceiver::SetStreams(
162 const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
163 // Remove remote track from any streams that are going away.
164 for (const auto& existing_stream : streams_) {
165 bool removed = true;
166 for (const auto& stream : streams) {
167 if (existing_stream->id() == stream->id()) {
168 RTC_DCHECK_EQ(existing_stream.get(), stream.get());
169 removed = false;
170 break;
171 }
172 }
173 if (removed) {
174 existing_stream->RemoveTrack(track_);
175 }
176 }
177 // Add remote track to any streams that are new.
178 for (const auto& stream : streams) {
179 bool added = true;
180 for (const auto& existing_stream : streams_) {
181 if (stream->id() == existing_stream->id()) {
182 RTC_DCHECK_EQ(stream.get(), existing_stream.get());
183 added = false;
184 break;
185 }
186 }
187 if (added) {
188 stream->AddTrack(track_);
189 }
190 }
191 streams_ = streams;
192}
193
194void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
195 observer_ = observer;
196 // Deliver any notifications the observer may have missed by being set late.
197 if (received_first_packet_ && observer_) {
198 observer_->OnFirstPacketReceived(media_type());
199 }
200}
201
Ruslan Burakov4bac79e2019-04-03 19:55:33 +0200202void VideoRtpReceiver::SetJitterBufferMinimumDelay(
203 absl::optional<double> delay_seconds) {
Ruslan Burakov428dcb22019-04-18 17:49:49 +0200204 delay_->Set(delay_seconds);
Ruslan Burakov4bac79e2019-04-03 19:55:33 +0200205}
206
Ruslan Burakov501bfba2019-02-11 10:29:19 +0100207void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
208 RTC_DCHECK(media_channel == nullptr ||
209 media_channel->media_type() == media_type());
210 media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
211}
212
213void VideoRtpReceiver::NotifyFirstPacketReceived() {
214 if (observer_) {
215 observer_->OnFirstPacketReceived(media_type());
216 }
217 received_first_packet_ = true;
218}
219
220std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
221 if (!media_channel_ || !ssrc_ || stopped_) {
222 return {};
223 }
224 return worker_thread_->Invoke<std::vector<RtpSource>>(
225 RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
226}
227
228} // namespace webrtc