Chromium Code Reviews| Index: webrtc/video/video_send_stream.cc |
| diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc |
| index 894117307091dcf4c4e1eb4629d0ca437332c104..9de92d1963784063fe4f058c3237060ecf16f137 100644 |
| --- a/webrtc/video/video_send_stream.cc |
| +++ b/webrtc/video/video_send_stream.cc |
| @@ -7,7 +7,6 @@ |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| - |
| #include "webrtc/video/video_send_stream.h" |
| #include <algorithm> |
| @@ -37,8 +36,6 @@ class RtcpIntraFrameObserver; |
| class TransportFeedbackObserver; |
| static const int kMinSendSidePacketHistorySize = 600; |
| -static const int kEncoderTimeOutMs = 2000; |
| - |
| namespace { |
| std::vector<RtpRtcp*> CreateRtpRtcpModules( |
| @@ -370,9 +367,202 @@ int CalulcateMaxPadBitrateBps(const VideoEncoderConfig& config, |
| } // namespace |
| namespace internal { |
| + |
| +class VideoSendStream::ConstructionTask : public rtc::QueuedTask { |
| + public: |
| + ConstructionTask(std::unique_ptr<VideoSendStreamInternal>* send_stream, |
|
tommi
2016/06/17 07:59:01
todo(tommi): see if there's a more elegant way to
perkj_webrtc
2016/06/27 14:34:35
Done.
|
| + rtc::Event* done_event, |
| + int num_cpu_cores, |
| + ProcessThread* module_process_thread, |
| + CallStats* call_stats, |
| + CongestionController* congestion_controller, |
| + BitrateAllocator* bitrate_allocator, |
| + SendDelayStats* send_delay_stats, |
| + VieRemb* remb, |
| + RtcEventLog* event_log, |
| + const VideoSendStream::Config& config, |
| + const VideoEncoderConfig& encoder_config, |
| + const std::map<uint32_t, RtpState>& suspended_ssrcs) |
| + : send_stream_(send_stream), |
| + done_event_(done_event), |
| + num_cpu_cores_(num_cpu_cores), |
| + call_stats_(call_stats), |
| + congestion_controller_(congestion_controller), |
| + bitrate_allocator_(bitrate_allocator), |
| + send_delay_stats_(send_delay_stats), |
| + remb_(remb), |
| + event_log_(event_log), |
| + config_(config), |
| + encoder_config_(encoder_config), |
| + suspended_ssrcs_(suspended_ssrcs) {} |
| + ~ConstructionTask() { done_event_->Set(); } |
| + |
| + bool Run() override { |
| + send_stream_->reset(new VideoSendStreamInternal( |
| + num_cpu_cores_, rtc::TaskQueue::Current(), call_stats_, |
| + congestion_controller_, bitrate_allocator_, send_delay_stats_, remb_, |
| + event_log_, config_, encoder_config_, suspended_ssrcs_)); |
| + return true; |
| + } |
| + |
| + private: |
| + std::unique_ptr<VideoSendStreamInternal>* send_stream_; |
| + rtc::Event* done_event_; |
| + const int num_cpu_cores_; |
| + CallStats* const call_stats_; |
| + CongestionController* const congestion_controller_; |
| + BitrateAllocator* const bitrate_allocator_; |
| + SendDelayStats* const send_delay_stats_; |
| + VieRemb* const remb_; |
| + RtcEventLog* const event_log_; |
| + const VideoSendStream::Config config_; |
| + const VideoEncoderConfig encoder_config_; |
| + const std::map<uint32_t, RtpState> suspended_ssrcs_; |
| +}; |
| + |
| +class VideoSendStream::DestructAndGetRTPStateTask : public rtc::QueuedTask { |
| + public: |
| + DestructAndGetRTPStateTask( |
| + VideoSendStream::RtpStateMap* state_map, |
| + std::unique_ptr<VideoSendStreamInternal> send_stream, |
| + rtc::Event* done_event) |
| + : state_map_(state_map), |
| + send_stream_(std::move(send_stream)), |
| + done_event_(done_event) {} |
| + ~DestructAndGetRTPStateTask() { |
| + send_stream_.reset(); |
| + done_event_->Set(); |
| + } |
| + |
| + bool Run() override { |
| + send_stream_->Stop(); |
| + *state_map_ = send_stream_->GetRtpStates(); |
| + send_stream_.reset(); |
| + return true; |
| + } |
| + |
| + private: |
| + VideoSendStream::RtpStateMap* state_map_; |
| + std::unique_ptr<VideoSendStreamInternal> send_stream_; |
| + rtc::Event* done_event_; |
| +}; |
| + |
| +class VideoSendStreamInternal::CheckEncoderActivityTask |
| + : public rtc::QueuedTask { |
| + public: |
| + static const int kEncoderTimeOutMs = 2000; |
| + explicit CheckEncoderActivityTask(VideoSendStreamInternal* send_stream) |
| + : send_stream_(send_stream) {} |
| + |
| + void Stop() { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + send_stream_ = nullptr; |
| + } |
| + |
| + private: |
| + bool Run() override { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + if (!send_stream_) |
| + return true; |
| + send_stream_->CheckEncoderActivity(); |
| + rtc::TaskQueue::Current()->PostDelayedTask( |
| + std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs); |
| + // Return false to prevent this task from being deleted. Ownership has been |
| + // transferred to the task queue when PostDelayedTask was called. |
| + return false; |
| + } |
| + rtc::ThreadChecker thread_checker_; |
| + VideoSendStreamInternal* send_stream_; |
| +}; |
| + |
| VideoSendStream::VideoSendStream( |
| int num_cpu_cores, |
| ProcessThread* module_process_thread, |
| + rtc::TaskQueue* worker_queu, |
| + CallStats* call_stats, |
| + CongestionController* congestion_controller, |
| + BitrateAllocator* bitrate_allocator, |
| + SendDelayStats* send_delay_stats, |
| + VieRemb* remb, |
| + RtcEventLog* event_log, |
| + const VideoSendStream::Config& config, |
| + const VideoEncoderConfig& encoder_config, |
| + const std::map<uint32_t, RtpState>& suspended_ssrcs) |
| + : worker_queu_(worker_queu), |
| + thread_sync_event_(false /* manual_reset */, false) { |
| + worker_queu_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask( |
| + &send_stream_, &thread_sync_event_, num_cpu_cores, module_process_thread, |
| + call_stats, congestion_controller, bitrate_allocator, send_delay_stats, |
| + remb, event_log, config, encoder_config, suspended_ssrcs))); |
| + |
| + // Wait for |construction_task| to complete so that |module_process_thread| |
| + // can be registered. |
| + thread_sync_event_.Wait(rtc::Event::kForever); |
| + // |send_stream_| can be null if |worker_queu_| is destroyed before the |
| + // ConstructionTask runs. |
| + if (send_stream_) |
| + send_stream_->RegisterProcessThread(module_process_thread); |
| +} |
| + |
| +VideoSendStream::~VideoSendStream() { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + LOG(LS_INFO) << "~VideoSendStream: "; |
| + RTC_DCHECK(!send_stream_); |
| +} |
| + |
| +void VideoSendStream::Start() { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + VideoSendStreamInternal* send_stream = send_stream_.get(); |
| + worker_queu_->PostTask([send_stream] { send_stream->Start(); }); |
| +} |
| + |
| +void VideoSendStream::Stop() { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + VideoSendStreamInternal* send_stream = send_stream_.get(); |
| + worker_queu_->PostTask([send_stream] { send_stream->Stop(); }); |
| +} |
| + |
| +VideoCaptureInput* VideoSendStream::Input() { |
| + return send_stream_->Input(); |
| +} |
| + |
| +void VideoSendStream::ReconfigureVideoEncoder( |
| + const VideoEncoderConfig& config) { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + VideoSendStreamInternal* send_stream = send_stream_.get(); |
| + worker_queu_->PostTask( |
| + [send_stream, config] { send_stream->ReconfigureVideoEncoder(config); }); |
| +} |
| + |
| +VideoSendStream::Stats VideoSendStream::GetStats() { |
| + return send_stream_->GetStats(); |
|
tommi
2016/06/17 07:59:01
what thread are we on here?
perkj_webrtc
2016/06/27 14:34:35
Added comments.
|
| +} |
| + |
| +void VideoSendStream::SignalNetworkState(NetworkState state) { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + VideoSendStreamInternal* send_stream = send_stream_.get(); |
| + worker_queu_->PostTask( |
| + [send_stream, state] { send_stream->SignalNetworkState(state); }); |
| +} |
| + |
| +VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() { |
| + RTC_DCHECK_RUN_ON(&thread_checker_); |
| + VideoSendStream::RtpStateMap state_map; |
| + send_stream_->DeRegisterProcessThread(); |
| + worker_queu_->PostTask( |
| + std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRTPStateTask( |
| + &state_map, std::move(send_stream_), &thread_sync_event_))); |
| + thread_sync_event_.Wait(rtc::Event::kForever); |
| + return state_map; |
| +} |
| + |
| +bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
| + return send_stream_->DeliverRtcp(packet, length); |
|
tommi
2016/06/17 07:59:01
and here?
perkj_webrtc
2016/06/27 14:34:35
added comment.
|
| +} |
| + |
| +VideoSendStreamInternal::VideoSendStreamInternal( |
| + int num_cpu_cores, |
| + rtc::TaskQueue* worker_queu, |
| CallStats* call_stats, |
| CongestionController* congestion_controller, |
| BitrateAllocator* bitrate_allocator, |
| @@ -388,7 +578,9 @@ VideoSendStream::VideoSendStream( |
| encoded_frame_proxy_(config.post_encode_callback), |
| config_(config), |
| suspended_ssrcs_(suspended_ssrcs), |
| - module_process_thread_(module_process_thread), |
| + module_process_thread_(nullptr), |
| + worker_queu_(worker_queu), |
| + check_encoder_activity_task_(nullptr), |
| call_stats_(call_stats), |
| congestion_controller_(congestion_controller), |
| bitrate_allocator_(bitrate_allocator), |
| @@ -397,17 +589,16 @@ VideoSendStream::VideoSendStream( |
| encoder_wakeup_event_(false, false), |
| stop_encoder_thread_(0), |
| send_stream_registered_as_observer_(false), |
| + max_padding_bitrate_(0), |
| + time_of_last_frame_activity_ms_(0), |
| + last_set_encoder_bitrate_bps_(0), |
| overuse_detector_( |
| Clock::GetRealTimeClock(), |
| GetCpuOveruseOptions(config.encoder_settings.full_overuse_time), |
| this, |
| config.post_encode_callback, |
| &stats_proxy_), |
| - vie_encoder_(num_cpu_cores, |
| - module_process_thread_, |
| - &stats_proxy_, |
| - &overuse_detector_, |
| - this), |
| + vie_encoder_(num_cpu_cores, &stats_proxy_, &overuse_detector_, this), |
| encoder_feedback_(Clock::GetRealTimeClock(), |
| config.rtp.ssrcs, |
| &vie_encoder_), |
| @@ -432,18 +623,17 @@ VideoSendStream::VideoSendStream( |
| config_.local_renderer, |
| &stats_proxy_, |
| &overuse_detector_) { |
| - LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| + LOG(LS_INFO) << "VideoSendStreamInternal: " << config_.ToString(); |
| + module_process_thread_checker_.DetachFromThread(); |
| RTC_DCHECK(!config_.rtp.ssrcs.empty()); |
| - RTC_DCHECK(module_process_thread_); |
| RTC_DCHECK(call_stats_); |
| RTC_DCHECK(congestion_controller_); |
| RTC_DCHECK(remb_); |
| - |
| // RTP/RTCP initialization. |
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| - module_process_thread_->RegisterModule(rtp_rtcp); |
| congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp); |
| } |
| @@ -487,45 +677,70 @@ VideoSendStream::VideoSendStream( |
| RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
| ReconfigureVideoEncoder(encoder_config); |
| - module_process_thread_->RegisterModule(&overuse_detector_); |
| - |
| encoder_thread_.Start(); |
| encoder_thread_.SetPriority(rtc::kHighPriority); |
| + |
| + std::unique_ptr<CheckEncoderActivityTask> check_encoder_activity_task( |
| + new CheckEncoderActivityTask(this)); |
| + check_encoder_activity_task_ = new CheckEncoderActivityTask(this); |
| + worker_queu_->PostDelayedTask( |
| + std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_), |
| + CheckEncoderActivityTask::kEncoderTimeOutMs); |
| } |
| -VideoSendStream::~VideoSendStream() { |
| - LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
| +void VideoSendStreamInternal::RegisterProcessThread( |
| + ProcessThread* module_process_thread) { |
| + RTC_DCHECK_RUN_ON(&module_process_thread_checker_); |
| + RTC_DCHECK(!module_process_thread_); |
| + module_process_thread_ = module_process_thread; |
| - Stop(); |
| + for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| + module_process_thread_->RegisterModule(rtp_rtcp); |
| + } |
| + module_process_thread_->RegisterModule(&overuse_detector_); |
| + vie_encoder_.RegisterProcessThread(module_process_thread); |
| +} |
| + |
| +void VideoSendStreamInternal::DeRegisterProcessThread() { |
| + RTC_DCHECK_RUN_ON(&module_process_thread_checker_); |
| + module_process_thread_->DeRegisterModule(&overuse_detector_); |
| + for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| + module_process_thread_->DeRegisterModule(rtp_rtcp); |
| + } |
| + vie_encoder_.DeRegisterProcessThread(); |
| +} |
| + |
| +VideoSendStreamInternal::~VideoSendStreamInternal() { |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| + LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_.ToString(); |
| // Stop the encoder thread permanently. |
| rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); |
| encoder_wakeup_event_.Set(); |
| encoder_thread_.Stop(); |
| - // This needs to happen after stopping the encoder thread, |
| - // since the encoder thread calls AddObserver. |
| bitrate_allocator_->RemoveObserver(this); |
| - module_process_thread_->DeRegisterModule(&overuse_detector_); |
| - |
| rtp_rtcp_modules_[0]->SetREMBStatus(false); |
| remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp); |
| - module_process_thread_->DeRegisterModule(rtp_rtcp); |
| delete rtp_rtcp; |
| } |
| + check_encoder_activity_task_->Stop(); |
| + LOG(LS_INFO) << "~VideoSendStreamInternal: done"; |
| } |
| -bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
| +bool VideoSendStreamInternal::DeliverRtcp(const uint8_t* packet, |
| + size_t length) { |
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
| rtp_rtcp->IncomingRtcpPacket(packet, length); |
| return true; |
| } |
| -void VideoSendStream::Start() { |
| +void VideoSendStreamInternal::Start() { |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| if (payload_router_.active()) |
| return; |
| TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start"); |
| @@ -535,7 +750,8 @@ void VideoSendStream::Start() { |
| vie_encoder_.Start(); |
| } |
| -void VideoSendStream::Stop() { |
| +void VideoSendStreamInternal::Stop() { |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| if (!payload_router_.active()) |
| return; |
| TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop"); |
| @@ -543,70 +759,38 @@ void VideoSendStream::Stop() { |
| payload_router_.set_active(false); |
| } |
| -VideoCaptureInput* VideoSendStream::Input() { |
| +VideoCaptureInput* VideoSendStreamInternal::Input() { |
| return &input_; |
| } |
| -bool VideoSendStream::EncoderThreadFunction(void* obj) { |
| - static_cast<VideoSendStream*>(obj)->EncoderProcess(); |
| +bool VideoSendStreamInternal::EncoderThreadFunction(void* obj) { |
| + static_cast<VideoSendStreamInternal*>(obj)->EncoderProcess(); |
| // We're done, return false to abort. |
| return false; |
| } |
| -void VideoSendStream::EncoderProcess() { |
| +void VideoSendStreamInternal::EncoderProcess() { |
| RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( |
| config_.encoder_settings.encoder, |
| config_.encoder_settings.payload_type, |
| config_.encoder_settings.internal_source)); |
| while (true) { |
| - // Wake up every kEncodeCheckForActivityPeriodMs to check if the encoder is |
| - // active. If not, deregister as BitrateAllocatorObserver. |
| - const int kEncodeCheckForActivityPeriodMs = 1000; |
| - encoder_wakeup_event_.Wait(kEncodeCheckForActivityPeriodMs); |
| + encoder_wakeup_event_.Wait(rtc::Event::kForever); |
| if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) |
| break; |
| - bool change_settings = false; |
| + std::unique_ptr<VideoCodec> pending_encoder_settings; |
| { |
| rtc::CritScope lock(&encoder_settings_crit_); |
| if (pending_encoder_settings_) { |
| - std::swap(current_encoder_settings_, pending_encoder_settings_); |
| + pending_encoder_settings = std::move(pending_encoder_settings_); |
| pending_encoder_settings_.reset(); |
| - change_settings = true; |
| } |
| } |
| - if (change_settings) { |
| - current_encoder_settings_->video_codec.startBitrate = |
| - bitrate_allocator_->AddObserver( |
| - this, current_encoder_settings_->video_codec.minBitrate * 1000, |
| - current_encoder_settings_->video_codec.maxBitrate * 1000, |
| - CalulcateMaxPadBitrateBps(current_encoder_settings_->config, |
| - config_.suspend_below_min_bitrate), |
| - !config_.suspend_below_min_bitrate) / |
| - 1000; |
| - send_stream_registered_as_observer_ = true; |
| - |
| - payload_router_.SetSendStreams(current_encoder_settings_->config.streams); |
| - vie_encoder_.SetEncoder(current_encoder_settings_->video_codec, |
| + if (pending_encoder_settings) { |
| + vie_encoder_.SetEncoder(*pending_encoder_settings, |
| payload_router_.MaxPayloadLength()); |
| - // Clear stats for disabled layers. |
| - for (size_t i = current_encoder_settings_->config.streams.size(); |
| - i < config_.rtp.ssrcs.size(); ++i) { |
| - stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]); |
| - } |
| - |
| - size_t number_of_temporal_layers = |
| - current_encoder_settings_->config.streams.back() |
| - .temporal_layer_thresholds_bps.size() + |
| - 1; |
| - protection_bitrate_calculator_.SetEncodingData( |
| - current_encoder_settings_->video_codec.startBitrate * 1000, |
| - current_encoder_settings_->video_codec.width, |
| - current_encoder_settings_->video_codec.height, |
| - current_encoder_settings_->video_codec.maxFramerate, |
| - number_of_temporal_layers, payload_router_.MaxPayloadLength()); |
| - |
| // We might've gotten new settings while configuring the encoder settings, |
| // restart from the top to see if that's the case before trying to encode |
| // a frame (which might correspond to the last frame size). |
| @@ -623,65 +807,107 @@ void VideoSendStream::EncoderProcess() { |
| } |
| vie_encoder_.EncodeVideoFrame(frame); |
| } |
| - |
| - // Check if the encoder has produced anything the last kEncoderTimeOutMs. |
| - // If not, deregister as BitrateAllocatorObserver. |
| - if (send_stream_registered_as_observer_ && |
| - vie_encoder_.time_of_last_frame_activity_ms() < |
| - rtc::TimeMillis() - kEncoderTimeOutMs) { |
| - // The encoder has timed out. |
| - LOG_F(LS_INFO) << "Encoder timed out."; |
| - bitrate_allocator_->RemoveObserver(this); |
| - send_stream_registered_as_observer_ = false; |
| - } |
| - if (!send_stream_registered_as_observer_ && |
| - vie_encoder_.time_of_last_frame_activity_ms() > |
| - rtc::TimeMillis() - kEncoderTimeOutMs) { |
| - LOG_F(LS_INFO) << "Encoder is active."; |
| - bitrate_allocator_->AddObserver( |
| - this, current_encoder_settings_->video_codec.minBitrate * 1000, |
| - current_encoder_settings_->video_codec.maxBitrate * 1000, |
| - CalulcateMaxPadBitrateBps(current_encoder_settings_->config, |
| - config_.suspend_below_min_bitrate), |
| - !config_.suspend_below_min_bitrate); |
| - send_stream_registered_as_observer_ = true; |
| - } |
| } |
| vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
| } |
| -void VideoSendStream::ReconfigureVideoEncoder( |
| +void VideoSendStreamInternal::CheckEncoderActivity() { |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| + |
| + int64_t time_of_last_frame_activity_ms; |
| + { |
| + rtc::CritScope lock(&encoder_settings_crit_); |
| + time_of_last_frame_activity_ms = time_of_last_frame_activity_ms_; |
| + } |
| + // If the encoder has not produced anything the last kEncoderTimeOutMs and it |
| + // is supposed to, deregister as BitrateAllocatorObserver. This can happen |
| + // if a camera stop producing frames, temporary or permantently during a call. |
| + if (send_stream_registered_as_observer_ && |
| + last_set_encoder_bitrate_bps_ > 0 && |
| + time_of_last_frame_activity_ms < |
| + rtc::TimeMillis() - CheckEncoderActivityTask::kEncoderTimeOutMs) { |
| + // The encoder has timed out. |
| + LOG(LS_INFO) << "Encoder timed out."; |
| + bitrate_allocator_->RemoveObserver(this); |
| + send_stream_registered_as_observer_ = false; |
| + } |
| + if (!send_stream_registered_as_observer_ && |
| + time_of_last_frame_activity_ms > |
| + rtc::TimeMillis() - CheckEncoderActivityTask::kEncoderTimeOutMs) { |
| + LOG(LS_INFO) << "Encoder is active."; |
| + bitrate_allocator_->AddObserver( |
| + this, current_video_codec_.minBitrate * 1000, |
| + current_video_codec_.maxBitrate * 1000, max_padding_bitrate_, |
| + !config_.suspend_below_min_bitrate); |
| + send_stream_registered_as_observer_ = true; |
| + } |
| +} |
| + |
| +void VideoSendStreamInternal::ReconfigureVideoEncoder( |
| const VideoEncoderConfig& config) { |
| + RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size()); |
| TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); |
| LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); |
| RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size()); |
| - VideoCodec video_codec = VideoEncoderConfigToVideoCodec( |
| + RTC_DCHECK_RUN_ON(worker_queu_); |
| + |
| + current_video_codec_ = VideoEncoderConfigToVideoCodec( |
| config, config_.encoder_settings.payload_name, |
| config_.encoder_settings.payload_type); |
| + |
| + max_padding_bitrate_ = |
| + CalulcateMaxPadBitrateBps(config, config_.suspend_below_min_bitrate); |
| + current_video_codec_.startBitrate = |
| + bitrate_allocator_->AddObserver( |
| + this, current_video_codec_.minBitrate * 1000, |
| + current_video_codec_.maxBitrate * 1000, max_padding_bitrate_, |
| + !config_.suspend_below_min_bitrate) / |
| + 1000; |
| + send_stream_registered_as_observer_ = true; |
| + |
| + payload_router_.SetSendStreams(config.streams); |
| + |
| + // Clear stats for disabled layers. |
| + for (size_t i = config.streams.size(); i < config_.rtp.ssrcs.size(); ++i) { |
| + stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]); |
| + } |
| + |
| + size_t number_of_temporal_layers = |
| + config.streams.back().temporal_layer_thresholds_bps.size() + 1; |
| + protection_bitrate_calculator_.SetEncodingData( |
| + current_video_codec_.startBitrate * 1000, current_video_codec_.width, |
| + current_video_codec_.height, current_video_codec_.maxFramerate, |
| + number_of_temporal_layers, payload_router_.MaxPayloadLength()); |
| + |
| { |
| rtc::CritScope lock(&encoder_settings_crit_); |
| - pending_encoder_settings_.reset(new EncoderSettings({video_codec, config})); |
| + pending_encoder_settings_.reset(new VideoCodec(current_video_codec_)); |
| } |
| encoder_wakeup_event_.Set(); |
| } |
| -VideoSendStream::Stats VideoSendStream::GetStats() { |
| +VideoSendStream::Stats VideoSendStreamInternal::GetStats() { |
| return stats_proxy_.GetStats(); |
| } |
| -void VideoSendStream::OveruseDetected() { |
| +void VideoSendStreamInternal::OveruseDetected() { |
| if (config_.overuse_callback) |
| config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); |
| } |
| -void VideoSendStream::NormalUsage() { |
| +void VideoSendStreamInternal::NormalUsage() { |
| if (config_.overuse_callback) |
| config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); |
| } |
| -int32_t VideoSendStream::Encoded(const EncodedImage& encoded_image, |
| - const CodecSpecificInfo* codec_specific_info, |
| - const RTPFragmentationHeader* fragmentation) { |
| +int32_t VideoSendStreamInternal::Encoded( |
| + const EncodedImage& encoded_image, |
| + const CodecSpecificInfo* codec_specific_info, |
| + const RTPFragmentationHeader* fragmentation) { |
| + { |
| + rtc::CritScope lock(&encoder_settings_crit_); |
| + time_of_last_frame_activity_ms_ = rtc::TimeMillis(); |
| + } |
| // |encoded_frame_proxy_| forwards frames to |config_.post_encode_callback|; |
| encoded_frame_proxy_.Encoded(encoded_image, codec_specific_info, |
| fragmentation); |
| @@ -715,7 +941,7 @@ int32_t VideoSendStream::Encoded(const EncodedImage& encoded_image, |
| return return_value; |
| } |
| -void VideoSendStream::ConfigureProtection() { |
| +void VideoSendStreamInternal::ConfigureProtection() { |
| // Enable NACK, FEC or both. |
| const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; |
| bool enable_protection_fec = config_.rtp.fec.ulpfec_payload_type != -1; |
| @@ -772,7 +998,7 @@ void VideoSendStream::ConfigureProtection() { |
| enable_protection_nack); |
| } |
| -void VideoSendStream::ConfigureSsrcs() { |
| +void VideoSendStreamInternal::ConfigureSsrcs() { |
| // Configure regular SSRCs. |
| for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| uint32_t ssrc = config_.rtp.ssrcs[i]; |
| @@ -780,7 +1006,7 @@ void VideoSendStream::ConfigureSsrcs() { |
| rtp_rtcp->SetSSRC(ssrc); |
| // Restore RTP state if previous existed. |
| - RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| + VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| if (it != suspended_ssrcs_.end()) |
| rtp_rtcp->SetRtpState(it->second); |
| } |
| @@ -795,7 +1021,7 @@ void VideoSendStream::ConfigureSsrcs() { |
| uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
| RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
| rtp_rtcp->SetRtxSsrc(ssrc); |
| - RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| + VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| if (it != suspended_ssrcs_.end()) |
| rtp_rtcp->SetRtxState(it->second); |
| } |
| @@ -816,7 +1042,7 @@ void VideoSendStream::ConfigureSsrcs() { |
| } |
| } |
| -std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
| +std::map<uint32_t, RtpState> VideoSendStreamInternal::GetRtpStates() const { |
| std::map<uint32_t, RtpState> rtp_states; |
| for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| uint32_t ssrc = config_.rtp.ssrcs[i]; |
| @@ -832,30 +1058,32 @@ std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
| return rtp_states; |
| } |
| -void VideoSendStream::SignalNetworkState(NetworkState state) { |
| +void VideoSendStreamInternal::SignalNetworkState(NetworkState state) { |
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode |
| : RtcpMode::kOff); |
| } |
| } |
| -void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, |
| - uint8_t fraction_loss, |
| - int64_t rtt) { |
| +void VideoSendStreamInternal::OnBitrateUpdated(uint32_t bitrate_bps, |
| + uint8_t fraction_loss, |
| + int64_t rtt) { |
| payload_router_.SetTargetSendBitrate(bitrate_bps); |
| // Get the encoder target rate. It is the estimated network rate - |
| // protection overhead. |
| uint32_t encoder_target_rate = protection_bitrate_calculator_.SetTargetRates( |
| bitrate_bps, stats_proxy_.GetSendFrameRate(), fraction_loss, rtt); |
| + last_set_encoder_bitrate_bps_ = encoder_target_rate; |
| vie_encoder_.OnBitrateUpdated(encoder_target_rate, fraction_loss, rtt); |
| } |
| -int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params, |
| - const FecProtectionParams* key_params, |
| - uint32_t* sent_video_rate_bps, |
| - uint32_t* sent_nack_rate_bps, |
| - uint32_t* sent_fec_rate_bps) { |
| +int VideoSendStreamInternal::ProtectionRequest( |
| + const FecProtectionParams* delta_params, |
| + const FecProtectionParams* key_params, |
| + uint32_t* sent_video_rate_bps, |
| + uint32_t* sent_nack_rate_bps, |
| + uint32_t* sent_fec_rate_bps) { |
| *sent_video_rate_bps = 0; |
| *sent_nack_rate_bps = 0; |
| *sent_fec_rate_bps = 0; |