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 |