OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 codec.width = 320; | 137 codec.width = 320; |
138 codec.height = 180; | 138 codec.height = 180; |
139 codec.startBitrate = codec.minBitrate = codec.maxBitrate = | 139 codec.startBitrate = codec.minBitrate = codec.maxBitrate = |
140 Call::Config::kDefaultStartBitrateBps / 1000; | 140 Call::Config::kDefaultStartBitrateBps / 1000; |
141 | 141 |
142 return codec; | 142 return codec; |
143 } | 143 } |
144 } // namespace | 144 } // namespace |
145 | 145 |
146 namespace internal { | 146 namespace internal { |
147 | |
148 // Since an IncomingVideoStream instance will create a thread/queue, we don't | |
149 // instantiate one unless we know we're going to be delivering the frames | |
150 // to a renderer. | |
151 // | |
152 // TODO(tommi): Consider making the functionality provided by the | |
153 // IncomingVideoStream classes, tied to the Config class instead or even higher | |
154 // level. That will make it an optional feature that will be up to the | |
155 // application to use or not use. Right now, we have two classes available, | |
156 // they both have threads involved which uses WebRTC's threading classes and | |
157 // that might not suit what the application wants to do. If one of them or | |
158 // neither, suits, the app can get some code size back as well as more control. | |
159 std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> | |
160 MaybeCreateIncomingVideoStream(const VideoReceiveStream::Config& config, | |
161 rtc::VideoSinkInterface<VideoFrame>* callback) { | |
162 std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> ret; | |
163 if (config.renderer) { | |
164 if (config.disable_prerenderer_smoothing) { | |
165 ret.reset(new IncomingVideoStreamNoSmoothing(callback)); | |
166 } else { | |
167 ret.reset(new IncomingVideoStream(config.render_delay_ms, callback)); | |
168 } | |
169 } | |
170 return ret; | |
171 } | |
172 | |
173 VideoReceiveStream::VideoReceiveStream( | 147 VideoReceiveStream::VideoReceiveStream( |
174 int num_cpu_cores, | 148 int num_cpu_cores, |
175 CongestionController* congestion_controller, | 149 CongestionController* congestion_controller, |
176 VideoReceiveStream::Config config, | 150 VideoReceiveStream::Config config, |
177 webrtc::VoiceEngine* voice_engine, | 151 webrtc::VoiceEngine* voice_engine, |
178 ProcessThread* process_thread, | 152 ProcessThread* process_thread, |
179 CallStats* call_stats, | 153 CallStats* call_stats, |
180 VieRemb* remb) | 154 VieRemb* remb) |
181 : transport_adapter_(config.rtcp_send_transport), | 155 : transport_adapter_(config.rtcp_send_transport), |
182 encoded_frame_proxy_(config.pre_decode_callback), | 156 encoded_frame_proxy_(config.pre_decode_callback), |
183 config_(std::move(config)), | 157 config_(std::move(config)), |
184 process_thread_(process_thread), | 158 process_thread_(process_thread), |
185 clock_(Clock::GetRealTimeClock()), | 159 clock_(Clock::GetRealTimeClock()), |
186 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), | 160 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), |
187 congestion_controller_(congestion_controller), | 161 congestion_controller_(congestion_controller), |
188 call_stats_(call_stats), | 162 call_stats_(call_stats), |
189 video_receiver_(clock_, nullptr, this, this, this), | 163 video_receiver_(clock_, nullptr, this, this, this), |
| 164 incoming_video_stream_(config_.disable_prerenderer_smoothing), |
190 stats_proxy_(&config_, clock_), | 165 stats_proxy_(&config_, clock_), |
191 rtp_stream_receiver_(&video_receiver_, | 166 rtp_stream_receiver_(&video_receiver_, |
192 congestion_controller_->GetRemoteBitrateEstimator( | 167 congestion_controller_->GetRemoteBitrateEstimator( |
193 UseSendSideBwe(config_)), | 168 UseSendSideBwe(config_)), |
194 &transport_adapter_, | 169 &transport_adapter_, |
195 call_stats_->rtcp_rtt_stats(), | 170 call_stats_->rtcp_rtt_stats(), |
196 congestion_controller_->pacer(), | 171 congestion_controller_->pacer(), |
197 congestion_controller_->packet_router(), | 172 congestion_controller_->packet_router(), |
198 remb, | 173 remb, |
199 &config_, | 174 &config_, |
200 &stats_proxy_, | 175 &stats_proxy_, |
201 process_thread_), | 176 process_thread_), |
| 177 video_stream_decoder_(&video_receiver_, |
| 178 &rtp_stream_receiver_, |
| 179 &rtp_stream_receiver_, |
| 180 rtp_stream_receiver_.IsRetransmissionsEnabled(), |
| 181 rtp_stream_receiver_.IsFecEnabled(), |
| 182 &stats_proxy_, |
| 183 &incoming_video_stream_, |
| 184 config.pre_render_callback), |
202 vie_sync_(&video_receiver_) { | 185 vie_sync_(&video_receiver_) { |
203 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); | 186 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); |
204 | 187 |
205 RTC_DCHECK(process_thread_); | 188 RTC_DCHECK(process_thread_); |
206 RTC_DCHECK(congestion_controller_); | 189 RTC_DCHECK(congestion_controller_); |
207 RTC_DCHECK(call_stats_); | 190 RTC_DCHECK(call_stats_); |
208 | 191 |
| 192 // Register the channel to receive stats updates. |
| 193 call_stats_->RegisterStatsObserver(&video_stream_decoder_); |
| 194 |
209 RTC_DCHECK(!config_.decoders.empty()); | 195 RTC_DCHECK(!config_.decoders.empty()); |
210 std::set<int> decoder_payload_types; | 196 std::set<int> decoder_payload_types; |
211 for (const Decoder& decoder : config_.decoders) { | 197 for (const Decoder& decoder : config_.decoders) { |
212 RTC_CHECK(decoder.decoder); | 198 RTC_CHECK(decoder.decoder); |
213 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == | 199 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == |
214 decoder_payload_types.end()) | 200 decoder_payload_types.end()) |
215 << "Duplicate payload type (" << decoder.payload_type | 201 << "Duplicate payload type (" << decoder.payload_type |
216 << ") for different decoders."; | 202 << ") for different decoders."; |
217 decoder_payload_types.insert(decoder.payload_type); | 203 decoder_payload_types.insert(decoder.payload_type); |
218 video_receiver_.RegisterExternalDecoder(decoder.decoder, | 204 video_receiver_.RegisterExternalDecoder(decoder.decoder, |
219 decoder.payload_type); | 205 decoder.payload_type); |
220 | 206 |
221 VideoCodec codec = CreateDecoderVideoCodec(decoder); | 207 VideoCodec codec = CreateDecoderVideoCodec(decoder); |
222 RTC_CHECK(rtp_stream_receiver_.SetReceiveCodec(codec)); | 208 RTC_CHECK(rtp_stream_receiver_.SetReceiveCodec(codec)); |
223 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( | 209 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( |
224 &codec, num_cpu_cores, false)); | 210 &codec, num_cpu_cores, false)); |
225 } | 211 } |
226 | 212 |
227 video_receiver_.SetRenderDelay(config.render_delay_ms); | 213 video_receiver_.SetRenderDelay(config.render_delay_ms); |
| 214 incoming_video_stream_.SetExpectedRenderDelay(config.render_delay_ms); |
| 215 incoming_video_stream_.SetExternalCallback(this); |
228 | 216 |
229 process_thread_->RegisterModule(&video_receiver_); | 217 process_thread_->RegisterModule(&video_receiver_); |
230 process_thread_->RegisterModule(&vie_sync_); | 218 process_thread_->RegisterModule(&vie_sync_); |
231 } | 219 } |
232 | 220 |
233 VideoReceiveStream::~VideoReceiveStream() { | 221 VideoReceiveStream::~VideoReceiveStream() { |
234 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); | 222 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); |
235 Stop(); | 223 Stop(); |
236 | 224 |
237 process_thread_->DeRegisterModule(&vie_sync_); | 225 process_thread_->DeRegisterModule(&vie_sync_); |
238 process_thread_->DeRegisterModule(&video_receiver_); | 226 process_thread_->DeRegisterModule(&video_receiver_); |
239 | 227 |
240 // Deregister external decoders so they are no longer running during | 228 // Deregister external decoders so they are no longer running during |
241 // destruction. This effectively stops the VCM since the decoder thread is | 229 // destruction. This effectively stops the VCM since the decoder thread is |
242 // stopped, the VCM is deregistered and no asynchronous decoder threads are | 230 // stopped, the VCM is deregistered and no asynchronous decoder threads are |
243 // running. | 231 // running. |
244 for (const Decoder& decoder : config_.decoders) | 232 for (const Decoder& decoder : config_.decoders) |
245 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); | 233 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); |
246 | 234 |
| 235 call_stats_->DeregisterStatsObserver(&video_stream_decoder_); |
| 236 |
247 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) | 237 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) |
248 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); | 238 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); |
249 } | 239 } |
250 | 240 |
251 void VideoReceiveStream::SignalNetworkState(NetworkState state) { | 241 void VideoReceiveStream::SignalNetworkState(NetworkState state) { |
252 rtp_stream_receiver_.SignalNetworkState(state); | 242 rtp_stream_receiver_.SignalNetworkState(state); |
253 } | 243 } |
254 | 244 |
255 | 245 |
256 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 246 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
257 return rtp_stream_receiver_.DeliverRtcp(packet, length); | 247 return rtp_stream_receiver_.DeliverRtcp(packet, length); |
258 } | 248 } |
259 | 249 |
260 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, | 250 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, |
261 size_t length, | 251 size_t length, |
262 const PacketTime& packet_time) { | 252 const PacketTime& packet_time) { |
263 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); | 253 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); |
264 } | 254 } |
265 | 255 |
266 void VideoReceiveStream::Start() { | 256 void VideoReceiveStream::Start() { |
267 if (decode_thread_.IsRunning()) | 257 if (decode_thread_.IsRunning()) |
268 return; | 258 return; |
269 transport_adapter_.Enable(); | 259 transport_adapter_.Enable(); |
270 incoming_video_stream_ = MaybeCreateIncomingVideoStream(config_, this); | 260 incoming_video_stream_.Start(); |
271 video_stream_decoder_.reset(new VideoStreamDecoder( | |
272 &video_receiver_, &rtp_stream_receiver_, &rtp_stream_receiver_, | |
273 rtp_stream_receiver_.IsRetransmissionsEnabled(), | |
274 rtp_stream_receiver_.IsFecEnabled(), &stats_proxy_, | |
275 incoming_video_stream_.get(), config_.pre_render_callback)); | |
276 // Register the channel to receive stats updates. | |
277 call_stats_->RegisterStatsObserver(video_stream_decoder_.get()); | |
278 // Start the decode thread | 261 // Start the decode thread |
279 decode_thread_.Start(); | 262 decode_thread_.Start(); |
280 decode_thread_.SetPriority(rtc::kHighestPriority); | 263 decode_thread_.SetPriority(rtc::kHighestPriority); |
281 rtp_stream_receiver_.StartReceive(); | 264 rtp_stream_receiver_.StartReceive(); |
282 } | 265 } |
283 | 266 |
284 void VideoReceiveStream::Stop() { | 267 void VideoReceiveStream::Stop() { |
| 268 incoming_video_stream_.Stop(); |
285 rtp_stream_receiver_.StopReceive(); | 269 rtp_stream_receiver_.StopReceive(); |
286 video_receiver_.TriggerDecoderShutdown(); | 270 video_receiver_.TriggerDecoderShutdown(); |
287 decode_thread_.Stop(); | 271 decode_thread_.Stop(); |
288 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); | |
289 video_stream_decoder_.reset(); | |
290 incoming_video_stream_.reset(); | |
291 transport_adapter_.Disable(); | 272 transport_adapter_.Disable(); |
292 } | 273 } |
293 | 274 |
294 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, | 275 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, |
295 int audio_channel_id) { | 276 int audio_channel_id) { |
296 if (voice_engine && audio_channel_id != -1) { | 277 if (voice_engine && audio_channel_id != -1) { |
297 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); | 278 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); |
298 vie_sync_.ConfigureSync(audio_channel_id, voe_sync_interface, | 279 vie_sync_.ConfigureSync(audio_channel_id, voe_sync_interface, |
299 rtp_stream_receiver_.rtp_rtcp(), | 280 rtp_stream_receiver_.rtp_rtcp(), |
300 rtp_stream_receiver_.GetRtpReceiver()); | 281 rtp_stream_receiver_.GetRtpReceiver()); |
301 voe_sync_interface->Release(); | 282 voe_sync_interface->Release(); |
302 } else { | 283 } else { |
303 vie_sync_.ConfigureSync(-1, nullptr, rtp_stream_receiver_.rtp_rtcp(), | 284 vie_sync_.ConfigureSync(-1, nullptr, rtp_stream_receiver_.rtp_rtcp(), |
304 rtp_stream_receiver_.GetRtpReceiver()); | 285 rtp_stream_receiver_.GetRtpReceiver()); |
305 } | 286 } |
306 } | 287 } |
307 | 288 |
308 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { | 289 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { |
309 return stats_proxy_.GetStats(); | 290 return stats_proxy_.GetStats(); |
310 } | 291 } |
311 | 292 |
312 // TODO(tommi): This method grabs a lock 6 times. | |
313 void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { | 293 void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { |
314 // TODO(tommi): OnDecodedFrame grabs a lock, incidentally the same lock | |
315 // that OnSyncOffsetUpdated() and OnRenderedFrame() below grab. | |
316 stats_proxy_.OnDecodedFrame(); | 294 stats_proxy_.OnDecodedFrame(); |
317 | 295 |
318 int64_t sync_offset_ms; | 296 int64_t sync_offset_ms; |
319 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the | 297 if (vie_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms)) |
320 // function itself, another in GetChannel() and a third in | |
321 // GetPlayoutTimestamp. Seems excessive. Anyhow, I'm assuming the function | |
322 // succeeds most of the time, which leads to grabbing a fourth lock. | |
323 if (vie_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms)) { | |
324 // TODO(tommi): OnSyncOffsetUpdated grabs a lock. | |
325 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms); | 298 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms); |
326 } | |
327 | 299 |
328 // config_.renderer must never be null if we're getting this callback. | 300 if (config_.renderer) |
329 config_.renderer->OnFrame(video_frame); | 301 config_.renderer->OnFrame(video_frame); |
330 | 302 |
331 // TODO(tommi): OnRenderFrame grabs a lock too. | |
332 stats_proxy_.OnRenderedFrame(video_frame.width(), video_frame.height()); | 303 stats_proxy_.OnRenderedFrame(video_frame.width(), video_frame.height()); |
333 } | 304 } |
334 | 305 |
335 // TODO(asapersson): Consider moving callback from video_encoder.h or | 306 // TODO(asapersson): Consider moving callback from video_encoder.h or |
336 // creating a different callback. | 307 // creating a different callback. |
337 int32_t VideoReceiveStream::Encoded( | 308 int32_t VideoReceiveStream::Encoded( |
338 const EncodedImage& encoded_image, | 309 const EncodedImage& encoded_image, |
339 const CodecSpecificInfo* codec_specific_info, | 310 const CodecSpecificInfo* codec_specific_info, |
340 const RTPFragmentationHeader* fragmentation) { | 311 const RTPFragmentationHeader* fragmentation) { |
341 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); | 312 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 const std::vector<uint16_t>& sequence_numbers) { | 346 const std::vector<uint16_t>& sequence_numbers) { |
376 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); | 347 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); |
377 } | 348 } |
378 | 349 |
379 void VideoReceiveStream::RequestKeyFrame() { | 350 void VideoReceiveStream::RequestKeyFrame() { |
380 rtp_stream_receiver_.RequestKeyFrame(); | 351 rtp_stream_receiver_.RequestKeyFrame(); |
381 } | 352 } |
382 | 353 |
383 } // namespace internal | 354 } // namespace internal |
384 } // namespace webrtc | 355 } // namespace webrtc |
OLD | NEW |