Combine video_send_stream_impl.cc and video_send_stream.cc
There is to reason to have two separate classes as they both represent the same thing.
Done in order to simplify further refactorings.
Bug: webrtc:14928
Change-Id: I33e5fe032c79396fbae970c8732c90eb2252accb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335040
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41561}
diff --git a/call/call.cc b/call/call.cc
index 7b1e3c4..c97cb6d 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -70,7 +70,7 @@
#include "video/send_delay_stats.h"
#include "video/stats_counter.h"
#include "video/video_receive_stream2.h"
-#include "video/video_send_stream.h"
+#include "video/video_send_stream_impl.h"
namespace webrtc {
@@ -388,9 +388,10 @@
// should be accessed on the network thread.
std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_
RTC_GUARDED_BY(worker_thread_);
- std::map<uint32_t, VideoSendStream*> video_send_ssrcs_
+ std::map<uint32_t, VideoSendStreamImpl*> video_send_ssrcs_
RTC_GUARDED_BY(worker_thread_);
- std::set<VideoSendStream*> video_send_streams_ RTC_GUARDED_BY(worker_thread_);
+ std::set<VideoSendStreamImpl*> video_send_streams_
+ RTC_GUARDED_BY(worker_thread_);
// True if `video_send_streams_` is empty, false if not. The atomic variable
// is used to decide UMA send statistics behavior and enables avoiding a
// PostTask().
@@ -886,9 +887,9 @@
// Copy ssrcs from `config` since `config` is moved.
std::vector<uint32_t> ssrcs = config.rtp.ssrcs;
- VideoSendStream* send_stream = new VideoSendStream(
+ VideoSendStreamImpl* send_stream = new VideoSendStreamImpl(
&env_.clock(), num_cpu_cores_, &env_.task_queue_factory(),
- network_thread_, call_stats_->AsRtcpRttStats(), transport_send_.get(),
+ call_stats_->AsRtcpRttStats(), transport_send_.get(),
config_.encode_metronome, bitrate_allocator_.get(),
video_send_delay_stats_.get(), &env_.event_log(), std::move(config),
std::move(encoder_config), suspended_video_send_ssrcs_,
@@ -932,12 +933,12 @@
RTC_DCHECK(send_stream != nullptr);
RTC_DCHECK_RUN_ON(worker_thread_);
- VideoSendStream* send_stream_impl =
- static_cast<VideoSendStream*>(send_stream);
+ VideoSendStreamImpl* send_stream_impl =
+ static_cast<VideoSendStreamImpl*>(send_stream);
auto it = video_send_ssrcs_.begin();
while (it != video_send_ssrcs_.end()) {
- if (it->second == static_cast<VideoSendStream*>(send_stream)) {
+ if (it->second == static_cast<VideoSendStreamImpl*>(send_stream)) {
send_stream_impl = it->second;
video_send_ssrcs_.erase(it++);
} else {
@@ -953,8 +954,8 @@
if (video_send_streams_.empty())
video_send_streams_empty_.store(true, std::memory_order_relaxed);
- VideoSendStream::RtpStateMap rtp_states;
- VideoSendStream::RtpPayloadStateMap rtp_payload_states;
+ VideoSendStreamImpl::RtpStateMap rtp_states;
+ VideoSendStreamImpl::RtpPayloadStateMap rtp_payload_states;
send_stream_impl->StopPermanentlyAndGetRtpStates(&rtp_states,
&rtp_payload_states);
for (const auto& kv : rtp_states) {
@@ -1334,7 +1335,7 @@
rtcp_delivered = true;
}
- for (VideoSendStream* stream : video_send_streams_) {
+ for (VideoSendStreamImpl* stream : video_send_streams_) {
stream->DeliverRtcp(packet.cdata(), packet.size());
rtcp_delivered = true;
}
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 3512275..78c7804 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -65,8 +65,6 @@
"video_quality_observer2.h",
"video_receive_stream2.cc",
"video_receive_stream2.h",
- "video_send_stream.cc",
- "video_send_stream.h",
"video_send_stream_impl.cc",
"video_send_stream_impl.h",
"video_stream_decoder2.cc",
@@ -82,13 +80,16 @@
":video_stream_encoder_impl",
":video_stream_encoder_interface",
"../api:array_view",
+ "../api:bitrate_allocation",
"../api:fec_controller_api",
"../api:field_trials_view",
"../api:frame_transformer_interface",
"../api:rtp_parameters",
+ "../api:rtp_sender_interface",
"../api:scoped_refptr",
"../api:sequence_checker",
"../api:transport_api",
+ "../api/adaptation:resource_adaptation_api",
"../api/crypto:frame_decryptor_interface",
"../api/crypto:options",
"../api/environment",
@@ -105,6 +106,8 @@
"../api/video:video_bitrate_allocator",
"../api/video:video_codec_constants",
"../api/video:video_frame",
+ "../api/video:video_frame_type",
+ "../api/video:video_layers_allocation",
"../api/video:video_rtp_headers",
"../api/video:video_stream_encoder",
"../api/video_codecs:video_codecs_api",
@@ -818,6 +821,8 @@
":video_stream_buffer_controller",
":video_stream_encoder_impl",
":video_stream_encoder_interface",
+ "../api:array_view",
+ "../api:bitrate_allocation",
"../api:create_frame_generator",
"../api:fake_frame_decryptor",
"../api:fake_frame_encryptor",
@@ -837,6 +842,7 @@
"../api:time_controller",
"../api:transport_api",
"../api/adaptation:resource_adaptation_api",
+ "../api/adaptation:resource_adaptation_api",
"../api/crypto:options",
"../api/environment",
"../api/environment:environment_factory",
@@ -858,11 +864,13 @@
"../api/video:video_bitrate_allocation",
"../api/video:video_frame",
"../api/video:video_frame_type",
+ "../api/video:video_layers_allocation",
"../api/video:video_rtp_headers",
"../api/video/test:video_frame_matchers",
"../api/video_codecs:scalability_mode",
"../api/video_codecs:video_codecs_api",
"../api/video_codecs:vp8_temporal_layers_factory",
+ "../call:bitrate_allocator",
"../call:call_interfaces",
"../call:fake_network",
"../call:mock_bitrate_allocator",
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
deleted file mode 100644
index f336a61..0000000
--- a/video/video_send_stream.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include "video/video_send_stream.h"
-
-#include <utility>
-
-#include "api/array_view.h"
-#include "api/task_queue/task_queue_base.h"
-#include "api/video/video_stream_encoder_settings.h"
-#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
-#include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
-#include "modules/rtp_rtcp/source/rtp_sender.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/strings/string_builder.h"
-#include "system_wrappers/include/clock.h"
-#include "video/adaptation/overuse_frame_detector.h"
-#include "video/frame_cadence_adapter.h"
-#include "video/video_stream_encoder.h"
-
-namespace webrtc {
-
-namespace {
-
-size_t CalculateMaxHeaderSize(const RtpConfig& config) {
- size_t header_size = kRtpHeaderSize;
- size_t extensions_size = 0;
- size_t fec_extensions_size = 0;
- if (!config.extensions.empty()) {
- RtpHeaderExtensionMap extensions_map(config.extensions);
- extensions_size = RtpHeaderExtensionSize(RTPSender::VideoExtensionSizes(),
- extensions_map);
- fec_extensions_size =
- RtpHeaderExtensionSize(RTPSender::FecExtensionSizes(), extensions_map);
- }
- header_size += extensions_size;
- if (config.flexfec.payload_type >= 0) {
- // All FEC extensions again plus maximum FlexFec overhead.
- header_size += fec_extensions_size + 32;
- } else {
- if (config.ulpfec.ulpfec_payload_type >= 0) {
- // Header with all the FEC extensions will be repeated plus maximum
- // UlpFec overhead.
- header_size += fec_extensions_size + 18;
- }
- if (config.ulpfec.red_payload_type >= 0) {
- header_size += 1; // RED header.
- }
- }
- // Additional room for Rtx.
- if (config.rtx.payload_type >= 0)
- header_size += kRtxHeaderSize;
- return header_size;
-}
-
-VideoStreamEncoder::BitrateAllocationCallbackType
-GetBitrateAllocationCallbackType(const VideoSendStream::Config& config,
- const FieldTrialsView& field_trials) {
- if (webrtc::RtpExtension::FindHeaderExtensionByUri(
- config.rtp.extensions,
- webrtc::RtpExtension::kVideoLayersAllocationUri,
- config.crypto_options.srtp.enable_encrypted_rtp_header_extensions
- ? RtpExtension::Filter::kPreferEncryptedExtension
- : RtpExtension::Filter::kDiscardEncryptedExtension)) {
- return VideoStreamEncoder::BitrateAllocationCallbackType::
- kVideoLayersAllocation;
- }
- if (field_trials.IsEnabled("WebRTC-Target-Bitrate-Rtcp")) {
- return VideoStreamEncoder::BitrateAllocationCallbackType::
- kVideoBitrateAllocation;
- }
- return VideoStreamEncoder::BitrateAllocationCallbackType::
- kVideoBitrateAllocationWhenScreenSharing;
-}
-
-RtpSenderFrameEncryptionConfig CreateFrameEncryptionConfig(
- const VideoSendStream::Config* config) {
- RtpSenderFrameEncryptionConfig frame_encryption_config;
- frame_encryption_config.frame_encryptor = config->frame_encryptor.get();
- frame_encryption_config.crypto_options = config->crypto_options;
- return frame_encryption_config;
-}
-
-RtpSenderObservers CreateObservers(RtcpRttStats* call_stats,
- EncoderRtcpFeedback* encoder_feedback,
- SendStatisticsProxy* stats_proxy,
- SendPacketObserver* send_packet_observer) {
- RtpSenderObservers observers;
- observers.rtcp_rtt_stats = call_stats;
- observers.intra_frame_callback = encoder_feedback;
- observers.rtcp_loss_notification_observer = encoder_feedback;
- observers.report_block_data_observer = stats_proxy;
- observers.rtp_stats = stats_proxy;
- observers.bitrate_observer = stats_proxy;
- observers.frame_count_observer = stats_proxy;
- observers.rtcp_type_observer = stats_proxy;
- observers.send_packet_observer = send_packet_observer;
- return observers;
-}
-
-std::unique_ptr<VideoStreamEncoder> CreateVideoStreamEncoder(
- Clock* clock,
- int num_cpu_cores,
- TaskQueueFactory* task_queue_factory,
- SendStatisticsProxy* stats_proxy,
- const VideoStreamEncoderSettings& encoder_settings,
- VideoStreamEncoder::BitrateAllocationCallbackType
- bitrate_allocation_callback_type,
- const FieldTrialsView& field_trials,
- Metronome* metronome,
- webrtc::VideoEncoderFactory::EncoderSelectorInterface* encoder_selector) {
- std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue =
- task_queue_factory->CreateTaskQueue("EncoderQueue",
- TaskQueueFactory::Priority::NORMAL);
- TaskQueueBase* encoder_queue_ptr = encoder_queue.get();
- return std::make_unique<VideoStreamEncoder>(
- clock, num_cpu_cores, stats_proxy, encoder_settings,
- std::make_unique<OveruseFrameDetector>(stats_proxy),
- FrameCadenceAdapterInterface::Create(
- clock, encoder_queue_ptr, metronome,
- /*worker_queue=*/TaskQueueBase::Current(), field_trials),
- std::move(encoder_queue), bitrate_allocation_callback_type, field_trials,
- encoder_selector);
-}
-
-} // namespace
-
-namespace internal {
-
-VideoSendStream::VideoSendStream(
- Clock* clock,
- int num_cpu_cores,
- TaskQueueFactory* task_queue_factory,
- TaskQueueBase* network_queue,
- RtcpRttStats* call_stats,
- RtpTransportControllerSendInterface* transport,
- Metronome* metronome,
- BitrateAllocatorInterface* bitrate_allocator,
- SendDelayStats* send_delay_stats,
- RtcEventLog* event_log,
- VideoSendStream::Config config,
- VideoEncoderConfig encoder_config,
- const std::map<uint32_t, RtpState>& suspended_ssrcs,
- const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
- std::unique_ptr<FecController> fec_controller,
- const FieldTrialsView& field_trials)
- : transport_(transport),
- stats_proxy_(clock, config, encoder_config.content_type, field_trials),
- send_packet_observer_(&stats_proxy_, send_delay_stats),
- config_(std::move(config)),
- content_type_(encoder_config.content_type),
- video_stream_encoder_(CreateVideoStreamEncoder(
- clock,
- num_cpu_cores,
- task_queue_factory,
- &stats_proxy_,
- config_.encoder_settings,
- GetBitrateAllocationCallbackType(config_, field_trials),
- field_trials,
- metronome,
- config_.encoder_selector)),
- encoder_feedback_(
- clock,
- config_.rtp.ssrcs,
- video_stream_encoder_.get(),
- [this](uint32_t ssrc, const std::vector<uint16_t>& seq_nums) {
- return rtp_video_sender_->GetSentRtpPacketInfos(ssrc, seq_nums);
- }),
- rtp_video_sender_(transport->CreateRtpVideoSender(
- suspended_ssrcs,
- suspended_payload_states,
- config_.rtp,
- config_.rtcp_report_interval_ms,
- config_.send_transport,
- CreateObservers(call_stats,
- &encoder_feedback_,
- &stats_proxy_,
- &send_packet_observer_),
- event_log,
- std::move(fec_controller),
- CreateFrameEncryptionConfig(&config_),
- config_.frame_transformer)),
- send_stream_(clock,
- &stats_proxy_,
- transport,
- bitrate_allocator,
- video_stream_encoder_.get(),
- &config_,
- encoder_config.max_bitrate_bps,
- encoder_config.bitrate_priority,
- encoder_config.content_type,
- rtp_video_sender_,
- field_trials) {
- RTC_DCHECK(config_.encoder_settings.encoder_factory);
- RTC_DCHECK(config_.encoder_settings.bitrate_allocator_factory);
-
- video_stream_encoder_->SetFecControllerOverride(rtp_video_sender_);
-
- ReconfigureVideoEncoder(std::move(encoder_config));
-}
-
-VideoSendStream::~VideoSendStream() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- RTC_DCHECK(!running_);
- transport_->DestroyRtpVideoSender(rtp_video_sender_);
-}
-
-void VideoSendStream::Start() {
- const std::vector<bool> active_layers(config_.rtp.ssrcs.size(), true);
- StartPerRtpStream(active_layers);
-}
-
-void VideoSendStream::StartPerRtpStream(const std::vector<bool> active_layers) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
-
- // Keep our `running_` flag expected state in sync with active layers since
- // the `send_stream_` will be implicitly stopped/started depending on the
- // state of the layers.
- bool running = false;
-
- rtc::StringBuilder active_layers_string;
- active_layers_string << "{";
- for (size_t i = 0; i < active_layers.size(); ++i) {
- if (active_layers[i]) {
- running = true;
- active_layers_string << "1";
- } else {
- active_layers_string << "0";
- }
- if (i < active_layers.size() - 1) {
- active_layers_string << ", ";
- }
- }
- active_layers_string << "}";
- RTC_LOG(LS_INFO) << "StartPerRtpStream: " << active_layers_string.str();
- send_stream_.StartPerRtpStream(active_layers);
- running_ = running;
-}
-
-void VideoSendStream::Stop() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- if (!running_)
- return;
- RTC_DLOG(LS_INFO) << "VideoSendStream::Stop";
- running_ = false;
- send_stream_.Stop();
-}
-
-bool VideoSendStream::started() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- return running_;
-}
-
-void VideoSendStream::AddAdaptationResource(
- rtc::scoped_refptr<Resource> resource) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- video_stream_encoder_->AddAdaptationResource(resource);
-}
-
-std::vector<rtc::scoped_refptr<Resource>>
-VideoSendStream::GetAdaptationResources() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- return video_stream_encoder_->GetAdaptationResources();
-}
-
-void VideoSendStream::SetSource(
- rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
- const DegradationPreference& degradation_preference) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- video_stream_encoder_->SetSource(source, degradation_preference);
-}
-
-void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
- ReconfigureVideoEncoder(std::move(config), nullptr);
-}
-
-void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config,
- SetParametersCallback callback) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- RTC_DCHECK_EQ(content_type_, config.content_type);
- RTC_LOG(LS_VERBOSE) << "Encoder config: " << config.ToString()
- << " VideoSendStream config: " << config_.ToString();
- video_stream_encoder_->ConfigureEncoder(
- std::move(config),
- config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp),
- std::move(callback));
-}
-
-VideoSendStream::Stats VideoSendStream::GetStats() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- return stats_proxy_.GetStats();
-}
-
-absl::optional<float> VideoSendStream::GetPacingFactorOverride() const {
- return send_stream_.configured_pacing_factor();
-}
-
-void VideoSendStream::StopPermanentlyAndGetRtpStates(
- VideoSendStream::RtpStateMap* rtp_state_map,
- VideoSendStream::RtpPayloadStateMap* payload_state_map) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- video_stream_encoder_->Stop();
-
- running_ = false;
- // Always run these cleanup steps regardless of whether running_ was set
- // or not. This will unregister callbacks before destruction.
- // See `VideoSendStreamImpl::StopVideoSendStream` for more.
- send_stream_.Stop();
- *rtp_state_map = send_stream_.GetRtpStates();
- *payload_state_map = send_stream_.GetRtpPayloadStates();
-}
-
-void VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- send_stream_.DeliverRtcp(packet, length);
-}
-
-void VideoSendStream::GenerateKeyFrame(const std::vector<std::string>& rids) {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- // Map rids to layers. If rids is empty, generate a keyframe for all layers.
- std::vector<VideoFrameType> next_frames(config_.rtp.ssrcs.size(),
- VideoFrameType::kVideoFrameKey);
- if (!config_.rtp.rids.empty() && !rids.empty()) {
- std::fill(next_frames.begin(), next_frames.end(),
- VideoFrameType::kVideoFrameDelta);
- for (const auto& rid : rids) {
- for (size_t i = 0; i < config_.rtp.rids.size(); i++) {
- if (config_.rtp.rids[i] == rid) {
- next_frames[i] = VideoFrameType::kVideoFrameKey;
- break;
- }
- }
- }
- }
- if (video_stream_encoder_) {
- video_stream_encoder_->SendKeyFrame(next_frames);
- }
-}
-
-} // namespace internal
-} // namespace webrtc
diff --git a/video/video_send_stream.h b/video/video_send_stream.h
deleted file mode 100644
index ff1bf0c..0000000
--- a/video/video_send_stream.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef VIDEO_VIDEO_SEND_STREAM_H_
-#define VIDEO_VIDEO_SEND_STREAM_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "api/fec_controller.h"
-#include "api/field_trials_view.h"
-#include "api/metronome/metronome.h"
-#include "api/sequence_checker.h"
-#include "api/task_queue/pending_task_safety_flag.h"
-#include "call/bitrate_allocator.h"
-#include "call/video_receive_stream.h"
-#include "call/video_send_stream.h"
-#include "rtc_base/event.h"
-#include "rtc_base/system/no_unique_address.h"
-#include "video/encoder_rtcp_feedback.h"
-#include "video/send_delay_stats.h"
-#include "video/send_statistics_proxy.h"
-#include "video/video_send_stream_impl.h"
-#include "video/video_stream_encoder_interface.h"
-
-namespace webrtc {
-namespace test {
-class VideoSendStreamPeer;
-} // namespace test
-
-class CallStats;
-class IvfFileWriter;
-class RateLimiter;
-class RtpRtcp;
-class RtpTransportControllerSendInterface;
-class RtcEventLog;
-
-namespace internal {
-
-class VideoSendStreamImpl;
-
-// VideoSendStream implements webrtc::VideoSendStream.
-// Internally, it delegates all public methods to VideoSendStreamImpl and / or
-// VideoStreamEncoder.
-class VideoSendStream : public webrtc::VideoSendStream {
- public:
- using RtpStateMap = std::map<uint32_t, RtpState>;
- using RtpPayloadStateMap = std::map<uint32_t, RtpPayloadState>;
-
- VideoSendStream(
- Clock* clock,
- int num_cpu_cores,
- TaskQueueFactory* task_queue_factory,
- TaskQueueBase* network_queue,
- RtcpRttStats* call_stats,
- RtpTransportControllerSendInterface* transport,
- Metronome* metronome,
- BitrateAllocatorInterface* bitrate_allocator,
- SendDelayStats* send_delay_stats,
- RtcEventLog* event_log,
- VideoSendStream::Config config,
- VideoEncoderConfig encoder_config,
- const std::map<uint32_t, RtpState>& suspended_ssrcs,
- const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
- std::unique_ptr<FecController> fec_controller,
- const FieldTrialsView& field_trials);
-
- ~VideoSendStream() override;
-
- void DeliverRtcp(const uint8_t* packet, size_t length);
-
- // webrtc::VideoSendStream implementation.
- void Start() override;
- void StartPerRtpStream(std::vector<bool> active_layers) override;
- void Stop() override;
- bool started() override;
-
- void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) override;
- std::vector<rtc::scoped_refptr<Resource>> GetAdaptationResources() override;
-
- void SetSource(rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
- const DegradationPreference& degradation_preference) override;
-
- void ReconfigureVideoEncoder(VideoEncoderConfig config) override;
- void ReconfigureVideoEncoder(VideoEncoderConfig config,
- SetParametersCallback callback) override;
- Stats GetStats() override;
-
- void StopPermanentlyAndGetRtpStates(RtpStateMap* rtp_state_map,
- RtpPayloadStateMap* payload_state_map);
- void GenerateKeyFrame(const std::vector<std::string>& rids) override;
-
- private:
- friend class test::VideoSendStreamPeer;
- class OnSendPacketObserver : public SendPacketObserver {
- public:
- OnSendPacketObserver(SendStatisticsProxy* stats_proxy,
- SendDelayStats* send_delay_stats)
- : stats_proxy_(*stats_proxy), send_delay_stats_(*send_delay_stats) {}
-
- void OnSendPacket(absl::optional<uint16_t> packet_id,
- Timestamp capture_time,
- uint32_t ssrc) override {
- stats_proxy_.OnSendPacket(ssrc, capture_time);
- if (packet_id.has_value()) {
- send_delay_stats_.OnSendPacket(*packet_id, capture_time, ssrc);
- }
- }
-
- private:
- SendStatisticsProxy& stats_proxy_;
- SendDelayStats& send_delay_stats_;
- };
-
- absl::optional<float> GetPacingFactorOverride() const;
-
- RTC_NO_UNIQUE_ADDRESS SequenceChecker thread_checker_;
- RtpTransportControllerSendInterface* const transport_;
-
- SendStatisticsProxy stats_proxy_;
- OnSendPacketObserver send_packet_observer_;
- const VideoSendStream::Config config_;
- const VideoEncoderConfig::ContentType content_type_;
- std::unique_ptr<VideoStreamEncoderInterface> video_stream_encoder_;
- EncoderRtcpFeedback encoder_feedback_;
- RtpVideoSenderInterface* const rtp_video_sender_;
- VideoSendStreamImpl send_stream_;
- bool running_ RTC_GUARDED_BY(thread_checker_) = false;
-};
-
-} // namespace internal
-} // namespace webrtc
-
-#endif // VIDEO_VIDEO_SEND_STREAM_H_
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 6075cc7..91790af 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -13,21 +13,51 @@
#include <algorithm>
#include <cstdint>
+#include <map>
+#include <memory>
#include <string>
#include <utility>
+#include <vector>
#include "absl/algorithm/container.h"
+#include "absl/types/optional.h"
+#include "api/adaptation/resource.h"
+#include "api/call/bitrate_allocation.h"
#include "api/crypto/crypto_options.h"
+#include "api/fec_controller.h"
#include "api/field_trials_view.h"
+#include "api/metronome/metronome.h"
#include "api/rtp_parameters.h"
+#include "api/rtp_sender_interface.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "api/units/data_rate.h"
+#include "api/units/time_delta.h"
+#include "api/video/encoded_image.h"
+#include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_codec_constants.h"
+#include "api/video/video_codec_type.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_frame_type.h"
+#include "api/video/video_layers_allocation.h"
+#include "api/video/video_source_interface.h"
+#include "api/video/video_stream_encoder_settings.h"
#include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder.h"
+#include "api/video_codecs/video_encoder_factory.h"
+#include "call/bitrate_allocator.h"
+#include "call/rtp_config.h"
#include "call/rtp_transport_controller_send_interface.h"
#include "call/video_send_stream.h"
#include "modules/pacing/pacing_controller.h"
+#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
+#include "modules/rtp_rtcp/source/rtp_sender.h"
+#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/alr_experiment.h"
#include "rtc_base/experiments/field_trial_parser.h"
@@ -35,9 +65,18 @@
#include "rtc_base/experiments/rate_control_settings.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/strings/string_builder.h"
+#include "rtc_base/task_utils/repeating_task.h"
#include "rtc_base/trace_event.h"
#include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
+#include "video/adaptation/overuse_frame_detector.h"
+#include "video/config/video_encoder_config.h"
+#include "video/encoder_rtcp_feedback.h"
+#include "video/frame_cadence_adapter.h"
+#include "video/send_delay_stats.h"
+#include "video/send_statistics_proxy.h"
+#include "video/video_stream_encoder.h"
+#include "video/video_stream_encoder_interface.h"
namespace webrtc {
namespace internal {
@@ -209,6 +248,107 @@
return kDefaultMinVideoBitrateBps;
}
+size_t CalculateMaxHeaderSize(const RtpConfig& config) {
+ size_t header_size = kRtpHeaderSize;
+ size_t extensions_size = 0;
+ size_t fec_extensions_size = 0;
+ if (!config.extensions.empty()) {
+ RtpHeaderExtensionMap extensions_map(config.extensions);
+ extensions_size = RtpHeaderExtensionSize(RTPSender::VideoExtensionSizes(),
+ extensions_map);
+ fec_extensions_size =
+ RtpHeaderExtensionSize(RTPSender::FecExtensionSizes(), extensions_map);
+ }
+ header_size += extensions_size;
+ if (config.flexfec.payload_type >= 0) {
+ // All FEC extensions again plus maximum FlexFec overhead.
+ header_size += fec_extensions_size + 32;
+ } else {
+ if (config.ulpfec.ulpfec_payload_type >= 0) {
+ // Header with all the FEC extensions will be repeated plus maximum
+ // UlpFec overhead.
+ header_size += fec_extensions_size + 18;
+ }
+ if (config.ulpfec.red_payload_type >= 0) {
+ header_size += 1; // RED header.
+ }
+ }
+ // Additional room for Rtx.
+ if (config.rtx.payload_type >= 0)
+ header_size += kRtxHeaderSize;
+ return header_size;
+}
+
+VideoStreamEncoder::BitrateAllocationCallbackType
+GetBitrateAllocationCallbackType(const VideoSendStream::Config& config,
+ const FieldTrialsView& field_trials) {
+ if (webrtc::RtpExtension::FindHeaderExtensionByUri(
+ config.rtp.extensions,
+ webrtc::RtpExtension::kVideoLayersAllocationUri,
+ config.crypto_options.srtp.enable_encrypted_rtp_header_extensions
+ ? RtpExtension::Filter::kPreferEncryptedExtension
+ : RtpExtension::Filter::kDiscardEncryptedExtension)) {
+ return VideoStreamEncoder::BitrateAllocationCallbackType::
+ kVideoLayersAllocation;
+ }
+ if (field_trials.IsEnabled("WebRTC-Target-Bitrate-Rtcp")) {
+ return VideoStreamEncoder::BitrateAllocationCallbackType::
+ kVideoBitrateAllocation;
+ }
+ return VideoStreamEncoder::BitrateAllocationCallbackType::
+ kVideoBitrateAllocationWhenScreenSharing;
+}
+
+RtpSenderFrameEncryptionConfig CreateFrameEncryptionConfig(
+ const VideoSendStream::Config* config) {
+ RtpSenderFrameEncryptionConfig frame_encryption_config;
+ frame_encryption_config.frame_encryptor = config->frame_encryptor.get();
+ frame_encryption_config.crypto_options = config->crypto_options;
+ return frame_encryption_config;
+}
+
+RtpSenderObservers CreateObservers(RtcpRttStats* call_stats,
+ EncoderRtcpFeedback* encoder_feedback,
+ SendStatisticsProxy* stats_proxy,
+ SendPacketObserver* send_packet_observer) {
+ RtpSenderObservers observers;
+ observers.rtcp_rtt_stats = call_stats;
+ observers.intra_frame_callback = encoder_feedback;
+ observers.rtcp_loss_notification_observer = encoder_feedback;
+ observers.report_block_data_observer = stats_proxy;
+ observers.rtp_stats = stats_proxy;
+ observers.bitrate_observer = stats_proxy;
+ observers.frame_count_observer = stats_proxy;
+ observers.rtcp_type_observer = stats_proxy;
+ observers.send_packet_observer = send_packet_observer;
+ return observers;
+}
+
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+ Clock* clock,
+ int num_cpu_cores,
+ TaskQueueFactory* task_queue_factory,
+ SendStatisticsProxy* stats_proxy,
+ const VideoStreamEncoderSettings& encoder_settings,
+ VideoStreamEncoder::BitrateAllocationCallbackType
+ bitrate_allocation_callback_type,
+ const FieldTrialsView& field_trials,
+ Metronome* metronome,
+ webrtc::VideoEncoderFactory::EncoderSelectorInterface* encoder_selector) {
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue =
+ task_queue_factory->CreateTaskQueue("EncoderQueue",
+ TaskQueueFactory::Priority::NORMAL);
+ TaskQueueBase* encoder_queue_ptr = encoder_queue.get();
+ return std::make_unique<VideoStreamEncoder>(
+ clock, num_cpu_cores, stats_proxy, encoder_settings,
+ std::make_unique<OveruseFrameDetector>(stats_proxy),
+ FrameCadenceAdapterInterface::Create(
+ clock, encoder_queue_ptr, metronome,
+ /*worker_queue=*/TaskQueueBase::Current(), field_trials),
+ std::move(encoder_queue), bitrate_allocation_callback_type, field_trials,
+ encoder_selector);
+}
+
} // namespace
PacingConfig::PacingConfig(const FieldTrialsView& field_trials)
@@ -222,66 +362,96 @@
VideoSendStreamImpl::VideoSendStreamImpl(
Clock* clock,
- SendStatisticsProxy* stats_proxy,
+ int num_cpu_cores,
+ TaskQueueFactory* task_queue_factory,
+ RtcpRttStats* call_stats,
RtpTransportControllerSendInterface* transport,
+ Metronome* metronome,
BitrateAllocatorInterface* bitrate_allocator,
- VideoStreamEncoderInterface* video_stream_encoder,
- const VideoSendStream::Config* config,
- int initial_encoder_max_bitrate,
- double initial_encoder_bitrate_priority,
- VideoEncoderConfig::ContentType content_type,
- RtpVideoSenderInterface* rtp_video_sender,
- const FieldTrialsView& field_trials)
- : clock_(clock),
- has_alr_probing_(config->periodic_alr_bandwidth_probing ||
- GetAlrSettings(field_trials, content_type)),
+ SendDelayStats* send_delay_stats,
+ RtcEventLog* event_log,
+ VideoSendStream::Config config,
+ VideoEncoderConfig encoder_config,
+ const std::map<uint32_t, RtpState>& suspended_ssrcs,
+ const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
+ std::unique_ptr<FecController> fec_controller,
+ const FieldTrialsView& field_trials,
+ std::unique_ptr<VideoStreamEncoderInterface> video_stream_encoder_for_test)
+ : transport_(transport),
+ stats_proxy_(clock, config, encoder_config.content_type, field_trials),
+ send_packet_observer_(&stats_proxy_, send_delay_stats),
+ config_(std::move(config)),
+ content_type_(encoder_config.content_type),
+ video_stream_encoder_(
+ video_stream_encoder_for_test
+ ? std::move(video_stream_encoder_for_test)
+ : CreateVideoStreamEncoder(
+ clock,
+ num_cpu_cores,
+ task_queue_factory,
+ &stats_proxy_,
+ config_.encoder_settings,
+ GetBitrateAllocationCallbackType(config_, field_trials),
+ field_trials,
+ metronome,
+ config_.encoder_selector)),
+ encoder_feedback_(
+ clock,
+ config_.rtp.ssrcs,
+ video_stream_encoder_.get(),
+ [this](uint32_t ssrc, const std::vector<uint16_t>& seq_nums) {
+ return rtp_video_sender_->GetSentRtpPacketInfos(ssrc, seq_nums);
+ }),
+ rtp_video_sender_(transport->CreateRtpVideoSender(
+ suspended_ssrcs,
+ suspended_payload_states,
+ config_.rtp,
+ config_.rtcp_report_interval_ms,
+ config_.send_transport,
+ CreateObservers(call_stats,
+ &encoder_feedback_,
+ &stats_proxy_,
+ &send_packet_observer_),
+ event_log,
+ std::move(fec_controller),
+ CreateFrameEncryptionConfig(&config_),
+ config_.frame_transformer)),
+ clock_(clock),
+ has_alr_probing_(
+ config_.periodic_alr_bandwidth_probing ||
+ GetAlrSettings(field_trials, encoder_config.content_type)),
pacing_config_(PacingConfig(field_trials)),
- stats_proxy_(stats_proxy),
- config_(config),
worker_queue_(TaskQueueBase::Current()),
timed_out_(false),
- transport_(transport),
+
bitrate_allocator_(bitrate_allocator),
disable_padding_(true),
max_padding_bitrate_(0),
encoder_min_bitrate_bps_(0),
encoder_max_bitrate_bps_(
- GetInitialEncoderMaxBitrate(initial_encoder_max_bitrate)),
+ GetInitialEncoderMaxBitrate(encoder_config.max_bitrate_bps)),
encoder_target_rate_bps_(0),
- encoder_bitrate_priority_(initial_encoder_bitrate_priority),
- video_stream_encoder_(video_stream_encoder),
- rtp_video_sender_(rtp_video_sender),
- configured_pacing_factor_(GetConfiguredPacingFactor(*config_,
- content_type,
+ encoder_bitrate_priority_(encoder_config.bitrate_priority),
+ configured_pacing_factor_(GetConfiguredPacingFactor(config_,
+ content_type_,
pacing_config_,
field_trials)) {
- RTC_DCHECK_GE(config_->rtp.payload_type, 0);
- RTC_DCHECK_LE(config_->rtp.payload_type, 127);
- RTC_DCHECK(!config_->rtp.ssrcs.empty());
+ RTC_DCHECK_GE(config_.rtp.payload_type, 0);
+ RTC_DCHECK_LE(config_.rtp.payload_type, 127);
+ RTC_DCHECK(!config_.rtp.ssrcs.empty());
RTC_DCHECK(transport_);
- RTC_DCHECK_NE(initial_encoder_max_bitrate, 0);
- RTC_LOG(LS_INFO) << "VideoSendStreamImpl: " << config_->ToString();
+ RTC_DCHECK_NE(encoder_max_bitrate_bps_, 0);
+ RTC_LOG(LS_INFO) << "VideoSendStreamImpl: " << config_.ToString();
RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled(field_trials));
- // Only request rotation at the source when we positively know that the remote
- // side doesn't support the rotation extension. This allows us to prepare the
- // encoder in the expectation that rotation is supported - which is the common
- // case.
- bool rotation_applied = absl::c_none_of(
- config_->rtp.extensions, [](const RtpExtension& extension) {
- return extension.uri == RtpExtension::kVideoRotationUri;
- });
-
- video_stream_encoder_->SetSink(this, rotation_applied);
-
absl::optional<bool> enable_alr_bw_probing;
// If send-side BWE is enabled, check if we should apply updated probing and
// pacing settings.
if (configured_pacing_factor_) {
absl::optional<AlrExperimentSettings> alr_settings =
- GetAlrSettings(field_trials, content_type);
+ GetAlrSettings(field_trials, content_type_);
int queue_time_limit_ms;
if (alr_settings) {
enable_alr_bw_probing = true;
@@ -293,11 +463,11 @@
queue_time_limit_ms = pacing_config_.max_pacing_delay.Get().ms();
}
- transport->SetQueueTimeLimit(queue_time_limit_ms);
+ transport_->SetQueueTimeLimit(queue_time_limit_ms);
}
- if (config_->periodic_alr_bandwidth_probing) {
- enable_alr_bw_probing = config_->periodic_alr_bandwidth_probing;
+ if (config_.periodic_alr_bandwidth_probing) {
+ enable_alr_bw_probing = config_.periodic_alr_bandwidth_probing;
}
if (enable_alr_bw_probing) {
@@ -307,13 +477,110 @@
if (configured_pacing_factor_)
transport_->SetPacingFactor(*configured_pacing_factor_);
+ // Only request rotation at the source when we positively know that the remote
+ // side doesn't support the rotation extension. This allows us to prepare the
+ // encoder in the expectation that rotation is supported - which is the common
+ // case.
+ bool rotation_applied = absl::c_none_of(
+ config_.rtp.extensions, [](const RtpExtension& extension) {
+ return extension.uri == RtpExtension::kVideoRotationUri;
+ });
+
+ video_stream_encoder_->SetSink(this, rotation_applied);
video_stream_encoder_->SetStartBitrate(
bitrate_allocator_->GetStartBitrate(this));
+ video_stream_encoder_->SetFecControllerOverride(rtp_video_sender_);
+ ReconfigureVideoEncoder(std::move(encoder_config));
}
VideoSendStreamImpl::~VideoSendStreamImpl() {
RTC_DCHECK_RUN_ON(&thread_checker_);
- RTC_LOG(LS_INFO) << "~VideoSendStreamImpl: " << config_->ToString();
+ RTC_LOG(LS_INFO) << "~VideoSendStreamImpl: " << config_.ToString();
+ RTC_DCHECK(!started());
+ transport_->DestroyRtpVideoSender(rtp_video_sender_);
+}
+
+void VideoSendStreamImpl::AddAdaptationResource(
+ rtc::scoped_refptr<Resource> resource) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ video_stream_encoder_->AddAdaptationResource(resource);
+}
+
+std::vector<rtc::scoped_refptr<Resource>>
+VideoSendStreamImpl::GetAdaptationResources() {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ return video_stream_encoder_->GetAdaptationResources();
+}
+
+void VideoSendStreamImpl::SetSource(
+ rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
+ const DegradationPreference& degradation_preference) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ video_stream_encoder_->SetSource(source, degradation_preference);
+}
+
+void VideoSendStreamImpl::ReconfigureVideoEncoder(VideoEncoderConfig config) {
+ ReconfigureVideoEncoder(std::move(config), nullptr);
+}
+
+void VideoSendStreamImpl::ReconfigureVideoEncoder(
+ VideoEncoderConfig config,
+ SetParametersCallback callback) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ RTC_DCHECK_EQ(content_type_, config.content_type);
+ RTC_LOG(LS_VERBOSE) << "Encoder config: " << config.ToString()
+ << " VideoSendStream config: " << config_.ToString();
+ video_stream_encoder_->ConfigureEncoder(
+ std::move(config),
+ config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp),
+ std::move(callback));
+}
+
+VideoSendStream::Stats VideoSendStreamImpl::GetStats() {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ return stats_proxy_.GetStats();
+}
+
+absl::optional<float> VideoSendStreamImpl::GetPacingFactorOverride() const {
+ return configured_pacing_factor_;
+}
+
+void VideoSendStreamImpl::StopPermanentlyAndGetRtpStates(
+ VideoSendStreamImpl::RtpStateMap* rtp_state_map,
+ VideoSendStreamImpl::RtpPayloadStateMap* payload_state_map) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ video_stream_encoder_->Stop();
+
+ running_ = false;
+ // Always run these cleanup steps regardless of whether running_ was set
+ // or not. This will unregister callbacks before destruction.
+ // See `VideoSendStreamImpl::StopVideoSendStream` for more.
+ Stop();
+ *rtp_state_map = GetRtpStates();
+ *payload_state_map = GetRtpPayloadStates();
+}
+
+void VideoSendStreamImpl::GenerateKeyFrame(
+ const std::vector<std::string>& rids) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ // Map rids to layers. If rids is empty, generate a keyframe for all layers.
+ std::vector<VideoFrameType> next_frames(config_.rtp.ssrcs.size(),
+ VideoFrameType::kVideoFrameKey);
+ if (!config_.rtp.rids.empty() && !rids.empty()) {
+ std::fill(next_frames.begin(), next_frames.end(),
+ VideoFrameType::kVideoFrameDelta);
+ for (const auto& rid : rids) {
+ for (size_t i = 0; i < config_.rtp.rids.size(); i++) {
+ if (config_.rtp.rids[i] == rid) {
+ next_frames[i] = VideoFrameType::kVideoFrameKey;
+ break;
+ }
+ }
+ }
+ }
+ if (video_stream_encoder_) {
+ video_stream_encoder_->SendKeyFrame(next_frames);
+ }
}
void VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
@@ -321,9 +588,35 @@
rtp_video_sender_->DeliverRtcp(packet, length);
}
+bool VideoSendStreamImpl::started() {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ return rtp_video_sender_->IsActive();
+}
+
+void VideoSendStreamImpl::Start() {
+ const std::vector<bool> active_layers(config_.rtp.ssrcs.size(), true);
+ StartPerRtpStream(active_layers);
+}
+
void VideoSendStreamImpl::StartPerRtpStream(
const std::vector<bool> active_layers) {
RTC_DCHECK_RUN_ON(&thread_checker_);
+
+ rtc::StringBuilder active_layers_string;
+ active_layers_string << "{";
+ for (size_t i = 0; i < active_layers.size(); ++i) {
+ if (active_layers[i]) {
+ active_layers_string << "1";
+ } else {
+ active_layers_string << "0";
+ }
+ if (i < active_layers.size() - 1) {
+ active_layers_string << ", ";
+ }
+ }
+ active_layers_string << "}";
+ RTC_LOG(LS_INFO) << "StartPerRtpStream: " << active_layers_string.str();
+
bool previously_active = rtp_video_sender_->IsActive();
rtp_video_sender_->SetActiveModules(active_layers);
if (!rtp_video_sender_->IsActive() && previously_active) {
@@ -381,7 +674,7 @@
check_encoder_activity_task_.Stop();
video_stream_encoder_->OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
DataRate::Zero(), 0, 0, 0);
- stats_proxy_->OnSetEncoderTargetRate(0);
+ stats_proxy_.OnSetEncoderTargetRate(0);
}
void VideoSendStreamImpl::SignalEncoderTimedOut() {
@@ -465,7 +758,7 @@
encoder_max_bitrate_bps_,
static_cast<uint32_t>(disable_padding_ ? 0 : max_padding_bitrate_),
/* priority_bitrate */ 0,
- !config_->suspend_below_min_bitrate,
+ !config_.suspend_below_min_bitrate,
encoder_bitrate_priority_};
}
@@ -478,12 +771,12 @@
RTC_DCHECK(!worker_queue_->IsCurrent());
auto closure = [this, streams = std::move(streams), is_svc, content_type,
min_transmit_bitrate_bps]() mutable {
- RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
+ RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size());
TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
RTC_DCHECK_RUN_ON(&thread_checker_);
const VideoCodecType codec_type =
- PayloadStringToCodecType(config_->rtp.payload_name);
+ PayloadStringToCodecType(config_.rtp.payload_name);
const absl::optional<DataRate> experimental_min_bitrate =
GetExperimentalMinVideoBitrate(codec_type);
@@ -512,11 +805,11 @@
// TODO(bugs.webrtc.org/10266): Query the VideoBitrateAllocator instead.
max_padding_bitrate_ = CalculateMaxPadBitrateBps(
streams, is_svc, content_type, min_transmit_bitrate_bps,
- config_->suspend_below_min_bitrate, has_alr_probing_);
+ config_.suspend_below_min_bitrate, has_alr_probing_);
// Clear stats for disabled layers.
- for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
- stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
+ for (size_t i = streams.size(); i < config_.rtp.ssrcs.size(); ++i) {
+ stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
}
const size_t num_temporal_layers =
@@ -592,7 +885,7 @@
update.stable_target_bitrate = update.target_bitrate;
}
- rtp_video_sender_->OnBitrateUpdated(update, stats_proxy_->GetSendFrameRate());
+ rtp_video_sender_->OnBitrateUpdated(update, stats_proxy_.GetSendFrameRate());
encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
const uint32_t protection_bitrate_bps =
rtp_video_sender_->GetProtectionBitrateBps();
@@ -623,7 +916,7 @@
encoder_target_rate, encoder_stable_target_rate, link_allocation,
rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
update.round_trip_time.ms(), update.cwnd_reduce_ratio);
- stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
+ stats_proxy_.OnSetEncoderTargetRate(encoder_target_rate_bps_);
return protection_bitrate_bps;
}
diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h
index c5e0980..89fb9db 100644
--- a/video/video_send_stream_impl.h
+++ b/video/video_send_stream_impl.h
@@ -16,21 +16,22 @@
#include <atomic>
#include <map>
#include <memory>
+#include <string>
#include <vector>
#include "absl/types/optional.h"
#include "api/field_trials_view.h"
+#include "api/metronome/metronome.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/video/encoded_image.h"
#include "api/video/video_bitrate_allocation.h"
-#include "api/video/video_bitrate_allocator.h"
#include "api/video_codecs/video_encoder.h"
#include "call/bitrate_allocator.h"
#include "call/rtp_config.h"
#include "call/rtp_transport_controller_send_interface.h"
#include "call/rtp_video_sender_interface.h"
-#include "modules/include/module_common_types.h"
+#include "call/video_send_stream.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/experiments/field_trial_parser.h"
@@ -38,10 +39,17 @@
#include "rtc_base/task_utils/repeating_task.h"
#include "rtc_base/thread_annotations.h"
#include "video/config/video_encoder_config.h"
+#include "video/encoder_rtcp_feedback.h"
+#include "video/send_delay_stats.h"
#include "video/send_statistics_proxy.h"
#include "video/video_stream_encoder_interface.h"
namespace webrtc {
+
+namespace test {
+class VideoSendStreamPeer;
+} // namespace test
+
namespace internal {
// Pacing buffer config; overridden by ALR config if provided.
@@ -54,32 +62,58 @@
FieldTrialParameter<TimeDelta> max_pacing_delay;
};
-// VideoSendStreamImpl implements internal::VideoSendStream.
-// It is created and destroyed on `rtp_transport_queue`. The intent is to
-// decrease the need for locking and to ensure methods are called in sequence.
-// Public methods except `DeliverRtcp` must be called on `rtp_transport_queue`.
-// DeliverRtcp is called on the libjingle worker thread or a network thread.
+// VideoSendStreamImpl implements webrtc::VideoSendStream.
+// It is created and destroyed on `worker queue`. The intent is to
// An encoder may deliver frames through the EncodedImageCallback on an
// arbitrary thread.
-class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
+class VideoSendStreamImpl : public webrtc::VideoSendStream,
+ public webrtc::BitrateAllocatorObserver,
public VideoStreamEncoderInterface::EncoderSink {
public:
+ using RtpStateMap = std::map<uint32_t, RtpState>;
+ using RtpPayloadStateMap = std::map<uint32_t, RtpPayloadState>;
+
VideoSendStreamImpl(Clock* clock,
- SendStatisticsProxy* stats_proxy,
+ int num_cpu_cores,
+ TaskQueueFactory* task_queue_factory,
+ RtcpRttStats* call_stats,
RtpTransportControllerSendInterface* transport,
+ Metronome* metronome,
BitrateAllocatorInterface* bitrate_allocator,
- VideoStreamEncoderInterface* video_stream_encoder,
- const VideoSendStream::Config* config,
- int initial_encoder_max_bitrate,
- double initial_encoder_bitrate_priority,
- VideoEncoderConfig::ContentType content_type,
- RtpVideoSenderInterface* rtp_video_sender,
- const FieldTrialsView& field_trials);
+ SendDelayStats* send_delay_stats,
+ RtcEventLog* event_log,
+ VideoSendStream::Config config,
+ VideoEncoderConfig encoder_config,
+ const RtpStateMap& suspended_ssrcs,
+ const RtpPayloadStateMap& suspended_payload_states,
+ std::unique_ptr<FecController> fec_controller,
+ const FieldTrialsView& field_trials,
+ std::unique_ptr<VideoStreamEncoderInterface>
+ video_stream_encoder_for_test = nullptr);
~VideoSendStreamImpl() override;
void DeliverRtcp(const uint8_t* packet, size_t length);
- void StartPerRtpStream(std::vector<bool> active_layers);
- void Stop();
+
+ // webrtc::VideoSendStream implementation.
+ void Start() override;
+ void StartPerRtpStream(std::vector<bool> active_layers) override;
+ void Stop() override;
+ bool started() override;
+
+ void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) override;
+ std::vector<rtc::scoped_refptr<Resource>> GetAdaptationResources() override;
+
+ void SetSource(rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
+ const DegradationPreference& degradation_preference) override;
+
+ void ReconfigureVideoEncoder(VideoEncoderConfig config) override;
+ void ReconfigureVideoEncoder(VideoEncoderConfig config,
+ SetParametersCallback callback) override;
+ Stats GetStats() override;
+
+ void StopPermanentlyAndGetRtpStates(RtpStateMap* rtp_state_map,
+ RtpPayloadStateMap* payload_state_map);
+ void GenerateKeyFrame(const std::vector<std::string>& rids) override;
// TODO(holmer): Move these to RtpTransportControllerSend.
std::map<uint32_t, RtpState> GetRtpStates() const;
@@ -91,6 +125,28 @@
}
private:
+ friend class test::VideoSendStreamPeer;
+ class OnSendPacketObserver : public SendPacketObserver {
+ public:
+ OnSendPacketObserver(SendStatisticsProxy* stats_proxy,
+ SendDelayStats* send_delay_stats)
+ : stats_proxy_(*stats_proxy), send_delay_stats_(*send_delay_stats) {}
+
+ void OnSendPacket(absl::optional<uint16_t> packet_id,
+ Timestamp capture_time,
+ uint32_t ssrc) override {
+ stats_proxy_.OnSendPacket(ssrc, capture_time);
+ if (packet_id.has_value()) {
+ send_delay_stats_.OnSendPacket(*packet_id, capture_time, ssrc);
+ }
+ }
+
+ private:
+ SendStatisticsProxy& stats_proxy_;
+ SendDelayStats& send_delay_stats_;
+ };
+
+ absl::optional<float> GetPacingFactorOverride() const;
// Implements BitrateAllocatorObserver.
uint32_t OnBitrateUpdated(BitrateAllocationUpdate update) override;
@@ -130,13 +186,22 @@
RTC_RUN_ON(thread_checker_);
RTC_NO_UNIQUE_ADDRESS SequenceChecker thread_checker_;
+
+ RtpTransportControllerSendInterface* const transport_;
+
+ SendStatisticsProxy stats_proxy_;
+ OnSendPacketObserver send_packet_observer_;
+ const VideoSendStream::Config config_;
+ const VideoEncoderConfig::ContentType content_type_;
+ std::unique_ptr<VideoStreamEncoderInterface> video_stream_encoder_;
+ EncoderRtcpFeedback encoder_feedback_;
+ RtpVideoSenderInterface* const rtp_video_sender_;
+ bool running_ RTC_GUARDED_BY(thread_checker_) = false;
+
Clock* const clock_;
const bool has_alr_probing_;
const PacingConfig pacing_config_;
- SendStatisticsProxy* const stats_proxy_;
- const VideoSendStream::Config* const config_;
-
TaskQueueBase* const worker_queue_;
RepeatingTaskHandle check_encoder_activity_task_
@@ -145,7 +210,6 @@
std::atomic_bool activity_;
bool timed_out_ RTC_GUARDED_BY(thread_checker_);
- RtpTransportControllerSendInterface* const transport_;
BitrateAllocatorInterface* const bitrate_allocator_;
bool disable_padding_ RTC_GUARDED_BY(thread_checker_);
@@ -155,9 +219,6 @@
uint32_t encoder_target_rate_bps_ RTC_GUARDED_BY(thread_checker_);
double encoder_bitrate_priority_ RTC_GUARDED_BY(thread_checker_);
- VideoStreamEncoderInterface* const video_stream_encoder_;
- RtpVideoSenderInterface* const rtp_video_sender_;
-
ScopedTaskSafety worker_queue_safety_;
// Context for the most recent and last sent video bitrate allocation. Used to
diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc
index c88ad06..9d003dc 100644
--- a/video/video_send_stream_impl_unittest.cc
+++ b/video/video_send_stream_impl_unittest.cc
@@ -11,31 +11,50 @@
#include "video/video_send_stream_impl.h"
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <map>
#include <memory>
#include <string>
+#include <utility>
+#include <vector>
#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/call/bitrate_allocation.h"
#include "api/rtc_event_log/rtc_event_log.h"
-#include "api/sequence_checker.h"
+#include "api/rtp_parameters.h"
#include "api/task_queue/task_queue_base.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
-#include "call/rtp_video_sender.h"
+#include "api/video/encoded_image.h"
+#include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_layers_allocation.h"
+#include "api/video_codecs/video_encoder.h"
+#include "call/bitrate_allocator.h"
+#include "call/rtp_config.h"
+#include "call/rtp_video_sender_interface.h"
#include "call/test/mock_bitrate_allocator.h"
#include "call/test/mock_rtp_transport_controller_send.h"
+#include "call/video_send_stream.h"
+#include "modules/pacing/packet_router.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_sequence_number_map.h"
-#include "modules/video_coding/fec_controller_default.h"
-#include "rtc_base/event.h"
+#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/experiments/alr_experiment.h"
-#include "rtc_base/fake_clock.h"
-#include "rtc_base/logging.h"
+#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/mock_transport.h"
#include "test/scoped_key_value_config.h"
#include "test/time_controller/simulated_time_controller.h"
+#include "video/config/video_encoder_config.h"
+#include "video/send_delay_stats.h"
+#include "video/send_statistics_proxy.h"
#include "video/test/mock_video_stream_encoder.h"
-#include "video/video_send_stream.h"
+#include "video/video_stream_encoder_interface.h"
namespace webrtc {
@@ -114,6 +133,7 @@
update.round_trip_time = TimeDelta::Zero();
return update;
}
+
} // namespace
class VideoSendStreamImplTest : public ::testing::Test {
@@ -159,13 +179,26 @@
EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_))
.WillOnce(Return(123000));
+ VideoEncoderConfig encoder_config;
+ encoder_config.max_bitrate_bps = initial_encoder_max_bitrate;
+ encoder_config.bitrate_priority = initial_encoder_bitrate_priority;
+ encoder_config.content_type = content_type;
+
std::map<uint32_t, RtpState> suspended_ssrcs;
std::map<uint32_t, RtpPayloadState> suspended_payload_states;
+
+ std::unique_ptr<NiceMock<MockVideoStreamEncoder>> video_stream_encoder =
+ std::make_unique<NiceMock<MockVideoStreamEncoder>>();
+ video_stream_encoder_ = video_stream_encoder.get();
auto ret = std::make_unique<VideoSendStreamImpl>(
- time_controller_.GetClock(), &stats_proxy_, &transport_controller_,
- &bitrate_allocator_, &video_stream_encoder_, &config_,
- initial_encoder_max_bitrate, initial_encoder_bitrate_priority,
- content_type, &rtp_video_sender_, field_trials_);
+ time_controller_.GetClock(),
+ /*num_cpu_cores=*/1, time_controller_.GetTaskQueueFactory(),
+ /*call_stats=*/nullptr, &transport_controller_,
+ /*metronome=*/nullptr, &bitrate_allocator_, &send_delay_stats_,
+ /*event_log=*/nullptr, config_.Copy(), encoder_config.Copy(),
+ suspended_ssrcs, suspended_payload_states,
+ /*fec_controller=*/nullptr, field_trials_,
+ std::move(video_stream_encoder));
// The call to GetStartBitrate() executes asynchronously on the tq.
// Ensure all tasks get to run.
@@ -181,7 +214,7 @@
NiceMock<MockTransport> transport_;
NiceMock<MockRtpTransportControllerSend> transport_controller_;
NiceMock<MockBitrateAllocator> bitrate_allocator_;
- NiceMock<MockVideoStreamEncoder> video_stream_encoder_;
+ NiceMock<MockVideoStreamEncoder>* video_stream_encoder_ = nullptr;
NiceMock<MockRtpVideoSender> rtp_video_sender_;
std::vector<bool> active_modules_;
@@ -218,6 +251,9 @@
config_.suspend_below_min_bitrate = kSuspend;
config_.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
1);
+ config_.rtp.ssrcs.emplace_back(1);
+ config_.rtp.ssrcs.emplace_back(2);
+
auto vss_impl = CreateVideoSendStreamImpl(
kDefaultInitialBitrateBps, kDefaultBitratePriority,
VideoEncoderConfig::ContentType::kRealtimeVideo);
@@ -248,9 +284,6 @@
int min_transmit_bitrate_bps = 30000;
- config_.rtp.ssrcs.emplace_back(1);
- config_.rtp.ssrcs.emplace_back(2);
-
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
.WillRepeatedly(Invoke(
[&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
@@ -284,6 +317,9 @@
config_.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
1);
config_.periodic_alr_bandwidth_probing = true;
+ config_.rtp.ssrcs.emplace_back(1);
+ config_.rtp.ssrcs.emplace_back(2);
+
auto vss_impl = CreateVideoSendStreamImpl(
kDefaultInitialBitrateBps, kDefaultBitratePriority,
VideoEncoderConfig::ContentType::kScreen);
@@ -316,9 +352,6 @@
// low_stream.target_bitrate_bps + high_stream.min_bitrate_bps.
int min_transmit_bitrate_bps = 400000;
- config_.rtp.ssrcs.emplace_back(1);
- config_.rtp.ssrcs.emplace_back(2);
-
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
.WillRepeatedly(Invoke(
[&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
@@ -347,6 +380,8 @@
UpdatesObserverOnConfigurationChangeWithSimulcastVideoHysteresis) {
test::ScopedKeyValueConfig hysteresis_experiment(
field_trials_, "WebRTC-VideoRateControl/video_hysteresis:1.25/");
+ config_.rtp.ssrcs.emplace_back(1);
+ config_.rtp.ssrcs.emplace_back(2);
auto vss_impl = CreateVideoSendStreamImpl(
kDefaultInitialBitrateBps, kDefaultBitratePriority,
@@ -374,9 +409,6 @@
high_stream.max_qp = 56;
high_stream.bitrate_priority = 1;
- config_.rtp.ssrcs.emplace_back(1);
- config_.rtp.ssrcs.emplace_back(2);
-
EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
.WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
MediaStreamAllocationConfig config) {
@@ -397,7 +429,8 @@
->OnEncoderConfigurationChanged(
std::vector<VideoStream>{low_stream, high_stream}, false,
VideoEncoderConfig::ContentType::kRealtimeVideo,
- /*min_transmit_bitrate_bps=*/0);
+ /*min_transmit_bitrate_bps=*/
+ 0);
});
time_controller_.AdvanceTime(TimeDelta::Zero());
vss_impl->Stop();
@@ -723,7 +756,7 @@
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
.WillOnce(Return(network_constrained_rate.bps()));
EXPECT_CALL(
- video_stream_encoder_,
+ *video_stream_encoder_,
OnBitrateUpdated(network_constrained_rate, network_constrained_rate,
network_constrained_rate, 0, _, 0));
static_cast<BitrateAllocatorObserver*>(vss_impl.get())
@@ -740,7 +773,7 @@
EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
.WillOnce(Return(rate_with_headroom.bps()));
- EXPECT_CALL(video_stream_encoder_,
+ EXPECT_CALL(*video_stream_encoder_,
OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
rate_with_headroom, 0, _, 0));
static_cast<BitrateAllocatorObserver*>(vss_impl.get())
@@ -757,7 +790,7 @@
.WillOnce(Return(rate_with_headroom.bps()));
const DataRate headroom_minus_protection =
rate_with_headroom - DataRate::BitsPerSec(protection_bitrate_bps);
- EXPECT_CALL(video_stream_encoder_,
+ EXPECT_CALL(*video_stream_encoder_,
OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
headroom_minus_protection, 0, _, 0));
static_cast<BitrateAllocatorObserver*>(vss_impl.get())
@@ -770,14 +803,14 @@
EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
.WillOnce(Return(rate_with_headroom.bps()));
- EXPECT_CALL(video_stream_encoder_,
+ EXPECT_CALL(*video_stream_encoder_,
OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
qvga_max_bitrate, 0, _, 0));
static_cast<BitrateAllocatorObserver*>(vss_impl.get())
->OnBitrateUpdated(update);
// Set rates to zero on stop.
- EXPECT_CALL(video_stream_encoder_,
+ EXPECT_CALL(*video_stream_encoder_,
OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
DataRate::Zero(), 0, 0, 0));
vss_impl->Stop();
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 3241740..37acd2d 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -75,7 +75,7 @@
#include "video/config/encoder_stream_factory.h"
#include "video/send_statistics_proxy.h"
#include "video/transport_adapter.h"
-#include "video/video_send_stream.h"
+#include "video/video_send_stream_impl.h"
namespace webrtc {
namespace test {
@@ -83,13 +83,13 @@
public:
explicit VideoSendStreamPeer(webrtc::VideoSendStream* base_class_stream)
: internal_stream_(
- static_cast<internal::VideoSendStream*>(base_class_stream)) {}
+ static_cast<internal::VideoSendStreamImpl*>(base_class_stream)) {}
absl::optional<float> GetPacingFactorOverride() const {
return internal_stream_->GetPacingFactorOverride();
}
private:
- internal::VideoSendStream const* const internal_stream_;
+ internal::VideoSendStreamImpl const* const internal_stream_;
};
} // namespace test