blob: 91c246c66eed27bf346cb7279a6f73d7f888914b [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:031/*
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 */
Mirko Bonadei92ea95e2017-09-15 04:47:3110#include "video/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:0311
perkj71ee44c2016-06-15 07:47:5312#include <utility>
pbos@webrtc.org29d58392013-05-16 12:08:0313
Yves Gerey3e707812018-11-28 15:47:4914#include "api/array_view.h"
Yves Gerey3e707812018-11-28 15:47:4915#include "api/video/video_stream_encoder_settings.h"
16#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
Danil Chapovalov7b189922018-10-03 08:15:3617#include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3118#include "modules/rtp_rtcp/source/rtp_sender.h"
Yves Gerey3e707812018-11-28 15:47:4919#include "rtc_base/checks.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4620#include "rtc_base/logging.h"
Rasmus Brandt9731a142020-02-26 14:42:1921#include "rtc_base/strings/string_builder.h"
Danil Chapovalov1aa75812019-03-05 10:11:3522#include "rtc_base/task_utils/to_queued_task.h"
Yves Gerey3e707812018-11-28 15:47:4923#include "system_wrappers/include/clock.h"
Rasmus Brandtbdc6c402018-11-06 11:55:5324#include "system_wrappers/include/field_trial.h"
Per Kjellanderb03b6c82021-01-03 09:26:0325#include "video/adaptation/overuse_frame_detector.h"
Sebastian Jansson8e0b15b2018-04-18 17:19:2226#include "video/video_send_stream_impl.h"
Per Kjellanderb03b6c82021-01-03 09:26:0327#include "video/video_stream_encoder.h"
pbos@webrtc.org29d58392013-05-16 12:08:0328
29namespace webrtc {
mflodman949c2f02015-10-16 09:31:1130
Per83d09102016-04-15 12:59:1331namespace {
32
Stefan Holmerdbdb3a02018-07-17 14:03:4633size_t CalculateMaxHeaderSize(const RtpConfig& config) {
Ilya Nikolaevskiy1d037ae2018-03-15 14:46:1734 size_t header_size = kRtpHeaderSize;
35 size_t extensions_size = 0;
36 size_t fec_extensions_size = 0;
Benjamin Wright1f4173e2019-03-14 00:59:3237 if (!config.extensions.empty()) {
Ilya Nikolaevskiy1d037ae2018-03-15 14:46:1738 RtpHeaderExtensionMap extensions_map(config.extensions);
Danil Chapovalov7b189922018-10-03 08:15:3639 extensions_size = RtpHeaderExtensionSize(RTPSender::VideoExtensionSizes(),
40 extensions_map);
Ilya Nikolaevskiy1d037ae2018-03-15 14:46:1741 fec_extensions_size =
Danil Chapovalov7b189922018-10-03 08:15:3642 RtpHeaderExtensionSize(RTPSender::FecExtensionSizes(), extensions_map);
Ilya Nikolaevskiy1d037ae2018-03-15 14:46:1743 }
44 header_size += extensions_size;
45 if (config.flexfec.payload_type >= 0) {
46 // All FEC extensions again plus maximum FlexFec overhead.
47 header_size += fec_extensions_size + 32;
48 } else {
49 if (config.ulpfec.ulpfec_payload_type >= 0) {
50 // Header with all the FEC extensions will be repeated plus maximum
51 // UlpFec overhead.
52 header_size += fec_extensions_size + 18;
53 }
54 if (config.ulpfec.red_payload_type >= 0) {
55 header_size += 1; // RED header.
56 }
57 }
58 // Additional room for Rtx.
59 if (config.rtx.payload_type >= 0)
60 header_size += kRtxHeaderSize;
61 return header_size;
62}
63
Per Kjellanderb03b6c82021-01-03 09:26:0364VideoStreamEncoder::BitrateAllocationCallbackType
65GetBitrateAllocationCallbackType(const VideoSendStream::Config& config) {
66 if (webrtc::RtpExtension::FindHeaderExtensionByUri(
67 config.rtp.extensions,
68 webrtc::RtpExtension::kVideoLayersAllocationUri)) {
69 return VideoStreamEncoder::BitrateAllocationCallbackType::
70 kVideoLayersAllocation;
71 }
72 if (field_trial::IsEnabled("WebRTC-Target-Bitrate-Rtcp")) {
73 return VideoStreamEncoder::BitrateAllocationCallbackType::
74 kVideoBitrateAllocation;
75 }
76 return VideoStreamEncoder::BitrateAllocationCallbackType::
77 kVideoBitrateAllocationWhenScreenSharing;
78}
79
Peter Boströme4499152016-02-05 10:13:2880} // namespace
81
pbos@webrtc.org024e4d52014-05-15 10:03:2482namespace internal {
perkj26091b12016-09-01 08:17:4083
pbos@webrtc.org2bb1bda2014-07-07 13:06:4884VideoSendStream::VideoSendStream(
Sebastian Jansson572c60f2019-03-04 17:30:4185 Clock* clock,
Peter Boström45553ae2015-05-08 11:54:3886 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 10:16:0587 ProcessThread* module_process_thread,
Sebastian Jansson74682c12019-03-01 10:50:2088 TaskQueueFactory* task_queue_factory,
Tommi8ae18ad2020-05-03 20:45:0289 RtcpRttStats* call_stats,
nisseb8f9a322017-03-27 12:36:1590 RtpTransportControllerSendInterface* transport,
Niels Möller67b011d2018-10-22 11:00:4091 BitrateAllocatorInterface* bitrate_allocator,
asapersson35151f32016-05-03 06:44:0192 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 08:58:4093 RtcEventLog* event_log,
perkj26091b12016-09-01 08:17:4094 VideoSendStream::Config config,
95 VideoEncoderConfig encoder_config,
Åsa Persson4bece9a2017-10-06 08:04:0496 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Ying Wang3b790f32018-01-19 16:58:5797 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Stefan Holmerdbdb3a02018-07-17 14:03:4698 std::unique_ptr<FecController> fec_controller)
Sebastian Jansson0b698262019-03-07 08:17:1999 : worker_queue_(transport->GetWorkerQueue()),
Sebastian Jansson572c60f2019-03-04 17:30:41100 stats_proxy_(clock, config, encoder_config.content_type),
sprangf24a0642017-02-28 21:23:26101 config_(std::move(config)),
102 content_type_(encoder_config.content_type) {
Niels Möller4db138e2018-04-19 07:04:13103 RTC_DCHECK(config_.encoder_settings.encoder_factory);
Jiawei Ouc2ebe212018-11-08 18:02:56104 RTC_DCHECK(config_.encoder_settings.bitrate_allocator_factory);
Niels Möller4db138e2018-04-19 07:04:13105
Per Kjellanderb03b6c82021-01-03 09:26:03106 video_stream_encoder_ = std::make_unique<VideoStreamEncoder>(
107 clock, num_cpu_cores, &stats_proxy_, config_.encoder_settings,
108 std::make_unique<OveruseFrameDetector>(&stats_proxy_), task_queue_factory,
109 GetBitrateAllocationCallbackType(config_));
110
Sebastian Jansson06b83aa2018-02-28 12:03:46111 // TODO(srte): Initialization should not be done posted on a task queue.
112 // Note that the posted task must not outlive this scope since the closure
113 // references local variables.
Danil Chapovalov1aa75812019-03-05 10:11:35114 worker_queue_->PostTask(ToQueuedTask(
Sebastian Jansson572c60f2019-03-04 17:30:41115 [this, clock, call_stats, transport, bitrate_allocator, send_delay_stats,
Sebastian Jansson06b83aa2018-02-28 12:03:46116 event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states,
Stefan Holmerdbdb3a02018-07-17 14:03:46117 &fec_controller]() {
Sebastian Jansson06b83aa2018-02-28 12:03:46118 send_stream_.reset(new VideoSendStreamImpl(
Sebastian Jansson572c60f2019-03-04 17:30:41119 clock, &stats_proxy_, worker_queue_, call_stats, transport,
Sebastian Jansson06b83aa2018-02-28 12:03:46120 bitrate_allocator, send_delay_stats, video_stream_encoder_.get(),
121 event_log, &config_, encoder_config.max_bitrate_bps,
122 encoder_config.bitrate_priority, suspended_ssrcs,
123 suspended_payload_states, encoder_config.content_type,
Bjorn A Mellem7a9a0922019-11-26 17:19:40124 std::move(fec_controller)));
Sebastian Jansson06b83aa2018-02-28 12:03:46125 },
126 [this]() { thread_sync_event_.Set(); }));
perkj26091b12016-09-01 08:17:40127
128 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
129 // |module_process_thread| must be registered and deregistered on the thread
130 // it was created on.
131 thread_sync_event_.Wait(rtc::Event::kForever);
132 send_stream_->RegisterProcessThread(module_process_thread);
perkj26091b12016-09-01 08:17:40133 ReconfigureVideoEncoder(std::move(encoder_config));
134}
135
136VideoSendStream::~VideoSendStream() {
137 RTC_DCHECK_RUN_ON(&thread_checker_);
138 RTC_DCHECK(!send_stream_);
139}
140
Seth Hampsoncc7125f2018-02-02 16:46:16141void VideoSendStream::UpdateActiveSimulcastLayers(
142 const std::vector<bool> active_layers) {
143 RTC_DCHECK_RUN_ON(&thread_checker_);
Rasmus Brandt9731a142020-02-26 14:42:19144
145 rtc::StringBuilder active_layers_string;
146 active_layers_string << "{";
147 for (size_t i = 0; i < active_layers.size(); ++i) {
148 if (active_layers[i]) {
149 active_layers_string << "1";
150 } else {
151 active_layers_string << "0";
152 }
153 if (i < active_layers.size() - 1) {
154 active_layers_string << ", ";
155 }
156 }
157 active_layers_string << "}";
158 RTC_LOG(LS_INFO) << "UpdateActiveSimulcastLayers: "
159 << active_layers_string.str();
160
Seth Hampsoncc7125f2018-02-02 16:46:16161 VideoSendStreamImpl* send_stream = send_stream_.get();
162 worker_queue_->PostTask([this, send_stream, active_layers] {
163 send_stream->UpdateActiveSimulcastLayers(active_layers);
164 thread_sync_event_.Set();
165 });
166
167 thread_sync_event_.Wait(rtc::Event::kForever);
168}
169
perkj26091b12016-09-01 08:17:40170void VideoSendStream::Start() {
171 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 10:09:25172 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 08:17:40173 VideoSendStreamImpl* send_stream = send_stream_.get();
174 worker_queue_->PostTask([this, send_stream] {
175 send_stream->Start();
176 thread_sync_event_.Set();
177 });
178
179 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 15:27:51180 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
181 // be synchronized.
perkj26091b12016-09-01 08:17:40182 thread_sync_event_.Wait(rtc::Event::kForever);
183}
184
185void VideoSendStream::Stop() {
186 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 10:09:25187 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 08:17:40188 VideoSendStreamImpl* send_stream = send_stream_.get();
189 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
190}
191
Henrik Boströmf4a99912020-06-11 10:07:14192void VideoSendStream::AddAdaptationResource(
193 rtc::scoped_refptr<Resource> resource) {
194 RTC_DCHECK_RUN_ON(&thread_checker_);
195 video_stream_encoder_->AddAdaptationResource(resource);
196}
197
198std::vector<rtc::scoped_refptr<Resource>>
199VideoSendStream::GetAdaptationResources() {
200 RTC_DCHECK_RUN_ON(&thread_checker_);
201 return video_stream_encoder_->GetAdaptationResources();
202}
203
perkja49cbd32016-09-16 14:53:41204void VideoSendStream::SetSource(
perkj803d97f2016-11-01 18:45:46205 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
206 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 14:53:41207 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 15:27:51208 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 08:17:40209}
210
211void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-03 06:45:26212 // TODO(perkj): Some test cases in VideoSendStreamTest call
213 // ReconfigureVideoEncoder from the network thread.
214 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 21:23:26215 RTC_DCHECK(content_type_ == config.content_type);
Ilya Nikolaevskiy1d037ae2018-03-15 14:46:17216 video_stream_encoder_->ConfigureEncoder(
217 std::move(config),
Niels Möllerf1338562018-04-26 07:51:47218 config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp));
perkj26091b12016-09-01 08:17:40219}
220
221VideoSendStream::Stats VideoSendStream::GetStats() {
222 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
223 // a network thread. See comment in Call::GetStats().
224 // RTC_DCHECK_RUN_ON(&thread_checker_);
225 return stats_proxy_.GetStats();
226}
227
Danil Chapovalovb9b146c2018-06-15 10:28:07228absl::optional<float> VideoSendStream::GetPacingFactorOverride() const {
Sebastian Janssona45c8da2018-01-16 09:55:29229 return send_stream_->configured_pacing_factor_;
230}
231
Åsa Persson4bece9a2017-10-06 08:04:04232void VideoSendStream::StopPermanentlyAndGetRtpStates(
233 VideoSendStream::RtpStateMap* rtp_state_map,
234 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 08:17:40235 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 15:27:51236 video_stream_encoder_->Stop();
perkj26091b12016-09-01 08:17:40237 send_stream_->DeRegisterProcessThread();
Sebastian Jansson1b2e90b2018-03-05 18:09:11238 worker_queue_->PostTask([this, rtp_state_map, payload_state_map]() {
239 send_stream_->Stop();
240 *rtp_state_map = send_stream_->GetRtpStates();
241 *payload_state_map = send_stream_->GetRtpPayloadStates();
242 send_stream_.reset();
243 thread_sync_event_.Set();
244 });
perkj26091b12016-09-01 08:17:40245 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 08:17:40246}
247
Niels Möller8fb1a6a2019-03-05 13:29:42248void VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
perkj26091b12016-09-01 08:17:40249 // Called on a network thread.
Niels Möller8fb1a6a2019-03-05 13:29:42250 send_stream_->DeliverRtcp(packet, length);
perkj26091b12016-09-01 08:17:40251}
252
pbos@webrtc.org29d58392013-05-16 12:08:03253} // namespace internal
254} // namespace webrtc