diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index 344577afb0..83e79484bb 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -21,13 +21,6 @@ #include "webrtc/video/receive_statistics_proxy.h" #include "webrtc/video_encoder.h" #include "webrtc/video_engine/include/vie_base.h" -#include "webrtc/video_engine/include/vie_capture.h" -#include "webrtc/video_engine/include/vie_codec.h" -#include "webrtc/video_engine/include/vie_external_codec.h" -#include "webrtc/video_engine/include/vie_image_process.h" -#include "webrtc/video_engine/include/vie_network.h" -#include "webrtc/video_engine/include/vie_render.h" -#include "webrtc/video_engine/include/vie_rtp_rtcp.h" #include "webrtc/video_receive_stream.h" namespace webrtc { diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h index c506bb08d0..ad6d0aa844 100644 --- a/webrtc/video/video_receive_stream.h +++ b/webrtc/video/video_receive_stream.h @@ -32,12 +32,6 @@ namespace webrtc { class VideoEngine; class ViEBase; -class ViECodec; -class ViEExternalCodec; -class ViEImageProcess; -class ViENetwork; -class ViERender; -class ViERTP_RTCP; class VoiceEngine; namespace internal { diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index adcd01c502..1afdd85fa1 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -19,12 +19,8 @@ #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/trace_event.h" +#include "webrtc/video_engine/encoder_state_feedback.h" #include "webrtc/video_engine/include/vie_base.h" -#include "webrtc/video_engine/include/vie_capture.h" -#include "webrtc/video_engine/include/vie_codec.h" -#include "webrtc/video_engine/include/vie_external_codec.h" -#include "webrtc/video_engine/include/vie_image_process.h" -#include "webrtc/video_engine/include/vie_network.h" #include "webrtc/video_engine/vie_capturer.h" #include "webrtc/video_engine/vie_channel.h" #include "webrtc/video_engine/vie_channel_group.h" @@ -206,7 +202,6 @@ VideoSendStream::VideoSendStream( config.encoder_settings.encoder, config.encoder_settings.payload_type, false)); - codec_ = ViECodec::GetInterface(video_engine); CHECK(ReconfigureVideoEncoder(encoder_config)); if (overuse_observer) { @@ -222,8 +217,14 @@ VideoSendStream::VideoSendStream( if (config_.post_encode_callback) vie_encoder_->RegisterPostEncodeImageCallback(&encoded_frame_proxy_); - if (config_.suspend_below_min_bitrate) - codec_->SuspendBelowMinBitrate(channel_); + if (config_.suspend_below_min_bitrate) { + vie_encoder_->SuspendBelowMinBitrate(); + // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no + // padding will be sent when the video is suspended so the video will be + // unable to recover. + // TODO(pbos): Pacing should probably be enabled outside of VideoSendStream. + vie_channel_->SetTransmissionSmoothingStatus(true); + } vie_channel_->RegisterSendChannelRtcpStatisticsCallback(&stats_proxy_); vie_channel_->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); @@ -231,11 +232,11 @@ VideoSendStream::VideoSendStream( vie_channel_->RegisterSendBitrateObserver(&stats_proxy_); vie_channel_->RegisterSendFrameCountObserver(&stats_proxy_); - codec_->RegisterEncoderObserver(channel_, stats_proxy_); + vie_encoder_->RegisterCodecObserver(&stats_proxy_); } VideoSendStream::~VideoSendStream() { - codec_->DeregisterEncoderObserver(channel_); + vie_encoder_->RegisterCodecObserver(nullptr); vie_channel_->RegisterSendFrameCountObserver(nullptr); vie_channel_->RegisterSendBitrateObserver(nullptr); @@ -258,7 +259,6 @@ VideoSendStream::~VideoSendStream() { video_engine_base_->DeleteChannel(channel_); video_engine_base_->Release(); - codec_->Release(); } void VideoSendStream::IncomingCapturedFrame(const I420VideoFrame& frame) { @@ -399,15 +399,10 @@ bool VideoSendStream::ReconfigureVideoEncoder( // the bitrate controller is already set from Call. video_codec.startBitrate = 0; - if (video_codec.minBitrate < kViEMinCodecBitrate) - video_codec.minBitrate = kViEMinCodecBitrate; - if (video_codec.maxBitrate < kViEMinCodecBitrate) - video_codec.maxBitrate = kViEMinCodecBitrate; - DCHECK_GT(streams[0].max_framerate, 0); video_codec.maxFramerate = streams[0].max_framerate; - if (codec_->SetSendCodec(channel_, video_codec) != 0) + if (!SetSendCodec(video_codec)) return false; DCHECK_GE(config.min_transmit_bitrate_bps, 0); @@ -497,5 +492,53 @@ int64_t VideoSendStream::GetRtt() const { } return -1; } + +bool VideoSendStream::SetSendCodec(VideoCodec video_codec) { + if (video_codec.maxBitrate == 0) { + // Unset max bitrate -> cap to one bit per pixel. + video_codec.maxBitrate = + (video_codec.width * video_codec.height * video_codec.maxFramerate) / + 1000; + } + + if (video_codec.minBitrate < kViEMinCodecBitrate) + video_codec.minBitrate = kViEMinCodecBitrate; + if (video_codec.maxBitrate < kViEMinCodecBitrate) + video_codec.maxBitrate = kViEMinCodecBitrate; + + // Stop the media flow while reconfiguring. + vie_encoder_->Pause(); + + if (vie_encoder_->SetEncoder(video_codec) != 0) { + LOG(LS_ERROR) << "Failed to set encoder."; + return false; + } + + if (vie_channel_->SetSendCodec(video_codec, false) != 0) { + LOG(LS_ERROR) << "Failed to set send codec."; + return false; + } + + // Not all configured SSRCs have to be utilized (simulcast senders don't have + // to send on all SSRCs at once etc.) + std::vector used_ssrcs = config_.rtp.ssrcs; + used_ssrcs.resize(static_cast(video_codec.numberOfSimulcastStreams)); + + // Update used SSRCs. + vie_encoder_->SetSsrcs(used_ssrcs); + EncoderStateFeedback* encoder_state_feedback = + channel_group_->GetEncoderStateFeedback(); + encoder_state_feedback->UpdateSsrcs(used_ssrcs, vie_encoder_); + + // Update the protection mode, we might be switching NACK/FEC. + vie_encoder_->UpdateProtectionMethod(vie_encoder_->nack_enabled(), + vie_channel_->IsSendingFecEnabled()); + + // Restart the media flow + vie_encoder_->Restart(); + + return true; +} + } // namespace internal } // namespace webrtc diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index d564996784..f066fc6f77 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -31,9 +31,7 @@ class ProcessThread; class ViEBase; class ViECapturer; class ViEChannel; -class ViECodec; class ViEEncoder; -class ViEExternalCodec; class VideoEngine; namespace internal { @@ -76,6 +74,7 @@ class VideoSendStream : public webrtc::VideoSendStream, int64_t GetRtt() const; private: + bool SetSendCodec(VideoCodec video_codec); void ConfigureSsrcs(); TransportAdapter transport_adapter_; EncodedFrameCallbackAdapter encoded_frame_proxy_; @@ -88,7 +87,6 @@ class VideoSendStream : public webrtc::VideoSendStream, ViEBase* video_engine_base_; ViEChannel* vie_channel_; - ViECodec* codec_; ViEEncoder* vie_encoder_; ViECapturer* vie_capturer_; diff --git a/webrtc/video_engine/encoder_state_feedback.cc b/webrtc/video_engine/encoder_state_feedback.cc index e5d6bd69de..4d9db5847d 100644 --- a/webrtc/video_engine/encoder_state_feedback.cc +++ b/webrtc/video_engine/encoder_state_feedback.cc @@ -12,6 +12,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/video_engine/vie_encoder.h" @@ -53,6 +54,23 @@ EncoderStateFeedback::~EncoderStateFeedback() { assert(encoders_.empty()); } +void EncoderStateFeedback::UpdateSsrcs(const std::vector& ssrcs, + ViEEncoder* encoder) { + CriticalSectionScoped lock(crit_.get()); + SsrcEncoderMap::iterator it = encoders_.begin(); + while (it != encoders_.end()) { + if (it->second == encoder) { + encoders_.erase(it++); + } else { + ++it; + } + } + for (uint32_t ssrc : ssrcs) { + DCHECK(encoders_.find(ssrc) == encoders_.end()); + encoders_[ssrc] = encoder; + } +} + bool EncoderStateFeedback::AddEncoder(uint32_t ssrc, ViEEncoder* encoder) { CriticalSectionScoped lock(crit_.get()); if (encoders_.find(ssrc) != encoders_.end()) { diff --git a/webrtc/video_engine/encoder_state_feedback.h b/webrtc/video_engine/encoder_state_feedback.h index 998793a254..d74c6c2ed0 100644 --- a/webrtc/video_engine/encoder_state_feedback.h +++ b/webrtc/video_engine/encoder_state_feedback.h @@ -15,6 +15,7 @@ #define WEBRTC_VIDEO_ENGINE_ENCODER_STATE_FEEDBACK_H_ #include +#include #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" @@ -34,6 +35,9 @@ class EncoderStateFeedback { EncoderStateFeedback(); ~EncoderStateFeedback(); + // Update SSRCs for an encoder. + void UpdateSsrcs(const std::vector& ssrc, ViEEncoder* encoder); + // Adds an encoder to receive feedback for a unique ssrc. bool AddEncoder(uint32_t ssrc, ViEEncoder* encoder); diff --git a/webrtc/video_engine/vie_channel_group.cc b/webrtc/video_engine/vie_channel_group.cc index f573ff1634..db61a84729 100644 --- a/webrtc/video_engine/vie_channel_group.cc +++ b/webrtc/video_engine/vie_channel_group.cc @@ -222,7 +222,7 @@ bool ChannelGroup::CreateSendChannel(int channel_id, int stream_idx = 0; channel->GetLocalSSRC(stream_idx, &ssrc); encoder_state_feedback_->AddEncoder(ssrc, encoder); - std::list ssrcs; + std::vector ssrcs; ssrcs.push_back(ssrc); encoder->SetSsrcs(ssrcs); return true; diff --git a/webrtc/video_engine/vie_codec_impl.cc b/webrtc/video_engine/vie_codec_impl.cc index 3d696812b7..d746c2cb56 100644 --- a/webrtc/video_engine/vie_codec_impl.cc +++ b/webrtc/video_engine/vie_codec_impl.cc @@ -241,7 +241,8 @@ int ViECodecImpl::SetSendCodec(const int video_channel, ssrcs.push_back(ssrc); } } - vie_encoder->SetSsrcs(ssrcs); + std::vector ssrc_vector(ssrcs.begin(), ssrcs.end()); + vie_encoder->SetSsrcs(ssrc_vector); shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs); // Update the protection mode, we might be switching NACK/FEC. diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index a08d4829d2..2e0fd231b1 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -767,7 +767,7 @@ void ViEEncoder::OnReceivedIntraFrameRequest(uint32_t ssrc) { int idx = 0; { CriticalSectionScoped cs(data_cs_.get()); - std::map::iterator stream_it = ssrc_streams_.find(ssrc); + auto stream_it = ssrc_streams_.find(ssrc); if (stream_it == ssrc_streams_.end()) { LOG_F(LS_WARNING) << "ssrc not found: " << ssrc << ", map size " << ssrc_streams_.size(); @@ -810,7 +810,7 @@ void ViEEncoder::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) { time_last_intra_request_ms_[new_ssrc] = last_intra_request_ms; } -bool ViEEncoder::SetSsrcs(const std::list& ssrcs) { +bool ViEEncoder::SetSsrcs(const std::vector& ssrcs) { VideoCodec codec; if (vcm_->SendCodec(&codec) != 0) return false; @@ -824,10 +824,8 @@ bool ViEEncoder::SetSsrcs(const std::list& ssrcs) { ssrc_streams_.clear(); time_last_intra_request_ms_.clear(); int idx = 0; - for (std::list::const_iterator it = ssrcs.begin(); - it != ssrcs.end(); ++it, ++idx) { - unsigned int ssrc = *it; - ssrc_streams_[ssrc] = idx; + for (uint32_t ssrc : ssrcs) { + ssrc_streams_[ssrc] = idx++; } return true; } diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h index 2909249712..27991e180e 100644 --- a/webrtc/video_engine/vie_encoder.h +++ b/webrtc/video_engine/vie_encoder.h @@ -11,7 +11,6 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_ENCODER_H_ #define WEBRTC_VIDEO_ENGINE_VIE_ENCODER_H_ -#include #include #include @@ -149,7 +148,7 @@ class ViEEncoder void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) override; // Sets SSRCs for all streams. - bool SetSsrcs(const std::list& ssrcs); + bool SetSsrcs(const std::vector& ssrcs); void SetMinTransmitBitrate(int min_transmit_bitrate_kbps); @@ -233,7 +232,7 @@ class ViEEncoder uint8_t picture_id_sli_ GUARDED_BY(data_cs_); bool has_received_rpsi_ GUARDED_BY(data_cs_); uint64_t picture_id_rpsi_ GUARDED_BY(data_cs_); - std::map ssrc_streams_ GUARDED_BY(data_cs_); + std::map ssrc_streams_ GUARDED_BY(data_cs_); bool video_suspended_ GUARDED_BY(data_cs_); I420FrameCallback* pre_encode_callback_ GUARDED_BY(callback_cs_);