blob: d6272e760c83ee91a0e02b6efd7a61febeda6e12 [file] [log] [blame]
Ruslan Burakov501bfba2019-02-11 09:29:191/*
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 17:08:3314
Harald Alvestrandc24a2182022-02-23 13:44:5915#include <string>
Ruslan Burakov501bfba2019-02-11 09:29:1916#include <utility>
17#include <vector>
18
Harald Alvestrand5761e7b2021-01-29 14:45:0819#include "api/video/recordable_encoded_frame.h"
Ruslan Burakov501bfba2019-02-11 09:29:1920#include "pc/video_track.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/location.h"
23#include "rtc_base/logging.h"
Ruslan Burakov501bfba2019-02-11 09:29:1924
25namespace webrtc {
26
27VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
28 std::string receiver_id,
29 std::vector<std::string> stream_ids)
30 : VideoRtpReceiver(worker_thread,
31 receiver_id,
32 CreateStreamsFromIds(std::move(stream_ids))) {}
33
34VideoRtpReceiver::VideoRtpReceiver(
35 rtc::Thread* worker_thread,
36 const std::string& receiver_id,
37 const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
38 : worker_thread_(worker_thread),
39 id_(receiver_id),
Tommi4ccdf9322021-05-17 12:50:1040 source_(rtc::make_ref_counted<VideoRtpTrackSource>(&source_callback_)),
Harald Alvestrand1ee33252020-09-24 13:31:1541 track_(VideoTrackProxyWithInternal<VideoTrack>::Create(
Ruslan Burakov501bfba2019-02-11 09:29:1942 rtc::Thread::Current(),
43 worker_thread,
Tommi09f57132022-02-17 12:19:5544 VideoTrack::Create(receiver_id, source_, worker_thread))),
Tommi4ccdf9322021-05-17 12:50:1045 attachment_id_(GenerateUniqueId()) {
Ruslan Burakov501bfba2019-02-11 09:29:1946 RTC_DCHECK(worker_thread_);
47 SetStreams(streams);
Tommi20d8d912022-02-08 20:12:1548 RTC_DCHECK_EQ(source_->state(), MediaSourceInterface::kInitializing);
Ruslan Burakov501bfba2019-02-11 09:29:1949}
50
51VideoRtpReceiver::~VideoRtpReceiver() {
Tommi4ccdf9322021-05-17 12:50:1052 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Tommi4ccdf9322021-05-17 12:50:1053 RTC_DCHECK(!media_channel_);
Ruslan Burakov501bfba2019-02-11 09:29:1954}
55
56std::vector<std::string> VideoRtpReceiver::stream_ids() const {
Tommi4ccdf9322021-05-17 12:50:1057 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Ruslan Burakov501bfba2019-02-11 09:29:1958 std::vector<std::string> stream_ids(streams_.size());
59 for (size_t i = 0; i < streams_.size(); ++i)
60 stream_ids[i] = streams_[i]->id();
61 return stream_ids;
62}
63
Tommi4ccdf9322021-05-17 12:50:1064rtc::scoped_refptr<DtlsTransportInterface> VideoRtpReceiver::dtls_transport()
65 const {
66 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
67 return dtls_transport_;
68}
69
70std::vector<rtc::scoped_refptr<MediaStreamInterface>>
71VideoRtpReceiver::streams() const {
72 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
73 return streams_;
74}
75
Ruslan Burakov501bfba2019-02-11 09:29:1976RtpParameters VideoRtpReceiver::GetParameters() const {
Tommi4ccdf9322021-05-17 12:50:1077 RTC_DCHECK_RUN_ON(worker_thread_);
78 if (!media_channel_)
Ruslan Burakov501bfba2019-02-11 09:29:1979 return RtpParameters();
Tommi4ccdf9322021-05-17 12:50:1080 return ssrc_ ? media_channel_->GetRtpReceiveParameters(*ssrc_)
81 : media_channel_->GetDefaultRtpReceiveParameters();
Ruslan Burakov501bfba2019-02-11 09:29:1982}
83
Ruslan Burakov501bfba2019-02-11 09:29:1984void VideoRtpReceiver::SetFrameDecryptor(
85 rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
Tommi4ccdf9322021-05-17 12:50:1086 RTC_DCHECK_RUN_ON(worker_thread_);
Ruslan Burakov501bfba2019-02-11 09:29:1987 frame_decryptor_ = std::move(frame_decryptor);
88 // Special Case: Set the frame decryptor to any value on any existing channel.
Tommi4ccdf9322021-05-17 12:50:1089 if (media_channel_ && ssrc_) {
90 media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
Ruslan Burakov501bfba2019-02-11 09:29:1991 }
92}
93
94rtc::scoped_refptr<FrameDecryptorInterface>
95VideoRtpReceiver::GetFrameDecryptor() const {
Tommi4ccdf9322021-05-17 12:50:1096 RTC_DCHECK_RUN_ON(worker_thread_);
Ruslan Burakov501bfba2019-02-11 09:29:1997 return frame_decryptor_;
98}
99
Marina Ciocea412a31b2020-02-28 15:02:06100void VideoRtpReceiver::SetDepacketizerToDecoderFrameTransformer(
101 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
Tommi4ccdf9322021-05-17 12:50:10102 RTC_DCHECK_RUN_ON(worker_thread_);
103 frame_transformer_ = std::move(frame_transformer);
104 if (media_channel_) {
105 media_channel_->SetDepacketizerToDecoderFrameTransformer(
106 ssrc_.value_or(0), frame_transformer_);
107 }
Marina Ciocea412a31b2020-02-28 15:02:06108}
109
Ruslan Burakov501bfba2019-02-11 09:29:19110void VideoRtpReceiver::Stop() {
Tommi4ccdf9322021-05-17 12:50:10111 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Tommi20d8d912022-02-08 20:12:15112 source_->SetState(MediaSourceInterface::kEnded);
Harald Alvestrand1ee33252020-09-24 13:31:15113 track_->internal()->set_ended();
114}
115
Tommi6589def2022-02-17 22:36:47116void VideoRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
Danil Chapovalov6e7c2682022-07-25 13:58:28117 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Tommi20d8d912022-02-08 20:12:15118 MediaSourceInterface::SourceState state = source_->state();
Tommi4ccdf9322021-05-17 12:50:10119 // TODO(tommi): Can we restart the media channel without blocking?
Tommi20d8d912022-02-08 20:12:15120 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Markus Handell9c27ed22019-12-04 11:57:58121 RTC_DCHECK_RUN_ON(worker_thread_);
Tommi6589def2022-02-17 22:36:47122 RestartMediaChannel_w(std::move(ssrc), state);
Markus Handell9c27ed22019-12-04 11:57:58123 });
Tommi20d8d912022-02-08 20:12:15124 source_->SetState(MediaSourceInterface::kLive);
Saurav Das7262fc22019-09-11 23:23:05125}
126
Tommi6589def2022-02-17 22:36:47127void VideoRtpReceiver::RestartMediaChannel_w(
128 absl::optional<uint32_t> ssrc,
129 MediaSourceInterface::SourceState state) {
Danil Chapovalov6e7c2682022-07-25 13:58:28130 RTC_DCHECK_RUN_ON(worker_thread_);
Tommi6589def2022-02-17 22:36:47131 if (!media_channel_) {
132 return; // Can't restart.
133 }
134
135 const bool encoded_sink_enabled = saved_encoded_sink_enabled_;
136
137 if (state != MediaSourceInterface::kInitializing) {
138 if (ssrc == ssrc_)
139 return;
140
141 // Disconnect from a previous ssrc.
142 SetSink(nullptr);
143
144 if (encoded_sink_enabled)
145 SetEncodedSinkEnabled(false);
146 }
147
148 // Set up the new ssrc.
149 ssrc_ = std::move(ssrc);
150 SetSink(source_->sink());
151 if (encoded_sink_enabled) {
152 SetEncodedSinkEnabled(true);
153 }
154
155 if (frame_transformer_ && media_channel_) {
156 media_channel_->SetDepacketizerToDecoderFrameTransformer(
157 ssrc_.value_or(0), frame_transformer_);
158 }
159
160 if (media_channel_ && ssrc_) {
161 if (frame_decryptor_) {
162 media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
163 }
164
165 media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
166 }
167}
168
Markus Handell9c27ed22019-12-04 11:57:58169void VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
Danil Chapovalov6e7c2682022-07-25 13:58:28170 RTC_DCHECK_RUN_ON(worker_thread_);
Saurav Das749f6602019-12-04 17:31:36171 if (ssrc_) {
172 media_channel_->SetSink(*ssrc_, sink);
Tommi4ccdf9322021-05-17 12:50:10173 } else {
174 media_channel_->SetDefaultSink(sink);
Saurav Das749f6602019-12-04 17:31:36175 }
Markus Handell9c27ed22019-12-04 11:57:58176}
177
Ruslan Burakov501bfba2019-02-11 09:29:19178void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
Tommi4ccdf9322021-05-17 12:50:10179 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Saurav Das7262fc22019-09-11 23:23:05180 RestartMediaChannel(ssrc);
181}
Ruslan Burakov493a6502019-02-27 14:32:48182
Saurav Das7262fc22019-09-11 23:23:05183void VideoRtpReceiver::SetupUnsignaledMediaChannel() {
Tommi4ccdf9322021-05-17 12:50:10184 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Saurav Das7262fc22019-09-11 23:23:05185 RestartMediaChannel(absl::nullopt);
Ruslan Burakov501bfba2019-02-11 09:29:19186}
187
Tommi4ccdf9322021-05-17 12:50:10188uint32_t VideoRtpReceiver::ssrc() const {
189 RTC_DCHECK_RUN_ON(worker_thread_);
190 return ssrc_.value_or(0);
191}
192
Ruslan Burakov501bfba2019-02-11 09:29:19193void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
Tommi4ccdf9322021-05-17 12:50:10194 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Ruslan Burakov501bfba2019-02-11 09:29:19195 SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
196}
197
Tommi4ccdf9322021-05-17 12:50:10198void VideoRtpReceiver::set_transport(
199 rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) {
200 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
201 dtls_transport_ = std::move(dtls_transport);
202}
203
Ruslan Burakov501bfba2019-02-11 09:29:19204void VideoRtpReceiver::SetStreams(
205 const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
Tommi4ccdf9322021-05-17 12:50:10206 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Ruslan Burakov501bfba2019-02-11 09:29:19207 // Remove remote track from any streams that are going away.
208 for (const auto& existing_stream : streams_) {
209 bool removed = true;
210 for (const auto& stream : streams) {
211 if (existing_stream->id() == stream->id()) {
212 RTC_DCHECK_EQ(existing_stream.get(), stream.get());
213 removed = false;
214 break;
215 }
216 }
217 if (removed) {
Harald Alvestrand2f7ad282022-04-21 11:35:43218 existing_stream->RemoveTrack(video_track());
Ruslan Burakov501bfba2019-02-11 09:29:19219 }
220 }
221 // Add remote track to any streams that are new.
222 for (const auto& stream : streams) {
223 bool added = true;
224 for (const auto& existing_stream : streams_) {
225 if (stream->id() == existing_stream->id()) {
226 RTC_DCHECK_EQ(stream.get(), existing_stream.get());
227 added = false;
228 break;
229 }
230 }
231 if (added) {
Harald Alvestrand2f7ad282022-04-21 11:35:43232 stream->AddTrack(video_track());
Ruslan Burakov501bfba2019-02-11 09:29:19233 }
234 }
235 streams_ = streams;
236}
237
238void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
Tommi4ccdf9322021-05-17 12:50:10239 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Ruslan Burakov501bfba2019-02-11 09:29:19240 observer_ = observer;
241 // Deliver any notifications the observer may have missed by being set late.
242 if (received_first_packet_ && observer_) {
243 observer_->OnFirstPacketReceived(media_type());
244 }
245}
246
Ruslan Burakov4bac79e2019-04-03 17:55:33247void VideoRtpReceiver::SetJitterBufferMinimumDelay(
248 absl::optional<double> delay_seconds) {
Tommi4ccdf9322021-05-17 12:50:10249 RTC_DCHECK_RUN_ON(worker_thread_);
250 delay_.Set(delay_seconds);
251 if (media_channel_ && ssrc_)
252 media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
Ruslan Burakov4bac79e2019-04-03 17:55:33253}
254
Ruslan Burakov501bfba2019-02-11 09:29:19255void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
Tommi6589def2022-02-17 22:36:47256 RTC_DCHECK_RUN_ON(worker_thread_);
Ruslan Burakov501bfba2019-02-11 09:29:19257 RTC_DCHECK(media_channel == nullptr ||
258 media_channel->media_type() == media_type());
Tommi4ccdf9322021-05-17 12:50:10259
Tommi6589def2022-02-17 22:36:47260 SetMediaChannel_w(media_channel);
Ruslan Burakov501bfba2019-02-11 09:29:19261}
262
Tommi4ccdf9322021-05-17 12:50:10263void VideoRtpReceiver::SetMediaChannel_w(cricket::MediaChannel* media_channel) {
Danil Chapovalov6e7c2682022-07-25 13:58:28264 RTC_DCHECK_RUN_ON(worker_thread_);
Tommi4ccdf9322021-05-17 12:50:10265 if (media_channel == media_channel_)
266 return;
267
Tommi6589def2022-02-17 22:36:47268 if (!media_channel) {
269 SetSink(nullptr);
270 }
271
Tommi4ccdf9322021-05-17 12:50:10272 bool encoded_sink_enabled = saved_encoded_sink_enabled_;
273 if (encoded_sink_enabled && media_channel_) {
274 // Turn off the old sink, if any.
275 SetEncodedSinkEnabled(false);
276 }
277
278 media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
279
280 if (media_channel_) {
281 if (saved_generate_keyframe_) {
282 // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
283 media_channel_->GenerateKeyFrame(ssrc_.value_or(0));
284 saved_generate_keyframe_ = false;
285 }
286 if (encoded_sink_enabled) {
287 SetEncodedSinkEnabled(true);
288 }
289 if (frame_transformer_) {
290 media_channel_->SetDepacketizerToDecoderFrameTransformer(
291 ssrc_.value_or(0), frame_transformer_);
292 }
293 }
Tommi6589def2022-02-17 22:36:47294
295 if (!media_channel)
296 source_->ClearCallback();
Tommi4ccdf9322021-05-17 12:50:10297}
298
Ruslan Burakov501bfba2019-02-11 09:29:19299void VideoRtpReceiver::NotifyFirstPacketReceived() {
Tommi4ccdf9322021-05-17 12:50:10300 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
Ruslan Burakov501bfba2019-02-11 09:29:19301 if (observer_) {
302 observer_->OnFirstPacketReceived(media_type());
303 }
304 received_first_packet_ = true;
305}
306
307std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
Tommi4ccdf9322021-05-17 12:50:10308 RTC_DCHECK_RUN_ON(worker_thread_);
309 if (!ssrc_ || !media_channel_)
310 return std::vector<RtpSource>();
311 return media_channel_->GetSources(*ssrc_);
Ruslan Burakov501bfba2019-02-11 09:29:19312}
313
Tommi6589def2022-02-17 22:36:47314void VideoRtpReceiver::SetupMediaChannel(absl::optional<uint32_t> ssrc,
315 cricket::MediaChannel* media_channel) {
316 RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
317 RTC_DCHECK(media_channel);
318 MediaSourceInterface::SourceState state = source_->state();
319 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
320 RTC_DCHECK_RUN_ON(worker_thread_);
321 SetMediaChannel_w(media_channel);
322 RestartMediaChannel_w(std::move(ssrc), state);
323 });
324 source_->SetState(MediaSourceInterface::kLive);
325}
326
Markus Handelld5e2f212019-11-26 08:30:08327void VideoRtpReceiver::OnGenerateKeyFrame() {
328 RTC_DCHECK_RUN_ON(worker_thread_);
Markus Handellfc907972019-12-05 11:41:40329 if (!media_channel_) {
330 RTC_LOG(LS_ERROR)
331 << "VideoRtpReceiver::OnGenerateKeyFrame: No video channel exists.";
332 return;
333 }
Markus Handell9c27ed22019-12-04 11:57:58334 // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
335 media_channel_->GenerateKeyFrame(ssrc_.value_or(0));
336 // We need to remember to request generation of a new key frame if the media
337 // channel changes, because there's no feedback whether the keyframe
338 // generation has completed on the channel.
339 saved_generate_keyframe_ = true;
Markus Handelld5e2f212019-11-26 08:30:08340}
341
342void VideoRtpReceiver::OnEncodedSinkEnabled(bool enable) {
343 RTC_DCHECK_RUN_ON(worker_thread_);
Markus Handell9c27ed22019-12-04 11:57:58344 SetEncodedSinkEnabled(enable);
345 // Always save the latest state of the callback in case the media_channel_
346 // changes.
347 saved_encoded_sink_enabled_ = enable;
348}
349
350void VideoRtpReceiver::SetEncodedSinkEnabled(bool enable) {
Danil Chapovalov6e7c2682022-07-25 13:58:28351 RTC_DCHECK_RUN_ON(worker_thread_);
Tommi4ccdf9322021-05-17 12:50:10352 if (!media_channel_)
353 return;
354
355 // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
356 const auto ssrc = ssrc_.value_or(0);
357
358 if (enable) {
359 media_channel_->SetRecordableEncodedFrameCallback(
360 ssrc, [source = source_](const RecordableEncodedFrame& frame) {
361 source->BroadcastRecordableEncodedFrame(frame);
362 });
363 } else {
364 media_channel_->ClearRecordableEncodedFrameCallback(ssrc);
Markus Handell9c27ed22019-12-04 11:57:58365 }
Markus Handelld5e2f212019-11-26 08:30:08366}
367
Ruslan Burakov501bfba2019-02-11 09:29:19368} // namespace webrtc