| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 |
| 11 #include "webrtc/media/engine/webrtcvideoengine2.h" | 11 #include "webrtc/media/engine/webrtcvideoengine2.h" |
| 12 | 12 |
| 13 #include <stdio.h> | 13 #include <stdio.h> |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 #include <set> | 15 #include <set> |
| 16 #include <string> | 16 #include <string> |
| 17 #include <utility> |
| 17 | 18 |
| 18 #include "webrtc/base/copyonwritebuffer.h" | 19 #include "webrtc/base/copyonwritebuffer.h" |
| 19 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
| 20 #include "webrtc/base/stringutils.h" | 21 #include "webrtc/base/stringutils.h" |
| 21 #include "webrtc/base/timeutils.h" | 22 #include "webrtc/base/timeutils.h" |
| 22 #include "webrtc/base/trace_event.h" | 23 #include "webrtc/base/trace_event.h" |
| 23 #include "webrtc/call.h" | 24 #include "webrtc/call.h" |
| 24 #include "webrtc/media/engine/constants.h" | 25 #include "webrtc/media/engine/constants.h" |
| 25 #include "webrtc/media/engine/simulcast.h" | 26 #include "webrtc/media/engine/simulcast.h" |
| 26 #include "webrtc/media/engine/webrtcmediaengine.h" | 27 #include "webrtc/media/engine/webrtcmediaengine.h" |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 } | 316 } |
| 316 | 317 |
| 317 int GetDefaultVp9TemporalLayers() { | 318 int GetDefaultVp9TemporalLayers() { |
| 318 int num_sl; | 319 int num_sl; |
| 319 int num_tl; | 320 int num_tl; |
| 320 if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { | 321 if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { |
| 321 return num_tl; | 322 return num_tl; |
| 322 } | 323 } |
| 323 return 1; | 324 return 1; |
| 324 } | 325 } |
| 326 |
| 327 class EncoderStreamFactory |
| 328 : public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface { |
| 329 public: |
| 330 EncoderStreamFactory(std::string codec_name, |
| 331 int max_qp, |
| 332 int max_framerate, |
| 333 bool is_screencast, |
| 334 bool conference_mode) |
| 335 : codec_name_(codec_name), |
| 336 max_qp_(max_qp), |
| 337 max_framerate_(max_framerate), |
| 338 is_screencast_(is_screencast), |
| 339 conference_mode_(conference_mode) {} |
| 340 |
| 341 private: |
| 342 std::vector<webrtc::VideoStream> CreateEncoderStreams( |
| 343 int width, |
| 344 int height, |
| 345 const webrtc::VideoEncoderConfig& encoder_config) override { |
| 346 if (encoder_config.number_of_streams > 1) { |
| 347 return GetSimulcastConfig(encoder_config.number_of_streams, width, height, |
| 348 encoder_config.max_bitrate_bps, max_qp_, |
| 349 max_framerate_); |
| 350 } |
| 351 |
| 352 // For unset max bitrates set default bitrate for non-simulcast. |
| 353 int max_bitrate_bps = |
| 354 (encoder_config.max_bitrate_bps > 0) |
| 355 ? encoder_config.max_bitrate_bps |
| 356 : GetMaxDefaultVideoBitrateKbps(width, height) * 1000; |
| 357 |
| 358 webrtc::VideoStream stream; |
| 359 stream.width = width; |
| 360 stream.height = height; |
| 361 stream.max_framerate = max_framerate_; |
| 362 stream.min_bitrate_bps = kMinVideoBitrateKbps * 1000; |
| 363 stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps; |
| 364 stream.max_qp = max_qp_; |
| 365 |
| 366 // Conference mode screencast uses 2 temporal layers split at 100kbit. |
| 367 if (conference_mode_ && is_screencast_) { |
| 368 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); |
| 369 // For screenshare in conference mode, tl0 and tl1 bitrates are |
| 370 // piggybacked |
| 371 // on the VideoCodec struct as target and max bitrates, respectively. |
| 372 // See eg. webrtc::VP8EncoderImpl::SetRates(). |
| 373 stream.target_bitrate_bps = config.tl0_bitrate_kbps * 1000; |
| 374 stream.max_bitrate_bps = config.tl1_bitrate_kbps * 1000; |
| 375 stream.temporal_layer_thresholds_bps.clear(); |
| 376 stream.temporal_layer_thresholds_bps.push_back(config.tl0_bitrate_kbps * |
| 377 1000); |
| 378 } |
| 379 |
| 380 if (CodecNamesEq(codec_name_, kVp9CodecName) && !is_screencast_) { |
| 381 stream.temporal_layer_thresholds_bps.resize( |
| 382 GetDefaultVp9TemporalLayers() - 1); |
| 383 } |
| 384 |
| 385 std::vector<webrtc::VideoStream> streams; |
| 386 streams.push_back(stream); |
| 387 return streams; |
| 388 } |
| 389 |
| 390 const std::string codec_name_; |
| 391 const int max_qp_; |
| 392 const int max_framerate_; |
| 393 const bool is_screencast_; |
| 394 const bool conference_mode_; |
| 395 }; |
| 396 |
| 325 } // namespace | 397 } // namespace |
| 326 | 398 |
| 327 // Constants defined in webrtc/media/engine/constants.h | 399 // Constants defined in webrtc/media/engine/constants.h |
| 328 // TODO(pbos): Move these to a separate constants.cc file. | 400 // TODO(pbos): Move these to a separate constants.cc file. |
| 329 const int kMinVideoBitrate = 30; | 401 const int kMinVideoBitrateKbps = 30; |
| 330 const int kStartVideoBitrate = 300; | |
| 331 | 402 |
| 332 const int kVideoMtu = 1200; | 403 const int kVideoMtu = 1200; |
| 333 const int kVideoRtpBufferSize = 65536; | 404 const int kVideoRtpBufferSize = 65536; |
| 334 | 405 |
| 335 // This constant is really an on/off, lower-level configurable NACK history | 406 // This constant is really an on/off, lower-level configurable NACK history |
| 336 // duration hasn't been implemented. | 407 // duration hasn't been implemented. |
| 337 static const int kNackHistoryMs = 1000; | 408 static const int kNackHistoryMs = 1000; |
| 338 | 409 |
| 339 static const int kDefaultQpMax = 56; | 410 static const int kDefaultQpMax = 56; |
| 340 | 411 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); | 462 codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); |
| 392 codec.SetParam(kH264FmtpPacketizationMode, "1"); | 463 codec.SetParam(kH264FmtpPacketizationMode, "1"); |
| 393 AddCodecAndMaybeRtxCodec(codec, &codecs); | 464 AddCodecAndMaybeRtxCodec(codec, &codecs); |
| 394 } | 465 } |
| 395 AddCodecAndMaybeRtxCodec(VideoCodec(kDefaultRedPlType, kRedCodecName), | 466 AddCodecAndMaybeRtxCodec(VideoCodec(kDefaultRedPlType, kRedCodecName), |
| 396 &codecs); | 467 &codecs); |
| 397 codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); | 468 codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); |
| 398 return codecs; | 469 return codecs; |
| 399 } | 470 } |
| 400 | 471 |
| 401 std::vector<webrtc::VideoStream> | |
| 402 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams( | |
| 403 const VideoCodec& codec, | |
| 404 const VideoOptions& options, | |
| 405 int max_bitrate_bps, | |
| 406 size_t num_streams) { | |
| 407 int max_qp = kDefaultQpMax; | |
| 408 codec.GetParam(kCodecParamMaxQuantization, &max_qp); | |
| 409 | |
| 410 return GetSimulcastConfig( | |
| 411 num_streams, codec.width, codec.height, max_bitrate_bps, max_qp, | |
| 412 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate); | |
| 413 } | |
| 414 | |
| 415 std::vector<webrtc::VideoStream> | |
| 416 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams( | |
| 417 const VideoCodec& codec, | |
| 418 const VideoOptions& options, | |
| 419 int max_bitrate_bps, | |
| 420 size_t num_streams) { | |
| 421 int codec_max_bitrate_kbps; | |
| 422 if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) { | |
| 423 max_bitrate_bps = codec_max_bitrate_kbps * 1000; | |
| 424 } | |
| 425 if (num_streams != 1) { | |
| 426 return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps, | |
| 427 num_streams); | |
| 428 } | |
| 429 | |
| 430 // For unset max bitrates set default bitrate for non-simulcast. | |
| 431 if (max_bitrate_bps <= 0) { | |
| 432 max_bitrate_bps = | |
| 433 GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000; | |
| 434 } | |
| 435 | |
| 436 webrtc::VideoStream stream; | |
| 437 stream.width = codec.width; | |
| 438 stream.height = codec.height; | |
| 439 stream.max_framerate = | |
| 440 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; | |
| 441 | |
| 442 stream.min_bitrate_bps = kMinVideoBitrate * 1000; | |
| 443 stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps; | |
| 444 | |
| 445 int max_qp = kDefaultQpMax; | |
| 446 codec.GetParam(kCodecParamMaxQuantization, &max_qp); | |
| 447 stream.max_qp = max_qp; | |
| 448 std::vector<webrtc::VideoStream> streams; | |
| 449 streams.push_back(stream); | |
| 450 return streams; | |
| 451 } | |
| 452 | |
| 453 rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings> | 472 rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings> |
| 454 WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( | 473 WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( |
| 455 const VideoCodec& codec) { | 474 const VideoCodec& codec) { |
| 475 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 456 bool is_screencast = parameters_.options.is_screencast.value_or(false); | 476 bool is_screencast = parameters_.options.is_screencast.value_or(false); |
| 457 // No automatic resizing when using simulcast or screencast. | 477 // No automatic resizing when using simulcast or screencast. |
| 458 bool automatic_resize = | 478 bool automatic_resize = |
| 459 !is_screencast && parameters_.config.rtp.ssrcs.size() == 1; | 479 !is_screencast && parameters_.config.rtp.ssrcs.size() == 1; |
| 460 bool frame_dropping = !is_screencast; | 480 bool frame_dropping = !is_screencast; |
| 461 bool denoising; | 481 bool denoising; |
| 462 bool codec_default_denoising = false; | 482 bool codec_default_denoising = false; |
| 463 if (is_screencast) { | 483 if (is_screencast) { |
| 464 denoising = false; | 484 denoising = false; |
| 465 } else { | 485 } else { |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 | 1556 |
| 1537 WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: | 1557 WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: |
| 1538 VideoSendStreamParameters( | 1558 VideoSendStreamParameters( |
| 1539 webrtc::VideoSendStream::Config config, | 1559 webrtc::VideoSendStream::Config config, |
| 1540 const VideoOptions& options, | 1560 const VideoOptions& options, |
| 1541 int max_bitrate_bps, | 1561 int max_bitrate_bps, |
| 1542 const rtc::Optional<VideoCodecSettings>& codec_settings) | 1562 const rtc::Optional<VideoCodecSettings>& codec_settings) |
| 1543 : config(std::move(config)), | 1563 : config(std::move(config)), |
| 1544 options(options), | 1564 options(options), |
| 1545 max_bitrate_bps(max_bitrate_bps), | 1565 max_bitrate_bps(max_bitrate_bps), |
| 1566 conference_mode(false), |
| 1546 codec_settings(codec_settings) {} | 1567 codec_settings(codec_settings) {} |
| 1547 | 1568 |
| 1548 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( | 1569 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( |
| 1549 webrtc::VideoEncoder* encoder, | 1570 webrtc::VideoEncoder* encoder, |
| 1550 webrtc::VideoCodecType type, | 1571 webrtc::VideoCodecType type, |
| 1551 bool external) | 1572 bool external) |
| 1552 : encoder(encoder), | 1573 : encoder(encoder), |
| 1553 external_encoder(nullptr), | 1574 external_encoder(nullptr), |
| 1554 type(type), | 1575 type(type), |
| 1555 external(external) { | 1576 external(external) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1580 cpu_restricted_counter_(0), | 1601 cpu_restricted_counter_(0), |
| 1581 number_of_cpu_adapt_changes_(0), | 1602 number_of_cpu_adapt_changes_(0), |
| 1582 frame_count_(0), | 1603 frame_count_(0), |
| 1583 cpu_restricted_frame_count_(0), | 1604 cpu_restricted_frame_count_(0), |
| 1584 source_(nullptr), | 1605 source_(nullptr), |
| 1585 external_encoder_factory_(external_encoder_factory), | 1606 external_encoder_factory_(external_encoder_factory), |
| 1586 stream_(nullptr), | 1607 stream_(nullptr), |
| 1587 encoder_sink_(nullptr), | 1608 encoder_sink_(nullptr), |
| 1588 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1609 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
| 1589 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1610 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
| 1590 pending_encoder_reconfiguration_(false), | |
| 1591 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), | 1611 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), |
| 1592 sending_(false), | 1612 sending_(false), |
| 1593 last_frame_timestamp_us_(0) { | 1613 last_frame_timestamp_us_(0) { |
| 1594 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1614 parameters_.config.rtp.max_packet_size = kVideoMtu; |
| 1595 parameters_.conference_mode = send_params.conference_mode; | 1615 parameters_.conference_mode = send_params.conference_mode; |
| 1596 | 1616 |
| 1597 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1617 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
| 1598 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, | 1618 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
| 1599 ¶meters_.config.rtp.rtx.ssrcs); | 1619 ¶meters_.config.rtp.rtx.ssrcs); |
| 1600 parameters_.config.rtp.c_name = sp.cname; | 1620 parameters_.config.rtp.c_name = sp.cname; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 rtc::CritScope cs(&lock_); | 1668 rtc::CritScope cs(&lock_); |
| 1649 | 1669 |
| 1650 if (video_frame.width() != last_frame_info_.width || | 1670 if (video_frame.width() != last_frame_info_.width || |
| 1651 video_frame.height() != last_frame_info_.height || | 1671 video_frame.height() != last_frame_info_.height || |
| 1652 video_frame.rotation() != last_frame_info_.rotation || | 1672 video_frame.rotation() != last_frame_info_.rotation || |
| 1653 video_frame.is_texture() != last_frame_info_.is_texture) { | 1673 video_frame.is_texture() != last_frame_info_.is_texture) { |
| 1654 last_frame_info_.width = video_frame.width(); | 1674 last_frame_info_.width = video_frame.width(); |
| 1655 last_frame_info_.height = video_frame.height(); | 1675 last_frame_info_.height = video_frame.height(); |
| 1656 last_frame_info_.rotation = video_frame.rotation(); | 1676 last_frame_info_.rotation = video_frame.rotation(); |
| 1657 last_frame_info_.is_texture = video_frame.is_texture(); | 1677 last_frame_info_.is_texture = video_frame.is_texture(); |
| 1658 pending_encoder_reconfiguration_ = true; | |
| 1659 | 1678 |
| 1660 LOG(LS_INFO) << "Video frame parameters changed: dimensions=" | 1679 LOG(LS_INFO) << "Video frame parameters changed: dimensions=" |
| 1661 << last_frame_info_.width << "x" << last_frame_info_.height | 1680 << last_frame_info_.width << "x" << last_frame_info_.height |
| 1662 << ", rotation=" << last_frame_info_.rotation | 1681 << ", rotation=" << last_frame_info_.rotation |
| 1663 << ", texture=" << last_frame_info_.is_texture; | 1682 << ", texture=" << last_frame_info_.is_texture; |
| 1664 } | 1683 } |
| 1665 | 1684 |
| 1666 if (encoder_sink_ == NULL) { | 1685 if (encoder_sink_ == NULL) { |
| 1667 // Frame input before send codecs are configured, dropping frame. | 1686 // Frame input before send codecs are configured, dropping frame. |
| 1668 return; | 1687 return; |
| 1669 } | 1688 } |
| 1670 | 1689 |
| 1671 last_frame_timestamp_us_ = video_frame.timestamp_us(); | 1690 last_frame_timestamp_us_ = video_frame.timestamp_us(); |
| 1672 | 1691 |
| 1673 if (pending_encoder_reconfiguration_) { | |
| 1674 ReconfigureEncoder(); | |
| 1675 pending_encoder_reconfiguration_ = false; | |
| 1676 } | |
| 1677 | |
| 1678 // Not sending, abort after reconfiguration. Reconfiguration should still | |
| 1679 // occur to permit sending this input as quickly as possible once we start | |
| 1680 // sending (without having to reconfigure then). | |
| 1681 if (!sending_) { | |
| 1682 return; | |
| 1683 } | |
| 1684 | |
| 1685 ++frame_count_; | 1692 ++frame_count_; |
| 1686 if (cpu_restricted_counter_ > 0) | 1693 if (cpu_restricted_counter_ > 0) |
| 1687 ++cpu_restricted_frame_count_; | 1694 ++cpu_restricted_frame_count_; |
| 1688 | 1695 |
| 1696 // Forward frame to the encoder regardless if we are sending or not. This is |
| 1697 // to ensure that the encoder can be reconfigured with the correct frame size |
| 1698 // as quickly as possible. |
| 1689 encoder_sink_->OnFrame(video_frame); | 1699 encoder_sink_->OnFrame(video_frame); |
| 1690 } | 1700 } |
| 1691 | 1701 |
| 1692 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( | 1702 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( |
| 1693 bool enable, | 1703 bool enable, |
| 1694 const VideoOptions* options, | 1704 const VideoOptions* options, |
| 1695 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { | 1705 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { |
| 1696 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); | 1706 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); |
| 1697 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1707 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1698 | 1708 |
| 1699 // Ignore |options| pointer if |enable| is false. | 1709 // Ignore |options| pointer if |enable| is false. |
| 1700 bool options_present = enable && options; | 1710 bool options_present = enable && options; |
| 1701 bool source_changing = source_ != source; | 1711 bool source_changing = source_ != source; |
| 1702 if (source_changing) { | 1712 if (source_changing) { |
| 1703 DisconnectSource(); | 1713 DisconnectSource(); |
| 1704 } | 1714 } |
| 1705 | 1715 |
| 1706 if (options_present || source_changing) { | 1716 if (options_present) { |
| 1707 rtc::CritScope cs(&lock_); | 1717 VideoOptions old_options = parameters_.options; |
| 1708 | 1718 parameters_.options.SetAll(*options); |
| 1709 if (options_present) { | 1719 // If options has changed and SetCodec has been called. |
| 1710 VideoOptions old_options = parameters_.options; | 1720 if (parameters_.options != old_options && stream_) { |
| 1711 parameters_.options.SetAll(*options); | 1721 ReconfigureEncoder(); |
| 1712 // Reconfigure encoder settings on the next frame or stream | |
| 1713 // recreation if the options changed. | |
| 1714 if (parameters_.options != old_options) { | |
| 1715 pending_encoder_reconfiguration_ = true; | |
| 1716 } | |
| 1717 } | |
| 1718 | |
| 1719 if (source_changing) { | |
| 1720 if (source == nullptr && encoder_sink_ != nullptr) { | |
| 1721 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; | |
| 1722 // Force this black frame not to be dropped due to timestamp order | |
| 1723 // check. As IncomingCapturedFrame will drop the frame if this frame's | |
| 1724 // timestamp is less than or equal to last frame's timestamp, it is | |
| 1725 // necessary to give this black frame a larger timestamp than the | |
| 1726 // previous one. | |
| 1727 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; | |
| 1728 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( | |
| 1729 webrtc::I420Buffer::Create(last_frame_info_.width, | |
| 1730 last_frame_info_.height)); | |
| 1731 black_buffer->SetToBlack(); | |
| 1732 | |
| 1733 encoder_sink_->OnFrame(webrtc::VideoFrame( | |
| 1734 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); | |
| 1735 } | |
| 1736 source_ = source; | |
| 1737 } | 1722 } |
| 1738 } | 1723 } |
| 1739 | 1724 |
| 1740 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 1725 if (source_changing) { |
| 1741 // that might cause a lock order inversion. | 1726 rtc::CritScope cs(&lock_); |
| 1727 if (source == nullptr && encoder_sink_ != nullptr && |
| 1728 last_frame_info_.width > 0) { |
| 1729 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; |
| 1730 // Force this black frame not to be dropped due to timestamp order |
| 1731 // check. As IncomingCapturedFrame will drop the frame if this frame's |
| 1732 // timestamp is less than or equal to last frame's timestamp, it is |
| 1733 // necessary to give this black frame a larger timestamp than the |
| 1734 // previous one. |
| 1735 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; |
| 1736 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( |
| 1737 webrtc::I420Buffer::Create(last_frame_info_.width, |
| 1738 last_frame_info_.height)); |
| 1739 black_buffer->SetToBlack(); |
| 1740 |
| 1741 encoder_sink_->OnFrame(webrtc::VideoFrame( |
| 1742 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); |
| 1743 } |
| 1744 source_ = source; |
| 1745 } |
| 1746 |
| 1742 if (source_changing && source_) { | 1747 if (source_changing && source_) { |
| 1748 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since |
| 1749 // that might cause a lock order inversion. |
| 1743 source_->AddOrUpdateSink(this, sink_wants_); | 1750 source_->AddOrUpdateSink(this, sink_wants_); |
| 1744 } | 1751 } |
| 1745 return true; | 1752 return true; |
| 1746 } | 1753 } |
| 1747 | 1754 |
| 1748 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { | 1755 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { |
| 1749 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1756 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1750 if (source_ == nullptr) { | 1757 if (source_ == nullptr) { |
| 1751 return; | 1758 return; |
| 1752 } | 1759 } |
| 1753 | 1760 |
| 1754 // |source_->RemoveSink| may not be called while holding |lock_| since | 1761 // |source_->RemoveSink| may not be called while holding |lock_| since |
| 1755 // that might cause a lock order inversion. | 1762 // that might cause a lock order inversion. |
| 1756 source_->RemoveSink(this); | 1763 source_->RemoveSink(this); |
| 1757 source_ = nullptr; | 1764 source_ = nullptr; |
| 1758 // Reset |cpu_restricted_counter_| if the source is changed. It is not | 1765 // Reset |cpu_restricted_counter_| if the source is changed. It is not |
| 1759 // possible to know if the video resolution is restricted by CPU usage after | 1766 // possible to know if the video resolution is restricted by CPU usage after |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1774 return webrtc::kVideoCodecVP9; | 1781 return webrtc::kVideoCodecVP9; |
| 1775 } else if (CodecNamesEq(name, kH264CodecName)) { | 1782 } else if (CodecNamesEq(name, kH264CodecName)) { |
| 1776 return webrtc::kVideoCodecH264; | 1783 return webrtc::kVideoCodecH264; |
| 1777 } | 1784 } |
| 1778 return webrtc::kVideoCodecUnknown; | 1785 return webrtc::kVideoCodecUnknown; |
| 1779 } | 1786 } |
| 1780 | 1787 |
| 1781 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder | 1788 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder |
| 1782 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( | 1789 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( |
| 1783 const VideoCodec& codec) { | 1790 const VideoCodec& codec) { |
| 1791 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1784 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); | 1792 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); |
| 1785 | 1793 |
| 1786 // Do not re-create encoders of the same type. | 1794 // Do not re-create encoders of the same type. |
| 1787 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { | 1795 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { |
| 1788 return allocated_encoder_; | 1796 return allocated_encoder_; |
| 1789 } | 1797 } |
| 1790 | 1798 |
| 1791 if (external_encoder_factory_ != NULL) { | 1799 if (external_encoder_factory_ != NULL) { |
| 1792 webrtc::VideoEncoder* encoder = | 1800 webrtc::VideoEncoder* encoder = |
| 1793 external_encoder_factory_->CreateVideoEncoder(type); | 1801 external_encoder_factory_->CreateVideoEncoder(type); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1808 } | 1816 } |
| 1809 | 1817 |
| 1810 // This shouldn't happen, we should not be trying to create something we don't | 1818 // This shouldn't happen, we should not be trying to create something we don't |
| 1811 // support. | 1819 // support. |
| 1812 RTC_DCHECK(false); | 1820 RTC_DCHECK(false); |
| 1813 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); | 1821 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); |
| 1814 } | 1822 } |
| 1815 | 1823 |
| 1816 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( | 1824 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( |
| 1817 AllocatedEncoder* encoder) { | 1825 AllocatedEncoder* encoder) { |
| 1826 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1818 if (encoder->external) { | 1827 if (encoder->external) { |
| 1819 external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder); | 1828 external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder); |
| 1820 } | 1829 } |
| 1821 delete encoder->encoder; | 1830 delete encoder->encoder; |
| 1822 } | 1831 } |
| 1823 | 1832 |
| 1824 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( | 1833 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( |
| 1825 const VideoCodecSettings& codec_settings) { | 1834 const VideoCodecSettings& codec_settings) { |
| 1835 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1826 parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec); | 1836 parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec); |
| 1827 RTC_DCHECK(!parameters_.encoder_config.streams.empty()); | 1837 RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u); |
| 1828 | 1838 |
| 1829 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); | 1839 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); |
| 1830 parameters_.config.encoder_settings.encoder = new_encoder.encoder; | 1840 parameters_.config.encoder_settings.encoder = new_encoder.encoder; |
| 1831 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; | 1841 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; |
| 1832 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; | 1842 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; |
| 1833 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; | 1843 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; |
| 1834 if (new_encoder.external) { | 1844 if (new_encoder.external) { |
| 1835 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); | 1845 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); |
| 1836 parameters_.config.encoder_settings.internal_source = | 1846 parameters_.config.encoder_settings.internal_source = |
| 1837 external_encoder_factory_->EncoderTypeHasInternalSource(type); | 1847 external_encoder_factory_->EncoderTypeHasInternalSource(type); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1858 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec."; | 1868 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec."; |
| 1859 RecreateWebRtcStream(); | 1869 RecreateWebRtcStream(); |
| 1860 if (allocated_encoder_.encoder != new_encoder.encoder) { | 1870 if (allocated_encoder_.encoder != new_encoder.encoder) { |
| 1861 DestroyVideoEncoder(&allocated_encoder_); | 1871 DestroyVideoEncoder(&allocated_encoder_); |
| 1862 allocated_encoder_ = new_encoder; | 1872 allocated_encoder_ = new_encoder; |
| 1863 } | 1873 } |
| 1864 } | 1874 } |
| 1865 | 1875 |
| 1866 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( | 1876 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( |
| 1867 const ChangedSendParameters& params) { | 1877 const ChangedSendParameters& params) { |
| 1868 { | 1878 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1869 rtc::CritScope cs(&lock_); | 1879 // |recreate_stream| means construction-time parameters have changed and the |
| 1870 // |recreate_stream| means construction-time parameters have changed and the | 1880 // sending stream needs to be reset with the new config. |
| 1871 // sending stream needs to be reset with the new config. | 1881 bool recreate_stream = false; |
| 1872 bool recreate_stream = false; | 1882 if (params.rtcp_mode) { |
| 1873 if (params.rtcp_mode) { | 1883 parameters_.config.rtp.rtcp_mode = *params.rtcp_mode; |
| 1874 parameters_.config.rtp.rtcp_mode = *params.rtcp_mode; | 1884 recreate_stream = true; |
| 1875 recreate_stream = true; | 1885 } |
| 1876 } | 1886 if (params.rtp_header_extensions) { |
| 1877 if (params.rtp_header_extensions) { | 1887 parameters_.config.rtp.extensions = *params.rtp_header_extensions; |
| 1878 parameters_.config.rtp.extensions = *params.rtp_header_extensions; | 1888 recreate_stream = true; |
| 1879 recreate_stream = true; | 1889 } |
| 1880 } | 1890 if (params.max_bandwidth_bps) { |
| 1881 if (params.max_bandwidth_bps) { | 1891 parameters_.max_bitrate_bps = *params.max_bandwidth_bps; |
| 1882 parameters_.max_bitrate_bps = *params.max_bandwidth_bps; | 1892 ReconfigureEncoder(); |
| 1883 pending_encoder_reconfiguration_ = true; | 1893 } |
| 1884 } | 1894 if (params.conference_mode) { |
| 1885 if (params.conference_mode) { | 1895 parameters_.conference_mode = *params.conference_mode; |
| 1886 parameters_.conference_mode = *params.conference_mode; | 1896 } |
| 1887 } | |
| 1888 | 1897 |
| 1889 // Set codecs and options. | 1898 // Set codecs and options. |
| 1890 if (params.codec) { | 1899 if (params.codec) { |
| 1891 SetCodec(*params.codec); | 1900 SetCodec(*params.codec); |
| 1892 recreate_stream = false; // SetCodec has already recreated the stream. | 1901 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1893 } else if (params.conference_mode && parameters_.codec_settings) { | 1902 } else if (params.conference_mode && parameters_.codec_settings) { |
| 1894 SetCodec(*parameters_.codec_settings); | 1903 SetCodec(*parameters_.codec_settings); |
| 1895 recreate_stream = false; // SetCodec has already recreated the stream. | 1904 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1896 } | 1905 } |
| 1897 if (recreate_stream) { | 1906 if (recreate_stream) { |
| 1898 LOG(LS_INFO) | 1907 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; |
| 1899 << "RecreateWebRtcStream (send) because of SetSendParameters"; | 1908 RecreateWebRtcStream(); |
| 1900 RecreateWebRtcStream(); | 1909 } |
| 1901 } | |
| 1902 } // release |lock_| | |
| 1903 | 1910 |
| 1904 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 1911 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since |
| 1905 // that might cause a lock order inversion. | 1912 // that might cause a lock order inversion. |
| 1906 if (params.rtp_header_extensions) { | 1913 if (params.rtp_header_extensions) { |
| 1907 sink_wants_.rotation_applied = !ContainsHeaderExtension( | 1914 sink_wants_.rotation_applied = !ContainsHeaderExtension( |
| 1908 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); | 1915 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); |
| 1909 if (source_) { | 1916 if (source_) { |
| 1910 source_->AddOrUpdateSink(this, sink_wants_); | 1917 source_->AddOrUpdateSink(this, sink_wants_); |
| 1911 } | 1918 } |
| 1912 } | 1919 } |
| 1913 } | 1920 } |
| 1914 | 1921 |
| 1915 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( | 1922 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( |
| 1916 const webrtc::RtpParameters& new_parameters) { | 1923 const webrtc::RtpParameters& new_parameters) { |
| 1924 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1917 if (!ValidateRtpParameters(new_parameters)) { | 1925 if (!ValidateRtpParameters(new_parameters)) { |
| 1918 return false; | 1926 return false; |
| 1919 } | 1927 } |
| 1920 | 1928 |
| 1921 rtc::CritScope cs(&lock_); | 1929 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != |
| 1922 if (new_parameters.encodings[0].max_bitrate_bps != | 1930 rtp_parameters_.encodings[0].max_bitrate_bps; |
| 1923 rtp_parameters_.encodings[0].max_bitrate_bps) { | |
| 1924 pending_encoder_reconfiguration_ = true; | |
| 1925 } | |
| 1926 rtp_parameters_ = new_parameters; | 1931 rtp_parameters_ = new_parameters; |
| 1927 // Codecs are currently handled at the WebRtcVideoChannel2 level. | 1932 // Codecs are currently handled at the WebRtcVideoChannel2 level. |
| 1928 rtp_parameters_.codecs.clear(); | 1933 rtp_parameters_.codecs.clear(); |
| 1934 if (reconfigure_encoder) { |
| 1935 ReconfigureEncoder(); |
| 1936 } |
| 1929 // Encoding may have been activated/deactivated. | 1937 // Encoding may have been activated/deactivated. |
| 1930 UpdateSendState(); | 1938 UpdateSendState(); |
| 1931 return true; | 1939 return true; |
| 1932 } | 1940 } |
| 1933 | 1941 |
| 1934 webrtc::RtpParameters | 1942 webrtc::RtpParameters |
| 1935 WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const { | 1943 WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const { |
| 1936 rtc::CritScope cs(&lock_); | 1944 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1937 return rtp_parameters_; | 1945 return rtp_parameters_; |
| 1938 } | 1946 } |
| 1939 | 1947 |
| 1940 bool WebRtcVideoChannel2::WebRtcVideoSendStream::ValidateRtpParameters( | 1948 bool WebRtcVideoChannel2::WebRtcVideoSendStream::ValidateRtpParameters( |
| 1941 const webrtc::RtpParameters& rtp_parameters) { | 1949 const webrtc::RtpParameters& rtp_parameters) { |
| 1942 if (rtp_parameters.encodings.size() != 1) { | 1950 if (rtp_parameters.encodings.size() != 1) { |
| 1943 LOG(LS_ERROR) | 1951 LOG(LS_ERROR) |
| 1944 << "Attempted to set RtpParameters without exactly one encoding"; | 1952 << "Attempted to set RtpParameters without exactly one encoding"; |
| 1945 return false; | 1953 return false; |
| 1946 } | 1954 } |
| 1947 return true; | 1955 return true; |
| 1948 } | 1956 } |
| 1949 | 1957 |
| 1950 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() { | 1958 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() { |
| 1959 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1951 // TODO(deadbeef): Need to handle more than one encoding in the future. | 1960 // TODO(deadbeef): Need to handle more than one encoding in the future. |
| 1952 RTC_DCHECK(rtp_parameters_.encodings.size() == 1u); | 1961 RTC_DCHECK(rtp_parameters_.encodings.size() == 1u); |
| 1953 if (sending_ && rtp_parameters_.encodings[0].active) { | 1962 if (sending_ && rtp_parameters_.encodings[0].active) { |
| 1954 RTC_DCHECK(stream_ != nullptr); | 1963 RTC_DCHECK(stream_ != nullptr); |
| 1955 stream_->Start(); | 1964 stream_->Start(); |
| 1956 } else { | 1965 } else { |
| 1957 if (stream_ != nullptr) { | 1966 if (stream_ != nullptr) { |
| 1958 stream_->Stop(); | 1967 stream_->Stop(); |
| 1959 } | 1968 } |
| 1960 } | 1969 } |
| 1961 } | 1970 } |
| 1962 | 1971 |
| 1963 webrtc::VideoEncoderConfig | 1972 webrtc::VideoEncoderConfig |
| 1964 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( | 1973 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( |
| 1965 const VideoCodec& codec) const { | 1974 const VideoCodec& codec) const { |
| 1975 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1966 webrtc::VideoEncoderConfig encoder_config; | 1976 webrtc::VideoEncoderConfig encoder_config; |
| 1967 bool is_screencast = parameters_.options.is_screencast.value_or(false); | 1977 bool is_screencast = parameters_.options.is_screencast.value_or(false); |
| 1968 if (is_screencast) { | 1978 if (is_screencast) { |
| 1969 encoder_config.min_transmit_bitrate_bps = | 1979 encoder_config.min_transmit_bitrate_bps = |
| 1970 1000 * parameters_.options.screencast_min_bitrate_kbps.value_or(0); | 1980 1000 * parameters_.options.screencast_min_bitrate_kbps.value_or(0); |
| 1971 encoder_config.content_type = | 1981 encoder_config.content_type = |
| 1972 webrtc::VideoEncoderConfig::ContentType::kScreen; | 1982 webrtc::VideoEncoderConfig::ContentType::kScreen; |
| 1973 } else { | 1983 } else { |
| 1974 encoder_config.min_transmit_bitrate_bps = 0; | 1984 encoder_config.min_transmit_bitrate_bps = 0; |
| 1975 encoder_config.content_type = | 1985 encoder_config.content_type = |
| 1976 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo; | 1986 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo; |
| 1977 } | 1987 } |
| 1978 | 1988 |
| 1979 // Restrict dimensions according to codec max. | |
| 1980 int width = last_frame_info_.width; | |
| 1981 int height = last_frame_info_.height; | |
| 1982 if (!is_screencast) { | |
| 1983 if (codec.width < width) | |
| 1984 width = codec.width; | |
| 1985 if (codec.height < height) | |
| 1986 height = codec.height; | |
| 1987 } | |
| 1988 | |
| 1989 VideoCodec clamped_codec = codec; | |
| 1990 clamped_codec.width = width; | |
| 1991 clamped_codec.height = height; | |
| 1992 | |
| 1993 // By default, the stream count for the codec configuration should match the | 1989 // By default, the stream count for the codec configuration should match the |
| 1994 // number of negotiated ssrcs. But if the codec is blacklisted for simulcast | 1990 // number of negotiated ssrcs. But if the codec is blacklisted for simulcast |
| 1995 // or a screencast, only configure a single stream. | 1991 // or a screencast, only configure a single stream. |
| 1996 size_t stream_count = parameters_.config.rtp.ssrcs.size(); | 1992 encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size(); |
| 1997 if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) { | 1993 if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) { |
| 1998 stream_count = 1; | 1994 encoder_config.number_of_streams = 1; |
| 1999 } | 1995 } |
| 2000 | 1996 |
| 2001 int stream_max_bitrate = | 1997 int stream_max_bitrate = |
| 2002 MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps, | 1998 MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps, |
| 2003 parameters_.max_bitrate_bps); | 1999 parameters_.max_bitrate_bps); |
| 2004 encoder_config.streams = CreateVideoStreams( | |
| 2005 clamped_codec, parameters_.options, stream_max_bitrate, stream_count); | |
| 2006 encoder_config.expect_encode_from_texture = last_frame_info_.is_texture; | |
| 2007 | 2000 |
| 2008 // Conference mode screencast uses 2 temporal layers split at 100kbit. | 2001 int codec_max_bitrate_kbps; |
| 2009 if (parameters_.conference_mode && is_screencast && | 2002 if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) { |
| 2010 encoder_config.streams.size() == 1) { | 2003 stream_max_bitrate = codec_max_bitrate_kbps * 1000; |
| 2011 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); | 2004 } |
| 2005 encoder_config.max_bitrate_bps = stream_max_bitrate; |
| 2012 | 2006 |
| 2013 // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked | 2007 int max_qp = kDefaultQpMax; |
| 2014 // on the VideoCodec struct as target and max bitrates, respectively. | 2008 codec.GetParam(kCodecParamMaxQuantization, &max_qp); |
| 2015 // See eg. webrtc::VP8EncoderImpl::SetRates(). | 2009 int max_framerate = |
| 2016 encoder_config.streams[0].target_bitrate_bps = | 2010 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; |
| 2017 config.tl0_bitrate_kbps * 1000; | 2011 |
| 2018 encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; | 2012 encoder_config.encoder_stream_factory = |
| 2019 encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); | 2013 new rtc::RefCountedObject<EncoderStreamFactory>( |
| 2020 encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( | 2014 codec.name, max_qp, max_framerate, is_screencast, |
| 2021 config.tl0_bitrate_kbps * 1000); | 2015 parameters_.conference_mode); |
| 2022 } | |
| 2023 if (CodecNamesEq(codec.name, kVp9CodecName) && !is_screencast && | |
| 2024 encoder_config.streams.size() == 1) { | |
| 2025 encoder_config.streams[0].temporal_layer_thresholds_bps.resize( | |
| 2026 GetDefaultVp9TemporalLayers() - 1); | |
| 2027 } | |
| 2028 return encoder_config; | 2016 return encoder_config; |
| 2029 } | 2017 } |
| 2030 | 2018 |
| 2031 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() { | 2019 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() { |
| 2032 RTC_DCHECK(!parameters_.encoder_config.streams.empty()); | 2020 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2021 RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u); |
| 2033 | 2022 |
| 2034 RTC_CHECK(parameters_.codec_settings); | 2023 RTC_CHECK(parameters_.codec_settings); |
| 2035 VideoCodecSettings codec_settings = *parameters_.codec_settings; | 2024 VideoCodecSettings codec_settings = *parameters_.codec_settings; |
| 2036 | 2025 |
| 2037 webrtc::VideoEncoderConfig encoder_config = | 2026 webrtc::VideoEncoderConfig encoder_config = |
| 2038 CreateVideoEncoderConfig(codec_settings.codec); | 2027 CreateVideoEncoderConfig(codec_settings.codec); |
| 2039 | 2028 |
| 2040 encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings( | 2029 encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings( |
| 2041 codec_settings.codec); | 2030 codec_settings.codec); |
| 2042 | 2031 |
| 2043 stream_->ReconfigureVideoEncoder(encoder_config.Copy()); | 2032 stream_->ReconfigureVideoEncoder(encoder_config.Copy()); |
| 2044 | 2033 |
| 2045 encoder_config.encoder_specific_settings = NULL; | 2034 encoder_config.encoder_specific_settings = NULL; |
| 2046 | 2035 |
| 2047 parameters_.encoder_config = std::move(encoder_config); | 2036 parameters_.encoder_config = std::move(encoder_config); |
| 2048 } | 2037 } |
| 2049 | 2038 |
| 2050 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { | 2039 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { |
| 2051 rtc::CritScope cs(&lock_); | 2040 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2052 sending_ = send; | 2041 sending_ = send; |
| 2053 UpdateSendState(); | 2042 UpdateSendState(); |
| 2054 } | 2043 } |
| 2055 | 2044 |
| 2056 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( | 2045 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( |
| 2057 VideoSinkInterface<webrtc::VideoFrame>* sink, | 2046 VideoSinkInterface<webrtc::VideoFrame>* sink, |
| 2058 const rtc::VideoSinkWants& wants) { | 2047 const rtc::VideoSinkWants& wants) { |
| 2059 // TODO(perkj): Actually consider the encoder |wants| and remove | 2048 // TODO(perkj): Actually consider the encoder |wants| and remove |
| 2060 // WebRtcVideoSendStream::OnLoadUpdate(Load load). | 2049 // WebRtcVideoSendStream::OnLoadUpdate(Load load). |
| 2061 rtc::CritScope cs(&lock_); | 2050 rtc::CritScope cs(&lock_); |
| 2062 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); | 2051 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); |
| 2063 encoder_sink_ = sink; | 2052 encoder_sink_ = sink; |
| 2064 } | 2053 } |
| 2065 | 2054 |
| 2066 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | 2055 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( |
| 2067 VideoSinkInterface<webrtc::VideoFrame>* sink) { | 2056 VideoSinkInterface<webrtc::VideoFrame>* sink) { |
| 2068 rtc::CritScope cs(&lock_); | 2057 rtc::CritScope cs(&lock_); |
| 2069 RTC_DCHECK_EQ(encoder_sink_, sink); | 2058 RTC_DCHECK_EQ(encoder_sink_, sink); |
| 2070 encoder_sink_ = nullptr; | 2059 encoder_sink_ = nullptr; |
| 2071 } | 2060 } |
| 2072 | 2061 |
| 2073 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { | 2062 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { |
| 2074 if (worker_thread_ != rtc::Thread::Current()) { | 2063 if (worker_thread_ != rtc::Thread::Current()) { |
| 2075 invoker_.AsyncInvoke<void>( | 2064 invoker_.AsyncInvoke<void>( |
| 2076 RTC_FROM_HERE, worker_thread_, | 2065 RTC_FROM_HERE, worker_thread_, |
| 2077 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, | 2066 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, |
| 2078 this, load)); | 2067 this, load)); |
| 2079 return; | 2068 return; |
| 2080 } | 2069 } |
| 2081 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2070 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2082 if (!source_) { | 2071 if (!source_) { |
| 2083 return; | 2072 return; |
| 2084 } | 2073 } |
| 2085 { | 2074 |
| 2075 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " |
| 2076 << (parameters_.options.is_screencast |
| 2077 ? (*parameters_.options.is_screencast ? "true" : "false") |
| 2078 : "unset"); |
| 2079 // Do not adapt resolution for screen content as this will likely result in |
| 2080 // blurry and unreadable text. |
| 2081 if (parameters_.options.is_screencast.value_or(false)) |
| 2082 return; |
| 2083 |
| 2084 rtc::Optional<int> max_pixel_count; |
| 2085 rtc::Optional<int> max_pixel_count_step_up; |
| 2086 if (load == kOveruse) { |
| 2086 rtc::CritScope cs(&lock_); | 2087 rtc::CritScope cs(&lock_); |
| 2087 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " | 2088 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { |
| 2088 << (parameters_.options.is_screencast | |
| 2089 ? (*parameters_.options.is_screencast ? "true" | |
| 2090 : "false") | |
| 2091 : "unset"); | |
| 2092 // Do not adapt resolution for screen content as this will likely result in | |
| 2093 // blurry and unreadable text. | |
| 2094 if (parameters_.options.is_screencast.value_or(false)) | |
| 2095 return; | 2089 return; |
| 2096 | |
| 2097 rtc::Optional<int> max_pixel_count; | |
| 2098 rtc::Optional<int> max_pixel_count_step_up; | |
| 2099 if (load == kOveruse) { | |
| 2100 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { | |
| 2101 return; | |
| 2102 } | |
| 2103 // The input video frame size will have a resolution with less than or | |
| 2104 // equal to |max_pixel_count| depending on how the source can scale the | |
| 2105 // input frame size. | |
| 2106 max_pixel_count = rtc::Optional<int>( | |
| 2107 (last_frame_info_.height * last_frame_info_.width * 3) / 5); | |
| 2108 // Increase |number_of_cpu_adapt_changes_| if | |
| 2109 // sink_wants_.max_pixel_count will be changed since | |
| 2110 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2111 // result in a new request for the source to change resolution. | |
| 2112 if (!sink_wants_.max_pixel_count || | |
| 2113 *sink_wants_.max_pixel_count > *max_pixel_count) { | |
| 2114 ++number_of_cpu_adapt_changes_; | |
| 2115 ++cpu_restricted_counter_; | |
| 2116 } | |
| 2117 } else { | |
| 2118 RTC_DCHECK(load == kUnderuse); | |
| 2119 // The input video frame size will have a resolution with "one step up" | |
| 2120 // pixels than |max_pixel_count_step_up| where "one step up" depends on | |
| 2121 // how the source can scale the input frame size. | |
| 2122 max_pixel_count_step_up = | |
| 2123 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); | |
| 2124 // Increase |number_of_cpu_adapt_changes_| if | |
| 2125 // sink_wants_.max_pixel_count_step_up will be changed since | |
| 2126 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2127 // result in a new request for the source to change resolution. | |
| 2128 if (sink_wants_.max_pixel_count || | |
| 2129 (sink_wants_.max_pixel_count_step_up && | |
| 2130 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { | |
| 2131 ++number_of_cpu_adapt_changes_; | |
| 2132 --cpu_restricted_counter_; | |
| 2133 } | |
| 2134 } | 2090 } |
| 2135 sink_wants_.max_pixel_count = max_pixel_count; | 2091 // The input video frame size will have a resolution with less than or |
| 2136 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; | 2092 // equal to |max_pixel_count| depending on how the source can scale the |
| 2093 // input frame size. |
| 2094 max_pixel_count = rtc::Optional<int>( |
| 2095 (last_frame_info_.height * last_frame_info_.width * 3) / 5); |
| 2096 // Increase |number_of_cpu_adapt_changes_| if |
| 2097 // sink_wants_.max_pixel_count will be changed since |
| 2098 // last time |source_->AddOrUpdateSink| was called. That is, this will |
| 2099 // result in a new request for the source to change resolution. |
| 2100 if (!sink_wants_.max_pixel_count || |
| 2101 *sink_wants_.max_pixel_count > *max_pixel_count) { |
| 2102 ++number_of_cpu_adapt_changes_; |
| 2103 ++cpu_restricted_counter_; |
| 2104 } |
| 2105 } else { |
| 2106 RTC_DCHECK(load == kUnderuse); |
| 2107 rtc::CritScope cs(&lock_); |
| 2108 // The input video frame size will have a resolution with "one step up" |
| 2109 // pixels than |max_pixel_count_step_up| where "one step up" depends on |
| 2110 // how the source can scale the input frame size. |
| 2111 max_pixel_count_step_up = |
| 2112 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); |
| 2113 // Increase |number_of_cpu_adapt_changes_| if |
| 2114 // sink_wants_.max_pixel_count_step_up will be changed since |
| 2115 // last time |source_->AddOrUpdateSink| was called. That is, this will |
| 2116 // result in a new request for the source to change resolution. |
| 2117 if (sink_wants_.max_pixel_count || |
| 2118 (sink_wants_.max_pixel_count_step_up && |
| 2119 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { |
| 2120 ++number_of_cpu_adapt_changes_; |
| 2121 --cpu_restricted_counter_; |
| 2122 } |
| 2137 } | 2123 } |
| 2124 sink_wants_.max_pixel_count = max_pixel_count; |
| 2125 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; |
| 2138 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 2126 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since |
| 2139 // that might cause a lock order inversion. | 2127 // that might cause a lock order inversion. |
| 2140 source_->AddOrUpdateSink(this, sink_wants_); | 2128 source_->AddOrUpdateSink(this, sink_wants_); |
| 2141 } | 2129 } |
| 2142 | 2130 |
| 2143 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( | 2131 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( |
| 2144 bool log_stats) { | 2132 bool log_stats) { |
| 2145 VideoSenderInfo info; | 2133 VideoSenderInfo info; |
| 2146 webrtc::VideoSendStream::Stats stats; | 2134 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2147 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2135 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |
| 2148 { | 2136 info.add_ssrc(ssrc); |
| 2149 rtc::CritScope cs(&lock_); | |
| 2150 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) | |
| 2151 info.add_ssrc(ssrc); | |
| 2152 | 2137 |
| 2153 if (parameters_.codec_settings) | 2138 if (parameters_.codec_settings) |
| 2154 info.codec_name = parameters_.codec_settings->codec.name; | 2139 info.codec_name = parameters_.codec_settings->codec.name; |
| 2155 | 2140 |
| 2156 if (stream_ == NULL) | 2141 if (stream_ == NULL) |
| 2157 return info; | 2142 return info; |
| 2158 | 2143 |
| 2159 stats = stream_->GetStats(); | 2144 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |
| 2160 } | |
| 2161 | 2145 |
| 2162 if (log_stats) | 2146 if (log_stats) |
| 2163 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); | 2147 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); |
| 2164 | 2148 |
| 2165 info.adapt_changes = number_of_cpu_adapt_changes_; | 2149 info.adapt_changes = number_of_cpu_adapt_changes_; |
| 2166 info.adapt_reason = | 2150 info.adapt_reason = |
| 2167 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; | 2151 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; |
| 2168 | 2152 |
| 2169 // Get bandwidth limitation info from stream_->GetStats(). | 2153 // Get bandwidth limitation info from stream_->GetStats(). |
| 2170 // Input resolution (output from video_adapter) can be further scaled down or | 2154 // Input resolution (output from video_adapter) can be further scaled down or |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2211 info.fraction_lost = | 2195 info.fraction_lost = |
| 2212 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / | 2196 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / |
| 2213 (1 << 8); | 2197 (1 << 8); |
| 2214 } | 2198 } |
| 2215 | 2199 |
| 2216 return info; | 2200 return info; |
| 2217 } | 2201 } |
| 2218 | 2202 |
| 2219 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( | 2203 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( |
| 2220 BandwidthEstimationInfo* bwe_info) { | 2204 BandwidthEstimationInfo* bwe_info) { |
| 2221 rtc::CritScope cs(&lock_); | 2205 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2222 if (stream_ == NULL) { | 2206 if (stream_ == NULL) { |
| 2223 return; | 2207 return; |
| 2224 } | 2208 } |
| 2225 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); | 2209 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |
| 2226 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = | 2210 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = |
| 2227 stats.substreams.begin(); | 2211 stats.substreams.begin(); |
| 2228 it != stats.substreams.end(); ++it) { | 2212 it != stats.substreams.end(); ++it) { |
| 2229 bwe_info->transmit_bitrate += it->second.total_bitrate_bps; | 2213 bwe_info->transmit_bitrate += it->second.total_bitrate_bps; |
| 2230 bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; | 2214 bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; |
| 2231 } | 2215 } |
| 2232 bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; | 2216 bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; |
| 2233 bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; | 2217 bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; |
| 2234 } | 2218 } |
| 2235 | 2219 |
| 2236 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { | 2220 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { |
| 2221 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2237 if (stream_ != NULL) { | 2222 if (stream_ != NULL) { |
| 2238 call_->DestroyVideoSendStream(stream_); | 2223 call_->DestroyVideoSendStream(stream_); |
| 2239 } | 2224 } |
| 2240 | 2225 |
| 2241 RTC_CHECK(parameters_.codec_settings); | 2226 RTC_CHECK(parameters_.codec_settings); |
| 2242 RTC_DCHECK_EQ((parameters_.encoder_config.content_type == | 2227 RTC_DCHECK_EQ((parameters_.encoder_config.content_type == |
| 2243 webrtc::VideoEncoderConfig::ContentType::kScreen), | 2228 webrtc::VideoEncoderConfig::ContentType::kScreen), |
| 2244 parameters_.options.is_screencast.value_or(false)) | 2229 parameters_.options.is_screencast.value_or(false)) |
| 2245 << "encoder content type inconsistent with screencast option"; | 2230 << "encoder content type inconsistent with screencast option"; |
| 2246 parameters_.encoder_config.encoder_specific_settings = | 2231 parameters_.encoder_config.encoder_specific_settings = |
| 2247 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); | 2232 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); |
| 2248 | 2233 |
| 2249 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); | 2234 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); |
| 2250 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { | 2235 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { |
| 2251 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 2236 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
| 2252 "payload type the set codec. Ignoring RTX."; | 2237 "payload type the set codec. Ignoring RTX."; |
| 2253 config.rtp.rtx.ssrcs.clear(); | 2238 config.rtp.rtx.ssrcs.clear(); |
| 2254 } | 2239 } |
| 2255 stream_ = call_->CreateVideoSendStream(std::move(config), | 2240 stream_ = call_->CreateVideoSendStream(std::move(config), |
| 2256 parameters_.encoder_config.Copy()); | 2241 parameters_.encoder_config.Copy()); |
| 2257 stream_->SetSource(this); | 2242 stream_->SetSource(this); |
| 2258 | 2243 |
| 2259 parameters_.encoder_config.encoder_specific_settings = NULL; | 2244 parameters_.encoder_config.encoder_specific_settings = NULL; |
| 2260 pending_encoder_reconfiguration_ = false; | |
| 2261 | 2245 |
| 2262 // Call stream_->Start() if necessary conditions are met. | 2246 // Call stream_->Start() if necessary conditions are met. |
| 2263 UpdateSendState(); | 2247 UpdateSendState(); |
| 2264 } | 2248 } |
| 2265 | 2249 |
| 2266 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( | 2250 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
| 2267 webrtc::Call* call, | 2251 webrtc::Call* call, |
| 2268 const StreamParams& sp, | 2252 const StreamParams& sp, |
| 2269 webrtc::VideoReceiveStream::Config config, | 2253 webrtc::VideoReceiveStream::Config config, |
| 2270 WebRtcVideoDecoderFactory* external_decoder_factory, | 2254 WebRtcVideoDecoderFactory* external_decoder_factory, |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2706 rtx_mapping[video_codecs[i].codec.id] != | 2690 rtx_mapping[video_codecs[i].codec.id] != |
| 2707 fec_settings.red_payload_type) { | 2691 fec_settings.red_payload_type) { |
| 2708 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2692 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
| 2709 } | 2693 } |
| 2710 } | 2694 } |
| 2711 | 2695 |
| 2712 return video_codecs; | 2696 return video_codecs; |
| 2713 } | 2697 } |
| 2714 | 2698 |
| 2715 } // namespace cricket | 2699 } // namespace cricket |
| OLD | NEW |