xref: /aosp_15_r20/external/webrtc/pc/video_rtp_receiver.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/video_rtp_receiver.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "api/video/recordable_encoded_frame.h"
20*d9f75844SAndroid Build Coastguard Worker #include "pc/video_track.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
25*d9f75844SAndroid Build Coastguard Worker 
VideoRtpReceiver(rtc::Thread * worker_thread,std::string receiver_id,std::vector<std::string> stream_ids)26*d9f75844SAndroid Build Coastguard Worker VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
27*d9f75844SAndroid Build Coastguard Worker                                    std::string receiver_id,
28*d9f75844SAndroid Build Coastguard Worker                                    std::vector<std::string> stream_ids)
29*d9f75844SAndroid Build Coastguard Worker     : VideoRtpReceiver(worker_thread,
30*d9f75844SAndroid Build Coastguard Worker                        receiver_id,
31*d9f75844SAndroid Build Coastguard Worker                        CreateStreamsFromIds(std::move(stream_ids))) {}
32*d9f75844SAndroid Build Coastguard Worker 
VideoRtpReceiver(rtc::Thread * worker_thread,const std::string & receiver_id,const std::vector<rtc::scoped_refptr<MediaStreamInterface>> & streams)33*d9f75844SAndroid Build Coastguard Worker VideoRtpReceiver::VideoRtpReceiver(
34*d9f75844SAndroid Build Coastguard Worker     rtc::Thread* worker_thread,
35*d9f75844SAndroid Build Coastguard Worker     const std::string& receiver_id,
36*d9f75844SAndroid Build Coastguard Worker     const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
37*d9f75844SAndroid Build Coastguard Worker     : worker_thread_(worker_thread),
38*d9f75844SAndroid Build Coastguard Worker       id_(receiver_id),
39*d9f75844SAndroid Build Coastguard Worker       source_(rtc::make_ref_counted<VideoRtpTrackSource>(&source_callback_)),
40*d9f75844SAndroid Build Coastguard Worker       track_(VideoTrackProxyWithInternal<VideoTrack>::Create(
41*d9f75844SAndroid Build Coastguard Worker           rtc::Thread::Current(),
42*d9f75844SAndroid Build Coastguard Worker           worker_thread,
43*d9f75844SAndroid Build Coastguard Worker           VideoTrack::Create(receiver_id, source_, worker_thread))),
44*d9f75844SAndroid Build Coastguard Worker       attachment_id_(GenerateUniqueId()) {
45*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(worker_thread_);
46*d9f75844SAndroid Build Coastguard Worker   SetStreams(streams);
47*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(source_->state(), MediaSourceInterface::kInitializing);
48*d9f75844SAndroid Build Coastguard Worker }
49*d9f75844SAndroid Build Coastguard Worker 
~VideoRtpReceiver()50*d9f75844SAndroid Build Coastguard Worker VideoRtpReceiver::~VideoRtpReceiver() {
51*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
52*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!media_channel_);
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker 
stream_ids() const55*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> VideoRtpReceiver::stream_ids() const {
56*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
57*d9f75844SAndroid Build Coastguard Worker   std::vector<std::string> stream_ids(streams_.size());
58*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < streams_.size(); ++i)
59*d9f75844SAndroid Build Coastguard Worker     stream_ids[i] = streams_[i]->id();
60*d9f75844SAndroid Build Coastguard Worker   return stream_ids;
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker 
dtls_transport() const63*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<DtlsTransportInterface> VideoRtpReceiver::dtls_transport()
64*d9f75844SAndroid Build Coastguard Worker     const {
65*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
66*d9f75844SAndroid Build Coastguard Worker   return dtls_transport_;
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker std::vector<rtc::scoped_refptr<MediaStreamInterface>>
streams() const70*d9f75844SAndroid Build Coastguard Worker VideoRtpReceiver::streams() const {
71*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
72*d9f75844SAndroid Build Coastguard Worker   return streams_;
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker 
GetParameters() const75*d9f75844SAndroid Build Coastguard Worker RtpParameters VideoRtpReceiver::GetParameters() const {
76*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
77*d9f75844SAndroid Build Coastguard Worker   if (!media_channel_)
78*d9f75844SAndroid Build Coastguard Worker     return RtpParameters();
79*d9f75844SAndroid Build Coastguard Worker   return ssrc_ ? media_channel_->GetRtpReceiveParameters(*ssrc_)
80*d9f75844SAndroid Build Coastguard Worker                : media_channel_->GetDefaultRtpReceiveParameters();
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker 
SetFrameDecryptor(rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor)83*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetFrameDecryptor(
84*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
85*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
86*d9f75844SAndroid Build Coastguard Worker   frame_decryptor_ = std::move(frame_decryptor);
87*d9f75844SAndroid Build Coastguard Worker   // Special Case: Set the frame decryptor to any value on any existing channel.
88*d9f75844SAndroid Build Coastguard Worker   if (media_channel_ && ssrc_) {
89*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
90*d9f75844SAndroid Build Coastguard Worker   }
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<FrameDecryptorInterface>
GetFrameDecryptor() const94*d9f75844SAndroid Build Coastguard Worker VideoRtpReceiver::GetFrameDecryptor() const {
95*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
96*d9f75844SAndroid Build Coastguard Worker   return frame_decryptor_;
97*d9f75844SAndroid Build Coastguard Worker }
98*d9f75844SAndroid Build Coastguard Worker 
SetDepacketizerToDecoderFrameTransformer(rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)99*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetDepacketizerToDecoderFrameTransformer(
100*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
101*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
102*d9f75844SAndroid Build Coastguard Worker   frame_transformer_ = std::move(frame_transformer);
103*d9f75844SAndroid Build Coastguard Worker   if (media_channel_) {
104*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetDepacketizerToDecoderFrameTransformer(
105*d9f75844SAndroid Build Coastguard Worker         ssrc_.value_or(0), frame_transformer_);
106*d9f75844SAndroid Build Coastguard Worker   }
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker 
Stop()109*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::Stop() {
110*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
111*d9f75844SAndroid Build Coastguard Worker   source_->SetState(MediaSourceInterface::kEnded);
112*d9f75844SAndroid Build Coastguard Worker   track_->internal()->set_ended();
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker 
RestartMediaChannel(absl::optional<uint32_t> ssrc)115*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
116*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
117*d9f75844SAndroid Build Coastguard Worker   MediaSourceInterface::SourceState state = source_->state();
118*d9f75844SAndroid Build Coastguard Worker   // TODO(tommi): Can we restart the media channel without blocking?
119*d9f75844SAndroid Build Coastguard Worker   worker_thread_->BlockingCall([&] {
120*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(worker_thread_);
121*d9f75844SAndroid Build Coastguard Worker     RestartMediaChannel_w(std::move(ssrc), state);
122*d9f75844SAndroid Build Coastguard Worker   });
123*d9f75844SAndroid Build Coastguard Worker   source_->SetState(MediaSourceInterface::kLive);
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker 
RestartMediaChannel_w(absl::optional<uint32_t> ssrc,MediaSourceInterface::SourceState state)126*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::RestartMediaChannel_w(
127*d9f75844SAndroid Build Coastguard Worker     absl::optional<uint32_t> ssrc,
128*d9f75844SAndroid Build Coastguard Worker     MediaSourceInterface::SourceState state) {
129*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
130*d9f75844SAndroid Build Coastguard Worker   if (!media_channel_) {
131*d9f75844SAndroid Build Coastguard Worker     return;  // Can't restart.
132*d9f75844SAndroid Build Coastguard Worker   }
133*d9f75844SAndroid Build Coastguard Worker 
134*d9f75844SAndroid Build Coastguard Worker   const bool encoded_sink_enabled = saved_encoded_sink_enabled_;
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   if (state != MediaSourceInterface::kInitializing) {
137*d9f75844SAndroid Build Coastguard Worker     if (ssrc == ssrc_)
138*d9f75844SAndroid Build Coastguard Worker       return;
139*d9f75844SAndroid Build Coastguard Worker 
140*d9f75844SAndroid Build Coastguard Worker     // Disconnect from a previous ssrc.
141*d9f75844SAndroid Build Coastguard Worker     SetSink(nullptr);
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker     if (encoded_sink_enabled)
144*d9f75844SAndroid Build Coastguard Worker       SetEncodedSinkEnabled(false);
145*d9f75844SAndroid Build Coastguard Worker   }
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   // Set up the new ssrc.
148*d9f75844SAndroid Build Coastguard Worker   ssrc_ = std::move(ssrc);
149*d9f75844SAndroid Build Coastguard Worker   SetSink(source_->sink());
150*d9f75844SAndroid Build Coastguard Worker   if (encoded_sink_enabled) {
151*d9f75844SAndroid Build Coastguard Worker     SetEncodedSinkEnabled(true);
152*d9f75844SAndroid Build Coastguard Worker   }
153*d9f75844SAndroid Build Coastguard Worker 
154*d9f75844SAndroid Build Coastguard Worker   if (frame_transformer_ && media_channel_) {
155*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetDepacketizerToDecoderFrameTransformer(
156*d9f75844SAndroid Build Coastguard Worker         ssrc_.value_or(0), frame_transformer_);
157*d9f75844SAndroid Build Coastguard Worker   }
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker   if (media_channel_ && ssrc_) {
160*d9f75844SAndroid Build Coastguard Worker     if (frame_decryptor_) {
161*d9f75844SAndroid Build Coastguard Worker       media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
162*d9f75844SAndroid Build Coastguard Worker     }
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
165*d9f75844SAndroid Build Coastguard Worker   }
166*d9f75844SAndroid Build Coastguard Worker }
167*d9f75844SAndroid Build Coastguard Worker 
SetSink(rtc::VideoSinkInterface<VideoFrame> * sink)168*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
169*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
170*d9f75844SAndroid Build Coastguard Worker   if (ssrc_) {
171*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetSink(*ssrc_, sink);
172*d9f75844SAndroid Build Coastguard Worker   } else {
173*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetDefaultSink(sink);
174*d9f75844SAndroid Build Coastguard Worker   }
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker 
SetupMediaChannel(uint32_t ssrc)177*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
178*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
179*d9f75844SAndroid Build Coastguard Worker   RestartMediaChannel(ssrc);
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker 
SetupUnsignaledMediaChannel()182*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetupUnsignaledMediaChannel() {
183*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
184*d9f75844SAndroid Build Coastguard Worker   RestartMediaChannel(absl::nullopt);
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker 
ssrc() const187*d9f75844SAndroid Build Coastguard Worker uint32_t VideoRtpReceiver::ssrc() const {
188*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
189*d9f75844SAndroid Build Coastguard Worker   return ssrc_.value_or(0);
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker 
set_stream_ids(std::vector<std::string> stream_ids)192*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
193*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
194*d9f75844SAndroid Build Coastguard Worker   SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker 
set_transport(rtc::scoped_refptr<DtlsTransportInterface> dtls_transport)197*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::set_transport(
198*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) {
199*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
200*d9f75844SAndroid Build Coastguard Worker   dtls_transport_ = std::move(dtls_transport);
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker 
SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>> & streams)203*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetStreams(
204*d9f75844SAndroid Build Coastguard Worker     const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
205*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
206*d9f75844SAndroid Build Coastguard Worker   // Remove remote track from any streams that are going away.
207*d9f75844SAndroid Build Coastguard Worker   for (const auto& existing_stream : streams_) {
208*d9f75844SAndroid Build Coastguard Worker     bool removed = true;
209*d9f75844SAndroid Build Coastguard Worker     for (const auto& stream : streams) {
210*d9f75844SAndroid Build Coastguard Worker       if (existing_stream->id() == stream->id()) {
211*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_EQ(existing_stream.get(), stream.get());
212*d9f75844SAndroid Build Coastguard Worker         removed = false;
213*d9f75844SAndroid Build Coastguard Worker         break;
214*d9f75844SAndroid Build Coastguard Worker       }
215*d9f75844SAndroid Build Coastguard Worker     }
216*d9f75844SAndroid Build Coastguard Worker     if (removed) {
217*d9f75844SAndroid Build Coastguard Worker       existing_stream->RemoveTrack(video_track());
218*d9f75844SAndroid Build Coastguard Worker     }
219*d9f75844SAndroid Build Coastguard Worker   }
220*d9f75844SAndroid Build Coastguard Worker   // Add remote track to any streams that are new.
221*d9f75844SAndroid Build Coastguard Worker   for (const auto& stream : streams) {
222*d9f75844SAndroid Build Coastguard Worker     bool added = true;
223*d9f75844SAndroid Build Coastguard Worker     for (const auto& existing_stream : streams_) {
224*d9f75844SAndroid Build Coastguard Worker       if (stream->id() == existing_stream->id()) {
225*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_EQ(stream.get(), existing_stream.get());
226*d9f75844SAndroid Build Coastguard Worker         added = false;
227*d9f75844SAndroid Build Coastguard Worker         break;
228*d9f75844SAndroid Build Coastguard Worker       }
229*d9f75844SAndroid Build Coastguard Worker     }
230*d9f75844SAndroid Build Coastguard Worker     if (added) {
231*d9f75844SAndroid Build Coastguard Worker       stream->AddTrack(video_track());
232*d9f75844SAndroid Build Coastguard Worker     }
233*d9f75844SAndroid Build Coastguard Worker   }
234*d9f75844SAndroid Build Coastguard Worker   streams_ = streams;
235*d9f75844SAndroid Build Coastguard Worker }
236*d9f75844SAndroid Build Coastguard Worker 
SetObserver(RtpReceiverObserverInterface * observer)237*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
238*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
239*d9f75844SAndroid Build Coastguard Worker   observer_ = observer;
240*d9f75844SAndroid Build Coastguard Worker   // Deliver any notifications the observer may have missed by being set late.
241*d9f75844SAndroid Build Coastguard Worker   if (received_first_packet_ && observer_) {
242*d9f75844SAndroid Build Coastguard Worker     observer_->OnFirstPacketReceived(media_type());
243*d9f75844SAndroid Build Coastguard Worker   }
244*d9f75844SAndroid Build Coastguard Worker }
245*d9f75844SAndroid Build Coastguard Worker 
SetJitterBufferMinimumDelay(absl::optional<double> delay_seconds)246*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetJitterBufferMinimumDelay(
247*d9f75844SAndroid Build Coastguard Worker     absl::optional<double> delay_seconds) {
248*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
249*d9f75844SAndroid Build Coastguard Worker   delay_.Set(delay_seconds);
250*d9f75844SAndroid Build Coastguard Worker   if (media_channel_ && ssrc_)
251*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker 
SetMediaChannel(cricket::MediaChannel * media_channel)254*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
255*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
256*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(media_channel == nullptr ||
257*d9f75844SAndroid Build Coastguard Worker              media_channel->media_type() == media_type());
258*d9f75844SAndroid Build Coastguard Worker 
259*d9f75844SAndroid Build Coastguard Worker   SetMediaChannel_w(media_channel);
260*d9f75844SAndroid Build Coastguard Worker }
261*d9f75844SAndroid Build Coastguard Worker 
SetMediaChannel_w(cricket::MediaChannel * media_channel)262*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetMediaChannel_w(cricket::MediaChannel* media_channel) {
263*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
264*d9f75844SAndroid Build Coastguard Worker   if (media_channel == media_channel_)
265*d9f75844SAndroid Build Coastguard Worker     return;
266*d9f75844SAndroid Build Coastguard Worker 
267*d9f75844SAndroid Build Coastguard Worker   if (!media_channel) {
268*d9f75844SAndroid Build Coastguard Worker     SetSink(nullptr);
269*d9f75844SAndroid Build Coastguard Worker   }
270*d9f75844SAndroid Build Coastguard Worker 
271*d9f75844SAndroid Build Coastguard Worker   bool encoded_sink_enabled = saved_encoded_sink_enabled_;
272*d9f75844SAndroid Build Coastguard Worker   if (encoded_sink_enabled && media_channel_) {
273*d9f75844SAndroid Build Coastguard Worker     // Turn off the old sink, if any.
274*d9f75844SAndroid Build Coastguard Worker     SetEncodedSinkEnabled(false);
275*d9f75844SAndroid Build Coastguard Worker   }
276*d9f75844SAndroid Build Coastguard Worker 
277*d9f75844SAndroid Build Coastguard Worker   media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
278*d9f75844SAndroid Build Coastguard Worker 
279*d9f75844SAndroid Build Coastguard Worker   if (media_channel_) {
280*d9f75844SAndroid Build Coastguard Worker     if (saved_generate_keyframe_) {
281*d9f75844SAndroid Build Coastguard Worker       // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
282*d9f75844SAndroid Build Coastguard Worker       media_channel_->RequestRecvKeyFrame(ssrc_.value_or(0));
283*d9f75844SAndroid Build Coastguard Worker       saved_generate_keyframe_ = false;
284*d9f75844SAndroid Build Coastguard Worker     }
285*d9f75844SAndroid Build Coastguard Worker     if (encoded_sink_enabled) {
286*d9f75844SAndroid Build Coastguard Worker       SetEncodedSinkEnabled(true);
287*d9f75844SAndroid Build Coastguard Worker     }
288*d9f75844SAndroid Build Coastguard Worker     if (frame_transformer_) {
289*d9f75844SAndroid Build Coastguard Worker       media_channel_->SetDepacketizerToDecoderFrameTransformer(
290*d9f75844SAndroid Build Coastguard Worker           ssrc_.value_or(0), frame_transformer_);
291*d9f75844SAndroid Build Coastguard Worker     }
292*d9f75844SAndroid Build Coastguard Worker   }
293*d9f75844SAndroid Build Coastguard Worker 
294*d9f75844SAndroid Build Coastguard Worker   if (!media_channel)
295*d9f75844SAndroid Build Coastguard Worker     source_->ClearCallback();
296*d9f75844SAndroid Build Coastguard Worker }
297*d9f75844SAndroid Build Coastguard Worker 
NotifyFirstPacketReceived()298*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::NotifyFirstPacketReceived() {
299*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
300*d9f75844SAndroid Build Coastguard Worker   if (observer_) {
301*d9f75844SAndroid Build Coastguard Worker     observer_->OnFirstPacketReceived(media_type());
302*d9f75844SAndroid Build Coastguard Worker   }
303*d9f75844SAndroid Build Coastguard Worker   received_first_packet_ = true;
304*d9f75844SAndroid Build Coastguard Worker }
305*d9f75844SAndroid Build Coastguard Worker 
GetSources() const306*d9f75844SAndroid Build Coastguard Worker std::vector<RtpSource> VideoRtpReceiver::GetSources() const {
307*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
308*d9f75844SAndroid Build Coastguard Worker   if (!ssrc_ || !media_channel_)
309*d9f75844SAndroid Build Coastguard Worker     return std::vector<RtpSource>();
310*d9f75844SAndroid Build Coastguard Worker   return media_channel_->GetSources(*ssrc_);
311*d9f75844SAndroid Build Coastguard Worker }
312*d9f75844SAndroid Build Coastguard Worker 
SetupMediaChannel(absl::optional<uint32_t> ssrc,cricket::MediaChannel * media_channel)313*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetupMediaChannel(absl::optional<uint32_t> ssrc,
314*d9f75844SAndroid Build Coastguard Worker                                          cricket::MediaChannel* media_channel) {
315*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
316*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(media_channel);
317*d9f75844SAndroid Build Coastguard Worker   MediaSourceInterface::SourceState state = source_->state();
318*d9f75844SAndroid Build Coastguard Worker   worker_thread_->BlockingCall([&] {
319*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(worker_thread_);
320*d9f75844SAndroid Build Coastguard Worker     SetMediaChannel_w(media_channel);
321*d9f75844SAndroid Build Coastguard Worker     RestartMediaChannel_w(std::move(ssrc), state);
322*d9f75844SAndroid Build Coastguard Worker   });
323*d9f75844SAndroid Build Coastguard Worker   source_->SetState(MediaSourceInterface::kLive);
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker 
OnGenerateKeyFrame()326*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::OnGenerateKeyFrame() {
327*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
328*d9f75844SAndroid Build Coastguard Worker   if (!media_channel_) {
329*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR)
330*d9f75844SAndroid Build Coastguard Worker         << "VideoRtpReceiver::OnGenerateKeyFrame: No video channel exists.";
331*d9f75844SAndroid Build Coastguard Worker     return;
332*d9f75844SAndroid Build Coastguard Worker   }
333*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
334*d9f75844SAndroid Build Coastguard Worker   media_channel_->RequestRecvKeyFrame(ssrc_.value_or(0));
335*d9f75844SAndroid Build Coastguard Worker   // We need to remember to request generation of a new key frame if the media
336*d9f75844SAndroid Build Coastguard Worker   // channel changes, because there's no feedback whether the keyframe
337*d9f75844SAndroid Build Coastguard Worker   // generation has completed on the channel.
338*d9f75844SAndroid Build Coastguard Worker   saved_generate_keyframe_ = true;
339*d9f75844SAndroid Build Coastguard Worker }
340*d9f75844SAndroid Build Coastguard Worker 
OnEncodedSinkEnabled(bool enable)341*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::OnEncodedSinkEnabled(bool enable) {
342*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
343*d9f75844SAndroid Build Coastguard Worker   SetEncodedSinkEnabled(enable);
344*d9f75844SAndroid Build Coastguard Worker   // Always save the latest state of the callback in case the media_channel_
345*d9f75844SAndroid Build Coastguard Worker   // changes.
346*d9f75844SAndroid Build Coastguard Worker   saved_encoded_sink_enabled_ = enable;
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker 
SetEncodedSinkEnabled(bool enable)349*d9f75844SAndroid Build Coastguard Worker void VideoRtpReceiver::SetEncodedSinkEnabled(bool enable) {
350*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(worker_thread_);
351*d9f75844SAndroid Build Coastguard Worker   if (!media_channel_)
352*d9f75844SAndroid Build Coastguard Worker     return;
353*d9f75844SAndroid Build Coastguard Worker 
354*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC
355*d9f75844SAndroid Build Coastguard Worker   const auto ssrc = ssrc_.value_or(0);
356*d9f75844SAndroid Build Coastguard Worker 
357*d9f75844SAndroid Build Coastguard Worker   if (enable) {
358*d9f75844SAndroid Build Coastguard Worker     media_channel_->SetRecordableEncodedFrameCallback(
359*d9f75844SAndroid Build Coastguard Worker         ssrc, [source = source_](const RecordableEncodedFrame& frame) {
360*d9f75844SAndroid Build Coastguard Worker           source->BroadcastRecordableEncodedFrame(frame);
361*d9f75844SAndroid Build Coastguard Worker         });
362*d9f75844SAndroid Build Coastguard Worker   } else {
363*d9f75844SAndroid Build Coastguard Worker     media_channel_->ClearRecordableEncodedFrameCallback(ssrc);
364*d9f75844SAndroid Build Coastguard Worker   }
365*d9f75844SAndroid Build Coastguard Worker }
366*d9f75844SAndroid Build Coastguard Worker 
367*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
368