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 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 ssrc_groups_(sp.ssrc_groups), | 1546 ssrc_groups_(sp.ssrc_groups), |
1547 call_(call), | 1547 call_(call), |
1548 enable_cpu_overuse_detection_(enable_cpu_overuse_detection), | 1548 enable_cpu_overuse_detection_(enable_cpu_overuse_detection), |
1549 source_(nullptr), | 1549 source_(nullptr), |
1550 external_encoder_factory_(external_encoder_factory), | 1550 external_encoder_factory_(external_encoder_factory), |
1551 stream_(nullptr), | 1551 stream_(nullptr), |
1552 encoder_sink_(nullptr), | 1552 encoder_sink_(nullptr), |
1553 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1553 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
1554 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1554 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
1555 allocated_encoder_(nullptr, cricket::VideoCodec(), false), | 1555 allocated_encoder_(nullptr, cricket::VideoCodec(), false), |
1556 sending_(false), | 1556 sending_(false) { |
1557 last_frame_timestamp_us_(0) { | |
1558 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1557 parameters_.config.rtp.max_packet_size = kVideoMtu; |
1559 parameters_.conference_mode = send_params.conference_mode; | 1558 parameters_.conference_mode = send_params.conference_mode; |
1560 | 1559 |
1561 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1560 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
1562 | 1561 |
1563 // ValidateStreamParams should prevent this from happening. | 1562 // ValidateStreamParams should prevent this from happening. |
1564 RTC_CHECK(!parameters_.config.rtp.ssrcs.empty()); | 1563 RTC_CHECK(!parameters_.config.rtp.ssrcs.empty()); |
1565 rtp_parameters_.encodings[0].ssrc = | 1564 rtp_parameters_.encodings[0].ssrc = |
1566 rtc::Optional<uint32_t>(parameters_.config.rtp.ssrcs[0]); | 1565 rtc::Optional<uint32_t>(parameters_.config.rtp.ssrcs[0]); |
1567 | 1566 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 } | 1604 } |
1606 } | 1605 } |
1607 | 1606 |
1608 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { | 1607 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { |
1609 if (stream_ != NULL) { | 1608 if (stream_ != NULL) { |
1610 call_->DestroyVideoSendStream(stream_); | 1609 call_->DestroyVideoSendStream(stream_); |
1611 } | 1610 } |
1612 DestroyVideoEncoder(&allocated_encoder_); | 1611 DestroyVideoEncoder(&allocated_encoder_); |
1613 } | 1612 } |
1614 | 1613 |
1615 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( | |
1616 const webrtc::VideoFrame& frame) { | |
1617 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); | |
1618 webrtc::VideoFrame video_frame(frame.video_frame_buffer(), | |
1619 frame.rotation(), | |
1620 frame.timestamp_us()); | |
1621 | |
1622 rtc::CritScope cs(&lock_); | |
1623 | |
1624 if (video_frame.width() != last_frame_info_.width || | |
1625 video_frame.height() != last_frame_info_.height || | |
1626 video_frame.rotation() != last_frame_info_.rotation || | |
1627 video_frame.is_texture() != last_frame_info_.is_texture) { | |
1628 last_frame_info_.width = video_frame.width(); | |
1629 last_frame_info_.height = video_frame.height(); | |
1630 last_frame_info_.rotation = video_frame.rotation(); | |
1631 last_frame_info_.is_texture = video_frame.is_texture(); | |
1632 | |
1633 LOG(LS_INFO) << "Video frame parameters changed: dimensions=" | |
1634 << last_frame_info_.width << "x" << last_frame_info_.height | |
1635 << ", rotation=" << last_frame_info_.rotation | |
1636 << ", texture=" << last_frame_info_.is_texture; | |
1637 } | |
1638 | |
1639 if (encoder_sink_ == NULL) { | |
1640 // Frame input before send codecs are configured, dropping frame. | |
1641 return; | |
1642 } | |
1643 | |
1644 last_frame_timestamp_us_ = video_frame.timestamp_us(); | |
1645 | |
1646 // Forward frame to the encoder regardless if we are sending or not. This is | |
1647 // to ensure that the encoder can be reconfigured with the correct frame size | |
1648 // as quickly as possible. | |
1649 encoder_sink_->OnFrame(video_frame); | |
1650 } | |
1651 | |
1652 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( | 1614 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( |
1653 bool enable, | 1615 bool enable, |
1654 const VideoOptions* options, | 1616 const VideoOptions* options, |
1655 rtc::VideoSourceInterface<webrtc::VideoFrame>* source) { | 1617 rtc::VideoSourceInterface<webrtc::VideoFrame>* source) { |
1656 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); | 1618 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); |
1657 RTC_DCHECK_RUN_ON(&thread_checker_); | 1619 RTC_DCHECK_RUN_ON(&thread_checker_); |
1658 | 1620 |
1659 // Ignore |options| pointer if |enable| is false. | 1621 // Ignore |options| pointer if |enable| is false. |
1660 bool options_present = enable && options; | 1622 bool options_present = enable && options; |
1661 bool source_changing = source_ != source; | |
1662 | 1623 |
1663 if (options_present) { | 1624 if (options_present) { |
1664 VideoOptions old_options = parameters_.options; | 1625 VideoOptions old_options = parameters_.options; |
1665 parameters_.options.SetAll(*options); | 1626 parameters_.options.SetAll(*options); |
1666 if (parameters_.options != old_options) { | 1627 if (parameters_.options != old_options) { |
1667 ReconfigureEncoder(); | 1628 ReconfigureEncoder(); |
1668 } | 1629 } |
1669 } | 1630 } |
1670 | 1631 |
1671 if (source_changing) { | |
1672 rtc::CritScope cs(&lock_); | |
1673 if (source == nullptr && last_frame_info_.width > 0 && encoder_sink_) { | |
1674 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; | |
1675 // Force this black frame not to be dropped due to timestamp order | |
1676 // check. As IncomingCapturedFrame will drop the frame if this frame's | |
1677 // timestamp is less than or equal to last frame's timestamp, it is | |
1678 // necessary to give this black frame a larger timestamp than the | |
1679 // previous one. | |
1680 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; | |
1681 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( | |
1682 webrtc::I420Buffer::Create(last_frame_info_.width, | |
1683 last_frame_info_.height)); | |
1684 webrtc::I420Buffer::SetBlack(black_buffer); | |
1685 | |
1686 encoder_sink_->OnFrame(webrtc::VideoFrame( | |
1687 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); | |
1688 } | |
1689 } | |
1690 | |
1691 // TODO(perkj, nisse): Remove |source_| and directly call | |
1692 // |stream_|->SetSource(source) once the video frame types have been | |
1693 // merged. | |
1694 if (source_ && stream_) { | 1632 if (source_ && stream_) { |
1695 stream_->SetSource( | 1633 stream_->SetSource( |
1696 nullptr, webrtc::VideoSendStream::DegradationPreference::kBalanced); | 1634 nullptr, webrtc::VideoSendStream::DegradationPreference::kBalanced); |
1697 } | 1635 } |
1698 // Switch to the new source. | 1636 // Switch to the new source. |
1699 source_ = source; | 1637 source_ = source; |
1700 if (source && stream_) { | 1638 if (source && stream_) { |
1701 // Do not adapt resolution for screen content as this will likely | 1639 // Do not adapt resolution for screen content as this will likely |
1702 // result in blurry and unreadable text. | 1640 // result in blurry and unreadable text. |
| 1641 // |this| acts like a VideoSource to make sure SinkWants are handled on the |
| 1642 // correct thread. |
1703 stream_->SetSource( | 1643 stream_->SetSource( |
1704 this, enable_cpu_overuse_detection_ && | 1644 this, enable_cpu_overuse_detection_ && |
1705 !parameters_.options.is_screencast.value_or(false) | 1645 !parameters_.options.is_screencast.value_or(false) |
1706 ? webrtc::VideoSendStream::DegradationPreference::kBalanced | 1646 ? webrtc::VideoSendStream::DegradationPreference::kBalanced |
1707 : webrtc::VideoSendStream::DegradationPreference:: | 1647 : webrtc::VideoSendStream::DegradationPreference:: |
1708 kMaintainResolution); | 1648 kMaintainResolution); |
1709 } | 1649 } |
1710 return true; | 1650 return true; |
1711 } | 1651 } |
1712 | 1652 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1966 parameters_.encoder_config = std::move(encoder_config); | 1906 parameters_.encoder_config = std::move(encoder_config); |
1967 } | 1907 } |
1968 | 1908 |
1969 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { | 1909 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { |
1970 RTC_DCHECK_RUN_ON(&thread_checker_); | 1910 RTC_DCHECK_RUN_ON(&thread_checker_); |
1971 sending_ = send; | 1911 sending_ = send; |
1972 UpdateSendState(); | 1912 UpdateSendState(); |
1973 } | 1913 } |
1974 | 1914 |
1975 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | 1915 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( |
1976 VideoSinkInterface<webrtc::VideoFrame>* sink) { | 1916 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) { |
1977 RTC_DCHECK_RUN_ON(&thread_checker_); | 1917 RTC_DCHECK_RUN_ON(&thread_checker_); |
1978 { | 1918 RTC_DCHECK(encoder_sink_ == sink); |
1979 rtc::CritScope cs(&lock_); | 1919 encoder_sink_ = nullptr; |
1980 RTC_DCHECK(encoder_sink_ == sink); | 1920 source_->RemoveSink(sink); |
1981 encoder_sink_ = nullptr; | |
1982 } | |
1983 source_->RemoveSink(this); | |
1984 } | 1921 } |
1985 | 1922 |
1986 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( | 1923 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( |
1987 VideoSinkInterface<webrtc::VideoFrame>* sink, | 1924 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink, |
1988 const rtc::VideoSinkWants& wants) { | 1925 const rtc::VideoSinkWants& wants) { |
1989 if (worker_thread_ == rtc::Thread::Current()) { | 1926 if (worker_thread_ == rtc::Thread::Current()) { |
1990 // AddOrUpdateSink is called on |worker_thread_| if this is the first | 1927 // AddOrUpdateSink is called on |worker_thread_| if this is the first |
1991 // registration of |sink|. | 1928 // registration of |sink|. |
1992 RTC_DCHECK_RUN_ON(&thread_checker_); | 1929 RTC_DCHECK_RUN_ON(&thread_checker_); |
1993 { | 1930 encoder_sink_ = sink; |
1994 rtc::CritScope cs(&lock_); | 1931 source_->AddOrUpdateSink(encoder_sink_, wants); |
1995 encoder_sink_ = sink; | |
1996 } | |
1997 source_->AddOrUpdateSink(this, wants); | |
1998 } else { | 1932 } else { |
1999 // Subsequent calls to AddOrUpdateSink will happen on the encoder task | 1933 // Subsequent calls to AddOrUpdateSink will happen on the encoder task |
2000 // queue. | 1934 // queue. |
2001 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [this, wants] { | 1935 invoker_.AsyncInvoke<void>( |
2002 RTC_DCHECK_RUN_ON(&thread_checker_); | 1936 RTC_FROM_HERE, worker_thread_, [this, sink, wants] { |
2003 bool encoder_sink_valid = true; | 1937 RTC_DCHECK_RUN_ON(&thread_checker_); |
2004 { | 1938 // |sink| may be invalidated after this task was posted since |
2005 rtc::CritScope cs(&lock_); | 1939 // RemoveSink is called on the worker thread. |
2006 encoder_sink_valid = encoder_sink_ != nullptr; | 1940 bool encoder_sink_valid = (sink == encoder_sink_); |
2007 } | 1941 if (source_ && encoder_sink_valid) { |
2008 // Since |source_| is still valid after a call to RemoveSink, check if | 1942 source_->AddOrUpdateSink(encoder_sink_, wants); |
2009 // |encoder_sink_| is still valid to check if this call should be | 1943 } |
2010 // cancelled. | 1944 }); |
2011 if (source_ && encoder_sink_valid) { | |
2012 source_->AddOrUpdateSink(this, wants); | |
2013 } | |
2014 }); | |
2015 } | 1945 } |
2016 } | 1946 } |
2017 | 1947 |
2018 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( | 1948 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( |
2019 bool log_stats) { | 1949 bool log_stats) { |
2020 VideoSenderInfo info; | 1950 VideoSenderInfo info; |
2021 RTC_DCHECK_RUN_ON(&thread_checker_); | 1951 RTC_DCHECK_RUN_ON(&thread_checker_); |
2022 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) | 1952 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |
2023 info.add_ssrc(ssrc); | 1953 info.add_ssrc(ssrc); |
2024 | 1954 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 2058 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
2129 "payload type the set codec. Ignoring RTX."; | 2059 "payload type the set codec. Ignoring RTX."; |
2130 config.rtp.rtx.ssrcs.clear(); | 2060 config.rtp.rtx.ssrcs.clear(); |
2131 } | 2061 } |
2132 stream_ = call_->CreateVideoSendStream(std::move(config), | 2062 stream_ = call_->CreateVideoSendStream(std::move(config), |
2133 parameters_.encoder_config.Copy()); | 2063 parameters_.encoder_config.Copy()); |
2134 | 2064 |
2135 parameters_.encoder_config.encoder_specific_settings = NULL; | 2065 parameters_.encoder_config.encoder_specific_settings = NULL; |
2136 | 2066 |
2137 if (source_) { | 2067 if (source_) { |
2138 // TODO(perkj, nisse): Remove |source_| and directly call | |
2139 // |stream_|->SetSource(source) once the video frame types have been | |
2140 // merged and |stream_| internally reconfigure the encoder on frame | |
2141 // resolution change. | |
2142 // Do not adapt resolution for screen content as this will likely result in | 2068 // Do not adapt resolution for screen content as this will likely result in |
2143 // blurry and unreadable text. | 2069 // blurry and unreadable text. |
| 2070 // |this| acts like a VideoSource to make sure SinkWants are handled on the |
| 2071 // correct thread. |
2144 stream_->SetSource( | 2072 stream_->SetSource( |
2145 this, enable_cpu_overuse_detection_ && | 2073 this, enable_cpu_overuse_detection_ && |
2146 !parameters_.options.is_screencast.value_or(false) | 2074 !parameters_.options.is_screencast.value_or(false) |
2147 ? webrtc::VideoSendStream::DegradationPreference::kBalanced | 2075 ? webrtc::VideoSendStream::DegradationPreference::kBalanced |
2148 : webrtc::VideoSendStream::DegradationPreference:: | 2076 : webrtc::VideoSendStream::DegradationPreference:: |
2149 kMaintainResolution); | 2077 kMaintainResolution); |
2150 } | 2078 } |
2151 | 2079 |
2152 // Call stream_->Start() if necessary conditions are met. | 2080 // Call stream_->Start() if necessary conditions are met. |
2153 UpdateSendState(); | 2081 UpdateSendState(); |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2587 rtx_mapping[video_codecs[i].codec.id] != | 2515 rtx_mapping[video_codecs[i].codec.id] != |
2588 ulpfec_config.red_payload_type) { | 2516 ulpfec_config.red_payload_type) { |
2589 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2517 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
2590 } | 2518 } |
2591 } | 2519 } |
2592 | 2520 |
2593 return video_codecs; | 2521 return video_codecs; |
2594 } | 2522 } |
2595 | 2523 |
2596 } // namespace cricket | 2524 } // namespace cricket |
OLD | NEW |