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