Chromium Code Reviews| 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 // out). This should effectively turn off CPU adaptations for systems that | 141 // out). This should effectively turn off CPU adaptations for systems that |
| 142 // remotely cope with the load right now. | 142 // remotely cope with the load right now. |
| 143 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { | 143 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { |
| 144 CpuOveruseOptions options; | 144 CpuOveruseOptions options; |
| 145 if (full_overuse_time) { | 145 if (full_overuse_time) { |
| 146 options.low_encode_usage_threshold_percent = 150; | 146 options.low_encode_usage_threshold_percent = 150; |
| 147 options.high_encode_usage_threshold_percent = 200; | 147 options.high_encode_usage_threshold_percent = 200; |
| 148 } | 148 } |
| 149 return options; | 149 return options; |
| 150 } | 150 } |
| 151 | |
| 152 VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, | |
| 153 const std::string& payload_name, | |
| 154 int payload_type) { | |
| 155 const std::vector<VideoStream>& streams = config.streams; | |
| 156 static const int kEncoderMinBitrateKbps = 30; | |
| 157 RTC_DCHECK(!streams.empty()); | |
| 158 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); | |
| 159 | |
| 160 VideoCodec video_codec; | |
| 161 memset(&video_codec, 0, sizeof(video_codec)); | |
| 162 video_codec.codecType = PayloadNameToCodecType(payload_name); | |
| 163 | |
| 164 switch (config.content_type) { | |
| 165 case VideoEncoderConfig::ContentType::kRealtimeVideo: | |
| 166 video_codec.mode = kRealtimeVideo; | |
| 167 break; | |
| 168 case VideoEncoderConfig::ContentType::kScreen: | |
| 169 video_codec.mode = kScreensharing; | |
| 170 if (config.streams.size() == 1 && | |
| 171 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { | |
| 172 video_codec.targetBitrate = | |
| 173 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; | |
| 174 } | |
| 175 break; | |
| 176 } | |
| 177 | |
| 178 if (video_codec.codecType == kVideoCodecVP8) { | |
|
stefan-webrtc
2016/03/14 13:14:03
Maybe change this to a switch {}?
pbos-webrtc
2016/03/14 15:12:58
Done.
| |
| 179 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); | |
| 180 } else if (video_codec.codecType == kVideoCodecVP9) { | |
| 181 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); | |
| 182 } else if (video_codec.codecType == kVideoCodecH264) { | |
| 183 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); | |
| 184 } | |
| 185 | |
| 186 if (video_codec.codecType == kVideoCodecVP8) { | |
| 187 if (config.encoder_specific_settings != nullptr) { | |
| 188 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( | |
| 189 config.encoder_specific_settings); | |
| 190 } | |
| 191 video_codec.codecSpecific.VP8.numberOfTemporalLayers = | |
| 192 static_cast<unsigned char>( | |
| 193 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
| 194 } else if (video_codec.codecType == kVideoCodecVP9) { | |
| 195 if (config.encoder_specific_settings != nullptr) { | |
| 196 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>( | |
| 197 config.encoder_specific_settings); | |
| 198 if (video_codec.mode == kScreensharing) { | |
| 199 video_codec.codecSpecific.VP9.flexibleMode = true; | |
| 200 // For now VP9 screensharing use 1 temporal and 2 spatial layers. | |
| 201 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1); | |
| 202 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2); | |
| 203 } | |
| 204 } | |
| 205 video_codec.codecSpecific.VP9.numberOfTemporalLayers = | |
| 206 static_cast<unsigned char>( | |
| 207 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
| 208 } else if (video_codec.codecType == kVideoCodecH264) { | |
| 209 if (config.encoder_specific_settings != nullptr) { | |
| 210 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>( | |
| 211 config.encoder_specific_settings); | |
| 212 } | |
| 213 } else { | |
| 214 // TODO(pbos): Support encoder_settings codec-agnostically. | |
| 215 RTC_DCHECK(config.encoder_specific_settings == nullptr) | |
| 216 << "Encoder-specific settings for codec type not wired up."; | |
| 217 } | |
| 218 | |
| 219 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1); | |
| 220 video_codec.plName[kPayloadNameSize - 1] = '\0'; | |
| 221 video_codec.plType = payload_type; | |
| 222 video_codec.numberOfSimulcastStreams = | |
| 223 static_cast<unsigned char>(streams.size()); | |
| 224 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; | |
| 225 if (video_codec.minBitrate < kEncoderMinBitrateKbps) | |
| 226 video_codec.minBitrate = kEncoderMinBitrateKbps; | |
| 227 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams)); | |
| 228 if (video_codec.codecType == kVideoCodecVP9) { | |
| 229 // If the vector is empty, bitrates will be configured automatically. | |
| 230 RTC_DCHECK(config.spatial_layers.empty() || | |
| 231 config.spatial_layers.size() == | |
| 232 video_codec.codecSpecific.VP9.numberOfSpatialLayers); | |
| 233 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers, | |
| 234 kMaxSimulcastStreams); | |
| 235 for (size_t i = 0; i < config.spatial_layers.size(); ++i) | |
| 236 video_codec.spatialLayers[i] = config.spatial_layers[i]; | |
| 237 } | |
| 238 for (size_t i = 0; i < streams.size(); ++i) { | |
| 239 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; | |
| 240 RTC_DCHECK_GT(streams[i].width, 0u); | |
| 241 RTC_DCHECK_GT(streams[i].height, 0u); | |
| 242 RTC_DCHECK_GT(streams[i].max_framerate, 0); | |
| 243 // Different framerates not supported per stream at the moment. | |
| 244 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); | |
| 245 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0); | |
| 246 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); | |
| 247 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); | |
| 248 RTC_DCHECK_GE(streams[i].max_qp, 0); | |
| 249 | |
| 250 sim_stream->width = static_cast<uint16_t>(streams[i].width); | |
| 251 sim_stream->height = static_cast<uint16_t>(streams[i].height); | |
| 252 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; | |
| 253 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; | |
| 254 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; | |
| 255 sim_stream->qpMax = streams[i].max_qp; | |
| 256 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( | |
| 257 streams[i].temporal_layer_thresholds_bps.size() + 1); | |
| 258 | |
| 259 video_codec.width = std::max(video_codec.width, | |
| 260 static_cast<uint16_t>(streams[i].width)); | |
| 261 video_codec.height = std::max( | |
| 262 video_codec.height, static_cast<uint16_t>(streams[i].height)); | |
| 263 video_codec.minBitrate = | |
| 264 std::min(static_cast<uint16_t>(video_codec.minBitrate), | |
| 265 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000)); | |
| 266 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; | |
| 267 video_codec.qpMax = std::max(video_codec.qpMax, | |
| 268 static_cast<unsigned int>(streams[i].max_qp)); | |
| 269 } | |
| 270 | |
| 271 if (video_codec.maxBitrate == 0) { | |
| 272 // Unset max bitrate -> cap to one bit per pixel. | |
| 273 video_codec.maxBitrate = | |
| 274 (video_codec.width * video_codec.height * video_codec.maxFramerate) / | |
| 275 1000; | |
| 276 } | |
| 277 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) | |
| 278 video_codec.maxBitrate = kEncoderMinBitrateKbps; | |
| 279 | |
| 280 RTC_DCHECK_GT(streams[0].max_framerate, 0); | |
| 281 video_codec.maxFramerate = streams[0].max_framerate; | |
| 282 | |
| 283 return video_codec; | |
| 284 } | |
| 285 | |
| 151 } // namespace | 286 } // namespace |
| 152 | 287 |
| 153 namespace internal { | 288 namespace internal { |
| 154 VideoSendStream::VideoSendStream( | 289 VideoSendStream::VideoSendStream( |
| 155 int num_cpu_cores, | 290 int num_cpu_cores, |
| 156 ProcessThread* module_process_thread, | 291 ProcessThread* module_process_thread, |
| 157 CallStats* call_stats, | 292 CallStats* call_stats, |
| 158 CongestionController* congestion_controller, | 293 CongestionController* congestion_controller, |
| 159 VieRemb* remb, | 294 VieRemb* remb, |
| 160 BitrateAllocator* bitrate_allocator, | 295 BitrateAllocator* bitrate_allocator, |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | 414 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); |
| 280 rtp_rtcp->SetMaxTransferUnit(mtu); | 415 rtp_rtcp->SetMaxTransferUnit(mtu); |
| 281 rtp_rtcp->RegisterVideoSendPayload( | 416 rtp_rtcp->RegisterVideoSendPayload( |
| 282 config_.encoder_settings.payload_type, | 417 config_.encoder_settings.payload_type, |
| 283 config_.encoder_settings.payload_name.c_str()); | 418 config_.encoder_settings.payload_name.c_str()); |
| 284 } | 419 } |
| 285 | 420 |
| 286 RTC_DCHECK(config.encoder_settings.encoder != nullptr); | 421 RTC_DCHECK(config.encoder_settings.encoder != nullptr); |
| 287 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); | 422 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); |
| 288 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); | 423 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
| 289 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | |
| 290 config.encoder_settings.encoder, | |
| 291 config.encoder_settings.payload_type, | |
| 292 config.encoder_settings.internal_source)); | |
| 293 | |
| 294 ReconfigureVideoEncoder(encoder_config); | 424 ReconfigureVideoEncoder(encoder_config); |
| 295 | 425 |
| 296 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); | 426 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); |
| 297 | 427 |
| 298 if (config_.post_encode_callback) | 428 if (config_.post_encode_callback) |
| 299 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); | 429 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); |
| 300 | 430 |
| 301 if (config_.suspend_below_min_bitrate) | |
| 302 vie_encoder_.SuspendBelowMinBitrate(); | |
| 303 | |
| 304 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); | 431 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); |
| 305 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); | 432 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); |
| 306 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); | 433 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); |
| 307 | 434 |
| 308 module_process_thread_->RegisterModule(&overuse_detector_); | 435 module_process_thread_->RegisterModule(&overuse_detector_); |
| 309 | 436 |
| 310 encoder_thread_.Start(); | 437 encoder_thread_.Start(); |
| 311 encoder_thread_.SetPriority(rtc::kHighPriority); | 438 encoder_thread_.SetPriority(rtc::kHighPriority); |
| 312 } | 439 } |
| 313 | 440 |
| 314 VideoSendStream::~VideoSendStream() { | 441 VideoSendStream::~VideoSendStream() { |
| 315 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); | 442 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
| 316 Stop(); | 443 Stop(); |
| 317 | 444 |
| 318 // Stop the encoder thread permanently. | 445 // Stop the encoder thread permanently. |
| 319 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); | 446 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); |
| 320 encoder_wakeup_event_.Set(); | 447 encoder_wakeup_event_.Set(); |
| 321 encoder_thread_.Stop(); | 448 encoder_thread_.Stop(); |
| 322 | 449 |
| 323 module_process_thread_->DeRegisterModule(&overuse_detector_); | 450 module_process_thread_->DeRegisterModule(&overuse_detector_); |
| 324 vie_channel_.RegisterSendFrameCountObserver(nullptr); | 451 vie_channel_.RegisterSendFrameCountObserver(nullptr); |
| 325 vie_channel_.RegisterSendBitrateObserver(nullptr); | 452 vie_channel_.RegisterSendBitrateObserver(nullptr); |
| 326 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); | 453 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); |
| 327 | 454 |
| 328 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); | |
| 329 | |
| 330 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); | 455 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); |
| 331 rtp_rtcp_modules_[0]->SetREMBStatus(false); | 456 rtp_rtcp_modules_[0]->SetREMBStatus(false); |
| 332 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); | 457 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
| 333 | 458 |
| 334 // ViEChannel outlives ViEEncoder so remove encoder from feedback before | 459 // ViEChannel outlives ViEEncoder so remove encoder from feedback before |
| 335 // destruction. | 460 // destruction. |
| 336 encoder_feedback_.TearDown(); | 461 encoder_feedback_.TearDown(); |
| 337 | 462 |
| 338 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( | 463 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( |
| 339 vie_receiver_->GetRemoteSsrc()); | 464 vie_receiver_->GetRemoteSsrc()); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 362 vie_receiver_->StopReceive(); | 487 vie_receiver_->StopReceive(); |
| 363 } | 488 } |
| 364 | 489 |
| 365 bool VideoSendStream::EncoderThreadFunction(void* obj) { | 490 bool VideoSendStream::EncoderThreadFunction(void* obj) { |
| 366 static_cast<VideoSendStream*>(obj)->EncoderProcess(); | 491 static_cast<VideoSendStream*>(obj)->EncoderProcess(); |
| 367 // We're done, return false to abort. | 492 // We're done, return false to abort. |
| 368 return false; | 493 return false; |
| 369 } | 494 } |
| 370 | 495 |
| 371 void VideoSendStream::EncoderProcess() { | 496 void VideoSendStream::EncoderProcess() { |
| 497 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | |
|
stefan-webrtc
2016/03/14 13:14:03
Is there anything we should DCHECK before this to
pbos-webrtc
2016/03/14 15:12:58
Don't think we have any good primitives for checki
| |
| 498 config_.encoder_settings.encoder, | |
| 499 config_.encoder_settings.payload_type, | |
| 500 config_.encoder_settings.internal_source)); | |
| 501 | |
| 372 while (true) { | 502 while (true) { |
| 373 encoder_wakeup_event_.Wait(rtc::Event::kForever); | 503 encoder_wakeup_event_.Wait(rtc::Event::kForever); |
| 374 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) | 504 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) |
| 375 return; | 505 break; |
| 506 rtc::Optional<EncoderSettings> encoder_settings; | |
| 507 { | |
| 508 rtc::CritScope lock(&encoder_settings_crit_); | |
| 509 if (pending_encoder_settings_) { | |
| 510 encoder_settings = pending_encoder_settings_; | |
| 511 pending_encoder_settings_ = rtc::Optional<EncoderSettings>(); | |
| 512 } | |
| 513 } | |
| 514 if (encoder_settings) { | |
| 515 vie_encoder_.SetEncoder(encoder_settings->video_codec, | |
| 516 encoder_settings->min_transmit_bitrate_bps); | |
| 517 if (config_.suspend_below_min_bitrate) | |
| 518 vie_encoder_.SuspendBelowMinBitrate(); | |
| 519 // We might've gotten new settings while configuring the encoder settings, | |
| 520 // restart from the top to see if that's the case before trying to encode | |
| 521 // a frame (which might correspond to the last frame size). | |
| 522 encoder_wakeup_event_.Set(); | |
| 523 continue; | |
| 524 } | |
| 376 | 525 |
| 377 VideoFrame frame; | 526 VideoFrame frame; |
| 378 if (input_.GetVideoFrame(&frame)) | 527 if (input_.GetVideoFrame(&frame)) |
| 379 vie_encoder_.EncodeVideoFrame(frame); | 528 vie_encoder_.EncodeVideoFrame(frame); |
| 380 } | 529 } |
| 530 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); | |
| 381 } | 531 } |
| 382 | 532 |
| 383 void VideoSendStream::ReconfigureVideoEncoder( | 533 void VideoSendStream::ReconfigureVideoEncoder( |
| 384 const VideoEncoderConfig& config) { | 534 const VideoEncoderConfig& config) { |
| 385 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); | 535 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); |
| 386 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); | 536 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); |
| 387 const std::vector<VideoStream>& streams = config.streams; | 537 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size()); |
| 388 static const int kEncoderMinBitrateKbps = 30; | 538 VideoCodec video_codec = VideoEncoderConfigToVideoCodec( |
| 389 RTC_DCHECK(!streams.empty()); | 539 config, config_.encoder_settings.payload_name, |
| 390 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); | 540 config_.encoder_settings.payload_type); |
| 391 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); | 541 rtc::CritScope lock(&encoder_settings_crit_); |
|
stefan-webrtc
2016/03/14 13:14:03
Maybe put this within its own scope?
pbos-webrtc
2016/03/14 15:12:58
Done.
| |
| 392 | 542 pending_encoder_settings_ = rtc::Optional<EncoderSettings>( |
| 393 VideoCodec video_codec; | 543 {video_codec, config.min_transmit_bitrate_bps}); |
| 394 memset(&video_codec, 0, sizeof(video_codec)); | 544 encoder_wakeup_event_.Set(); |
| 395 video_codec.codecType = | |
| 396 PayloadNameToCodecType(config_.encoder_settings.payload_name); | |
| 397 | |
| 398 switch (config.content_type) { | |
| 399 case VideoEncoderConfig::ContentType::kRealtimeVideo: | |
| 400 video_codec.mode = kRealtimeVideo; | |
| 401 break; | |
| 402 case VideoEncoderConfig::ContentType::kScreen: | |
| 403 video_codec.mode = kScreensharing; | |
| 404 if (config.streams.size() == 1 && | |
| 405 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { | |
| 406 video_codec.targetBitrate = | |
| 407 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; | |
| 408 } | |
| 409 break; | |
| 410 } | |
| 411 | |
| 412 if (video_codec.codecType == kVideoCodecVP8) { | |
| 413 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); | |
| 414 } else if (video_codec.codecType == kVideoCodecVP9) { | |
| 415 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); | |
| 416 } else if (video_codec.codecType == kVideoCodecH264) { | |
| 417 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); | |
| 418 } | |
| 419 | |
| 420 if (video_codec.codecType == kVideoCodecVP8) { | |
| 421 if (config.encoder_specific_settings != nullptr) { | |
| 422 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( | |
| 423 config.encoder_specific_settings); | |
| 424 } | |
| 425 video_codec.codecSpecific.VP8.numberOfTemporalLayers = | |
| 426 static_cast<unsigned char>( | |
| 427 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
| 428 } else if (video_codec.codecType == kVideoCodecVP9) { | |
| 429 if (config.encoder_specific_settings != nullptr) { | |
| 430 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>( | |
| 431 config.encoder_specific_settings); | |
| 432 if (video_codec.mode == kScreensharing) { | |
| 433 video_codec.codecSpecific.VP9.flexibleMode = true; | |
| 434 // For now VP9 screensharing use 1 temporal and 2 spatial layers. | |
| 435 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1); | |
| 436 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2); | |
| 437 } | |
| 438 } | |
| 439 video_codec.codecSpecific.VP9.numberOfTemporalLayers = | |
| 440 static_cast<unsigned char>( | |
| 441 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
| 442 } else if (video_codec.codecType == kVideoCodecH264) { | |
| 443 if (config.encoder_specific_settings != nullptr) { | |
| 444 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>( | |
| 445 config.encoder_specific_settings); | |
| 446 } | |
| 447 } else { | |
| 448 // TODO(pbos): Support encoder_settings codec-agnostically. | |
| 449 RTC_DCHECK(config.encoder_specific_settings == nullptr) | |
| 450 << "Encoder-specific settings for codec type not wired up."; | |
| 451 } | |
| 452 | |
| 453 strncpy(video_codec.plName, | |
| 454 config_.encoder_settings.payload_name.c_str(), | |
| 455 kPayloadNameSize - 1); | |
| 456 video_codec.plName[kPayloadNameSize - 1] = '\0'; | |
| 457 video_codec.plType = config_.encoder_settings.payload_type; | |
| 458 video_codec.numberOfSimulcastStreams = | |
| 459 static_cast<unsigned char>(streams.size()); | |
| 460 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; | |
| 461 if (video_codec.minBitrate < kEncoderMinBitrateKbps) | |
| 462 video_codec.minBitrate = kEncoderMinBitrateKbps; | |
| 463 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams)); | |
| 464 if (video_codec.codecType == kVideoCodecVP9) { | |
| 465 // If the vector is empty, bitrates will be configured automatically. | |
| 466 RTC_DCHECK(config.spatial_layers.empty() || | |
| 467 config.spatial_layers.size() == | |
| 468 video_codec.codecSpecific.VP9.numberOfSpatialLayers); | |
| 469 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers, | |
| 470 kMaxSimulcastStreams); | |
| 471 for (size_t i = 0; i < config.spatial_layers.size(); ++i) | |
| 472 video_codec.spatialLayers[i] = config.spatial_layers[i]; | |
| 473 } | |
| 474 for (size_t i = 0; i < streams.size(); ++i) { | |
| 475 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; | |
| 476 RTC_DCHECK_GT(streams[i].width, 0u); | |
| 477 RTC_DCHECK_GT(streams[i].height, 0u); | |
| 478 RTC_DCHECK_GT(streams[i].max_framerate, 0); | |
| 479 // Different framerates not supported per stream at the moment. | |
| 480 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); | |
| 481 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0); | |
| 482 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); | |
| 483 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); | |
| 484 RTC_DCHECK_GE(streams[i].max_qp, 0); | |
| 485 | |
| 486 sim_stream->width = static_cast<uint16_t>(streams[i].width); | |
| 487 sim_stream->height = static_cast<uint16_t>(streams[i].height); | |
| 488 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; | |
| 489 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; | |
| 490 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; | |
| 491 sim_stream->qpMax = streams[i].max_qp; | |
| 492 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( | |
| 493 streams[i].temporal_layer_thresholds_bps.size() + 1); | |
| 494 | |
| 495 video_codec.width = std::max(video_codec.width, | |
| 496 static_cast<uint16_t>(streams[i].width)); | |
| 497 video_codec.height = std::max( | |
| 498 video_codec.height, static_cast<uint16_t>(streams[i].height)); | |
| 499 video_codec.minBitrate = | |
| 500 std::min(static_cast<uint16_t>(video_codec.minBitrate), | |
| 501 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000)); | |
| 502 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; | |
| 503 video_codec.qpMax = std::max(video_codec.qpMax, | |
| 504 static_cast<unsigned int>(streams[i].max_qp)); | |
| 505 } | |
| 506 | |
| 507 if (video_codec.maxBitrate == 0) { | |
| 508 // Unset max bitrate -> cap to one bit per pixel. | |
| 509 video_codec.maxBitrate = | |
| 510 (video_codec.width * video_codec.height * video_codec.maxFramerate) / | |
| 511 1000; | |
| 512 } | |
| 513 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) | |
| 514 video_codec.maxBitrate = kEncoderMinBitrateKbps; | |
| 515 | |
| 516 RTC_DCHECK_GT(streams[0].max_framerate, 0); | |
| 517 video_codec.maxFramerate = streams[0].max_framerate; | |
| 518 | |
| 519 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); | |
| 520 } | 545 } |
| 521 | 546 |
| 522 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 547 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
| 523 return vie_receiver_->DeliverRtcp(packet, length); | 548 return vie_receiver_->DeliverRtcp(packet, length); |
| 524 } | 549 } |
| 525 | 550 |
| 526 VideoSendStream::Stats VideoSendStream::GetStats() { | 551 VideoSendStream::Stats VideoSendStream::GetStats() { |
| 527 return stats_proxy_.GetStats(); | 552 return stats_proxy_.GetStats(); |
| 528 } | 553 } |
| 529 | 554 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) | 634 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
| 610 rtp_rtcp->SetRTCPStatus(RtcpMode::kOff); | 635 rtp_rtcp->SetRTCPStatus(RtcpMode::kOff); |
| 611 } | 636 } |
| 612 } | 637 } |
| 613 | 638 |
| 614 int VideoSendStream::GetPaddingNeededBps() const { | 639 int VideoSendStream::GetPaddingNeededBps() const { |
| 615 return vie_encoder_.GetPaddingNeededBps(); | 640 return vie_encoder_.GetPaddingNeededBps(); |
| 616 } | 641 } |
| 617 } // namespace internal | 642 } // namespace internal |
| 618 } // namespace webrtc | 643 } // namespace webrtc |
| OLD | NEW |