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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 // out). This should effectively turn off CPU adaptations for systems that | 189 // out). This should effectively turn off CPU adaptations for systems that |
190 // remotely cope with the load right now. | 190 // remotely cope with the load right now. |
191 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { | 191 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { |
192 CpuOveruseOptions options; | 192 CpuOveruseOptions options; |
193 if (full_overuse_time) { | 193 if (full_overuse_time) { |
194 options.low_encode_usage_threshold_percent = 150; | 194 options.low_encode_usage_threshold_percent = 150; |
195 options.high_encode_usage_threshold_percent = 200; | 195 options.high_encode_usage_threshold_percent = 200; |
196 } | 196 } |
197 return options; | 197 return options; |
198 } | 198 } |
| 199 |
| 200 VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, |
| 201 const std::string& payload_name, |
| 202 int payload_type) { |
| 203 const std::vector<VideoStream>& streams = config.streams; |
| 204 static const int kEncoderMinBitrateKbps = 30; |
| 205 RTC_DCHECK(!streams.empty()); |
| 206 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); |
| 207 |
| 208 VideoCodec video_codec; |
| 209 memset(&video_codec, 0, sizeof(video_codec)); |
| 210 video_codec.codecType = PayloadNameToCodecType(payload_name); |
| 211 |
| 212 switch (config.content_type) { |
| 213 case VideoEncoderConfig::ContentType::kRealtimeVideo: |
| 214 video_codec.mode = kRealtimeVideo; |
| 215 break; |
| 216 case VideoEncoderConfig::ContentType::kScreen: |
| 217 video_codec.mode = kScreensharing; |
| 218 if (config.streams.size() == 1 && |
| 219 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { |
| 220 video_codec.targetBitrate = |
| 221 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; |
| 222 } |
| 223 break; |
| 224 } |
| 225 |
| 226 switch (video_codec.codecType) { |
| 227 case kVideoCodecVP8: { |
| 228 if (config.encoder_specific_settings) { |
| 229 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( |
| 230 config.encoder_specific_settings); |
| 231 } else { |
| 232 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); |
| 233 } |
| 234 video_codec.codecSpecific.VP8.numberOfTemporalLayers = |
| 235 static_cast<unsigned char>( |
| 236 streams.back().temporal_layer_thresholds_bps.size() + 1); |
| 237 break; |
| 238 } |
| 239 case kVideoCodecVP9: { |
| 240 if (config.encoder_specific_settings) { |
| 241 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>( |
| 242 config.encoder_specific_settings); |
| 243 if (video_codec.mode == kScreensharing) { |
| 244 video_codec.codecSpecific.VP9.flexibleMode = true; |
| 245 // For now VP9 screensharing use 1 temporal and 2 spatial layers. |
| 246 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, |
| 247 1); |
| 248 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2); |
| 249 } |
| 250 } else { |
| 251 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); |
| 252 } |
| 253 video_codec.codecSpecific.VP9.numberOfTemporalLayers = |
| 254 static_cast<unsigned char>( |
| 255 streams.back().temporal_layer_thresholds_bps.size() + 1); |
| 256 break; |
| 257 } |
| 258 case kVideoCodecH264: { |
| 259 if (config.encoder_specific_settings) { |
| 260 video_codec.codecSpecific.H264 = |
| 261 *reinterpret_cast<const VideoCodecH264*>( |
| 262 config.encoder_specific_settings); |
| 263 } else { |
| 264 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); |
| 265 } |
| 266 break; |
| 267 } |
| 268 default: |
| 269 // TODO(pbos): Support encoder_settings codec-agnostically. |
| 270 RTC_DCHECK(!config.encoder_specific_settings) |
| 271 << "Encoder-specific settings for codec type not wired up."; |
| 272 break; |
| 273 } |
| 274 |
| 275 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1); |
| 276 video_codec.plName[kPayloadNameSize - 1] = '\0'; |
| 277 video_codec.plType = payload_type; |
| 278 video_codec.numberOfSimulcastStreams = |
| 279 static_cast<unsigned char>(streams.size()); |
| 280 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; |
| 281 if (video_codec.minBitrate < kEncoderMinBitrateKbps) |
| 282 video_codec.minBitrate = kEncoderMinBitrateKbps; |
| 283 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams)); |
| 284 if (video_codec.codecType == kVideoCodecVP9) { |
| 285 // If the vector is empty, bitrates will be configured automatically. |
| 286 RTC_DCHECK(config.spatial_layers.empty() || |
| 287 config.spatial_layers.size() == |
| 288 video_codec.codecSpecific.VP9.numberOfSpatialLayers); |
| 289 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers, |
| 290 kMaxSimulcastStreams); |
| 291 for (size_t i = 0; i < config.spatial_layers.size(); ++i) |
| 292 video_codec.spatialLayers[i] = config.spatial_layers[i]; |
| 293 } |
| 294 for (size_t i = 0; i < streams.size(); ++i) { |
| 295 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; |
| 296 RTC_DCHECK_GT(streams[i].width, 0u); |
| 297 RTC_DCHECK_GT(streams[i].height, 0u); |
| 298 RTC_DCHECK_GT(streams[i].max_framerate, 0); |
| 299 // Different framerates not supported per stream at the moment. |
| 300 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); |
| 301 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0); |
| 302 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); |
| 303 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); |
| 304 RTC_DCHECK_GE(streams[i].max_qp, 0); |
| 305 |
| 306 sim_stream->width = static_cast<uint16_t>(streams[i].width); |
| 307 sim_stream->height = static_cast<uint16_t>(streams[i].height); |
| 308 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; |
| 309 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; |
| 310 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; |
| 311 sim_stream->qpMax = streams[i].max_qp; |
| 312 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( |
| 313 streams[i].temporal_layer_thresholds_bps.size() + 1); |
| 314 |
| 315 video_codec.width = std::max(video_codec.width, |
| 316 static_cast<uint16_t>(streams[i].width)); |
| 317 video_codec.height = std::max( |
| 318 video_codec.height, static_cast<uint16_t>(streams[i].height)); |
| 319 video_codec.minBitrate = |
| 320 std::min(static_cast<uint16_t>(video_codec.minBitrate), |
| 321 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000)); |
| 322 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; |
| 323 video_codec.qpMax = std::max(video_codec.qpMax, |
| 324 static_cast<unsigned int>(streams[i].max_qp)); |
| 325 } |
| 326 |
| 327 if (video_codec.maxBitrate == 0) { |
| 328 // Unset max bitrate -> cap to one bit per pixel. |
| 329 video_codec.maxBitrate = |
| 330 (video_codec.width * video_codec.height * video_codec.maxFramerate) / |
| 331 1000; |
| 332 } |
| 333 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) |
| 334 video_codec.maxBitrate = kEncoderMinBitrateKbps; |
| 335 |
| 336 RTC_DCHECK_GT(streams[0].max_framerate, 0); |
| 337 video_codec.maxFramerate = streams[0].max_framerate; |
| 338 |
| 339 return video_codec; |
| 340 } |
| 341 |
199 } // namespace | 342 } // namespace |
200 | 343 |
201 namespace internal { | 344 namespace internal { |
202 VideoSendStream::VideoSendStream( | 345 VideoSendStream::VideoSendStream( |
203 int num_cpu_cores, | 346 int num_cpu_cores, |
204 ProcessThread* module_process_thread, | 347 ProcessThread* module_process_thread, |
205 CallStats* call_stats, | 348 CallStats* call_stats, |
206 CongestionController* congestion_controller, | 349 CongestionController* congestion_controller, |
207 BitrateAllocator* bitrate_allocator, | 350 BitrateAllocator* bitrate_allocator, |
208 VieRemb* remb, | 351 VieRemb* remb, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | 450 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); |
308 rtp_rtcp->SetMaxTransferUnit(mtu); | 451 rtp_rtcp->SetMaxTransferUnit(mtu); |
309 rtp_rtcp->RegisterVideoSendPayload( | 452 rtp_rtcp->RegisterVideoSendPayload( |
310 config_.encoder_settings.payload_type, | 453 config_.encoder_settings.payload_type, |
311 config_.encoder_settings.payload_name.c_str()); | 454 config_.encoder_settings.payload_name.c_str()); |
312 } | 455 } |
313 | 456 |
314 RTC_DCHECK(config.encoder_settings.encoder); | 457 RTC_DCHECK(config.encoder_settings.encoder); |
315 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); | 458 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); |
316 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); | 459 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
317 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | |
318 config.encoder_settings.encoder, | |
319 config.encoder_settings.payload_type, | |
320 config.encoder_settings.internal_source)); | |
321 | |
322 ReconfigureVideoEncoder(encoder_config); | 460 ReconfigureVideoEncoder(encoder_config); |
323 | 461 |
324 if (config_.suspend_below_min_bitrate) { | |
325 vcm_->SuspendBelowMinBitrate(); | |
326 bitrate_allocator_->EnforceMinBitrate(false); | |
327 } | |
328 | |
329 module_process_thread_->RegisterModule(&overuse_detector_); | 462 module_process_thread_->RegisterModule(&overuse_detector_); |
330 | 463 |
331 encoder_thread_.Start(); | 464 encoder_thread_.Start(); |
332 encoder_thread_.SetPriority(rtc::kHighPriority); | 465 encoder_thread_.SetPriority(rtc::kHighPriority); |
333 } | 466 } |
334 | 467 |
335 VideoSendStream::~VideoSendStream() { | 468 VideoSendStream::~VideoSendStream() { |
336 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); | 469 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
337 | 470 |
338 Stop(); | 471 Stop(); |
339 | 472 |
340 // Stop the encoder thread permanently. | 473 // Stop the encoder thread permanently. |
341 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); | 474 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); |
342 encoder_wakeup_event_.Set(); | 475 encoder_wakeup_event_.Set(); |
343 encoder_thread_.Stop(); | 476 encoder_thread_.Stop(); |
344 | 477 |
345 // This needs to happen after stopping the encoder thread, | 478 // This needs to happen after stopping the encoder thread, |
346 // since the encoder thread calls AddObserver. | 479 // since the encoder thread calls AddObserver. |
347 bitrate_allocator_->RemoveObserver(this); | 480 bitrate_allocator_->RemoveObserver(this); |
348 | 481 |
349 module_process_thread_->DeRegisterModule(&overuse_detector_); | 482 module_process_thread_->DeRegisterModule(&overuse_detector_); |
350 | 483 |
351 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); | |
352 | |
353 rtp_rtcp_modules_[0]->SetREMBStatus(false); | 484 rtp_rtcp_modules_[0]->SetREMBStatus(false); |
354 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); | 485 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
355 | 486 |
356 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 487 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
357 congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp); | 488 congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp); |
358 module_process_thread_->DeRegisterModule(rtp_rtcp); | 489 module_process_thread_->DeRegisterModule(rtp_rtcp); |
359 delete rtp_rtcp; | 490 delete rtp_rtcp; |
360 } | 491 } |
361 } | 492 } |
362 | 493 |
(...skipping 20 matching lines...) Expand all Loading... |
383 payload_router_.set_active(false); | 514 payload_router_.set_active(false); |
384 } | 515 } |
385 | 516 |
386 bool VideoSendStream::EncoderThreadFunction(void* obj) { | 517 bool VideoSendStream::EncoderThreadFunction(void* obj) { |
387 static_cast<VideoSendStream*>(obj)->EncoderProcess(); | 518 static_cast<VideoSendStream*>(obj)->EncoderProcess(); |
388 // We're done, return false to abort. | 519 // We're done, return false to abort. |
389 return false; | 520 return false; |
390 } | 521 } |
391 | 522 |
392 void VideoSendStream::EncoderProcess() { | 523 void VideoSendStream::EncoderProcess() { |
| 524 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( |
| 525 config_.encoder_settings.encoder, |
| 526 config_.encoder_settings.payload_type, |
| 527 config_.encoder_settings.internal_source)); |
| 528 |
393 while (true) { | 529 while (true) { |
394 encoder_wakeup_event_.Wait(rtc::Event::kForever); | 530 encoder_wakeup_event_.Wait(rtc::Event::kForever); |
395 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) | 531 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) |
396 return; | 532 break; |
| 533 rtc::Optional<EncoderSettings> encoder_settings; |
| 534 { |
| 535 rtc::CritScope lock(&encoder_settings_crit_); |
| 536 if (pending_encoder_settings_) { |
| 537 encoder_settings = pending_encoder_settings_; |
| 538 pending_encoder_settings_ = rtc::Optional<EncoderSettings>(); |
| 539 } |
| 540 } |
| 541 if (encoder_settings) { |
| 542 encoder_settings->video_codec.startBitrate = |
| 543 bitrate_allocator_->AddObserver( |
| 544 this, encoder_settings->video_codec.minBitrate * 1000, |
| 545 encoder_settings->video_codec.maxBitrate * 1000) / |
| 546 1000; |
| 547 vie_encoder_.SetEncoder(encoder_settings->video_codec, |
| 548 encoder_settings->min_transmit_bitrate_bps); |
| 549 if (config_.suspend_below_min_bitrate) { |
| 550 vcm_->SuspendBelowMinBitrate(); |
| 551 bitrate_allocator_->EnforceMinBitrate(false); |
| 552 } |
| 553 // We might've gotten new settings while configuring the encoder settings, |
| 554 // restart from the top to see if that's the case before trying to encode |
| 555 // a frame (which might correspond to the last frame size). |
| 556 encoder_wakeup_event_.Set(); |
| 557 continue; |
| 558 } |
397 | 559 |
398 VideoFrame frame; | 560 VideoFrame frame; |
399 if (input_.GetVideoFrame(&frame)) | 561 if (input_.GetVideoFrame(&frame)) |
400 vie_encoder_.EncodeVideoFrame(frame); | 562 vie_encoder_.EncodeVideoFrame(frame); |
401 } | 563 } |
| 564 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
402 } | 565 } |
403 | 566 |
404 void VideoSendStream::ReconfigureVideoEncoder( | 567 void VideoSendStream::ReconfigureVideoEncoder( |
405 const VideoEncoderConfig& config) { | 568 const VideoEncoderConfig& config) { |
406 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); | 569 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); |
407 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); | 570 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); |
408 const std::vector<VideoStream>& streams = config.streams; | 571 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size()); |
409 static const int kEncoderMinBitrateKbps = 30; | 572 VideoCodec video_codec = VideoEncoderConfigToVideoCodec( |
410 RTC_DCHECK(!streams.empty()); | 573 config, config_.encoder_settings.payload_name, |
411 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); | 574 config_.encoder_settings.payload_type); |
412 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); | 575 { |
413 | 576 rtc::CritScope lock(&encoder_settings_crit_); |
414 VideoCodec video_codec; | 577 pending_encoder_settings_ = rtc::Optional<EncoderSettings>( |
415 memset(&video_codec, 0, sizeof(video_codec)); | 578 {video_codec, config.min_transmit_bitrate_bps}); |
416 video_codec.codecType = | |
417 PayloadNameToCodecType(config_.encoder_settings.payload_name); | |
418 | |
419 switch (config.content_type) { | |
420 case VideoEncoderConfig::ContentType::kRealtimeVideo: | |
421 video_codec.mode = kRealtimeVideo; | |
422 break; | |
423 case VideoEncoderConfig::ContentType::kScreen: | |
424 video_codec.mode = kScreensharing; | |
425 if (config.streams.size() == 1 && | |
426 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { | |
427 video_codec.targetBitrate = | |
428 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; | |
429 } | |
430 break; | |
431 } | 579 } |
432 | 580 encoder_wakeup_event_.Set(); |
433 if (video_codec.codecType == kVideoCodecVP8) { | |
434 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); | |
435 } else if (video_codec.codecType == kVideoCodecVP9) { | |
436 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); | |
437 } else if (video_codec.codecType == kVideoCodecH264) { | |
438 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); | |
439 } | |
440 | |
441 if (video_codec.codecType == kVideoCodecVP8) { | |
442 if (config.encoder_specific_settings) { | |
443 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( | |
444 config.encoder_specific_settings); | |
445 } | |
446 video_codec.codecSpecific.VP8.numberOfTemporalLayers = | |
447 static_cast<unsigned char>( | |
448 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
449 } else if (video_codec.codecType == kVideoCodecVP9) { | |
450 if (config.encoder_specific_settings) { | |
451 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>( | |
452 config.encoder_specific_settings); | |
453 if (video_codec.mode == kScreensharing) { | |
454 video_codec.codecSpecific.VP9.flexibleMode = true; | |
455 // For now VP9 screensharing use 1 temporal and 2 spatial layers. | |
456 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1); | |
457 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2); | |
458 } | |
459 } | |
460 video_codec.codecSpecific.VP9.numberOfTemporalLayers = | |
461 static_cast<unsigned char>( | |
462 streams.back().temporal_layer_thresholds_bps.size() + 1); | |
463 } else if (video_codec.codecType == kVideoCodecH264) { | |
464 if (config.encoder_specific_settings) { | |
465 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>( | |
466 config.encoder_specific_settings); | |
467 } | |
468 } else { | |
469 // TODO(pbos): Support encoder_settings codec-agnostically. | |
470 RTC_DCHECK(!config.encoder_specific_settings) | |
471 << "Encoder-specific settings for codec type not wired up."; | |
472 } | |
473 | |
474 strncpy(video_codec.plName, | |
475 config_.encoder_settings.payload_name.c_str(), | |
476 kPayloadNameSize - 1); | |
477 video_codec.plName[kPayloadNameSize - 1] = '\0'; | |
478 video_codec.plType = config_.encoder_settings.payload_type; | |
479 video_codec.numberOfSimulcastStreams = | |
480 static_cast<unsigned char>(streams.size()); | |
481 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; | |
482 if (video_codec.minBitrate < kEncoderMinBitrateKbps) | |
483 video_codec.minBitrate = kEncoderMinBitrateKbps; | |
484 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams)); | |
485 if (video_codec.codecType == kVideoCodecVP9) { | |
486 // If the vector is empty, bitrates will be configured automatically. | |
487 RTC_DCHECK(config.spatial_layers.empty() || | |
488 config.spatial_layers.size() == | |
489 video_codec.codecSpecific.VP9.numberOfSpatialLayers); | |
490 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers, | |
491 kMaxSimulcastStreams); | |
492 for (size_t i = 0; i < config.spatial_layers.size(); ++i) | |
493 video_codec.spatialLayers[i] = config.spatial_layers[i]; | |
494 } | |
495 for (size_t i = 0; i < streams.size(); ++i) { | |
496 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; | |
497 RTC_DCHECK_GT(streams[i].width, 0u); | |
498 RTC_DCHECK_GT(streams[i].height, 0u); | |
499 RTC_DCHECK_GT(streams[i].max_framerate, 0); | |
500 // Different framerates not supported per stream at the moment. | |
501 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); | |
502 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0); | |
503 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); | |
504 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); | |
505 RTC_DCHECK_GE(streams[i].max_qp, 0); | |
506 | |
507 sim_stream->width = static_cast<uint16_t>(streams[i].width); | |
508 sim_stream->height = static_cast<uint16_t>(streams[i].height); | |
509 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; | |
510 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; | |
511 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; | |
512 sim_stream->qpMax = streams[i].max_qp; | |
513 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( | |
514 streams[i].temporal_layer_thresholds_bps.size() + 1); | |
515 | |
516 video_codec.width = std::max(video_codec.width, | |
517 static_cast<uint16_t>(streams[i].width)); | |
518 video_codec.height = std::max( | |
519 video_codec.height, static_cast<uint16_t>(streams[i].height)); | |
520 video_codec.minBitrate = | |
521 std::min(static_cast<uint16_t>(video_codec.minBitrate), | |
522 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000)); | |
523 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; | |
524 video_codec.qpMax = std::max(video_codec.qpMax, | |
525 static_cast<unsigned int>(streams[i].max_qp)); | |
526 } | |
527 | |
528 if (video_codec.maxBitrate == 0) { | |
529 // Unset max bitrate -> cap to one bit per pixel. | |
530 video_codec.maxBitrate = | |
531 (video_codec.width * video_codec.height * video_codec.maxFramerate) / | |
532 1000; | |
533 } | |
534 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) | |
535 video_codec.maxBitrate = kEncoderMinBitrateKbps; | |
536 | |
537 RTC_DCHECK_GT(streams[0].max_framerate, 0); | |
538 video_codec.maxFramerate = streams[0].max_framerate; | |
539 | |
540 video_codec.startBitrate = | |
541 bitrate_allocator_->AddObserver(this, | |
542 video_codec.minBitrate * 1000, | |
543 video_codec.maxBitrate * 1000) / 1000; | |
544 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); | |
545 } | 581 } |
546 | 582 |
547 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 583 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
548 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) | 584 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
549 rtp_rtcp->IncomingRtcpPacket(packet, length); | 585 rtp_rtcp->IncomingRtcpPacket(packet, length); |
550 return true; | 586 return true; |
551 } | 587 } |
552 | 588 |
553 VideoSendStream::Stats VideoSendStream::GetStats() { | 589 VideoSendStream::Stats VideoSendStream::GetStats() { |
554 return stats_proxy_.GetStats(); | 590 return stats_proxy_.GetStats(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 &module_nack_rate); | 757 &module_nack_rate); |
722 *sent_video_rate_bps += module_video_rate; | 758 *sent_video_rate_bps += module_video_rate; |
723 *sent_nack_rate_bps += module_nack_rate; | 759 *sent_nack_rate_bps += module_nack_rate; |
724 *sent_fec_rate_bps += module_fec_rate; | 760 *sent_fec_rate_bps += module_fec_rate; |
725 } | 761 } |
726 return 0; | 762 return 0; |
727 } | 763 } |
728 | 764 |
729 } // namespace internal | 765 } // namespace internal |
730 } // namespace webrtc | 766 } // namespace webrtc |
OLD | NEW |