pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 +0000 | [diff] [blame] | 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 | */ |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 10 | #include "video/video_send_stream.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 +0000 | [diff] [blame] | 11 | |
perkj | 71ee44c | 2016-06-15 00:47:53 -0700 | [diff] [blame] | 12 | #include <utility> |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 +0000 | [diff] [blame] | 13 | |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 14 | #include "api/array_view.h" |
Niels Möller | 213618e | 2018-07-24 09:29:58 +0200 | [diff] [blame] | 15 | #include "api/video/video_stream_encoder_create.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 16 | #include "api/video/video_stream_encoder_settings.h" |
| 17 | #include "modules/rtp_rtcp/include/rtp_header_extension_map.h" |
Danil Chapovalov | 7b18992 | 2018-10-03 10:15:36 +0200 | [diff] [blame] | 18 | #include "modules/rtp_rtcp/source/rtp_header_extension_size.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 19 | #include "modules/rtp_rtcp/source/rtp_sender.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 20 | #include "rtc_base/checks.h" |
Stefan Holmer | dbdb3a0 | 2018-07-17 16:03:46 +0200 | [diff] [blame] | 21 | #include "rtc_base/logging.h" |
Danil Chapovalov | 1aa7581 | 2019-03-05 11:11:35 +0100 | [diff] [blame] | 22 | #include "rtc_base/task_utils/to_queued_task.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 23 | #include "system_wrappers/include/clock.h" |
Rasmus Brandt | bdc6c40 | 2018-11-06 12:55:53 +0100 | [diff] [blame] | 24 | #include "system_wrappers/include/field_trial.h" |
Sebastian Jansson | 8e0b15b | 2018-04-18 19:19:22 +0200 | [diff] [blame] | 25 | #include "video/video_send_stream_impl.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 +0000 | [diff] [blame] | 26 | |
| 27 | namespace webrtc { |
mflodman | 949c2f0 | 2015-10-16 02:31:11 -0700 | [diff] [blame] | 28 | |
Per | 83d0910 | 2016-04-15 14:59:13 +0200 | [diff] [blame] | 29 | namespace { |
| 30 | |
Rasmus Brandt | bdc6c40 | 2018-11-06 12:55:53 +0100 | [diff] [blame] | 31 | constexpr char kTargetBitrateRtcpFieldTrial[] = "WebRTC-Target-Bitrate-Rtcp"; |
| 32 | |
Stefan Holmer | dbdb3a0 | 2018-07-17 16:03:46 +0200 | [diff] [blame] | 33 | size_t CalculateMaxHeaderSize(const RtpConfig& config) { |
Ilya Nikolaevskiy | 1d037ae | 2018-03-15 15:46:17 +0100 | [diff] [blame] | 34 | size_t header_size = kRtpHeaderSize; |
| 35 | size_t extensions_size = 0; |
| 36 | size_t fec_extensions_size = 0; |
Benjamin Wright | 1f4173e | 2019-03-13 17:59:32 -0700 | [diff] [blame] | 37 | if (!config.extensions.empty()) { |
Ilya Nikolaevskiy | 1d037ae | 2018-03-15 15:46:17 +0100 | [diff] [blame] | 38 | RtpHeaderExtensionMap extensions_map(config.extensions); |
Danil Chapovalov | 7b18992 | 2018-10-03 10:15:36 +0200 | [diff] [blame] | 39 | extensions_size = RtpHeaderExtensionSize(RTPSender::VideoExtensionSizes(), |
| 40 | extensions_map); |
Ilya Nikolaevskiy | 1d037ae | 2018-03-15 15:46:17 +0100 | [diff] [blame] | 41 | fec_extensions_size = |
Danil Chapovalov | 7b18992 | 2018-10-03 10:15:36 +0200 | [diff] [blame] | 42 | RtpHeaderExtensionSize(RTPSender::FecExtensionSizes(), extensions_map); |
Ilya Nikolaevskiy | 1d037ae | 2018-03-15 15:46:17 +0100 | [diff] [blame] | 43 | } |
| 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 | |
Peter Boström | e449915 | 2016-02-05 11:13:28 +0100 | [diff] [blame] | 64 | } // namespace |
| 65 | |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 +0000 | [diff] [blame] | 66 | namespace internal { |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 67 | |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 +0000 | [diff] [blame] | 68 | VideoSendStream::VideoSendStream( |
Sebastian Jansson | 572c60f | 2019-03-04 18:30:41 +0100 | [diff] [blame] | 69 | Clock* clock, |
Peter Boström | 45553ae | 2015-05-08 13:54:38 +0200 | [diff] [blame] | 70 | int num_cpu_cores, |
Peter Boström | f16fcbe | 2015-04-30 12:16:05 +0200 | [diff] [blame] | 71 | ProcessThread* module_process_thread, |
Sebastian Jansson | 74682c1 | 2019-03-01 11:50:20 +0100 | [diff] [blame] | 72 | TaskQueueFactory* task_queue_factory, |
mflodman | e378702 | 2015-10-21 13:24:28 +0200 | [diff] [blame] | 73 | CallStats* call_stats, |
nisse | b8f9a32 | 2017-03-27 05:36:15 -0700 | [diff] [blame] | 74 | RtpTransportControllerSendInterface* transport, |
Niels Möller | 67b011d | 2018-10-22 13:00:40 +0200 | [diff] [blame] | 75 | BitrateAllocatorInterface* bitrate_allocator, |
asapersson | 35151f3 | 2016-05-02 23:44:01 -0700 | [diff] [blame] | 76 | SendDelayStats* send_delay_stats, |
terelius | adafe0b | 2016-05-26 01:58:40 -0700 | [diff] [blame] | 77 | RtcEventLog* event_log, |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 78 | VideoSendStream::Config config, |
| 79 | VideoEncoderConfig encoder_config, |
Åsa Persson | 4bece9a | 2017-10-06 10:04:04 +0200 | [diff] [blame] | 80 | const std::map<uint32_t, RtpState>& suspended_ssrcs, |
Ying Wang | 3b790f3 | 2018-01-19 17:58:57 +0100 | [diff] [blame] | 81 | const std::map<uint32_t, RtpPayloadState>& suspended_payload_states, |
Stefan Holmer | dbdb3a0 | 2018-07-17 16:03:46 +0200 | [diff] [blame] | 82 | std::unique_ptr<FecController> fec_controller) |
Sebastian Jansson | 0b69826 | 2019-03-07 09:17:19 +0100 | [diff] [blame] | 83 | : worker_queue_(transport->GetWorkerQueue()), |
Sebastian Jansson | 572c60f | 2019-03-04 18:30:41 +0100 | [diff] [blame] | 84 | stats_proxy_(clock, config, encoder_config.content_type), |
sprang | f24a064 | 2017-02-28 13:23:26 -0800 | [diff] [blame] | 85 | config_(std::move(config)), |
| 86 | content_type_(encoder_config.content_type) { |
Niels Möller | 4db138e | 2018-04-19 09:04:13 +0200 | [diff] [blame] | 87 | RTC_DCHECK(config_.encoder_settings.encoder_factory); |
Jiawei Ou | c2ebe21 | 2018-11-08 10:02:56 -0800 | [diff] [blame] | 88 | RTC_DCHECK(config_.encoder_settings.bitrate_allocator_factory); |
Niels Möller | 4db138e | 2018-04-19 09:04:13 +0200 | [diff] [blame] | 89 | |
Sebastian Jansson | 74682c1 | 2019-03-01 11:50:20 +0100 | [diff] [blame] | 90 | video_stream_encoder_ = |
Sebastian Jansson | 572c60f | 2019-03-04 18:30:41 +0100 | [diff] [blame] | 91 | CreateVideoStreamEncoder(clock, task_queue_factory, num_cpu_cores, |
| 92 | &stats_proxy_, config_.encoder_settings); |
Sebastian Jansson | 06b83aa | 2018-02-28 13:03:46 +0100 | [diff] [blame] | 93 | // TODO(srte): Initialization should not be done posted on a task queue. |
| 94 | // Note that the posted task must not outlive this scope since the closure |
| 95 | // references local variables. |
Danil Chapovalov | 1aa7581 | 2019-03-05 11:11:35 +0100 | [diff] [blame] | 96 | worker_queue_->PostTask(ToQueuedTask( |
Sebastian Jansson | 572c60f | 2019-03-04 18:30:41 +0100 | [diff] [blame] | 97 | [this, clock, call_stats, transport, bitrate_allocator, send_delay_stats, |
Sebastian Jansson | 06b83aa | 2018-02-28 13:03:46 +0100 | [diff] [blame] | 98 | event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states, |
Stefan Holmer | dbdb3a0 | 2018-07-17 16:03:46 +0200 | [diff] [blame] | 99 | &fec_controller]() { |
Sebastian Jansson | 06b83aa | 2018-02-28 13:03:46 +0100 | [diff] [blame] | 100 | send_stream_.reset(new VideoSendStreamImpl( |
Sebastian Jansson | 572c60f | 2019-03-04 18:30:41 +0100 | [diff] [blame] | 101 | clock, &stats_proxy_, worker_queue_, call_stats, transport, |
Sebastian Jansson | 06b83aa | 2018-02-28 13:03:46 +0100 | [diff] [blame] | 102 | bitrate_allocator, send_delay_stats, video_stream_encoder_.get(), |
| 103 | event_log, &config_, encoder_config.max_bitrate_bps, |
| 104 | encoder_config.bitrate_priority, suspended_ssrcs, |
| 105 | suspended_payload_states, encoder_config.content_type, |
Niels Möller | 4687915 | 2019-01-07 15:54:47 +0100 | [diff] [blame] | 106 | std::move(fec_controller), config_.media_transport)); |
Sebastian Jansson | 06b83aa | 2018-02-28 13:03:46 +0100 | [diff] [blame] | 107 | }, |
| 108 | [this]() { thread_sync_event_.Set(); })); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 109 | |
| 110 | // Wait for ConstructionTask to complete so that |send_stream_| can be used. |
| 111 | // |module_process_thread| must be registered and deregistered on the thread |
| 112 | // it was created on. |
| 113 | thread_sync_event_.Wait(rtc::Event::kForever); |
| 114 | send_stream_->RegisterProcessThread(module_process_thread); |
Rasmus Brandt | bdc6c40 | 2018-11-06 12:55:53 +0100 | [diff] [blame] | 115 | // TODO(sprang): Enable this also for regular video calls by default, if it |
| 116 | // works well. |
| 117 | if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen || |
| 118 | field_trial::IsEnabled(kTargetBitrateRtcpFieldTrial)) { |
Niels Möller | 0327c2d | 2018-05-21 14:09:31 +0200 | [diff] [blame] | 119 | video_stream_encoder_->SetBitrateAllocationObserver(send_stream_.get()); |
sprang | 44b3ef6 | 2017-01-13 07:30:25 -0800 | [diff] [blame] | 120 | } |
Ying Wang | 38a31b0 | 2017-12-21 12:26:19 +0000 | [diff] [blame] | 121 | |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 122 | ReconfigureVideoEncoder(std::move(encoder_config)); |
| 123 | } |
| 124 | |
| 125 | VideoSendStream::~VideoSendStream() { |
| 126 | RTC_DCHECK_RUN_ON(&thread_checker_); |
| 127 | RTC_DCHECK(!send_stream_); |
| 128 | } |
| 129 | |
Seth Hampson | cc7125f | 2018-02-02 08:46:16 -0800 | [diff] [blame] | 130 | void VideoSendStream::UpdateActiveSimulcastLayers( |
| 131 | const std::vector<bool> active_layers) { |
| 132 | RTC_DCHECK_RUN_ON(&thread_checker_); |
| 133 | RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers"; |
| 134 | VideoSendStreamImpl* send_stream = send_stream_.get(); |
| 135 | worker_queue_->PostTask([this, send_stream, active_layers] { |
| 136 | send_stream->UpdateActiveSimulcastLayers(active_layers); |
| 137 | thread_sync_event_.Set(); |
| 138 | }); |
| 139 | |
| 140 | thread_sync_event_.Wait(rtc::Event::kForever); |
| 141 | } |
| 142 | |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 143 | void VideoSendStream::Start() { |
| 144 | RTC_DCHECK_RUN_ON(&thread_checker_); |
Mirko Bonadei | 675513b | 2017-11-09 11:09:25 +0100 | [diff] [blame] | 145 | RTC_LOG(LS_INFO) << "VideoSendStream::Start"; |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 146 | VideoSendStreamImpl* send_stream = send_stream_.get(); |
| 147 | worker_queue_->PostTask([this, send_stream] { |
| 148 | send_stream->Start(); |
| 149 | thread_sync_event_.Set(); |
| 150 | }); |
| 151 | |
| 152 | // It is expected that after VideoSendStream::Start has been called, incoming |
mflodman | cc3d442 | 2017-08-03 08:27:51 -0700 | [diff] [blame] | 153 | // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to |
| 154 | // be synchronized. |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 155 | thread_sync_event_.Wait(rtc::Event::kForever); |
| 156 | } |
| 157 | |
| 158 | void VideoSendStream::Stop() { |
| 159 | RTC_DCHECK_RUN_ON(&thread_checker_); |
Mirko Bonadei | 675513b | 2017-11-09 11:09:25 +0100 | [diff] [blame] | 160 | RTC_LOG(LS_INFO) << "VideoSendStream::Stop"; |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 161 | VideoSendStreamImpl* send_stream = send_stream_.get(); |
| 162 | worker_queue_->PostTask([send_stream] { send_stream->Stop(); }); |
| 163 | } |
| 164 | |
perkj | a49cbd3 | 2016-09-16 07:53:41 -0700 | [diff] [blame] | 165 | void VideoSendStream::SetSource( |
perkj | 803d97f | 2016-11-01 11:45:46 -0700 | [diff] [blame] | 166 | rtc::VideoSourceInterface<webrtc::VideoFrame>* source, |
| 167 | const DegradationPreference& degradation_preference) { |
perkj | a49cbd3 | 2016-09-16 07:53:41 -0700 | [diff] [blame] | 168 | RTC_DCHECK_RUN_ON(&thread_checker_); |
mflodman | cc3d442 | 2017-08-03 08:27:51 -0700 | [diff] [blame] | 169 | video_stream_encoder_->SetSource(source, degradation_preference); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) { |
perkj | fa10b55 | 2016-10-02 23:45:26 -0700 | [diff] [blame] | 173 | // TODO(perkj): Some test cases in VideoSendStreamTest call |
| 174 | // ReconfigureVideoEncoder from the network thread. |
| 175 | // RTC_DCHECK_RUN_ON(&thread_checker_); |
sprang | f24a064 | 2017-02-28 13:23:26 -0800 | [diff] [blame] | 176 | RTC_DCHECK(content_type_ == config.content_type); |
Ilya Nikolaevskiy | 1d037ae | 2018-03-15 15:46:17 +0100 | [diff] [blame] | 177 | video_stream_encoder_->ConfigureEncoder( |
| 178 | std::move(config), |
Niels Möller | f133856 | 2018-04-26 09:51:47 +0200 | [diff] [blame] | 179 | config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp)); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | VideoSendStream::Stats VideoSendStream::GetStats() { |
| 183 | // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from |
| 184 | // a network thread. See comment in Call::GetStats(). |
| 185 | // RTC_DCHECK_RUN_ON(&thread_checker_); |
| 186 | return stats_proxy_.GetStats(); |
| 187 | } |
| 188 | |
Danil Chapovalov | b9b146c | 2018-06-15 12:28:07 +0200 | [diff] [blame] | 189 | absl::optional<float> VideoSendStream::GetPacingFactorOverride() const { |
Sebastian Jansson | a45c8da | 2018-01-16 10:55:29 +0100 | [diff] [blame] | 190 | return send_stream_->configured_pacing_factor_; |
| 191 | } |
| 192 | |
Åsa Persson | 4bece9a | 2017-10-06 10:04:04 +0200 | [diff] [blame] | 193 | void VideoSendStream::StopPermanentlyAndGetRtpStates( |
| 194 | VideoSendStream::RtpStateMap* rtp_state_map, |
| 195 | VideoSendStream::RtpPayloadStateMap* payload_state_map) { |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 196 | RTC_DCHECK_RUN_ON(&thread_checker_); |
mflodman | cc3d442 | 2017-08-03 08:27:51 -0700 | [diff] [blame] | 197 | video_stream_encoder_->Stop(); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 198 | send_stream_->DeRegisterProcessThread(); |
Sebastian Jansson | 1b2e90b | 2018-03-05 19:09:11 +0100 | [diff] [blame] | 199 | worker_queue_->PostTask([this, rtp_state_map, payload_state_map]() { |
| 200 | send_stream_->Stop(); |
| 201 | *rtp_state_map = send_stream_->GetRtpStates(); |
| 202 | *payload_state_map = send_stream_->GetRtpPayloadStates(); |
| 203 | send_stream_.reset(); |
| 204 | thread_sync_event_.Set(); |
| 205 | }); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 206 | thread_sync_event_.Wait(rtc::Event::kForever); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 207 | } |
| 208 | |
Niels Möller | 8fb1a6a | 2019-03-05 14:29:42 +0100 | [diff] [blame] | 209 | void VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 210 | // Called on a network thread. |
Niels Möller | 8fb1a6a | 2019-03-05 14:29:42 +0100 | [diff] [blame] | 211 | send_stream_->DeliverRtcp(packet, length); |
perkj | 26091b1 | 2016-09-01 01:17:40 -0700 | [diff] [blame] | 212 | } |
| 213 | |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 +0000 | [diff] [blame] | 214 | } // namespace internal |
| 215 | } // namespace webrtc |