| Index: webrtc/media/engine/webrtcvideoengine2.cc
|
| diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
|
| index 5176c115b70d8224978abad1c1555e327c9e39e6..86bf02855af52df8211fecbb0e239d6e5aeb910e 100644
|
| --- a/webrtc/media/engine/webrtcvideoengine2.cc
|
| +++ b/webrtc/media/engine/webrtcvideoengine2.cc
|
| @@ -14,6 +14,7 @@
|
| #include <algorithm>
|
| #include <set>
|
| #include <string>
|
| +#include <utility>
|
|
|
| #include "webrtc/base/copyonwritebuffer.h"
|
| #include "webrtc/base/logging.h"
|
| @@ -322,12 +323,83 @@ int GetDefaultVp9TemporalLayers() {
|
| }
|
| return 1;
|
| }
|
| +
|
| +class EncoderStreamFactory
|
| + : public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
|
| + public:
|
| + EncoderStreamFactory(std::string codec_name,
|
| + int max_qp,
|
| + int max_framerate,
|
| + bool is_screencast,
|
| + bool conference_mode)
|
| + : codec_name_(codec_name),
|
| + max_qp_(max_qp),
|
| + max_framerate_(max_framerate),
|
| + is_screencast_(is_screencast),
|
| + conference_mode_(conference_mode) {}
|
| +
|
| + private:
|
| + std::vector<webrtc::VideoStream> CreateEncoderStreams(
|
| + int width,
|
| + int height,
|
| + const webrtc::VideoEncoderConfig& encoder_config) override {
|
| + RTC_DCHECK(encoder_config.number_of_streams > 1 ? !is_screencast_ : true);
|
| + if (encoder_config.number_of_streams > 1) {
|
| + return GetSimulcastConfig(encoder_config.number_of_streams, width, height,
|
| + encoder_config.max_bitrate_bps, max_qp_,
|
| + max_framerate_);
|
| + }
|
| +
|
| + // For unset max bitrates set default bitrate for non-simulcast.
|
| + int max_bitrate_bps =
|
| + (encoder_config.max_bitrate_bps > 0)
|
| + ? encoder_config.max_bitrate_bps
|
| + : GetMaxDefaultVideoBitrateKbps(width, height) * 1000;
|
| +
|
| + webrtc::VideoStream stream;
|
| + stream.width = width;
|
| + stream.height = height;
|
| + stream.max_framerate = max_framerate_;
|
| + stream.min_bitrate_bps = kMinVideoBitrateKbps * 1000;
|
| + stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
|
| + stream.max_qp = max_qp_;
|
| +
|
| + // Conference mode screencast uses 2 temporal layers split at 100kbit.
|
| + if (conference_mode_ && is_screencast_) {
|
| + ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
|
| + // For screenshare in conference mode, tl0 and tl1 bitrates are
|
| + // piggybacked
|
| + // on the VideoCodec struct as target and max bitrates, respectively.
|
| + // See eg. webrtc::VP8EncoderImpl::SetRates().
|
| + stream.target_bitrate_bps = config.tl0_bitrate_kbps * 1000;
|
| + stream.max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
|
| + stream.temporal_layer_thresholds_bps.clear();
|
| + stream.temporal_layer_thresholds_bps.push_back(config.tl0_bitrate_kbps *
|
| + 1000);
|
| + }
|
| +
|
| + if (CodecNamesEq(codec_name_, kVp9CodecName) && !is_screencast_) {
|
| + stream.temporal_layer_thresholds_bps.resize(
|
| + GetDefaultVp9TemporalLayers() - 1);
|
| + }
|
| +
|
| + std::vector<webrtc::VideoStream> streams;
|
| + streams.push_back(stream);
|
| + return streams;
|
| + }
|
| +
|
| + const std::string codec_name_;
|
| + const int max_qp_;
|
| + const int max_framerate_;
|
| + const bool is_screencast_;
|
| + const bool conference_mode_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| // Constants defined in webrtc/media/engine/constants.h
|
| // TODO(pbos): Move these to a separate constants.cc file.
|
| -const int kMinVideoBitrate = 30;
|
| -const int kStartVideoBitrate = 300;
|
| +const int kMinVideoBitrateKbps = 30;
|
|
|
| const int kVideoMtu = 1200;
|
| const int kVideoRtpBufferSize = 65536;
|
| @@ -398,61 +470,10 @@ std::vector<VideoCodec> DefaultVideoCodecList() {
|
| return codecs;
|
| }
|
|
|
| -std::vector<webrtc::VideoStream>
|
| -WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams(
|
| - const VideoCodec& codec,
|
| - const VideoOptions& options,
|
| - int max_bitrate_bps,
|
| - size_t num_streams) {
|
| - int max_qp = kDefaultQpMax;
|
| - codec.GetParam(kCodecParamMaxQuantization, &max_qp);
|
| -
|
| - return GetSimulcastConfig(
|
| - num_streams, codec.width, codec.height, max_bitrate_bps, max_qp,
|
| - codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate);
|
| -}
|
| -
|
| -std::vector<webrtc::VideoStream>
|
| -WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams(
|
| - const VideoCodec& codec,
|
| - const VideoOptions& options,
|
| - int max_bitrate_bps,
|
| - size_t num_streams) {
|
| - int codec_max_bitrate_kbps;
|
| - if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
|
| - max_bitrate_bps = codec_max_bitrate_kbps * 1000;
|
| - }
|
| - if (num_streams != 1) {
|
| - return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps,
|
| - num_streams);
|
| - }
|
| -
|
| - // For unset max bitrates set default bitrate for non-simulcast.
|
| - if (max_bitrate_bps <= 0) {
|
| - max_bitrate_bps =
|
| - GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000;
|
| - }
|
| -
|
| - webrtc::VideoStream stream;
|
| - stream.width = codec.width;
|
| - stream.height = codec.height;
|
| - stream.max_framerate =
|
| - codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
|
| -
|
| - stream.min_bitrate_bps = kMinVideoBitrate * 1000;
|
| - stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
|
| -
|
| - int max_qp = kDefaultQpMax;
|
| - codec.GetParam(kCodecParamMaxQuantization, &max_qp);
|
| - stream.max_qp = max_qp;
|
| - std::vector<webrtc::VideoStream> streams;
|
| - streams.push_back(stream);
|
| - return streams;
|
| -}
|
| -
|
| rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
|
| const VideoCodec& codec) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| bool is_screencast = parameters_.options.is_screencast.value_or(false);
|
| // No automatic resizing when using simulcast or screencast.
|
| bool automatic_resize =
|
| @@ -1543,6 +1564,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
|
| : config(std::move(config)),
|
| options(options),
|
| max_bitrate_bps(max_bitrate_bps),
|
| + conference_mode(false),
|
| codec_settings(codec_settings) {}
|
|
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
|
| @@ -1587,7 +1609,6 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
|
| encoder_sink_(nullptr),
|
| parameters_(std::move(config), options, max_bitrate_bps, codec_settings),
|
| rtp_parameters_(CreateRtpParametersWithOneEncoding()),
|
| - pending_encoder_reconfiguration_(false),
|
| allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false),
|
| sending_(false),
|
| last_frame_timestamp_us_(0) {
|
| @@ -1655,7 +1676,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame(
|
| last_frame_info_.height = video_frame.height();
|
| last_frame_info_.rotation = video_frame.rotation();
|
| last_frame_info_.is_texture = video_frame.is_texture();
|
| - pending_encoder_reconfiguration_ = true;
|
|
|
| LOG(LS_INFO) << "Video frame parameters changed: dimensions="
|
| << last_frame_info_.width << "x" << last_frame_info_.height
|
| @@ -1670,22 +1690,13 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame(
|
|
|
| last_frame_timestamp_us_ = video_frame.timestamp_us();
|
|
|
| - if (pending_encoder_reconfiguration_) {
|
| - ReconfigureEncoder();
|
| - pending_encoder_reconfiguration_ = false;
|
| - }
|
| -
|
| - // Not sending, abort after reconfiguration. Reconfiguration should still
|
| - // occur to permit sending this input as quickly as possible once we start
|
| - // sending (without having to reconfigure then).
|
| - if (!sending_) {
|
| - return;
|
| - }
|
| -
|
| ++frame_count_;
|
| if (cpu_restricted_counter_ > 0)
|
| ++cpu_restricted_frame_count_;
|
|
|
| + // Forward frame to the encoder regardless if we are sending or not. This is
|
| + // to ensure that the encoder can be reconfigured with the correct frame size
|
| + // as quickly as possible.
|
| encoder_sink_->OnFrame(video_frame);
|
| }
|
|
|
| @@ -1694,7 +1705,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend(
|
| const VideoOptions* options,
|
| rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
|
| TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend");
|
| - RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
|
|
| // Ignore |options| pointer if |enable| is false.
|
| bool options_present = enable && options;
|
| @@ -1703,50 +1714,46 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend(
|
| DisconnectSource();
|
| }
|
|
|
| - if (options_present || source_changing) {
|
| - rtc::CritScope cs(&lock_);
|
| -
|
| - if (options_present) {
|
| - VideoOptions old_options = parameters_.options;
|
| - parameters_.options.SetAll(*options);
|
| - // Reconfigure encoder settings on the next frame or stream
|
| - // recreation if the options changed.
|
| - if (parameters_.options != old_options) {
|
| - pending_encoder_reconfiguration_ = true;
|
| - }
|
| + if (options_present) {
|
| + VideoOptions old_options = parameters_.options;
|
| + parameters_.options.SetAll(*options);
|
| + if (parameters_.options != old_options) {
|
| + ReconfigureEncoder();
|
| }
|
| + }
|
|
|
| - if (source_changing) {
|
| - if (source == nullptr && encoder_sink_ != nullptr) {
|
| - LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
|
| - // Force this black frame not to be dropped due to timestamp order
|
| - // check. As IncomingCapturedFrame will drop the frame if this frame's
|
| - // timestamp is less than or equal to last frame's timestamp, it is
|
| - // necessary to give this black frame a larger timestamp than the
|
| - // previous one.
|
| - last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec;
|
| - rtc::scoped_refptr<webrtc::I420Buffer> black_buffer(
|
| - webrtc::I420Buffer::Create(last_frame_info_.width,
|
| - last_frame_info_.height));
|
| - black_buffer->SetToBlack();
|
| -
|
| - encoder_sink_->OnFrame(webrtc::VideoFrame(
|
| - black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_));
|
| - }
|
| - source_ = source;
|
| + if (source_changing) {
|
| + rtc::CritScope cs(&lock_);
|
| + if (source == nullptr && encoder_sink_ != nullptr &&
|
| + last_frame_info_.width > 0) {
|
| + LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
|
| + // Force this black frame not to be dropped due to timestamp order
|
| + // check. As IncomingCapturedFrame will drop the frame if this frame's
|
| + // timestamp is less than or equal to last frame's timestamp, it is
|
| + // necessary to give this black frame a larger timestamp than the
|
| + // previous one.
|
| + last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec;
|
| + rtc::scoped_refptr<webrtc::I420Buffer> black_buffer(
|
| + webrtc::I420Buffer::Create(last_frame_info_.width,
|
| + last_frame_info_.height));
|
| + black_buffer->SetToBlack();
|
| +
|
| + encoder_sink_->OnFrame(webrtc::VideoFrame(
|
| + black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_));
|
| }
|
| + source_ = source;
|
| }
|
|
|
| - // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
|
| - // that might cause a lock order inversion.
|
| if (source_changing && source_) {
|
| + // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
|
| + // that might cause a lock order inversion.
|
| source_->AddOrUpdateSink(this, sink_wants_);
|
| }
|
| return true;
|
| }
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() {
|
| - RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (source_ == nullptr) {
|
| return;
|
| }
|
| @@ -1781,6 +1788,7 @@ webrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
|
| const VideoCodec& codec) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
|
|
|
| // Do not re-create encoders of the same type.
|
| @@ -1815,6 +1823,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
|
| AllocatedEncoder* encoder) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (encoder->external) {
|
| external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder);
|
| }
|
| @@ -1823,8 +1832,9 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
|
| const VideoCodecSettings& codec_settings) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec);
|
| - RTC_DCHECK(!parameters_.encoder_config.streams.empty());
|
| + RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u);
|
|
|
| AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
|
| parameters_.config.encoder_settings.encoder = new_encoder.encoder;
|
| @@ -1865,41 +1875,38 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
|
| const ChangedSendParameters& params) {
|
| - {
|
| - rtc::CritScope cs(&lock_);
|
| - // |recreate_stream| means construction-time parameters have changed and the
|
| - // sending stream needs to be reset with the new config.
|
| - bool recreate_stream = false;
|
| - if (params.rtcp_mode) {
|
| - parameters_.config.rtp.rtcp_mode = *params.rtcp_mode;
|
| - recreate_stream = true;
|
| - }
|
| - if (params.rtp_header_extensions) {
|
| - parameters_.config.rtp.extensions = *params.rtp_header_extensions;
|
| - recreate_stream = true;
|
| - }
|
| - if (params.max_bandwidth_bps) {
|
| - parameters_.max_bitrate_bps = *params.max_bandwidth_bps;
|
| - pending_encoder_reconfiguration_ = true;
|
| - }
|
| - if (params.conference_mode) {
|
| - parameters_.conference_mode = *params.conference_mode;
|
| - }
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + // |recreate_stream| means construction-time parameters have changed and the
|
| + // sending stream needs to be reset with the new config.
|
| + bool recreate_stream = false;
|
| + if (params.rtcp_mode) {
|
| + parameters_.config.rtp.rtcp_mode = *params.rtcp_mode;
|
| + recreate_stream = true;
|
| + }
|
| + if (params.rtp_header_extensions) {
|
| + parameters_.config.rtp.extensions = *params.rtp_header_extensions;
|
| + recreate_stream = true;
|
| + }
|
| + if (params.max_bandwidth_bps) {
|
| + parameters_.max_bitrate_bps = *params.max_bandwidth_bps;
|
| + ReconfigureEncoder();
|
| + }
|
| + if (params.conference_mode) {
|
| + parameters_.conference_mode = *params.conference_mode;
|
| + }
|
|
|
| - // Set codecs and options.
|
| - if (params.codec) {
|
| - SetCodec(*params.codec);
|
| - recreate_stream = false; // SetCodec has already recreated the stream.
|
| - } else if (params.conference_mode && parameters_.codec_settings) {
|
| - SetCodec(*parameters_.codec_settings);
|
| - recreate_stream = false; // SetCodec has already recreated the stream.
|
| - }
|
| - if (recreate_stream) {
|
| - LOG(LS_INFO)
|
| - << "RecreateWebRtcStream (send) because of SetSendParameters";
|
| - RecreateWebRtcStream();
|
| - }
|
| - } // release |lock_|
|
| + // Set codecs and options.
|
| + if (params.codec) {
|
| + SetCodec(*params.codec);
|
| + recreate_stream = false; // SetCodec has already recreated the stream.
|
| + } else if (params.conference_mode && parameters_.codec_settings) {
|
| + SetCodec(*parameters_.codec_settings);
|
| + recreate_stream = false; // SetCodec has already recreated the stream.
|
| + }
|
| + if (recreate_stream) {
|
| + LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters";
|
| + RecreateWebRtcStream();
|
| + }
|
|
|
| // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
|
| // that might cause a lock order inversion.
|
| @@ -1914,18 +1921,19 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
|
|
|
| bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters(
|
| const webrtc::RtpParameters& new_parameters) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (!ValidateRtpParameters(new_parameters)) {
|
| return false;
|
| }
|
|
|
| - rtc::CritScope cs(&lock_);
|
| - if (new_parameters.encodings[0].max_bitrate_bps !=
|
| - rtp_parameters_.encodings[0].max_bitrate_bps) {
|
| - pending_encoder_reconfiguration_ = true;
|
| - }
|
| + bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps !=
|
| + rtp_parameters_.encodings[0].max_bitrate_bps;
|
| rtp_parameters_ = new_parameters;
|
| // Codecs are currently handled at the WebRtcVideoChannel2 level.
|
| rtp_parameters_.codecs.clear();
|
| + if (reconfigure_encoder) {
|
| + ReconfigureEncoder();
|
| + }
|
| // Encoding may have been activated/deactivated.
|
| UpdateSendState();
|
| return true;
|
| @@ -1933,7 +1941,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters(
|
|
|
| webrtc::RtpParameters
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const {
|
| - rtc::CritScope cs(&lock_);
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| return rtp_parameters_;
|
| }
|
|
|
| @@ -1948,6 +1956,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::ValidateRtpParameters(
|
| }
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| // TODO(deadbeef): Need to handle more than one encoding in the future.
|
| RTC_DCHECK(rtp_parameters_.encodings.size() == 1u);
|
| if (sending_ && rtp_parameters_.encodings[0].active) {
|
| @@ -1963,6 +1972,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() {
|
| webrtc::VideoEncoderConfig
|
| WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
|
| const VideoCodec& codec) const {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| webrtc::VideoEncoderConfig encoder_config;
|
| bool is_screencast = parameters_.options.is_screencast.value_or(false);
|
| if (is_screencast) {
|
| @@ -1976,60 +1986,45 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
|
| webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
|
| }
|
|
|
| - // Restrict dimensions according to codec max.
|
| - int width = last_frame_info_.width;
|
| - int height = last_frame_info_.height;
|
| - if (!is_screencast) {
|
| - if (codec.width < width)
|
| - width = codec.width;
|
| - if (codec.height < height)
|
| - height = codec.height;
|
| - }
|
| -
|
| - VideoCodec clamped_codec = codec;
|
| - clamped_codec.width = width;
|
| - clamped_codec.height = height;
|
| -
|
| // By default, the stream count for the codec configuration should match the
|
| // number of negotiated ssrcs. But if the codec is blacklisted for simulcast
|
| // or a screencast, only configure a single stream.
|
| - size_t stream_count = parameters_.config.rtp.ssrcs.size();
|
| + encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size();
|
| if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) {
|
| - stream_count = 1;
|
| + encoder_config.number_of_streams = 1;
|
| }
|
|
|
| int stream_max_bitrate =
|
| MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps,
|
| parameters_.max_bitrate_bps);
|
| - encoder_config.streams = CreateVideoStreams(
|
| - clamped_codec, parameters_.options, stream_max_bitrate, stream_count);
|
| - encoder_config.expect_encode_from_texture = last_frame_info_.is_texture;
|
| -
|
| - // Conference mode screencast uses 2 temporal layers split at 100kbit.
|
| - if (parameters_.conference_mode && is_screencast &&
|
| - encoder_config.streams.size() == 1) {
|
| - ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
|
| -
|
| - // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked
|
| - // on the VideoCodec struct as target and max bitrates, respectively.
|
| - // See eg. webrtc::VP8EncoderImpl::SetRates().
|
| - encoder_config.streams[0].target_bitrate_bps =
|
| - config.tl0_bitrate_kbps * 1000;
|
| - encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
|
| - encoder_config.streams[0].temporal_layer_thresholds_bps.clear();
|
| - encoder_config.streams[0].temporal_layer_thresholds_bps.push_back(
|
| - config.tl0_bitrate_kbps * 1000);
|
| - }
|
| - if (CodecNamesEq(codec.name, kVp9CodecName) && !is_screencast &&
|
| - encoder_config.streams.size() == 1) {
|
| - encoder_config.streams[0].temporal_layer_thresholds_bps.resize(
|
| - GetDefaultVp9TemporalLayers() - 1);
|
| +
|
| + int codec_max_bitrate_kbps;
|
| + if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
|
| + stream_max_bitrate = codec_max_bitrate_kbps * 1000;
|
| }
|
| + encoder_config.max_bitrate_bps = stream_max_bitrate;
|
| +
|
| + int max_qp = kDefaultQpMax;
|
| + codec.GetParam(kCodecParamMaxQuantization, &max_qp);
|
| + int max_framerate =
|
| + codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
|
| +
|
| + encoder_config.video_stream_factory =
|
| + new rtc::RefCountedObject<EncoderStreamFactory>(
|
| + codec.name, max_qp, max_framerate, is_screencast,
|
| + parameters_.conference_mode);
|
| return encoder_config;
|
| }
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() {
|
| - RTC_DCHECK(!parameters_.encoder_config.streams.empty());
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + if (!stream_) {
|
| + // The webrtc::VideoSendStream |stream_|has not yet been created but other
|
| + // parameters has changed.
|
| + return;
|
| + }
|
| +
|
| + RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u);
|
|
|
| RTC_CHECK(parameters_.codec_settings);
|
| VideoCodecSettings codec_settings = *parameters_.codec_settings;
|
| @@ -2048,7 +2043,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() {
|
| }
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) {
|
| - rtc::CritScope cs(&lock_);
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| sending_ = send;
|
| UpdateSendState();
|
| }
|
| @@ -2078,63 +2073,62 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) {
|
| this, load));
|
| return;
|
| }
|
| - RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (!source_) {
|
| return;
|
| }
|
| - {
|
| +
|
| + LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: "
|
| + << (parameters_.options.is_screencast
|
| + ? (*parameters_.options.is_screencast ? "true" : "false")
|
| + : "unset");
|
| + // Do not adapt resolution for screen content as this will likely result in
|
| + // blurry and unreadable text.
|
| + if (parameters_.options.is_screencast.value_or(false))
|
| + return;
|
| +
|
| + rtc::Optional<int> max_pixel_count;
|
| + rtc::Optional<int> max_pixel_count_step_up;
|
| + if (load == kOveruse) {
|
| rtc::CritScope cs(&lock_);
|
| - LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: "
|
| - << (parameters_.options.is_screencast
|
| - ? (*parameters_.options.is_screencast ? "true"
|
| - : "false")
|
| - : "unset");
|
| - // Do not adapt resolution for screen content as this will likely result in
|
| - // blurry and unreadable text.
|
| - if (parameters_.options.is_screencast.value_or(false))
|
| + if (cpu_restricted_counter_ >= kMaxCpuDowngrades) {
|
| return;
|
| -
|
| - rtc::Optional<int> max_pixel_count;
|
| - rtc::Optional<int> max_pixel_count_step_up;
|
| - if (load == kOveruse) {
|
| - if (cpu_restricted_counter_ >= kMaxCpuDowngrades) {
|
| - return;
|
| - }
|
| - // The input video frame size will have a resolution with less than or
|
| - // equal to |max_pixel_count| depending on how the source can scale the
|
| - // input frame size.
|
| - max_pixel_count = rtc::Optional<int>(
|
| - (last_frame_info_.height * last_frame_info_.width * 3) / 5);
|
| - // Increase |number_of_cpu_adapt_changes_| if
|
| - // sink_wants_.max_pixel_count will be changed since
|
| - // last time |source_->AddOrUpdateSink| was called. That is, this will
|
| - // result in a new request for the source to change resolution.
|
| - if (!sink_wants_.max_pixel_count ||
|
| - *sink_wants_.max_pixel_count > *max_pixel_count) {
|
| - ++number_of_cpu_adapt_changes_;
|
| - ++cpu_restricted_counter_;
|
| - }
|
| - } else {
|
| - RTC_DCHECK(load == kUnderuse);
|
| - // The input video frame size will have a resolution with "one step up"
|
| - // pixels than |max_pixel_count_step_up| where "one step up" depends on
|
| - // how the source can scale the input frame size.
|
| - max_pixel_count_step_up =
|
| - rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width);
|
| - // Increase |number_of_cpu_adapt_changes_| if
|
| - // sink_wants_.max_pixel_count_step_up will be changed since
|
| - // last time |source_->AddOrUpdateSink| was called. That is, this will
|
| - // result in a new request for the source to change resolution.
|
| - if (sink_wants_.max_pixel_count ||
|
| - (sink_wants_.max_pixel_count_step_up &&
|
| - *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) {
|
| - ++number_of_cpu_adapt_changes_;
|
| - --cpu_restricted_counter_;
|
| - }
|
| }
|
| - sink_wants_.max_pixel_count = max_pixel_count;
|
| - sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up;
|
| + // The input video frame size will have a resolution with less than or
|
| + // equal to |max_pixel_count| depending on how the source can scale the
|
| + // input frame size.
|
| + max_pixel_count = rtc::Optional<int>(
|
| + (last_frame_info_.height * last_frame_info_.width * 3) / 5);
|
| + // Increase |number_of_cpu_adapt_changes_| if
|
| + // sink_wants_.max_pixel_count will be changed since
|
| + // last time |source_->AddOrUpdateSink| was called. That is, this will
|
| + // result in a new request for the source to change resolution.
|
| + if (!sink_wants_.max_pixel_count ||
|
| + *sink_wants_.max_pixel_count > *max_pixel_count) {
|
| + ++number_of_cpu_adapt_changes_;
|
| + ++cpu_restricted_counter_;
|
| + }
|
| + } else {
|
| + RTC_DCHECK(load == kUnderuse);
|
| + rtc::CritScope cs(&lock_);
|
| + // The input video frame size will have a resolution with "one step up"
|
| + // pixels than |max_pixel_count_step_up| where "one step up" depends on
|
| + // how the source can scale the input frame size.
|
| + max_pixel_count_step_up =
|
| + rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width);
|
| + // Increase |number_of_cpu_adapt_changes_| if
|
| + // sink_wants_.max_pixel_count_step_up will be changed since
|
| + // last time |source_->AddOrUpdateSink| was called. That is, this will
|
| + // result in a new request for the source to change resolution.
|
| + if (sink_wants_.max_pixel_count ||
|
| + (sink_wants_.max_pixel_count_step_up &&
|
| + *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) {
|
| + ++number_of_cpu_adapt_changes_;
|
| + --cpu_restricted_counter_;
|
| + }
|
| }
|
| + sink_wants_.max_pixel_count = max_pixel_count;
|
| + sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up;
|
| // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
|
| // that might cause a lock order inversion.
|
| source_->AddOrUpdateSink(this, sink_wants_);
|
| @@ -2143,21 +2137,17 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) {
|
| VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo(
|
| bool log_stats) {
|
| VideoSenderInfo info;
|
| - webrtc::VideoSendStream::Stats stats;
|
| - RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| - {
|
| - rtc::CritScope cs(&lock_);
|
| - for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
|
| - info.add_ssrc(ssrc);
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
|
| + info.add_ssrc(ssrc);
|
|
|
| - if (parameters_.codec_settings)
|
| - info.codec_name = parameters_.codec_settings->codec.name;
|
| + if (parameters_.codec_settings)
|
| + info.codec_name = parameters_.codec_settings->codec.name;
|
|
|
| - if (stream_ == NULL)
|
| - return info;
|
| + if (stream_ == NULL)
|
| + return info;
|
|
|
| - stats = stream_->GetStats();
|
| - }
|
| + webrtc::VideoSendStream::Stats stats = stream_->GetStats();
|
|
|
| if (log_stats)
|
| LOG(LS_INFO) << stats.ToString(rtc::TimeMillis());
|
| @@ -2218,7 +2208,7 @@ VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo(
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
|
| BandwidthEstimationInfo* bwe_info) {
|
| - rtc::CritScope cs(&lock_);
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (stream_ == NULL) {
|
| return;
|
| }
|
| @@ -2234,6 +2224,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
|
| }
|
|
|
| void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| if (stream_ != NULL) {
|
| call_->DestroyVideoSendStream(stream_);
|
| }
|
| @@ -2257,7 +2248,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
|
| stream_->SetSource(this);
|
|
|
| parameters_.encoder_config.encoder_specific_settings = NULL;
|
| - pending_encoder_reconfiguration_ = false;
|
|
|
| // Call stream_->Start() if necessary conditions are met.
|
| UpdateSendState();
|
|
|