1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "video/video_send_stream.h"
11 
12 #include <utility>
13 
14 #include "api/array_view.h"
15 #include "api/video/video_stream_encoder_create.h"
16 #include "api/video/video_stream_encoder_settings.h"
17 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
18 #include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
19 #include "modules/rtp_rtcp/source/rtp_sender.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/logging.h"
22 #include "rtc_base/strings/string_builder.h"
23 #include "rtc_base/task_utils/to_queued_task.h"
24 #include "system_wrappers/include/clock.h"
25 #include "system_wrappers/include/field_trial.h"
26 #include "video/video_send_stream_impl.h"
27 
28 namespace webrtc {
29 
30 namespace {
31 
32 constexpr char kTargetBitrateRtcpFieldTrial[] = "WebRTC-Target-Bitrate-Rtcp";
33 
CalculateMaxHeaderSize(const RtpConfig & config)34 size_t CalculateMaxHeaderSize(const RtpConfig& config) {
35   size_t header_size = kRtpHeaderSize;
36   size_t extensions_size = 0;
37   size_t fec_extensions_size = 0;
38   if (!config.extensions.empty()) {
39     RtpHeaderExtensionMap extensions_map(config.extensions);
40     extensions_size = RtpHeaderExtensionSize(RTPSender::VideoExtensionSizes(),
41                                              extensions_map);
42     fec_extensions_size =
43         RtpHeaderExtensionSize(RTPSender::FecExtensionSizes(), extensions_map);
44   }
45   header_size += extensions_size;
46   if (config.flexfec.payload_type >= 0) {
47     // All FEC extensions again plus maximum FlexFec overhead.
48     header_size += fec_extensions_size + 32;
49   } else {
50     if (config.ulpfec.ulpfec_payload_type >= 0) {
51       // Header with all the FEC extensions will be repeated plus maximum
52       // UlpFec overhead.
53       header_size += fec_extensions_size + 18;
54     }
55     if (config.ulpfec.red_payload_type >= 0) {
56       header_size += 1;  // RED header.
57     }
58   }
59   // Additional room for Rtx.
60   if (config.rtx.payload_type >= 0)
61     header_size += kRtxHeaderSize;
62   return header_size;
63 }
64 
65 }  // namespace
66 
67 namespace internal {
68 
VideoSendStream(Clock * clock,int num_cpu_cores,ProcessThread * module_process_thread,TaskQueueFactory * task_queue_factory,RtcpRttStats * call_stats,RtpTransportControllerSendInterface * transport,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)69 VideoSendStream::VideoSendStream(
70     Clock* clock,
71     int num_cpu_cores,
72     ProcessThread* module_process_thread,
73     TaskQueueFactory* task_queue_factory,
74     RtcpRttStats* call_stats,
75     RtpTransportControllerSendInterface* transport,
76     BitrateAllocatorInterface* bitrate_allocator,
77     SendDelayStats* send_delay_stats,
78     RtcEventLog* event_log,
79     VideoSendStream::Config config,
80     VideoEncoderConfig encoder_config,
81     const std::map<uint32_t, RtpState>& suspended_ssrcs,
82     const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
83     std::unique_ptr<FecController> fec_controller)
84     : worker_queue_(transport->GetWorkerQueue()),
85       stats_proxy_(clock, config, encoder_config.content_type),
86       config_(std::move(config)),
87       content_type_(encoder_config.content_type) {
88   RTC_DCHECK(config_.encoder_settings.encoder_factory);
89   RTC_DCHECK(config_.encoder_settings.bitrate_allocator_factory);
90 
91   video_stream_encoder_ =
92       CreateVideoStreamEncoder(clock, task_queue_factory, num_cpu_cores,
93                                &stats_proxy_, config_.encoder_settings);
94   // TODO(srte): Initialization should not be done posted on a task queue.
95   // Note that the posted task must not outlive this scope since the closure
96   // references local variables.
97   worker_queue_->PostTask(ToQueuedTask(
98       [this, clock, call_stats, transport, bitrate_allocator, send_delay_stats,
99        event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states,
100        &fec_controller]() {
101         send_stream_.reset(new VideoSendStreamImpl(
102             clock, &stats_proxy_, worker_queue_, call_stats, transport,
103             bitrate_allocator, send_delay_stats, video_stream_encoder_.get(),
104             event_log, &config_, encoder_config.max_bitrate_bps,
105             encoder_config.bitrate_priority, suspended_ssrcs,
106             suspended_payload_states, encoder_config.content_type,
107             std::move(fec_controller)));
108       },
109       [this]() { thread_sync_event_.Set(); }));
110 
111   // Wait for ConstructionTask to complete so that |send_stream_| can be used.
112   // |module_process_thread| must be registered and deregistered on the thread
113   // it was created on.
114   thread_sync_event_.Wait(rtc::Event::kForever);
115   send_stream_->RegisterProcessThread(module_process_thread);
116   // TODO(sprang): Enable this also for regular video calls by default, if it
117   // works well.
118   if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen ||
119       field_trial::IsEnabled(kTargetBitrateRtcpFieldTrial)) {
120     video_stream_encoder_->SetBitrateAllocationObserver(send_stream_.get());
121   }
122 
123   ReconfigureVideoEncoder(std::move(encoder_config));
124 }
125 
~VideoSendStream()126 VideoSendStream::~VideoSendStream() {
127   RTC_DCHECK_RUN_ON(&thread_checker_);
128   RTC_DCHECK(!send_stream_);
129 }
130 
UpdateActiveSimulcastLayers(const std::vector<bool> active_layers)131 void VideoSendStream::UpdateActiveSimulcastLayers(
132     const std::vector<bool> active_layers) {
133   RTC_DCHECK_RUN_ON(&thread_checker_);
134 
135   rtc::StringBuilder active_layers_string;
136   active_layers_string << "{";
137   for (size_t i = 0; i < active_layers.size(); ++i) {
138     if (active_layers[i]) {
139       active_layers_string << "1";
140     } else {
141       active_layers_string << "0";
142     }
143     if (i < active_layers.size() - 1) {
144       active_layers_string << ", ";
145     }
146   }
147   active_layers_string << "}";
148   RTC_LOG(LS_INFO) << "UpdateActiveSimulcastLayers: "
149                    << active_layers_string.str();
150 
151   VideoSendStreamImpl* send_stream = send_stream_.get();
152   worker_queue_->PostTask([this, send_stream, active_layers] {
153     send_stream->UpdateActiveSimulcastLayers(active_layers);
154     thread_sync_event_.Set();
155   });
156 
157   thread_sync_event_.Wait(rtc::Event::kForever);
158 }
159 
Start()160 void VideoSendStream::Start() {
161   RTC_DCHECK_RUN_ON(&thread_checker_);
162   RTC_LOG(LS_INFO) << "VideoSendStream::Start";
163   VideoSendStreamImpl* send_stream = send_stream_.get();
164   worker_queue_->PostTask([this, send_stream] {
165     send_stream->Start();
166     thread_sync_event_.Set();
167   });
168 
169   // It is expected that after VideoSendStream::Start has been called, incoming
170   // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
171   // be synchronized.
172   thread_sync_event_.Wait(rtc::Event::kForever);
173 }
174 
Stop()175 void VideoSendStream::Stop() {
176   RTC_DCHECK_RUN_ON(&thread_checker_);
177   RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
178   VideoSendStreamImpl* send_stream = send_stream_.get();
179   worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
180 }
181 
AddAdaptationResource(rtc::scoped_refptr<Resource> resource)182 void VideoSendStream::AddAdaptationResource(
183     rtc::scoped_refptr<Resource> resource) {
184   RTC_DCHECK_RUN_ON(&thread_checker_);
185   video_stream_encoder_->AddAdaptationResource(resource);
186 }
187 
188 std::vector<rtc::scoped_refptr<Resource>>
GetAdaptationResources()189 VideoSendStream::GetAdaptationResources() {
190   RTC_DCHECK_RUN_ON(&thread_checker_);
191   return video_stream_encoder_->GetAdaptationResources();
192 }
193 
SetSource(rtc::VideoSourceInterface<webrtc::VideoFrame> * source,const DegradationPreference & degradation_preference)194 void VideoSendStream::SetSource(
195     rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
196     const DegradationPreference& degradation_preference) {
197   RTC_DCHECK_RUN_ON(&thread_checker_);
198   video_stream_encoder_->SetSource(source, degradation_preference);
199 }
200 
ReconfigureVideoEncoder(VideoEncoderConfig config)201 void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
202   // TODO(perkj): Some test cases in VideoSendStreamTest call
203   // ReconfigureVideoEncoder from the network thread.
204   // RTC_DCHECK_RUN_ON(&thread_checker_);
205   RTC_DCHECK(content_type_ == config.content_type);
206   video_stream_encoder_->ConfigureEncoder(
207       std::move(config),
208       config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp));
209 }
210 
GetStats()211 VideoSendStream::Stats VideoSendStream::GetStats() {
212   // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
213   // a network thread. See comment in Call::GetStats().
214   // RTC_DCHECK_RUN_ON(&thread_checker_);
215   return stats_proxy_.GetStats();
216 }
217 
GetPacingFactorOverride() const218 absl::optional<float> VideoSendStream::GetPacingFactorOverride() const {
219   return send_stream_->configured_pacing_factor_;
220 }
221 
StopPermanentlyAndGetRtpStates(VideoSendStream::RtpStateMap * rtp_state_map,VideoSendStream::RtpPayloadStateMap * payload_state_map)222 void VideoSendStream::StopPermanentlyAndGetRtpStates(
223     VideoSendStream::RtpStateMap* rtp_state_map,
224     VideoSendStream::RtpPayloadStateMap* payload_state_map) {
225   RTC_DCHECK_RUN_ON(&thread_checker_);
226   video_stream_encoder_->Stop();
227   send_stream_->DeRegisterProcessThread();
228   worker_queue_->PostTask([this, rtp_state_map, payload_state_map]() {
229     send_stream_->Stop();
230     *rtp_state_map = send_stream_->GetRtpStates();
231     *payload_state_map = send_stream_->GetRtpPayloadStates();
232     send_stream_.reset();
233     thread_sync_event_.Set();
234   });
235   thread_sync_event_.Wait(rtc::Event::kForever);
236 }
237 
DeliverRtcp(const uint8_t * packet,size_t length)238 void VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
239   // Called on a network thread.
240   send_stream_->DeliverRtcp(packet, length);
241 }
242 
243 }  // namespace internal
244 }  // namespace webrtc
245