1 /* 2 * Copyright (c) 2013 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 "webrtc/video/video_send_stream.h" 12 13 #include <algorithm> 14 #include <sstream> 15 #include <string> 16 #include <vector> 17 18 #include "webrtc/base/checks.h" 19 #include "webrtc/base/logging.h" 20 #include "webrtc/base/trace_event.h" 21 #include "webrtc/call/congestion_controller.h" 22 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 23 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" 24 #include "webrtc/modules/pacing/packet_router.h" 25 #include "webrtc/video/call_stats.h" 26 #include "webrtc/video/encoder_state_feedback.h" 27 #include "webrtc/video/payload_router.h" 28 #include "webrtc/video/video_capture_input.h" 29 #include "webrtc/video/vie_channel.h" 30 #include "webrtc/video/vie_encoder.h" 31 #include "webrtc/video_send_stream.h" 32 33 namespace webrtc { 34 35 class PacedSender; 36 class RtcpIntraFrameObserver; 37 class TransportFeedbackObserver; 38 39 std::string 40 VideoSendStream::Config::EncoderSettings::ToString() const { 41 std::stringstream ss; 42 ss << "{payload_name: " << payload_name; 43 ss << ", payload_type: " << payload_type; 44 ss << ", encoder: " << (encoder != nullptr ? "(VideoEncoder)" : "nullptr"); 45 ss << '}'; 46 return ss.str(); 47 } 48 49 std::string VideoSendStream::Config::Rtp::Rtx::ToString() 50 const { 51 std::stringstream ss; 52 ss << "{ssrcs: ["; 53 for (size_t i = 0; i < ssrcs.size(); ++i) { 54 ss << ssrcs[i]; 55 if (i != ssrcs.size() - 1) 56 ss << ", "; 57 } 58 ss << ']'; 59 60 ss << ", payload_type: " << payload_type; 61 ss << '}'; 62 return ss.str(); 63 } 64 65 std::string VideoSendStream::Config::Rtp::ToString() const { 66 std::stringstream ss; 67 ss << "{ssrcs: ["; 68 for (size_t i = 0; i < ssrcs.size(); ++i) { 69 ss << ssrcs[i]; 70 if (i != ssrcs.size() - 1) 71 ss << ", "; 72 } 73 ss << ']'; 74 ss << ", max_packet_size: " << max_packet_size; 75 ss << ", extensions: ["; 76 for (size_t i = 0; i < extensions.size(); ++i) { 77 ss << extensions[i].ToString(); 78 if (i != extensions.size() - 1) 79 ss << ", "; 80 } 81 ss << ']'; 82 83 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; 84 ss << ", fec: " << fec.ToString(); 85 ss << ", rtx: " << rtx.ToString(); 86 ss << ", c_name: " << c_name; 87 ss << '}'; 88 return ss.str(); 89 } 90 91 std::string VideoSendStream::Config::ToString() const { 92 std::stringstream ss; 93 ss << "{encoder_settings: " << encoder_settings.ToString(); 94 ss << ", rtp: " << rtp.ToString(); 95 ss << ", pre_encode_callback: " 96 << (pre_encode_callback != nullptr ? "(I420FrameCallback)" : "nullptr"); 97 ss << ", post_encode_callback: " << (post_encode_callback != nullptr 98 ? "(EncodedFrameObserver)" 99 : "nullptr"); 100 ss << ", local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)" 101 : "nullptr"); 102 ss << ", render_delay_ms: " << render_delay_ms; 103 ss << ", target_delay_ms: " << target_delay_ms; 104 ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on" 105 : "off"); 106 ss << '}'; 107 return ss.str(); 108 } 109 110 namespace internal { 111 VideoSendStream::VideoSendStream( 112 int num_cpu_cores, 113 ProcessThread* module_process_thread, 114 CallStats* call_stats, 115 CongestionController* congestion_controller, 116 BitrateAllocator* bitrate_allocator, 117 const VideoSendStream::Config& config, 118 const VideoEncoderConfig& encoder_config, 119 const std::map<uint32_t, RtpState>& suspended_ssrcs) 120 : stats_proxy_(Clock::GetRealTimeClock(), 121 config, 122 encoder_config.content_type), 123 transport_adapter_(config.send_transport), 124 encoded_frame_proxy_(config.post_encode_callback), 125 config_(config), 126 suspended_ssrcs_(suspended_ssrcs), 127 module_process_thread_(module_process_thread), 128 call_stats_(call_stats), 129 congestion_controller_(congestion_controller), 130 encoder_feedback_(new EncoderStateFeedback()), 131 use_config_bitrate_(true) { 132 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); 133 RTC_DCHECK(!config_.rtp.ssrcs.empty()); 134 135 // Set up Call-wide sequence numbers, if configured for this send stream. 136 TransportFeedbackObserver* transport_feedback_observer = nullptr; 137 for (const RtpExtension& extension : config.rtp.extensions) { 138 if (extension.name == RtpExtension::kTransportSequenceNumber) { 139 transport_feedback_observer = 140 congestion_controller_->GetTransportFeedbackObserver(); 141 break; 142 } 143 } 144 145 const std::vector<uint32_t>& ssrcs = config.rtp.ssrcs; 146 147 vie_encoder_.reset(new ViEEncoder( 148 num_cpu_cores, module_process_thread_, &stats_proxy_, 149 config.pre_encode_callback, congestion_controller_->pacer(), 150 bitrate_allocator)); 151 RTC_CHECK(vie_encoder_->Init()); 152 153 vie_channel_.reset(new ViEChannel( 154 num_cpu_cores, config.send_transport, module_process_thread_, 155 encoder_feedback_->GetRtcpIntraFrameObserver(), 156 congestion_controller_->GetBitrateController()-> 157 CreateRtcpBandwidthObserver(), 158 transport_feedback_observer, 159 congestion_controller_->GetRemoteBitrateEstimator(false), 160 call_stats_->rtcp_rtt_stats(), congestion_controller_->pacer(), 161 congestion_controller_->packet_router(), ssrcs.size(), true)); 162 RTC_CHECK(vie_channel_->Init() == 0); 163 164 call_stats_->RegisterStatsObserver(vie_channel_->GetStatsObserver()); 165 166 vie_encoder_->StartThreadsAndSetSharedMembers( 167 vie_channel_->send_payload_router(), 168 vie_channel_->vcm_protection_callback()); 169 170 std::vector<uint32_t> first_ssrc(1, ssrcs[0]); 171 vie_encoder_->SetSsrcs(first_ssrc); 172 173 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { 174 const std::string& extension = config_.rtp.extensions[i].name; 175 int id = config_.rtp.extensions[i].id; 176 // One-byte-extension local identifiers are in the range 1-14 inclusive. 177 RTC_DCHECK_GE(id, 1); 178 RTC_DCHECK_LE(id, 14); 179 if (extension == RtpExtension::kTOffset) { 180 RTC_CHECK_EQ(0, vie_channel_->SetSendTimestampOffsetStatus(true, id)); 181 } else if (extension == RtpExtension::kAbsSendTime) { 182 RTC_CHECK_EQ(0, vie_channel_->SetSendAbsoluteSendTimeStatus(true, id)); 183 } else if (extension == RtpExtension::kVideoRotation) { 184 RTC_CHECK_EQ(0, vie_channel_->SetSendVideoRotationStatus(true, id)); 185 } else if (extension == RtpExtension::kTransportSequenceNumber) { 186 RTC_CHECK_EQ(0, vie_channel_->SetSendTransportSequenceNumber(true, id)); 187 } else { 188 RTC_NOTREACHED() << "Registering unsupported RTP extension."; 189 } 190 } 191 192 congestion_controller_->SetChannelRembStatus(true, false, 193 vie_channel_->rtp_rtcp()); 194 195 // Enable NACK, FEC or both. 196 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; 197 const bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; 198 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. 199 vie_channel_->SetProtectionMode(enable_protection_nack, enable_protection_fec, 200 config_.rtp.fec.red_payload_type, 201 config_.rtp.fec.ulpfec_payload_type); 202 vie_encoder_->SetProtectionMethod(enable_protection_nack, 203 enable_protection_fec); 204 205 ConfigureSsrcs(); 206 207 vie_channel_->SetRTCPCName(config_.rtp.c_name.c_str()); 208 209 input_.reset(new internal::VideoCaptureInput( 210 module_process_thread_, vie_encoder_.get(), config_.local_renderer, 211 &stats_proxy_, this, config_.encoding_time_observer)); 212 213 // 28 to match packet overhead in ModuleRtpRtcpImpl. 214 RTC_DCHECK_LE(config_.rtp.max_packet_size, static_cast<size_t>(0xFFFF - 28)); 215 vie_channel_->SetMTU(static_cast<uint16_t>(config_.rtp.max_packet_size + 28)); 216 217 RTC_DCHECK(config.encoder_settings.encoder != nullptr); 218 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); 219 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); 220 RTC_CHECK_EQ(0, vie_encoder_->RegisterExternalEncoder( 221 config.encoder_settings.encoder, 222 config.encoder_settings.payload_type, 223 config.encoder_settings.internal_source)); 224 225 RTC_CHECK(ReconfigureVideoEncoder(encoder_config)); 226 227 vie_channel_->RegisterSendSideDelayObserver(&stats_proxy_); 228 229 if (config_.post_encode_callback) 230 vie_encoder_->RegisterPostEncodeImageCallback(&encoded_frame_proxy_); 231 232 if (config_.suspend_below_min_bitrate) 233 vie_encoder_->SuspendBelowMinBitrate(); 234 235 congestion_controller_->AddEncoder(vie_encoder_.get()); 236 encoder_feedback_->AddEncoder(ssrcs, vie_encoder_.get()); 237 238 vie_channel_->RegisterSendChannelRtcpStatisticsCallback(&stats_proxy_); 239 vie_channel_->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); 240 vie_channel_->RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); 241 vie_channel_->RegisterSendBitrateObserver(&stats_proxy_); 242 vie_channel_->RegisterSendFrameCountObserver(&stats_proxy_); 243 } 244 245 VideoSendStream::~VideoSendStream() { 246 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); 247 vie_channel_->RegisterSendFrameCountObserver(nullptr); 248 vie_channel_->RegisterSendBitrateObserver(nullptr); 249 vie_channel_->RegisterRtcpPacketTypeCounterObserver(nullptr); 250 vie_channel_->RegisterSendChannelRtpStatisticsCallback(nullptr); 251 vie_channel_->RegisterSendChannelRtcpStatisticsCallback(nullptr); 252 253 // Remove capture input (thread) so that it's not running after the current 254 // channel is deleted. 255 input_.reset(); 256 257 vie_encoder_->DeRegisterExternalEncoder( 258 config_.encoder_settings.payload_type); 259 260 call_stats_->DeregisterStatsObserver(vie_channel_->GetStatsObserver()); 261 congestion_controller_->SetChannelRembStatus(false, false, 262 vie_channel_->rtp_rtcp()); 263 264 // Remove the feedback, stop all encoding threads and processing. This must be 265 // done before deleting the channel. 266 congestion_controller_->RemoveEncoder(vie_encoder_.get()); 267 encoder_feedback_->RemoveEncoder(vie_encoder_.get()); 268 vie_encoder_->StopThreadsAndRemoveSharedMembers(); 269 270 uint32_t remote_ssrc = vie_channel_->GetRemoteSSRC(); 271 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( 272 remote_ssrc); 273 } 274 275 VideoCaptureInput* VideoSendStream::Input() { 276 return input_.get(); 277 } 278 279 void VideoSendStream::Start() { 280 transport_adapter_.Enable(); 281 vie_encoder_->Pause(); 282 if (vie_channel_->StartSend() == 0) { 283 // Was not already started, trigger a keyframe. 284 vie_encoder_->SendKeyFrame(); 285 } 286 vie_encoder_->Restart(); 287 vie_channel_->StartReceive(); 288 } 289 290 void VideoSendStream::Stop() { 291 // TODO(pbos): Make sure the encoder stops here. 292 vie_channel_->StopSend(); 293 vie_channel_->StopReceive(); 294 transport_adapter_.Disable(); 295 } 296 297 bool VideoSendStream::ReconfigureVideoEncoder( 298 const VideoEncoderConfig& config) { 299 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); 300 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); 301 const std::vector<VideoStream>& streams = config.streams; 302 RTC_DCHECK(!streams.empty()); 303 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); 304 305 VideoCodec video_codec; 306 memset(&video_codec, 0, sizeof(video_codec)); 307 if (config_.encoder_settings.payload_name == "VP8") { 308 video_codec.codecType = kVideoCodecVP8; 309 } else if (config_.encoder_settings.payload_name == "VP9") { 310 video_codec.codecType = kVideoCodecVP9; 311 } else if (config_.encoder_settings.payload_name == "H264") { 312 video_codec.codecType = kVideoCodecH264; 313 } else { 314 video_codec.codecType = kVideoCodecGeneric; 315 } 316 317 switch (config.content_type) { 318 case VideoEncoderConfig::ContentType::kRealtimeVideo: 319 video_codec.mode = kRealtimeVideo; 320 break; 321 case VideoEncoderConfig::ContentType::kScreen: 322 video_codec.mode = kScreensharing; 323 if (config.streams.size() == 1 && 324 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { 325 video_codec.targetBitrate = 326 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; 327 } 328 break; 329 } 330 331 if (video_codec.codecType == kVideoCodecVP8) { 332 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); 333 } else if (video_codec.codecType == kVideoCodecVP9) { 334 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); 335 } else if (video_codec.codecType == kVideoCodecH264) { 336 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); 337 } 338 339 if (video_codec.codecType == kVideoCodecVP8) { 340 if (config.encoder_specific_settings != nullptr) { 341 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( 342 config.encoder_specific_settings); 343 } 344 video_codec.codecSpecific.VP8.numberOfTemporalLayers = 345 static_cast<unsigned char>( 346 streams.back().temporal_layer_thresholds_bps.size() + 1); 347 } else if (video_codec.codecType == kVideoCodecVP9) { 348 if (config.encoder_specific_settings != nullptr) { 349 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>( 350 config.encoder_specific_settings); 351 if (video_codec.mode == kScreensharing) { 352 video_codec.codecSpecific.VP9.flexibleMode = true; 353 // For now VP9 screensharing use 1 temporal and 2 spatial layers. 354 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1); 355 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2); 356 } 357 } 358 video_codec.codecSpecific.VP9.numberOfTemporalLayers = 359 static_cast<unsigned char>( 360 streams.back().temporal_layer_thresholds_bps.size() + 1); 361 } else if (video_codec.codecType == kVideoCodecH264) { 362 if (config.encoder_specific_settings != nullptr) { 363 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>( 364 config.encoder_specific_settings); 365 } 366 } else { 367 // TODO(pbos): Support encoder_settings codec-agnostically. 368 RTC_DCHECK(config.encoder_specific_settings == nullptr) 369 << "Encoder-specific settings for codec type not wired up."; 370 } 371 372 strncpy(video_codec.plName, 373 config_.encoder_settings.payload_name.c_str(), 374 kPayloadNameSize - 1); 375 video_codec.plName[kPayloadNameSize - 1] = '\0'; 376 video_codec.plType = config_.encoder_settings.payload_type; 377 video_codec.numberOfSimulcastStreams = 378 static_cast<unsigned char>(streams.size()); 379 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; 380 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams)); 381 if (video_codec.codecType == kVideoCodecVP9) { 382 // If the vector is empty, bitrates will be configured automatically. 383 RTC_DCHECK(config.spatial_layers.empty() || 384 config.spatial_layers.size() == 385 video_codec.codecSpecific.VP9.numberOfSpatialLayers); 386 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 387 kMaxSimulcastStreams); 388 for (size_t i = 0; i < config.spatial_layers.size(); ++i) 389 video_codec.spatialLayers[i] = config.spatial_layers[i]; 390 } 391 for (size_t i = 0; i < streams.size(); ++i) { 392 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; 393 RTC_DCHECK_GT(streams[i].width, 0u); 394 RTC_DCHECK_GT(streams[i].height, 0u); 395 RTC_DCHECK_GT(streams[i].max_framerate, 0); 396 // Different framerates not supported per stream at the moment. 397 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); 398 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0); 399 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); 400 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); 401 RTC_DCHECK_GE(streams[i].max_qp, 0); 402 403 sim_stream->width = static_cast<uint16_t>(streams[i].width); 404 sim_stream->height = static_cast<uint16_t>(streams[i].height); 405 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; 406 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; 407 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; 408 sim_stream->qpMax = streams[i].max_qp; 409 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( 410 streams[i].temporal_layer_thresholds_bps.size() + 1); 411 412 video_codec.width = std::max(video_codec.width, 413 static_cast<uint16_t>(streams[i].width)); 414 video_codec.height = std::max( 415 video_codec.height, static_cast<uint16_t>(streams[i].height)); 416 video_codec.minBitrate = 417 std::min(static_cast<uint16_t>(video_codec.minBitrate), 418 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000)); 419 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; 420 video_codec.qpMax = std::max(video_codec.qpMax, 421 static_cast<unsigned int>(streams[i].max_qp)); 422 } 423 424 // Set to zero to not update the bitrate controller from ViEEncoder, as 425 // the bitrate controller is already set from Call. 426 video_codec.startBitrate = 0; 427 428 RTC_DCHECK_GT(streams[0].max_framerate, 0); 429 video_codec.maxFramerate = streams[0].max_framerate; 430 431 if (!SetSendCodec(video_codec)) 432 return false; 433 434 // Clear stats for disabled layers. 435 for (size_t i = video_codec.numberOfSimulcastStreams; 436 i < config_.rtp.ssrcs.size(); ++i) { 437 stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]); 438 } 439 440 stats_proxy_.SetContentType(config.content_type); 441 442 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); 443 vie_encoder_->SetMinTransmitBitrate(config.min_transmit_bitrate_bps / 1000); 444 445 encoder_config_ = config; 446 use_config_bitrate_ = false; 447 return true; 448 } 449 450 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { 451 return vie_channel_->ReceivedRTCPPacket(packet, length) == 0; 452 } 453 454 VideoSendStream::Stats VideoSendStream::GetStats() { 455 return stats_proxy_.GetStats(); 456 } 457 458 void VideoSendStream::OveruseDetected() { 459 if (config_.overuse_callback) 460 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); 461 } 462 463 void VideoSendStream::NormalUsage() { 464 if (config_.overuse_callback) 465 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); 466 } 467 468 void VideoSendStream::ConfigureSsrcs() { 469 vie_channel_->SetSSRC(config_.rtp.ssrcs.front(), kViEStreamTypeNormal, 0); 470 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { 471 uint32_t ssrc = config_.rtp.ssrcs[i]; 472 vie_channel_->SetSSRC(ssrc, kViEStreamTypeNormal, 473 static_cast<unsigned char>(i)); 474 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); 475 if (it != suspended_ssrcs_.end()) 476 vie_channel_->SetRtpStateForSsrc(ssrc, it->second); 477 } 478 479 if (config_.rtp.rtx.ssrcs.empty()) { 480 return; 481 } 482 483 // Set up RTX. 484 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); 485 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { 486 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; 487 vie_channel_->SetSSRC(config_.rtp.rtx.ssrcs[i], kViEStreamTypeRtx, 488 static_cast<unsigned char>(i)); 489 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); 490 if (it != suspended_ssrcs_.end()) 491 vie_channel_->SetRtpStateForSsrc(ssrc, it->second); 492 } 493 494 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); 495 vie_channel_->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, 496 config_.encoder_settings.payload_type); 497 } 498 499 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { 500 std::map<uint32_t, RtpState> rtp_states; 501 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { 502 uint32_t ssrc = config_.rtp.ssrcs[i]; 503 rtp_states[ssrc] = vie_channel_->GetRtpStateForSsrc(ssrc); 504 } 505 506 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { 507 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; 508 rtp_states[ssrc] = vie_channel_->GetRtpStateForSsrc(ssrc); 509 } 510 511 return rtp_states; 512 } 513 514 void VideoSendStream::SignalNetworkState(NetworkState state) { 515 // When network goes up, enable RTCP status before setting transmission state. 516 // When it goes down, disable RTCP afterwards. This ensures that any packets 517 // sent due to the network state changed will not be dropped. 518 if (state == kNetworkUp) 519 vie_channel_->SetRTCPMode(config_.rtp.rtcp_mode); 520 vie_encoder_->SetNetworkTransmissionState(state == kNetworkUp); 521 if (state == kNetworkDown) 522 vie_channel_->SetRTCPMode(RtcpMode::kOff); 523 } 524 525 int64_t VideoSendStream::GetRtt() const { 526 webrtc::RtcpStatistics rtcp_stats; 527 uint16_t frac_lost; 528 uint32_t cumulative_lost; 529 uint32_t extended_max_sequence_number; 530 uint32_t jitter; 531 int64_t rtt_ms; 532 if (vie_channel_->GetSendRtcpStatistics(&frac_lost, &cumulative_lost, 533 &extended_max_sequence_number, 534 &jitter, &rtt_ms) == 0) { 535 return rtt_ms; 536 } 537 return -1; 538 } 539 540 int VideoSendStream::GetPaddingNeededBps() const { 541 return vie_encoder_->GetPaddingNeededBps(); 542 } 543 544 bool VideoSendStream::SetSendCodec(VideoCodec video_codec) { 545 static const int kEncoderMinBitrate = 30; 546 if (video_codec.maxBitrate == 0) { 547 // Unset max bitrate -> cap to one bit per pixel. 548 video_codec.maxBitrate = 549 (video_codec.width * video_codec.height * video_codec.maxFramerate) / 550 1000; 551 } 552 553 if (video_codec.minBitrate < kEncoderMinBitrate) 554 video_codec.minBitrate = kEncoderMinBitrate; 555 if (video_codec.maxBitrate < kEncoderMinBitrate) 556 video_codec.maxBitrate = kEncoderMinBitrate; 557 558 // Stop the media flow while reconfiguring. 559 vie_encoder_->Pause(); 560 561 if (vie_encoder_->SetEncoder(video_codec) != 0) { 562 LOG(LS_ERROR) << "Failed to set encoder."; 563 return false; 564 } 565 566 if (vie_channel_->SetSendCodec(video_codec, false) != 0) { 567 LOG(LS_ERROR) << "Failed to set send codec."; 568 return false; 569 } 570 571 // Not all configured SSRCs have to be utilized (simulcast senders don't have 572 // to send on all SSRCs at once etc.) 573 std::vector<uint32_t> used_ssrcs = config_.rtp.ssrcs; 574 used_ssrcs.resize(static_cast<size_t>(video_codec.numberOfSimulcastStreams)); 575 vie_encoder_->SetSsrcs(used_ssrcs); 576 577 // Restart the media flow 578 vie_encoder_->Restart(); 579 580 return true; 581 } 582 583 } // namespace internal 584 } // namespace webrtc 585