Chromium Code Reviews| 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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { | 244 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { |
| 246 LOG(LS_ERROR) | 245 LOG(LS_ERROR) |
| 247 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " | 246 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " |
| 248 << sp.ToString(); | 247 << sp.ToString(); |
| 249 return false; | 248 return false; |
| 250 } | 249 } |
| 251 | 250 |
| 252 return true; | 251 return true; |
| 253 } | 252 } |
| 254 | 253 |
| 255 inline bool ContainsHeaderExtension( | |
| 256 const std::vector<webrtc::RtpExtension>& extensions, | |
| 257 const std::string& uri) { | |
| 258 for (const auto& kv : extensions) { | |
| 259 if (kv.uri == uri) { | |
| 260 return true; | |
| 261 } | |
| 262 } | |
| 263 return false; | |
| 264 } | |
| 265 | |
| 266 // Returns true if the given codec is disallowed from doing simulcast. | 254 // Returns true if the given codec is disallowed from doing simulcast. |
| 267 bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { | 255 bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { |
| 268 return CodecNamesEq(codec_name, kH264CodecName) || | 256 return CodecNamesEq(codec_name, kH264CodecName) || |
| 269 CodecNamesEq(codec_name, kVp9CodecName); | 257 CodecNamesEq(codec_name, kVp9CodecName); |
| 270 } | 258 } |
| 271 | 259 |
| 272 // The selected thresholds for QVGA and VGA corresponded to a QP around 10. | 260 // The selected thresholds for QVGA and VGA corresponded to a QP around 10. |
| 273 // The change in QP declined above the selected bitrates. | 261 // The change in QP declined above the selected bitrates. |
| 274 static int GetMaxDefaultVideoBitrateKbps(int width, int height) { | 262 static int GetMaxDefaultVideoBitrateKbps(int width, int height) { |
| 275 if (width * height <= 320 * 240) { | 263 if (width * height <= 320 * 240) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 const int kVideoRtpBufferSize = 65536; | 391 const int kVideoRtpBufferSize = 65536; |
| 404 | 392 |
| 405 // This constant is really an on/off, lower-level configurable NACK history | 393 // This constant is really an on/off, lower-level configurable NACK history |
| 406 // duration hasn't been implemented. | 394 // duration hasn't been implemented. |
| 407 static const int kNackHistoryMs = 1000; | 395 static const int kNackHistoryMs = 1000; |
| 408 | 396 |
| 409 static const int kDefaultQpMax = 56; | 397 static const int kDefaultQpMax = 56; |
| 410 | 398 |
| 411 static const int kDefaultRtcpReceiverReportSsrc = 1; | 399 static const int kDefaultRtcpReceiverReportSsrc = 1; |
| 412 | 400 |
| 413 // Down grade resolution at most 2 times for CPU reasons. | |
| 414 static const int kMaxCpuDowngrades = 2; | |
| 415 | |
| 416 // Minimum time interval for logging stats. | 401 // Minimum time interval for logging stats. |
| 417 static const int64_t kStatsLogIntervalMs = 10000; | 402 static const int64_t kStatsLogIntervalMs = 10000; |
| 418 | 403 |
| 419 // Adds |codec| to |list|, and also adds an RTX codec if |codec|'s name is | 404 // Adds |codec| to |list|, and also adds an RTX codec if |codec|'s name is |
| 420 // recognized. | 405 // recognized. |
| 421 // TODO(deadbeef): Should we add RTX codecs for external codecs whose names we | 406 // TODO(deadbeef): Should we add RTX codecs for external codecs whose names we |
| 422 // don't recognize? | 407 // don't recognize? |
| 423 void AddCodecAndMaybeRtxCodec(const VideoCodec& codec, | 408 void AddCodecAndMaybeRtxCodec(const VideoCodec& codec, |
| 424 std::vector<VideoCodec>* codecs) { | 409 std::vector<VideoCodec>* codecs) { |
| 425 codecs->push_back(codec); | 410 codecs->push_back(codec); |
| (...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1588 int max_bitrate_bps, | 1573 int max_bitrate_bps, |
| 1589 const rtc::Optional<VideoCodecSettings>& codec_settings, | 1574 const rtc::Optional<VideoCodecSettings>& codec_settings, |
| 1590 const rtc::Optional<std::vector<webrtc::RtpExtension>>& rtp_extensions, | 1575 const rtc::Optional<std::vector<webrtc::RtpExtension>>& rtp_extensions, |
| 1591 // TODO(deadbeef): Don't duplicate information between send_params, | 1576 // TODO(deadbeef): Don't duplicate information between send_params, |
| 1592 // rtp_extensions, options, etc. | 1577 // rtp_extensions, options, etc. |
| 1593 const VideoSendParameters& send_params) | 1578 const VideoSendParameters& send_params) |
| 1594 : worker_thread_(rtc::Thread::Current()), | 1579 : worker_thread_(rtc::Thread::Current()), |
| 1595 ssrcs_(sp.ssrcs), | 1580 ssrcs_(sp.ssrcs), |
| 1596 ssrc_groups_(sp.ssrc_groups), | 1581 ssrc_groups_(sp.ssrc_groups), |
| 1597 call_(call), | 1582 call_(call), |
| 1598 cpu_restricted_counter_(0), | 1583 enable_cpu_overuse_detection_(enable_cpu_overuse_detection), |
| 1599 number_of_cpu_adapt_changes_(0), | |
| 1600 frame_count_(0), | |
| 1601 cpu_restricted_frame_count_(0), | |
| 1602 source_(nullptr), | 1584 source_(nullptr), |
| 1603 external_encoder_factory_(external_encoder_factory), | 1585 external_encoder_factory_(external_encoder_factory), |
| 1604 stream_(nullptr), | 1586 stream_(nullptr), |
| 1605 encoder_sink_(nullptr), | 1587 encoder_sink_(nullptr), |
| 1606 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1588 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
| 1607 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1589 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
| 1608 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), | 1590 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), |
| 1609 sending_(false), | 1591 sending_(false), |
| 1610 last_frame_timestamp_us_(0) { | 1592 last_frame_timestamp_us_(0) { |
| 1611 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1593 parameters_.config.rtp.max_packet_size = kVideoMtu; |
| 1612 parameters_.conference_mode = send_params.conference_mode; | 1594 parameters_.conference_mode = send_params.conference_mode; |
| 1613 | 1595 |
| 1614 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1596 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
| 1615 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, | 1597 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
| 1616 ¶meters_.config.rtp.rtx.ssrcs); | 1598 ¶meters_.config.rtp.rtx.ssrcs); |
| 1617 parameters_.config.rtp.c_name = sp.cname; | 1599 parameters_.config.rtp.c_name = sp.cname; |
| 1618 if (rtp_extensions) { | 1600 if (rtp_extensions) { |
| 1619 parameters_.config.rtp.extensions = *rtp_extensions; | 1601 parameters_.config.rtp.extensions = *rtp_extensions; |
| 1620 } | 1602 } |
| 1621 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size | 1603 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size |
| 1622 ? webrtc::RtcpMode::kReducedSize | 1604 ? webrtc::RtcpMode::kReducedSize |
| 1623 : webrtc::RtcpMode::kCompound; | 1605 : webrtc::RtcpMode::kCompound; |
| 1624 parameters_.config.overuse_callback = | |
| 1625 enable_cpu_overuse_detection ? this : nullptr; | |
| 1626 | |
| 1627 // Only request rotation at the source when we positively know that the remote | |
| 1628 // side doesn't support the rotation extension. This allows us to prepare the | |
| 1629 // encoder in the expectation that rotation is supported - which is the common | |
| 1630 // case. | |
| 1631 sink_wants_.rotation_applied = | |
| 1632 rtp_extensions && | |
| 1633 !ContainsHeaderExtension(*rtp_extensions, | |
| 1634 webrtc::RtpExtension::kVideoRotationUri); | |
| 1635 | |
| 1636 if (codec_settings) { | 1606 if (codec_settings) { |
| 1637 SetCodec(*codec_settings); | 1607 SetCodec(*codec_settings); |
| 1638 } | 1608 } |
| 1639 } | 1609 } |
| 1640 | 1610 |
| 1641 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { | 1611 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { |
| 1642 DisconnectSource(); | |
| 1643 if (stream_ != NULL) { | 1612 if (stream_ != NULL) { |
| 1644 call_->DestroyVideoSendStream(stream_); | 1613 call_->DestroyVideoSendStream(stream_); |
| 1645 } | 1614 } |
| 1646 DestroyVideoEncoder(&allocated_encoder_); | 1615 DestroyVideoEncoder(&allocated_encoder_); |
| 1647 UpdateHistograms(); | |
| 1648 } | |
| 1649 | |
| 1650 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateHistograms() const { | |
| 1651 const int kMinRequiredFrames = 200; | |
| 1652 if (frame_count_ > kMinRequiredFrames) { | |
| 1653 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.CpuLimitedResolutionInPercent", | |
| 1654 cpu_restricted_frame_count_ * 100 / frame_count_); | |
| 1655 } | |
| 1656 } | 1616 } |
| 1657 | 1617 |
| 1658 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( | 1618 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( |
| 1659 const VideoFrame& frame) { | 1619 const VideoFrame& frame) { |
| 1660 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); | 1620 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); |
| 1661 webrtc::VideoFrame video_frame(frame.video_frame_buffer(), | 1621 webrtc::VideoFrame video_frame(frame.video_frame_buffer(), |
| 1662 frame.rotation(), | 1622 frame.rotation(), |
| 1663 frame.timestamp_us()); | 1623 frame.timestamp_us()); |
| 1664 | 1624 |
| 1665 rtc::CritScope cs(&lock_); | 1625 rtc::CritScope cs(&lock_); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1679 << ", texture=" << last_frame_info_.is_texture; | 1639 << ", texture=" << last_frame_info_.is_texture; |
| 1680 } | 1640 } |
| 1681 | 1641 |
| 1682 if (encoder_sink_ == NULL) { | 1642 if (encoder_sink_ == NULL) { |
| 1683 // Frame input before send codecs are configured, dropping frame. | 1643 // Frame input before send codecs are configured, dropping frame. |
| 1684 return; | 1644 return; |
| 1685 } | 1645 } |
| 1686 | 1646 |
| 1687 last_frame_timestamp_us_ = video_frame.timestamp_us(); | 1647 last_frame_timestamp_us_ = video_frame.timestamp_us(); |
| 1688 | 1648 |
| 1689 ++frame_count_; | |
| 1690 if (cpu_restricted_counter_ > 0) | |
| 1691 ++cpu_restricted_frame_count_; | |
| 1692 | |
| 1693 // Forward frame to the encoder regardless if we are sending or not. This is | 1649 // Forward frame to the encoder regardless if we are sending or not. This is |
| 1694 // to ensure that the encoder can be reconfigured with the correct frame size | 1650 // to ensure that the encoder can be reconfigured with the correct frame size |
| 1695 // as quickly as possible. | 1651 // as quickly as possible. |
| 1696 encoder_sink_->OnFrame(video_frame); | 1652 encoder_sink_->OnFrame(video_frame); |
| 1697 } | 1653 } |
| 1698 | 1654 |
| 1699 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( | 1655 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( |
| 1700 bool enable, | 1656 bool enable, |
| 1701 const VideoOptions* options, | 1657 const VideoOptions* options, |
| 1702 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { | 1658 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { |
| 1703 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); | 1659 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); |
| 1704 RTC_DCHECK_RUN_ON(&thread_checker_); | 1660 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1705 | 1661 |
| 1706 // Ignore |options| pointer if |enable| is false. | 1662 // Ignore |options| pointer if |enable| is false. |
| 1707 bool options_present = enable && options; | 1663 bool options_present = enable && options; |
| 1708 bool source_changing = source_ != source; | 1664 bool source_changing = source_ != source; |
| 1709 if (source_changing) { | |
| 1710 DisconnectSource(); | |
| 1711 } | |
| 1712 | 1665 |
| 1713 if (options_present) { | 1666 if (options_present) { |
| 1714 VideoOptions old_options = parameters_.options; | 1667 VideoOptions old_options = parameters_.options; |
| 1715 parameters_.options.SetAll(*options); | 1668 parameters_.options.SetAll(*options); |
| 1716 if (parameters_.options != old_options) { | 1669 if (parameters_.options != old_options) { |
| 1717 ReconfigureEncoder(); | 1670 ReconfigureEncoder(); |
| 1718 } | 1671 } |
| 1719 } | 1672 } |
| 1720 | 1673 |
| 1721 if (source_changing) { | 1674 if (source_changing) { |
| 1722 rtc::CritScope cs(&lock_); | 1675 rtc::CritScope cs(&lock_); |
| 1723 if (source == nullptr && encoder_sink_ != nullptr && | 1676 if (source == nullptr && last_frame_info_.width > 0 && encoder_sink_) { |
| 1724 last_frame_info_.width > 0) { | |
| 1725 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; | 1677 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; |
| 1726 // Force this black frame not to be dropped due to timestamp order | 1678 // Force this black frame not to be dropped due to timestamp order |
| 1727 // check. As IncomingCapturedFrame will drop the frame if this frame's | 1679 // check. As IncomingCapturedFrame will drop the frame if this frame's |
| 1728 // timestamp is less than or equal to last frame's timestamp, it is | 1680 // timestamp is less than or equal to last frame's timestamp, it is |
| 1729 // necessary to give this black frame a larger timestamp than the | 1681 // necessary to give this black frame a larger timestamp than the |
| 1730 // previous one. | 1682 // previous one. |
| 1731 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; | 1683 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; |
| 1732 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( | 1684 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( |
| 1733 webrtc::I420Buffer::Create(last_frame_info_.width, | 1685 webrtc::I420Buffer::Create(last_frame_info_.width, |
| 1734 last_frame_info_.height)); | 1686 last_frame_info_.height)); |
| 1735 black_buffer->SetToBlack(); | 1687 black_buffer->SetToBlack(); |
| 1736 | 1688 |
| 1737 encoder_sink_->OnFrame(webrtc::VideoFrame( | 1689 encoder_sink_->OnFrame(webrtc::VideoFrame( |
| 1738 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); | 1690 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); |
| 1739 } | 1691 } |
| 1740 source_ = source; | |
| 1741 } | 1692 } |
| 1742 | 1693 |
| 1743 if (source_changing && source_) { | 1694 // TODO(perkj, nisse): Remove |source_| and directly call |
| 1744 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 1695 // |stream_|->SetSource(source) once the video frame types have been |
| 1745 // that might cause a lock order inversion. | 1696 // merged. |
|
nisse-webrtc
2016/10/28 10:53:44
That time is now. ;-)
perkj_webrtc
2016/10/28 14:05:34
Great- but it is a little bit more to it so I woul
nisse-webrtc
2016/10/31 07:52:46
Sure. I'd also really like to see this change land
| |
| 1746 source_->AddOrUpdateSink(this, sink_wants_); | 1697 if (source_ && stream_) { |
| 1698 stream_->SetSource( | |
| 1699 nullptr, webrtc::VideoSendStream::DegradationPreference::kBalanced); | |
| 1700 } | |
| 1701 // Switch to the new source. | |
| 1702 source_ = source; | |
| 1703 if (source && stream_) { | |
| 1704 // Do not adapt resolution for screen content as this will likely | |
| 1705 // result in blurry and unreadable text. | |
| 1706 stream_->SetSource( | |
| 1707 this, enable_cpu_overuse_detection_ && | |
| 1708 !parameters_.options.is_screencast.value_or(false) | |
| 1709 ? webrtc::VideoSendStream::DegradationPreference::kBalanced | |
| 1710 : webrtc::VideoSendStream::DegradationPreference:: | |
| 1711 kMaintainResolution); | |
| 1747 } | 1712 } |
| 1748 return true; | 1713 return true; |
| 1749 } | 1714 } |
| 1750 | 1715 |
| 1751 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { | |
| 1752 RTC_DCHECK_RUN_ON(&thread_checker_); | |
| 1753 if (source_ == nullptr) { | |
| 1754 return; | |
| 1755 } | |
| 1756 | |
| 1757 // |source_->RemoveSink| may not be called while holding |lock_| since | |
| 1758 // that might cause a lock order inversion. | |
| 1759 source_->RemoveSink(this); | |
| 1760 source_ = nullptr; | |
| 1761 // Reset |cpu_restricted_counter_| if the source is changed. It is not | |
| 1762 // possible to know if the video resolution is restricted by CPU usage after | |
| 1763 // the source is changed since the next source might be screen capture | |
| 1764 // with another resolution and frame rate. | |
| 1765 cpu_restricted_counter_ = 0; | |
| 1766 } | |
| 1767 | |
| 1768 const std::vector<uint32_t>& | 1716 const std::vector<uint32_t>& |
| 1769 WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const { | 1717 WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const { |
| 1770 return ssrcs_; | 1718 return ssrcs_; |
| 1771 } | 1719 } |
| 1772 | 1720 |
| 1773 webrtc::VideoCodecType CodecTypeFromName(const std::string& name) { | 1721 webrtc::VideoCodecType CodecTypeFromName(const std::string& name) { |
| 1774 if (CodecNamesEq(name, kVp8CodecName)) { | 1722 if (CodecNamesEq(name, kVp8CodecName)) { |
| 1775 return webrtc::kVideoCodecVP8; | 1723 return webrtc::kVideoCodecVP8; |
| 1776 } else if (CodecNamesEq(name, kVp9CodecName)) { | 1724 } else if (CodecNamesEq(name, kVp9CodecName)) { |
| 1777 return webrtc::kVideoCodecVP9; | 1725 return webrtc::kVideoCodecVP9; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1896 SetCodec(*params.codec); | 1844 SetCodec(*params.codec); |
| 1897 recreate_stream = false; // SetCodec has already recreated the stream. | 1845 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1898 } else if (params.conference_mode && parameters_.codec_settings) { | 1846 } else if (params.conference_mode && parameters_.codec_settings) { |
| 1899 SetCodec(*parameters_.codec_settings); | 1847 SetCodec(*parameters_.codec_settings); |
| 1900 recreate_stream = false; // SetCodec has already recreated the stream. | 1848 recreate_stream = false; // SetCodec has already recreated the stream. |
| 1901 } | 1849 } |
| 1902 if (recreate_stream) { | 1850 if (recreate_stream) { |
| 1903 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; | 1851 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; |
| 1904 RecreateWebRtcStream(); | 1852 RecreateWebRtcStream(); |
| 1905 } | 1853 } |
| 1906 | |
| 1907 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
| 1908 // that might cause a lock order inversion. | |
| 1909 if (params.rtp_header_extensions) { | |
| 1910 sink_wants_.rotation_applied = !ContainsHeaderExtension( | |
| 1911 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); | |
| 1912 if (source_) { | |
| 1913 source_->AddOrUpdateSink(this, sink_wants_); | |
| 1914 } | |
| 1915 } | |
| 1916 } | 1854 } |
| 1917 | 1855 |
| 1918 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( | 1856 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( |
| 1919 const webrtc::RtpParameters& new_parameters) { | 1857 const webrtc::RtpParameters& new_parameters) { |
| 1920 RTC_DCHECK_RUN_ON(&thread_checker_); | 1858 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 1921 if (!ValidateRtpParameters(new_parameters)) { | 1859 if (!ValidateRtpParameters(new_parameters)) { |
| 1922 return false; | 1860 return false; |
| 1923 } | 1861 } |
| 1924 | 1862 |
| 1925 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != | 1863 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2034 | 1972 |
| 2035 parameters_.encoder_config = std::move(encoder_config); | 1973 parameters_.encoder_config = std::move(encoder_config); |
| 2036 } | 1974 } |
| 2037 | 1975 |
| 2038 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { | 1976 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { |
| 2039 RTC_DCHECK_RUN_ON(&thread_checker_); | 1977 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2040 sending_ = send; | 1978 sending_ = send; |
| 2041 UpdateSendState(); | 1979 UpdateSendState(); |
| 2042 } | 1980 } |
| 2043 | 1981 |
| 1982 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | |
| 1983 VideoSinkInterface<webrtc::VideoFrame>* sink) { | |
| 1984 RTC_DCHECK_RUN_ON(&thread_checker_); | |
| 1985 { | |
| 1986 rtc::CritScope cs(&lock_); | |
| 1987 RTC_DCHECK(encoder_sink_ == sink); | |
| 1988 encoder_sink_ = nullptr; | |
| 1989 } | |
| 1990 source_->RemoveSink(this); | |
| 1991 } | |
| 1992 | |
| 2044 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( | 1993 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( |
| 2045 VideoSinkInterface<webrtc::VideoFrame>* sink, | 1994 VideoSinkInterface<webrtc::VideoFrame>* sink, |
| 2046 const rtc::VideoSinkWants& wants) { | 1995 const rtc::VideoSinkWants& wants) { |
| 2047 // TODO(perkj): Actually consider the encoder |wants| and remove | 1996 if (worker_thread_ == rtc::Thread::Current()) { |
| 2048 // WebRtcVideoSendStream::OnLoadUpdate(Load load). | 1997 // AddOrUpdateSink is called on |worker_thread_| if this is the first |
| 2049 rtc::CritScope cs(&lock_); | 1998 // registration of |sink|. |
| 2050 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); | 1999 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2051 encoder_sink_ = sink; | 2000 { |
| 2052 } | 2001 rtc::CritScope cs(&lock_); |
| 2053 | 2002 encoder_sink_ = sink; |
| 2054 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | 2003 } |
| 2055 VideoSinkInterface<webrtc::VideoFrame>* sink) { | 2004 source_->AddOrUpdateSink(this, wants); |
| 2056 rtc::CritScope cs(&lock_); | 2005 } else { |
| 2057 RTC_DCHECK_EQ(encoder_sink_, sink); | 2006 // Subsequent calls to AddOrUpdateSink will happen on the encoder task |
| 2058 encoder_sink_ = nullptr; | 2007 // queue. |
| 2059 } | 2008 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [this, wants] { |
| 2060 | 2009 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2061 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { | 2010 bool encoder_sink_valid = true; |
| 2062 if (worker_thread_ != rtc::Thread::Current()) { | 2011 { |
| 2063 invoker_.AsyncInvoke<void>( | 2012 rtc::CritScope cs(&lock_); |
| 2064 RTC_FROM_HERE, worker_thread_, | 2013 encoder_sink_valid = encoder_sink_ != nullptr; |
| 2065 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, | 2014 } |
| 2066 this, load)); | 2015 // Since |source_| is still valid after a call to RemoveSink, check if |
| 2067 return; | 2016 // |encoder_sink_| is still valid to check if this call should be |
| 2017 // cancelled. | |
| 2018 if (source_ && encoder_sink_valid) { | |
| 2019 source_->AddOrUpdateSink(this, wants); | |
| 2020 } | |
| 2021 }); | |
| 2068 } | 2022 } |
| 2069 RTC_DCHECK_RUN_ON(&thread_checker_); | |
| 2070 if (!source_) { | |
| 2071 return; | |
| 2072 } | |
| 2073 | |
| 2074 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " | |
| 2075 << (parameters_.options.is_screencast | |
| 2076 ? (*parameters_.options.is_screencast ? "true" : "false") | |
| 2077 : "unset"); | |
| 2078 // Do not adapt resolution for screen content as this will likely result in | |
| 2079 // blurry and unreadable text. | |
| 2080 if (parameters_.options.is_screencast.value_or(false)) | |
| 2081 return; | |
| 2082 | |
| 2083 rtc::Optional<int> max_pixel_count; | |
| 2084 rtc::Optional<int> max_pixel_count_step_up; | |
| 2085 if (load == kOveruse) { | |
| 2086 rtc::CritScope cs(&lock_); | |
| 2087 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { | |
| 2088 return; | |
| 2089 } | |
| 2090 // The input video frame size will have a resolution with less than or | |
| 2091 // equal to |max_pixel_count| depending on how the source can scale the | |
| 2092 // input frame size. | |
| 2093 max_pixel_count = rtc::Optional<int>( | |
| 2094 (last_frame_info_.height * last_frame_info_.width * 3) / 5); | |
| 2095 // Increase |number_of_cpu_adapt_changes_| if | |
| 2096 // sink_wants_.max_pixel_count will be changed since | |
| 2097 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2098 // result in a new request for the source to change resolution. | |
| 2099 if (!sink_wants_.max_pixel_count || | |
| 2100 *sink_wants_.max_pixel_count > *max_pixel_count) { | |
| 2101 ++number_of_cpu_adapt_changes_; | |
| 2102 ++cpu_restricted_counter_; | |
| 2103 } | |
| 2104 } else { | |
| 2105 RTC_DCHECK(load == kUnderuse); | |
| 2106 rtc::CritScope cs(&lock_); | |
| 2107 // The input video frame size will have a resolution with "one step up" | |
| 2108 // pixels than |max_pixel_count_step_up| where "one step up" depends on | |
| 2109 // how the source can scale the input frame size. | |
| 2110 max_pixel_count_step_up = | |
| 2111 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); | |
| 2112 // Increase |number_of_cpu_adapt_changes_| if | |
| 2113 // sink_wants_.max_pixel_count_step_up will be changed since | |
| 2114 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
| 2115 // result in a new request for the source to change resolution. | |
| 2116 if (sink_wants_.max_pixel_count || | |
| 2117 (sink_wants_.max_pixel_count_step_up && | |
| 2118 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { | |
| 2119 ++number_of_cpu_adapt_changes_; | |
| 2120 --cpu_restricted_counter_; | |
| 2121 } | |
| 2122 } | |
| 2123 sink_wants_.max_pixel_count = max_pixel_count; | |
| 2124 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; | |
| 2125 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
| 2126 // that might cause a lock order inversion. | |
| 2127 source_->AddOrUpdateSink(this, sink_wants_); | |
| 2128 } | 2023 } |
| 2129 | 2024 |
| 2130 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( | 2025 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( |
| 2131 bool log_stats) { | 2026 bool log_stats) { |
| 2132 VideoSenderInfo info; | 2027 VideoSenderInfo info; |
| 2133 RTC_DCHECK_RUN_ON(&thread_checker_); | 2028 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 2134 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) | 2029 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |
| 2135 info.add_ssrc(ssrc); | 2030 info.add_ssrc(ssrc); |
| 2136 | 2031 |
| 2137 if (parameters_.codec_settings) | 2032 if (parameters_.codec_settings) |
| 2138 info.codec_name = parameters_.codec_settings->codec.name; | 2033 info.codec_name = parameters_.codec_settings->codec.name; |
| 2139 | 2034 |
| 2140 if (stream_ == NULL) | 2035 if (stream_ == NULL) |
| 2141 return info; | 2036 return info; |
| 2142 | 2037 |
| 2143 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); | 2038 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |
| 2144 | 2039 |
| 2145 if (log_stats) | 2040 if (log_stats) |
| 2146 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); | 2041 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); |
| 2147 | 2042 |
| 2148 info.adapt_changes = number_of_cpu_adapt_changes_; | 2043 info.adapt_changes = stats.number_of_cpu_adapt_changes; |
| 2149 info.adapt_reason = | 2044 info.adapt_reason = |
| 2150 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; | 2045 stats.cpu_limited_resolution ? ADAPTREASON_CPU : ADAPTREASON_NONE; |
| 2151 | 2046 |
| 2152 // Get bandwidth limitation info from stream_->GetStats(). | 2047 // Get bandwidth limitation info from stream_->GetStats(). |
| 2153 // Input resolution (output from video_adapter) can be further scaled down or | 2048 // Input resolution (output from video_adapter) can be further scaled down or |
| 2154 // higher video layer(s) can be dropped due to bitrate constraints. | 2049 // higher video layer(s) can be dropped due to bitrate constraints. |
| 2155 // Note, adapt_changes only include changes from the video_adapter. | 2050 // Note, adapt_changes only include changes from the video_adapter. |
| 2156 if (stats.bw_limited_resolution) | 2051 if (stats.bw_limited_resolution) |
| 2157 info.adapt_reason |= ADAPTREASON_BANDWIDTH; | 2052 info.adapt_reason |= ADAPTREASON_BANDWIDTH; |
| 2158 | 2053 |
| 2159 info.encoder_implementation_name = stats.encoder_implementation_name; | 2054 info.encoder_implementation_name = stats.encoder_implementation_name; |
| 2160 info.ssrc_groups = ssrc_groups_; | 2055 info.ssrc_groups = ssrc_groups_; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2232 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); | 2127 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); |
| 2233 | 2128 |
| 2234 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); | 2129 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); |
| 2235 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { | 2130 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { |
| 2236 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 2131 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
| 2237 "payload type the set codec. Ignoring RTX."; | 2132 "payload type the set codec. Ignoring RTX."; |
| 2238 config.rtp.rtx.ssrcs.clear(); | 2133 config.rtp.rtx.ssrcs.clear(); |
| 2239 } | 2134 } |
| 2240 stream_ = call_->CreateVideoSendStream(std::move(config), | 2135 stream_ = call_->CreateVideoSendStream(std::move(config), |
| 2241 parameters_.encoder_config.Copy()); | 2136 parameters_.encoder_config.Copy()); |
| 2242 stream_->SetSource(this); | |
| 2243 | 2137 |
| 2244 parameters_.encoder_config.encoder_specific_settings = NULL; | 2138 parameters_.encoder_config.encoder_specific_settings = NULL; |
| 2245 | 2139 |
| 2140 if (source_) { | |
| 2141 // TODO(perkj, nisse): Remove |source_| and directly call | |
| 2142 // |stream_|->SetSource(source) once the video frame types have been | |
| 2143 // merged and |stream_| internally reconfigure the encoder on frame | |
| 2144 // resolution change. | |
| 2145 // Do not adapt resolution for screen content as this will likely result in | |
| 2146 // blurry and unreadable text. | |
| 2147 stream_->SetSource( | |
| 2148 this, enable_cpu_overuse_detection_ && | |
| 2149 !parameters_.options.is_screencast.value_or(false) | |
| 2150 ? webrtc::VideoSendStream::DegradationPreference::kBalanced | |
| 2151 : webrtc::VideoSendStream::DegradationPreference:: | |
| 2152 kMaintainResolution); | |
| 2153 } | |
| 2154 | |
| 2246 // Call stream_->Start() if necessary conditions are met. | 2155 // Call stream_->Start() if necessary conditions are met. |
| 2247 UpdateSendState(); | 2156 UpdateSendState(); |
| 2248 } | 2157 } |
| 2249 | 2158 |
| 2250 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( | 2159 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
| 2251 webrtc::Call* call, | 2160 webrtc::Call* call, |
| 2252 const StreamParams& sp, | 2161 const StreamParams& sp, |
| 2253 webrtc::VideoReceiveStream::Config config, | 2162 webrtc::VideoReceiveStream::Config config, |
| 2254 WebRtcVideoDecoderFactory* external_decoder_factory, | 2163 WebRtcVideoDecoderFactory* external_decoder_factory, |
| 2255 bool default_stream, | 2164 bool default_stream, |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2688 rtx_mapping[video_codecs[i].codec.id] != | 2597 rtx_mapping[video_codecs[i].codec.id] != |
| 2689 ulpfec_config.red_payload_type) { | 2598 ulpfec_config.red_payload_type) { |
| 2690 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2599 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
| 2691 } | 2600 } |
| 2692 } | 2601 } |
| 2693 | 2602 |
| 2694 return video_codecs; | 2603 return video_codecs; |
| 2695 } | 2604 } |
| 2696 | 2605 |
| 2697 } // namespace cricket | 2606 } // namespace cricket |
| OLD | NEW |