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