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; |