| 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 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "webrtc/call.h" | 24 #include "webrtc/call.h" |
| 25 #include "webrtc/media/engine/constants.h" | 25 #include "webrtc/media/engine/constants.h" |
| 26 #include "webrtc/media/engine/simulcast.h" | 26 #include "webrtc/media/engine/simulcast.h" |
| 27 #include "webrtc/media/engine/webrtcmediaengine.h" | 27 #include "webrtc/media/engine/webrtcmediaengine.h" |
| 28 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" | 28 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" |
| 29 #include "webrtc/media/engine/webrtcvoiceengine.h" | 29 #include "webrtc/media/engine/webrtcvoiceengine.h" |
| 30 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" | 30 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" |
| 31 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" | 31 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" |
| 32 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" | 32 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" |
| 33 #include "webrtc/system_wrappers/include/field_trial.h" | 33 #include "webrtc/system_wrappers/include/field_trial.h" |
| 34 #include "webrtc/system_wrappers/include/metrics.h" | |
| 35 #include "webrtc/video_decoder.h" | 34 #include "webrtc/video_decoder.h" |
| 36 #include "webrtc/video_encoder.h" | 35 #include "webrtc/video_encoder.h" |
| 37 | 36 |
| 38 namespace cricket { | 37 namespace cricket { |
| 39 namespace { | 38 namespace { |
| 40 | 39 |
| 41 // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. | 40 // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. |
| 42 class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { | 41 class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { |
| 43 public: | 42 public: |
| 44 // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned | 43 // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { | 229 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { |
| 231 LOG(LS_ERROR) | 230 LOG(LS_ERROR) |
| 232 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " | 231 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " |
| 233 << sp.ToString(); | 232 << sp.ToString(); |
| 234 return false; | 233 return false; |
| 235 } | 234 } |
| 236 | 235 |
| 237 return true; | 236 return true; |
| 238 } | 237 } |
| 239 | 238 |
| 240 inline bool ContainsHeaderExtension( | |
| 241 const std::vector<webrtc::RtpExtension>& extensions, | |
| 242 const std::string& uri) { | |
| 243 for (const auto& kv : extensions) { | |
| 244 if (kv.uri == uri) { | |
| 245 return true; | |
| 246 } | |
| 247 } | |
| 248 return false; | |
| 249 } | |
| 250 | |
| 251 // Returns true if the given codec is disallowed from doing simulcast. | 239 // Returns true if the given codec is disallowed from doing simulcast. |
| 252 bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { | 240 bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { |
| 253 return CodecNamesEq(codec_name, kH264CodecName) || | 241 return CodecNamesEq(codec_name, kH264CodecName) || |
| 254 CodecNamesEq(codec_name, kVp9CodecName); | 242 CodecNamesEq(codec_name, kVp9CodecName); |
| 255 } | 243 } |
| 256 | 244 |
| 257 // The selected thresholds for QVGA and VGA corresponded to a QP around 10. | 245 // The selected thresholds for QVGA and VGA corresponded to a QP around 10. |
| 258 // The change in QP declined above the selected bitrates. | 246 // The change in QP declined above the selected bitrates. |
| 259 static int GetMaxDefaultVideoBitrateKbps(int width, int height) { | 247 static int GetMaxDefaultVideoBitrateKbps(int width, int height) { |
| 260 if (width * height <= 320 * 240) { | 248 if (width * height <= 320 * 240) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 const int kVideoRtpBufferSize = 65536; | 376 const int kVideoRtpBufferSize = 65536; |
| 389 | 377 |
| 390 // This constant is really an on/off, lower-level configurable NACK history | 378 // This constant is really an on/off, lower-level configurable NACK history |
| 391 // duration hasn't been implemented. | 379 // duration hasn't been implemented. |
| 392 static const int kNackHistoryMs = 1000; | 380 static const int kNackHistoryMs = 1000; |
| 393 | 381 |
| 394 static const int kDefaultQpMax = 56; | 382 static const int kDefaultQpMax = 56; |
| 395 | 383 |
| 396 static const int kDefaultRtcpReceiverReportSsrc = 1; | 384 static const int kDefaultRtcpReceiverReportSsrc = 1; |
| 397 | 385 |
| 398 // Down grade resolution at most 2 times for CPU reasons. | |
| 399 static const int kMaxCpuDowngrades = 2; | |
| 400 | |
| 401 // Minimum time interval for logging stats. | 386 // Minimum time interval for logging stats. |
| 402 static const int64_t kStatsLogIntervalMs = 10000; | 387 static const int64_t kStatsLogIntervalMs = 10000; |
| 403 | 388 |
| 404 // Adds |codec| to |list|, and also adds an RTX codec if |codec|'s name is | 389 // Adds |codec| to |list|, and also adds an RTX codec if |codec|'s name is |
| 405 // recognized. | 390 // recognized. |
| 406 // TODO(deadbeef): Should we add RTX codecs for external codecs whose names we | 391 // TODO(deadbeef): Should we add RTX codecs for external codecs whose names we |
| 407 // don't recognize? | 392 // don't recognize? |
| 408 void AddCodecAndMaybeRtxCodec(const VideoCodec& codec, | 393 void AddCodecAndMaybeRtxCodec(const VideoCodec& codec, |
| 409 std::vector<VideoCodec>* codecs) { | 394 std::vector<VideoCodec>* codecs) { |
| 410 codecs->push_back(codec); | 395 codecs->push_back(codec); |
| (...skipping 1149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 int max_bitrate_bps, | 1545 int max_bitrate_bps, |
| 1561 const rtc::Optional<VideoCodecSettings>& codec_settings, | 1546 const rtc::Optional<VideoCodecSettings>& codec_settings, |
| 1562 const rtc::Optional<std::vector<webrtc::RtpExtension>>& rtp_extensions, | 1547 const rtc::Optional<std::vector<webrtc::RtpExtension>>& rtp_extensions, |
| 1563 // TODO(deadbeef): Don't duplicate information between send_params, | 1548 // TODO(deadbeef): Don't duplicate information between send_params, |
| 1564 // rtp_extensions, options, etc. | 1549 // rtp_extensions, options, etc. |
| 1565 const VideoSendParameters& send_params) | 1550 const VideoSendParameters& send_params) |
| 1566 : worker_thread_(rtc::Thread::Current()), | 1551 : worker_thread_(rtc::Thread::Current()), |
| 1567 ssrcs_(sp.ssrcs), | 1552 ssrcs_(sp.ssrcs), |
| 1568 ssrc_groups_(sp.ssrc_groups), | 1553 ssrc_groups_(sp.ssrc_groups), |
| 1569 call_(call), | 1554 call_(call), |
| 1570 cpu_restricted_counter_(0), | 1555 enable_cpu_overuse_detection_(enable_cpu_overuse_detection), |
| 1571 number_of_cpu_adapt_changes_(0), | |
| 1572 frame_count_(0), | |
| 1573 cpu_restricted_frame_count_(0), | |
| 1574 source_(nullptr), | 1556 source_(nullptr), |
| 1575 external_encoder_factory_(external_encoder_factory), | 1557 external_encoder_factory_(external_encoder_factory), |
| 1576 stream_(nullptr), | 1558 stream_(nullptr), |
| 1577 encoder_sink_(nullptr), | 1559 encoder_sink_(nullptr), |
| 1578 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1560 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
| 1579 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1561 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
| 1580 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), | 1562 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), |
| 1581 sending_(false), | 1563 sending_(false), |
| 1582 last_frame_timestamp_us_(0) { | 1564 last_frame_timestamp_us_(0) { |
| 1583 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1565 parameters_.config.rtp.max_packet_size = kVideoMtu; |
| 1584 parameters_.conference_mode = send_params.conference_mode; | 1566 parameters_.conference_mode = send_params.conference_mode; |
| 1585 | 1567 |
| 1586 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1568 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
| 1587 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, | 1569 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
| 1588 ¶meters_.config.rtp.rtx.ssrcs); | 1570 ¶meters_.config.rtp.rtx.ssrcs); |
| 1589 parameters_.config.rtp.c_name = sp.cname; | 1571 parameters_.config.rtp.c_name = sp.cname; |
| 1590 if (rtp_extensions) { | 1572 if (rtp_extensions) { |
| 1591 parameters_.config.rtp.extensions = *rtp_extensions; | 1573 parameters_.config.rtp.extensions = *rtp_extensions; |
| 1592 } | 1574 } |
| 1593 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size | 1575 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size |
| 1594 ? webrtc::RtcpMode::kReducedSize | 1576 ? webrtc::RtcpMode::kReducedSize |
| 1595 : webrtc::RtcpMode::kCompound; | 1577 : webrtc::RtcpMode::kCompound; |
| 1596 parameters_.config.overuse_callback = | |
| 1597 enable_cpu_overuse_detection ? this : nullptr; | |
| 1598 | |
| 1599 // Only request rotation at the source when we positively know that the remote | |
| 1600 // side doesn't support the rotation extension. This allows us to prepare the | |
| 1601 // encoder in the expectation that rotation is supported - which is the common | |
| 1602 // case. | |
| 1603 sink_wants_.rotation_applied = | |
| 1604 rtp_extensions && | |
| 1605 !ContainsHeaderExtension(*rtp_extensions, | |
| 1606 webrtc::RtpExtension::kVideoRotationUri); | |
| 1607 | |
| 1608 if (codec_settings) { | 1578 if (codec_settings) { |
| 1609 SetCodec(*codec_settings); | 1579 SetCodec(*codec_settings); |
| 1610 } | 1580 } |
| 1611 } | 1581 } |
| 1612 | 1582 |
| 1613 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { | 1583 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { |
| 1614 DisconnectSource(); | |
| 1615 if (stream_ != NULL) { | 1584 if (stream_ != NULL) { |
| 1616 call_->DestroyVideoSendStream(stream_); | 1585 call_->DestroyVideoSendStream(stream_); |
| 1617 } | 1586 } |
| 1618 DestroyVideoEncoder(&allocated_encoder_); | 1587 DestroyVideoEncoder(&allocated_encoder_); |
| 1619 UpdateHistograms(); | |
| 1620 } | |
| 1621 | |
| 1622 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateHistograms() const { | |
| 1623 const int kMinRequiredFrames = 200; | |
| 1624 if (frame_count_ > kMinRequiredFrames) { | |
| 1625 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.CpuLimitedResolutionInPercent", | |
| 1626 cpu_restricted_frame_count_ * 100 / frame_count_); | |
| 1627 } | |
| 1628 } | 1588 } |
| 1629 | 1589 |
| 1630 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( | 1590 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( |
| 1631 const VideoFrame& frame) { | 1591 const VideoFrame& frame) { |
| 1632 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); | 1592 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); |
| 1633 webrtc::VideoFrame video_frame(frame.video_frame_buffer(), | 1593 webrtc::VideoFrame video_frame(frame.video_frame_buffer(), |
| 1634 frame.rotation(), | 1594 frame.rotation(), |
| 1635 frame.timestamp_us()); | 1595 frame.timestamp_us()); |
| 1636 | 1596 |
| 1637 rtc::CritScope cs(&lock_); | 1597 rtc::CritScope cs(&lock_); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1651 << ", texture=" << last_frame_info_.is_texture; | 1611 << ", texture=" << last_frame_info_.is_texture; |
| 1652 } | 1612 } |
| 1653 | 1613 |
| 1654 if (encoder_sink_ == NULL) { | 1614 if (encoder_sink_ == NULL) { |
| 1655 // Frame input before send codecs are configured, dropping frame. | 1615 // Frame input before send codecs are configured, dropping frame. |
| 1656 return; | 1616 return; |
| 1657 } | 1617 } |
| 1658 | 1618 |
| 1659 last_frame_timestamp_us_ = video_frame.timestamp_us(); | 1619 last_frame_timestamp_us_ = video_frame.timestamp_us(); |
| 1660 | 1620 |
| 1661 ++frame_count_; | |
| 1662 if (cpu_restricted_counter_ > 0) | |
| 1663 ++cpu_restricted_frame_count_; | |
| 1664 | |
| 1665 // Forward frame to the encoder regardless if we are sending or not. This is | 1621 // Forward frame to the encoder regardless if we are sending or not. This is |
| 1666 // to ensure that the encoder can be reconfigured with the correct frame size | 1622 // to ensure that the encoder can be reconfigured with the correct frame size |
| 1667 // as quickly as possible. | 1623 // as quickly as possible. |
| 1668 encoder_sink_->OnFrame(video_frame); | 1624 encoder_sink_->OnFrame(video_frame); |
| 1669 } | 1625 } |
| 1670 | 1626 |
| 1671 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( | 1627 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( |
| 1672 bool enable, | 1628 bool enable, |
| 1673 const VideoOptions* options, | 1629 const VideoOptions* options, |
| 1674 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { | 1630 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { |
| 1675 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); | 1631 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); |
| 1676 RTC_DCHECK_RUN_ON(&thread_checker_); | 1632 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1677 | 1633 |
| 1678 // Ignore |options| pointer if |enable| is false. | 1634 // Ignore |options| pointer if |enable| is false. |
| 1679 bool options_present = enable && options; | 1635 bool options_present = enable && options; |
| 1680 bool source_changing = source_ != source; | 1636 bool source_changing = source_ != source; |
| 1681 if (source_changing) { | |
| 1682 DisconnectSource(); | |
| 1683 } | |
| 1684 | 1637 |
| 1685 if (options_present) { | 1638 if (options_present) { |
| 1686 VideoOptions old_options = parameters_.options; | 1639 VideoOptions old_options = parameters_.options; |
| 1687 parameters_.options.SetAll(*options); | 1640 parameters_.options.SetAll(*options); |
| 1688 if (parameters_.options != old_options) { | 1641 if (parameters_.options != old_options) { |
| 1689 ReconfigureEncoder(); | 1642 ReconfigureEncoder(); |
| 1690 } | 1643 } |
| 1691 } | 1644 } |
| 1692 | 1645 |
| 1693 if (source_changing) { | 1646 if (source_changing) { |
| 1694 rtc::CritScope cs(&lock_); | 1647 rtc::CritScope cs(&lock_); |
| 1695 if (source == nullptr && encoder_sink_ != nullptr && | 1648 if (source == nullptr && last_frame_info_.width > 0 && encoder_sink_) { |
| 1696 last_frame_info_.width > 0) { | |
| 1697 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; | 1649 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; |
| 1698 // Force this black frame not to be dropped due to timestamp order | 1650 // Force this black frame not to be dropped due to timestamp order |
| 1699 // check. As IncomingCapturedFrame will drop the frame if this frame's | 1651 // check. As IncomingCapturedFrame will drop the frame if this frame's |
| 1700 // timestamp is less than or equal to last frame's timestamp, it is | 1652 // timestamp is less than or equal to last frame's timestamp, it is |
| 1701 // necessary to give this black frame a larger timestamp than the | 1653 // necessary to give this black frame a larger timestamp than the |
| 1702 // previous one. | 1654 // previous one. |
| 1703 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; | 1655 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; |
| 1704 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( | 1656 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( |
| 1705 webrtc::I420Buffer::Create(last_frame_info_.width, | 1657 webrtc::I420Buffer::Create(last_frame_info_.width, |
| 1706 last_frame_info_.height)); | 1658 last_frame_info_.height)); |
| 1707 black_buffer->SetToBlack(); | 1659 black_buffer->SetToBlack(); |
| 1708 | 1660 |
| 1709 encoder_sink_->OnFrame(webrtc::VideoFrame( | 1661 encoder_sink_->OnFrame(webrtc::VideoFrame( |
| 1710 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); | 1662 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); |
| 1711 } | 1663 } |
| 1712 source_ = source; | |
| 1713 } | 1664 } |
| 1714 | 1665 |
| 1715 if (source_changing && source_) { | 1666 // TODO(perkj, nisse): Remove |source_| and directly call |
| 1716 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 1667 // |stream_|->SetSource(source) once the video frame types have been |
| 1717 // that might cause a lock order inversion. | 1668 // merged. |
| 1718 source_->AddOrUpdateSink(this, sink_wants_); | 1669 if (source_ && stream_) { |
| 1670 stream_->SetSource( |
| 1671 nullptr, webrtc::VideoSendStream::DegradationPreference::kBalanced); |
| 1672 } |
| 1673 // Switch to the new source. |
| 1674 source_ = source; |
| 1675 if (source && stream_) { |
| 1676 // Do not adapt resolution for screen content as this will likely |
| 1677 // result in blurry and unreadable text. |
| 1678 stream_->SetSource( |
| 1679 this, enable_cpu_overuse_detection_ && |
| 1680 !parameters_.options.is_screencast.value_or(false) |
| 1681 ? webrtc::VideoSendStream::DegradationPreference::kBalanced |
| 1682 : webrtc::VideoSendStream::DegradationPreference:: |
| 1683 kMaintainResolution); |
| 1719 } | 1684 } |
| 1720 return true; | 1685 return true; |
| 1721 } | 1686 } |
| 1722 | 1687 |
| 1723 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { | |
| 1724 RTC_DCHECK_RUN_ON(&thread_checker_); | |
| 1725 if (source_ == nullptr) { | |
| 1726 return; | |
| 1727 } | |
| 1728 | |
| 1729 // |source_->RemoveSink| may not be called while holding |lock_| since | |
| 1730 // that might cause a lock order inversion. | |
| 1731 source_->RemoveSink(this); | |
| 1732 source_ = nullptr; | |
| 1733 // Reset |cpu_restricted_counter_| if the source is changed. It is not | |
| 1734 // possible to know if the video resolution is restricted by CPU usage after | |
| 1735 // the source is changed since the next source might be screen capture | |
| 1736 // with another resolution and frame rate. | |
| 1737 cpu_restricted_counter_ = 0; | |
| 1738 } | |
| 1739 | |
| 1740 const std::vector<uint32_t>& | 1688 const std::vector<uint32_t>& |
| 1741 WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const { | 1689 WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const { |
| 1742 return ssrcs_; | 1690 return ssrcs_; |
| 1743 } | 1691 } |
| 1744 | 1692 |
| 1745 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder | 1693 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder |
| 1746 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( | 1694 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( |
| 1747 const VideoCodec& codec) { | 1695 const VideoCodec& codec) { |
| 1748 RTC_DCHECK_RUN_ON(&thread_checker_); | 1696 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1749 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); | 1697 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1857 SetCodec(*params.codec); | 1805 SetCodec(*params.codec); |
| 1858 recreate_stream = false; // SetCodec has already recreated the stream. | 1806 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1859 } else if (params.conference_mode && parameters_.codec_settings) { | 1807 } else if (params.conference_mode && parameters_.codec_settings) { |
| 1860 SetCodec(*parameters_.codec_settings); | 1808 SetCodec(*parameters_.codec_settings); |
| 1861 recreate_stream = false; // SetCodec has already recreated the stream. | 1809 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1862 } | 1810 } |
| 1863 if (recreate_stream) { | 1811 if (recreate_stream) { |
| 1864 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; | 1812 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; |
| 1865 RecreateWebRtcStream(); | 1813 RecreateWebRtcStream(); |
| 1866 } | 1814 } |
| 1867 | |
| 1868 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
| 1869 // that might cause a lock order inversion. | |
| 1870 if (params.rtp_header_extensions) { | |
| 1871 sink_wants_.rotation_applied = !ContainsHeaderExtension( | |
| 1872 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); | |
| 1873 if (source_) { | |
| 1874 source_->AddOrUpdateSink(this, sink_wants_); | |
| 1875 } | |
| 1876 } | |
| 1877 } | 1815 } |
| 1878 | 1816 |
| 1879 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( | 1817 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( |
| 1880 const webrtc::RtpParameters& new_parameters) { | 1818 const webrtc::RtpParameters& new_parameters) { |
| 1881 RTC_DCHECK_RUN_ON(&thread_checker_); | 1819 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1882 if (!ValidateRtpParameters(new_parameters)) { | 1820 if (!ValidateRtpParameters(new_parameters)) { |
| 1883 return false; | 1821 return false; |
| 1884 } | 1822 } |
| 1885 | 1823 |
| 1886 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != | 1824 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1995 | 1933 |
| 1996 parameters_.encoder_config = std::move(encoder_config); | 1934 parameters_.encoder_config = std::move(encoder_config); |
| 1997 } | 1935 } |
| 1998 | 1936 |
| 1999 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { | 1937 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { |
| 2000 RTC_DCHECK_RUN_ON(&thread_checker_); | 1938 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2001 sending_ = send; | 1939 sending_ = send; |
| 2002 UpdateSendState(); | 1940 UpdateSendState(); |
| 2003 } | 1941 } |
| 2004 | 1942 |
| 1943 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( |
| 1944 VideoSinkInterface<webrtc::VideoFrame>* sink) { |
| 1945 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1946 { |
| 1947 rtc::CritScope cs(&lock_); |
| 1948 RTC_DCHECK(encoder_sink_ == sink); |
| 1949 encoder_sink_ = nullptr; |
| 1950 } |
| 1951 source_->RemoveSink(this); |
| 1952 } |
| 1953 |
| 2005 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( | 1954 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( |
| 2006 VideoSinkInterface<webrtc::VideoFrame>* sink, | 1955 VideoSinkInterface<webrtc::VideoFrame>* sink, |
| 2007 const rtc::VideoSinkWants& wants) { | 1956 const rtc::VideoSinkWants& wants) { |
| 2008 // TODO(perkj): Actually consider the encoder |wants| and remove | 1957 if (worker_thread_ == rtc::Thread::Current()) { |
| 2009 // WebRtcVideoSendStream::OnLoadUpdate(Load load). | 1958 // AddOrUpdateSink is called on |worker_thread_| if this is the first |
| 2010 rtc::CritScope cs(&lock_); | 1959 // registration of |sink|. |
| 2011 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); | 1960 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2012 encoder_sink_ = sink; | 1961 { |
| 2013 } | 1962 rtc::CritScope cs(&lock_); |
| 2014 | 1963 encoder_sink_ = sink; |
| 2015 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | 1964 } |
| 2016 VideoSinkInterface<webrtc::VideoFrame>* sink) { | 1965 source_->AddOrUpdateSink(this, wants); |
| 2017 rtc::CritScope cs(&lock_); | 1966 } else { |
| 2018 RTC_DCHECK_EQ(encoder_sink_, sink); | 1967 // Subsequent calls to AddOrUpdateSink will happen on the encoder task |
| 2019 encoder_sink_ = nullptr; | 1968 // queue. |
| 2020 } | 1969 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [this, wants] { |
| 2021 | 1970 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2022 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { | 1971 bool encoder_sink_valid = true; |
| 2023 if (worker_thread_ != rtc::Thread::Current()) { | 1972 { |
| 2024 invoker_.AsyncInvoke<void>( | 1973 rtc::CritScope cs(&lock_); |
| 2025 RTC_FROM_HERE, worker_thread_, | 1974 encoder_sink_valid = encoder_sink_ != nullptr; |
| 2026 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, | 1975 } |
| 2027 this, load)); | 1976 // Since |source_| is still valid after a call to RemoveSink, check if |
| 2028 return; | 1977 // |encoder_sink_| is still valid to check if this call should be |
| 1978 // cancelled. |
| 1979 if (source_ && encoder_sink_valid) { |
| 1980 source_->AddOrUpdateSink(this, wants); |
| 1981 } |
| 1982 }); |
| 2029 } | 1983 } |
| 2030 RTC_DCHECK_RUN_ON(&thread_checker_); | |
| 2031 if (!source_) { | |
| 2032 return; | |
| 2033 } | |
| 2034 | |
| 2035 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " | |
| 2036 << (parameters_.options.is_screencast | |
| 2037 ? (*parameters_.options.is_screencast ? "true" : "false") | |
| 2038 : "unset"); | |
| 2039 // Do not adapt resolution for screen content as this will likely result in | |
| 2040 // blurry and unreadable text. | |
| 2041 if (parameters_.options.is_screencast.value_or(false)) | |
| 2042 return; | |
| 2043 | |
| 2044 rtc::Optional<int> max_pixel_count; | |
| 2045 rtc::Optional<int> max_pixel_count_step_up; | |
| 2046 if (load == kOveruse) { | |
| 2047 rtc::CritScope cs(&lock_); | |
| 2048 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { | |
| 2049 return; | |
| 2050 } | |
| 2051 // The input video frame size will have a resolution with less than or | |
| 2052 // equal to |max_pixel_count| depending on how the source can scale the | |
| 2053 // input frame size. | |
| 2054 max_pixel_count = rtc::Optional<int>( | |
| 2055 (last_frame_info_.height * last_frame_info_.width * 3) / 5); | |
| 2056 // Increase |number_of_cpu_adapt_changes_| if | |
| 2057 // sink_wants_.max_pixel_count will be changed since | |
| 2058 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2059 // result in a new request for the source to change resolution. | |
| 2060 if (!sink_wants_.max_pixel_count || | |
| 2061 *sink_wants_.max_pixel_count > *max_pixel_count) { | |
| 2062 ++number_of_cpu_adapt_changes_; | |
| 2063 ++cpu_restricted_counter_; | |
| 2064 } | |
| 2065 } else { | |
| 2066 RTC_DCHECK(load == kUnderuse); | |
| 2067 rtc::CritScope cs(&lock_); | |
| 2068 // The input video frame size will have a resolution with "one step up" | |
| 2069 // pixels than |max_pixel_count_step_up| where "one step up" depends on | |
| 2070 // how the source can scale the input frame size. | |
| 2071 max_pixel_count_step_up = | |
| 2072 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); | |
| 2073 // Increase |number_of_cpu_adapt_changes_| if | |
| 2074 // sink_wants_.max_pixel_count_step_up will be changed since | |
| 2075 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2076 // result in a new request for the source to change resolution. | |
| 2077 if (sink_wants_.max_pixel_count || | |
| 2078 (sink_wants_.max_pixel_count_step_up && | |
| 2079 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { | |
| 2080 ++number_of_cpu_adapt_changes_; | |
| 2081 --cpu_restricted_counter_; | |
| 2082 } | |
| 2083 } | |
| 2084 sink_wants_.max_pixel_count = max_pixel_count; | |
| 2085 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; | |
| 2086 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
| 2087 // that might cause a lock order inversion. | |
| 2088 source_->AddOrUpdateSink(this, sink_wants_); | |
| 2089 } | 1984 } |
| 2090 | 1985 |
| 2091 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( | 1986 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( |
| 2092 bool log_stats) { | 1987 bool log_stats) { |
| 2093 VideoSenderInfo info; | 1988 VideoSenderInfo info; |
| 2094 RTC_DCHECK_RUN_ON(&thread_checker_); | 1989 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2095 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) | 1990 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |
| 2096 info.add_ssrc(ssrc); | 1991 info.add_ssrc(ssrc); |
| 2097 | 1992 |
| 2098 if (parameters_.codec_settings) | 1993 if (parameters_.codec_settings) |
| 2099 info.codec_name = parameters_.codec_settings->codec.name; | 1994 info.codec_name = parameters_.codec_settings->codec.name; |
| 2100 | 1995 |
| 2101 if (stream_ == NULL) | 1996 if (stream_ == NULL) |
| 2102 return info; | 1997 return info; |
| 2103 | 1998 |
| 2104 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); | 1999 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |
| 2105 | 2000 |
| 2106 if (log_stats) | 2001 if (log_stats) |
| 2107 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); | 2002 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); |
| 2108 | 2003 |
| 2109 info.adapt_changes = number_of_cpu_adapt_changes_; | 2004 info.adapt_changes = stats.number_of_cpu_adapt_changes; |
| 2110 info.adapt_reason = | 2005 info.adapt_reason = |
| 2111 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; | 2006 stats.cpu_limited_resolution ? ADAPTREASON_CPU : ADAPTREASON_NONE; |
| 2112 | 2007 |
| 2113 // Get bandwidth limitation info from stream_->GetStats(). | 2008 // Get bandwidth limitation info from stream_->GetStats(). |
| 2114 // Input resolution (output from video_adapter) can be further scaled down or | 2009 // Input resolution (output from video_adapter) can be further scaled down or |
| 2115 // higher video layer(s) can be dropped due to bitrate constraints. | 2010 // higher video layer(s) can be dropped due to bitrate constraints. |
| 2116 // Note, adapt_changes only include changes from the video_adapter. | 2011 // Note, adapt_changes only include changes from the video_adapter. |
| 2117 if (stats.bw_limited_resolution) | 2012 if (stats.bw_limited_resolution) |
| 2118 info.adapt_reason |= ADAPTREASON_BANDWIDTH; | 2013 info.adapt_reason |= ADAPTREASON_BANDWIDTH; |
| 2119 | 2014 |
| 2120 info.encoder_implementation_name = stats.encoder_implementation_name; | 2015 info.encoder_implementation_name = stats.encoder_implementation_name; |
| 2121 info.ssrc_groups = ssrc_groups_; | 2016 info.ssrc_groups = ssrc_groups_; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2194 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); | 2089 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); |
| 2195 | 2090 |
| 2196 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); | 2091 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); |
| 2197 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { | 2092 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { |
| 2198 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 2093 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
| 2199 "payload type the set codec. Ignoring RTX."; | 2094 "payload type the set codec. Ignoring RTX."; |
| 2200 config.rtp.rtx.ssrcs.clear(); | 2095 config.rtp.rtx.ssrcs.clear(); |
| 2201 } | 2096 } |
| 2202 stream_ = call_->CreateVideoSendStream(std::move(config), | 2097 stream_ = call_->CreateVideoSendStream(std::move(config), |
| 2203 parameters_.encoder_config.Copy()); | 2098 parameters_.encoder_config.Copy()); |
| 2204 stream_->SetSource(this); | |
| 2205 | 2099 |
| 2206 parameters_.encoder_config.encoder_specific_settings = NULL; | 2100 parameters_.encoder_config.encoder_specific_settings = NULL; |
| 2207 | 2101 |
| 2102 if (source_) { |
| 2103 // TODO(perkj, nisse): Remove |source_| and directly call |
| 2104 // |stream_|->SetSource(source) once the video frame types have been |
| 2105 // merged and |stream_| internally reconfigure the encoder on frame |
| 2106 // resolution change. |
| 2107 // Do not adapt resolution for screen content as this will likely result in |
| 2108 // blurry and unreadable text. |
| 2109 stream_->SetSource( |
| 2110 this, enable_cpu_overuse_detection_ && |
| 2111 !parameters_.options.is_screencast.value_or(false) |
| 2112 ? webrtc::VideoSendStream::DegradationPreference::kBalanced |
| 2113 : webrtc::VideoSendStream::DegradationPreference:: |
| 2114 kMaintainResolution); |
| 2115 } |
| 2116 |
| 2208 // Call stream_->Start() if necessary conditions are met. | 2117 // Call stream_->Start() if necessary conditions are met. |
| 2209 UpdateSendState(); | 2118 UpdateSendState(); |
| 2210 } | 2119 } |
| 2211 | 2120 |
| 2212 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( | 2121 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
| 2213 webrtc::Call* call, | 2122 webrtc::Call* call, |
| 2214 const StreamParams& sp, | 2123 const StreamParams& sp, |
| 2215 webrtc::VideoReceiveStream::Config config, | 2124 webrtc::VideoReceiveStream::Config config, |
| 2216 WebRtcVideoDecoderFactory* external_decoder_factory, | 2125 WebRtcVideoDecoderFactory* external_decoder_factory, |
| 2217 bool default_stream, | 2126 bool default_stream, |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 rtx_mapping[video_codecs[i].codec.id] != | 2559 rtx_mapping[video_codecs[i].codec.id] != |
| 2651 ulpfec_config.red_payload_type) { | 2560 ulpfec_config.red_payload_type) { |
| 2652 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2561 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
| 2653 } | 2562 } |
| 2654 } | 2563 } |
| 2655 | 2564 |
| 2656 return video_codecs; | 2565 return video_codecs; |
| 2657 } | 2566 } |
| 2658 | 2567 |
| 2659 } // namespace cricket | 2568 } // namespace cricket |
| OLD | NEW |