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 |
147 VideoReceiveStream::VideoReceiveStream( | 173 VideoReceiveStream::VideoReceiveStream( |
148 int num_cpu_cores, | 174 int num_cpu_cores, |
149 CongestionController* congestion_controller, | 175 CongestionController* congestion_controller, |
150 VideoReceiveStream::Config config, | 176 VideoReceiveStream::Config config, |
151 webrtc::VoiceEngine* voice_engine, | 177 webrtc::VoiceEngine* voice_engine, |
152 ProcessThread* process_thread, | 178 ProcessThread* process_thread, |
153 CallStats* call_stats, | 179 CallStats* call_stats, |
154 VieRemb* remb) | 180 VieRemb* remb) |
155 : transport_adapter_(config.rtcp_send_transport), | 181 : transport_adapter_(config.rtcp_send_transport), |
156 encoded_frame_proxy_(config.pre_decode_callback), | 182 encoded_frame_proxy_(config.pre_decode_callback), |
157 config_(std::move(config)), | 183 config_(std::move(config)), |
158 process_thread_(process_thread), | 184 process_thread_(process_thread), |
159 clock_(Clock::GetRealTimeClock()), | 185 clock_(Clock::GetRealTimeClock()), |
160 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), | 186 decode_thread_(DecodeThreadFunction, this, "DecodingThread"), |
161 congestion_controller_(congestion_controller), | 187 congestion_controller_(congestion_controller), |
162 call_stats_(call_stats), | 188 call_stats_(call_stats), |
163 video_receiver_(clock_, nullptr, this, this, this), | 189 video_receiver_(clock_, nullptr, this, this, this), |
164 incoming_video_stream_(config_.disable_prerenderer_smoothing), | |
165 stats_proxy_(&config_, clock_), | 190 stats_proxy_(&config_, clock_), |
166 rtp_stream_receiver_(&video_receiver_, | 191 rtp_stream_receiver_(&video_receiver_, |
167 congestion_controller_->GetRemoteBitrateEstimator( | 192 congestion_controller_->GetRemoteBitrateEstimator( |
168 UseSendSideBwe(config_)), | 193 UseSendSideBwe(config_)), |
169 &transport_adapter_, | 194 &transport_adapter_, |
170 call_stats_->rtcp_rtt_stats(), | 195 call_stats_->rtcp_rtt_stats(), |
171 congestion_controller_->pacer(), | 196 congestion_controller_->pacer(), |
172 congestion_controller_->packet_router(), | 197 congestion_controller_->packet_router(), |
173 remb, | 198 remb, |
174 &config_, | 199 &config_, |
175 &stats_proxy_, | 200 &stats_proxy_, |
176 process_thread_), | 201 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), | |
185 vie_sync_(&video_receiver_) { | 202 vie_sync_(&video_receiver_) { |
186 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); | 203 LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString(); |
187 | 204 |
188 RTC_DCHECK(process_thread_); | 205 RTC_DCHECK(process_thread_); |
189 RTC_DCHECK(congestion_controller_); | 206 RTC_DCHECK(congestion_controller_); |
190 RTC_DCHECK(call_stats_); | 207 RTC_DCHECK(call_stats_); |
191 | 208 |
192 // Register the channel to receive stats updates. | |
193 call_stats_->RegisterStatsObserver(&video_stream_decoder_); | |
194 | |
195 RTC_DCHECK(!config_.decoders.empty()); | 209 RTC_DCHECK(!config_.decoders.empty()); |
196 std::set<int> decoder_payload_types; | 210 std::set<int> decoder_payload_types; |
197 for (const Decoder& decoder : config_.decoders) { | 211 for (const Decoder& decoder : config_.decoders) { |
198 RTC_CHECK(decoder.decoder); | 212 RTC_CHECK(decoder.decoder); |
199 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == | 213 RTC_CHECK(decoder_payload_types.find(decoder.payload_type) == |
200 decoder_payload_types.end()) | 214 decoder_payload_types.end()) |
201 << "Duplicate payload type (" << decoder.payload_type | 215 << "Duplicate payload type (" << decoder.payload_type |
202 << ") for different decoders."; | 216 << ") for different decoders."; |
203 decoder_payload_types.insert(decoder.payload_type); | 217 decoder_payload_types.insert(decoder.payload_type); |
204 video_receiver_.RegisterExternalDecoder(decoder.decoder, | 218 video_receiver_.RegisterExternalDecoder(decoder.decoder, |
205 decoder.payload_type); | 219 decoder.payload_type); |
206 | 220 |
207 VideoCodec codec = CreateDecoderVideoCodec(decoder); | 221 VideoCodec codec = CreateDecoderVideoCodec(decoder); |
208 RTC_CHECK(rtp_stream_receiver_.SetReceiveCodec(codec)); | 222 RTC_CHECK(rtp_stream_receiver_.SetReceiveCodec(codec)); |
209 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( | 223 RTC_CHECK_EQ(VCM_OK, video_receiver_.RegisterReceiveCodec( |
210 &codec, num_cpu_cores, false)); | 224 &codec, num_cpu_cores, false)); |
211 } | 225 } |
212 | 226 |
213 video_receiver_.SetRenderDelay(config.render_delay_ms); | 227 video_receiver_.SetRenderDelay(config.render_delay_ms); |
214 incoming_video_stream_.SetExpectedRenderDelay(config.render_delay_ms); | |
215 incoming_video_stream_.SetExternalCallback(this); | |
216 | 228 |
217 process_thread_->RegisterModule(&video_receiver_); | 229 process_thread_->RegisterModule(&video_receiver_); |
218 process_thread_->RegisterModule(&vie_sync_); | 230 process_thread_->RegisterModule(&vie_sync_); |
219 } | 231 } |
220 | 232 |
221 VideoReceiveStream::~VideoReceiveStream() { | 233 VideoReceiveStream::~VideoReceiveStream() { |
222 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); | 234 LOG(LS_INFO) << "~VideoReceiveStream: " << config_.ToString(); |
223 Stop(); | 235 Stop(); |
224 | 236 |
225 process_thread_->DeRegisterModule(&vie_sync_); | 237 process_thread_->DeRegisterModule(&vie_sync_); |
226 process_thread_->DeRegisterModule(&video_receiver_); | 238 process_thread_->DeRegisterModule(&video_receiver_); |
227 | 239 |
228 // Deregister external decoders so they are no longer running during | 240 // Deregister external decoders so they are no longer running during |
229 // destruction. This effectively stops the VCM since the decoder thread is | 241 // destruction. This effectively stops the VCM since the decoder thread is |
230 // stopped, the VCM is deregistered and no asynchronous decoder threads are | 242 // stopped, the VCM is deregistered and no asynchronous decoder threads are |
231 // running. | 243 // running. |
232 for (const Decoder& decoder : config_.decoders) | 244 for (const Decoder& decoder : config_.decoders) |
233 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); | 245 video_receiver_.RegisterExternalDecoder(nullptr, decoder.payload_type); |
234 | 246 |
235 call_stats_->DeregisterStatsObserver(&video_stream_decoder_); | |
236 | |
237 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) | 247 congestion_controller_->GetRemoteBitrateEstimator(UseSendSideBwe(config_)) |
238 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); | 248 ->RemoveStream(rtp_stream_receiver_.GetRemoteSsrc()); |
239 } | 249 } |
240 | 250 |
241 void VideoReceiveStream::SignalNetworkState(NetworkState state) { | 251 void VideoReceiveStream::SignalNetworkState(NetworkState state) { |
242 rtp_stream_receiver_.SignalNetworkState(state); | 252 rtp_stream_receiver_.SignalNetworkState(state); |
243 } | 253 } |
244 | 254 |
245 | 255 |
246 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 256 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
247 return rtp_stream_receiver_.DeliverRtcp(packet, length); | 257 return rtp_stream_receiver_.DeliverRtcp(packet, length); |
248 } | 258 } |
249 | 259 |
250 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, | 260 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, |
251 size_t length, | 261 size_t length, |
252 const PacketTime& packet_time) { | 262 const PacketTime& packet_time) { |
253 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); | 263 return rtp_stream_receiver_.DeliverRtp(packet, length, packet_time); |
254 } | 264 } |
255 | 265 |
256 void VideoReceiveStream::Start() { | 266 void VideoReceiveStream::Start() { |
257 if (decode_thread_.IsRunning()) | 267 if (decode_thread_.IsRunning()) |
258 return; | 268 return; |
259 transport_adapter_.Enable(); | 269 transport_adapter_.Enable(); |
260 incoming_video_stream_.Start(); | 270 incoming_video_stream_ = MaybeCreateIncomingVideoStream(config_, this); |
| 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()); |
261 // Start the decode thread | 278 // Start the decode thread |
262 decode_thread_.Start(); | 279 decode_thread_.Start(); |
263 decode_thread_.SetPriority(rtc::kHighestPriority); | 280 decode_thread_.SetPriority(rtc::kHighestPriority); |
264 rtp_stream_receiver_.StartReceive(); | 281 rtp_stream_receiver_.StartReceive(); |
265 } | 282 } |
266 | 283 |
267 void VideoReceiveStream::Stop() { | 284 void VideoReceiveStream::Stop() { |
268 incoming_video_stream_.Stop(); | |
269 rtp_stream_receiver_.StopReceive(); | 285 rtp_stream_receiver_.StopReceive(); |
270 video_receiver_.TriggerDecoderShutdown(); | 286 video_receiver_.TriggerDecoderShutdown(); |
271 decode_thread_.Stop(); | 287 decode_thread_.Stop(); |
| 288 call_stats_->DeregisterStatsObserver(video_stream_decoder_.get()); |
| 289 video_stream_decoder_.reset(); |
| 290 incoming_video_stream_.reset(); |
272 transport_adapter_.Disable(); | 291 transport_adapter_.Disable(); |
273 } | 292 } |
274 | 293 |
275 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, | 294 void VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine, |
276 int audio_channel_id) { | 295 int audio_channel_id) { |
277 if (voice_engine && audio_channel_id != -1) { | 296 if (voice_engine && audio_channel_id != -1) { |
278 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); | 297 VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine); |
279 vie_sync_.ConfigureSync(audio_channel_id, voe_sync_interface, | 298 vie_sync_.ConfigureSync(audio_channel_id, voe_sync_interface, |
280 rtp_stream_receiver_.rtp_rtcp(), | 299 rtp_stream_receiver_.rtp_rtcp(), |
281 rtp_stream_receiver_.GetRtpReceiver()); | 300 rtp_stream_receiver_.GetRtpReceiver()); |
282 voe_sync_interface->Release(); | 301 voe_sync_interface->Release(); |
283 } else { | 302 } else { |
284 vie_sync_.ConfigureSync(-1, nullptr, rtp_stream_receiver_.rtp_rtcp(), | 303 vie_sync_.ConfigureSync(-1, nullptr, rtp_stream_receiver_.rtp_rtcp(), |
285 rtp_stream_receiver_.GetRtpReceiver()); | 304 rtp_stream_receiver_.GetRtpReceiver()); |
286 } | 305 } |
287 } | 306 } |
288 | 307 |
289 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { | 308 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { |
290 return stats_proxy_.GetStats(); | 309 return stats_proxy_.GetStats(); |
291 } | 310 } |
292 | 311 |
| 312 // TODO(tommi): This method grabs a lock 6 times. |
293 void VideoReceiveStream::OnFrame(const VideoFrame& video_frame) { | 313 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. |
294 stats_proxy_.OnDecodedFrame(); | 316 stats_proxy_.OnDecodedFrame(); |
295 | 317 |
296 int64_t sync_offset_ms; | 318 int64_t sync_offset_ms; |
297 if (vie_sync_.GetStreamSyncOffsetInMs(video_frame, &sync_offset_ms)) | 319 // TODO(tommi): GetStreamSyncOffsetInMs grabs three locks. One inside the |
| 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. |
298 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms); | 325 stats_proxy_.OnSyncOffsetUpdated(sync_offset_ms); |
| 326 } |
299 | 327 |
300 if (config_.renderer) | 328 // config_.renderer must never be null if we're getting this callback. |
301 config_.renderer->OnFrame(video_frame); | 329 config_.renderer->OnFrame(video_frame); |
302 | 330 |
| 331 // TODO(tommi): OnRenderFrame grabs a lock too. |
303 stats_proxy_.OnRenderedFrame(video_frame.width(), video_frame.height()); | 332 stats_proxy_.OnRenderedFrame(video_frame.width(), video_frame.height()); |
304 } | 333 } |
305 | 334 |
306 // TODO(asapersson): Consider moving callback from video_encoder.h or | 335 // TODO(asapersson): Consider moving callback from video_encoder.h or |
307 // creating a different callback. | 336 // creating a different callback. |
308 int32_t VideoReceiveStream::Encoded( | 337 int32_t VideoReceiveStream::Encoded( |
309 const EncodedImage& encoded_image, | 338 const EncodedImage& encoded_image, |
310 const CodecSpecificInfo* codec_specific_info, | 339 const CodecSpecificInfo* codec_specific_info, |
311 const RTPFragmentationHeader* fragmentation) { | 340 const RTPFragmentationHeader* fragmentation) { |
312 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); | 341 stats_proxy_.OnPreDecode(encoded_image, codec_specific_info); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 const std::vector<uint16_t>& sequence_numbers) { | 375 const std::vector<uint16_t>& sequence_numbers) { |
347 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); | 376 rtp_stream_receiver_.RequestPacketRetransmit(sequence_numbers); |
348 } | 377 } |
349 | 378 |
350 void VideoReceiveStream::RequestKeyFrame() { | 379 void VideoReceiveStream::RequestKeyFrame() { |
351 rtp_stream_receiver_.RequestKeyFrame(); | 380 rtp_stream_receiver_.RequestKeyFrame(); |
352 } | 381 } |
353 | 382 |
354 } // namespace internal | 383 } // namespace internal |
355 } // namespace webrtc | 384 } // namespace webrtc |
OLD | NEW |