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