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 |