blob: 02e8b17f9d2dbef9236317e28d1a9680714096de [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001/*
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 06:47:31 +020010#include "video/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000011
perkj71ee44c2016-06-15 00:47:53 -070012#include <utility>
pbos@webrtc.org29d58392013-05-16 12:08:03 +000013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/rtp_rtcp/source/rtp_sender.h"
Sebastian Jansson8e0b15b2018-04-18 19:19:22 +020015#include "video/video_send_stream_impl.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000016
17namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070018
Ying Wang3b790f32018-01-19 17:58:57 +010019
Per83d09102016-04-15 14:59:13 +020020namespace {
21
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +010022size_t CalculateMaxHeaderSize(const VideoSendStream::Config::Rtp& config) {
23 size_t header_size = kRtpHeaderSize;
24 size_t extensions_size = 0;
25 size_t fec_extensions_size = 0;
26 if (config.extensions.size() > 0) {
27 RtpHeaderExtensionMap extensions_map(config.extensions);
28 extensions_size =
29 extensions_map.GetTotalLengthInBytes(RTPSender::VideoExtensionSizes());
30 fec_extensions_size =
31 extensions_map.GetTotalLengthInBytes(RTPSender::FecExtensionSizes());
32 }
33 header_size += extensions_size;
34 if (config.flexfec.payload_type >= 0) {
35 // All FEC extensions again plus maximum FlexFec overhead.
36 header_size += fec_extensions_size + 32;
37 } else {
38 if (config.ulpfec.ulpfec_payload_type >= 0) {
39 // Header with all the FEC extensions will be repeated plus maximum
40 // UlpFec overhead.
41 header_size += fec_extensions_size + 18;
42 }
43 if (config.ulpfec.red_payload_type >= 0) {
44 header_size += 1; // RED header.
45 }
46 }
47 // Additional room for Rtx.
48 if (config.rtx.payload_type >= 0)
49 header_size += kRtxHeaderSize;
50 return header_size;
51}
52
Peter Boströme4499152016-02-05 11:13:28 +010053} // namespace
54
pbos@webrtc.org024e4d52014-05-15 10:03:24 +000055namespace internal {
perkj26091b12016-09-01 01:17:40 -070056
perkj26091b12016-09-01 01:17:40 -070057
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000058VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +020059 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +020060 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -070061 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +020062 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -070063 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -080064 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -070065 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070066 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -070067 VideoSendStream::Config config,
68 VideoEncoderConfig encoder_config,
Åsa Persson4bece9a2017-10-06 10:04:04 +020069 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Ying Wang3b790f32018-01-19 17:58:57 +010070 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Sebastian Jansson25e51102018-03-01 15:56:47 +010071 std::unique_ptr<FecController> fec_controller,
72 RateLimiter* retransmission_limiter)
perkj26091b12016-09-01 01:17:40 -070073 : worker_queue_(worker_queue),
74 thread_sync_event_(false /* manual_reset */, false),
75 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -080076 config,
77 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -080078 config_(std::move(config)),
79 content_type_(encoder_config.content_type) {
Niels Möller73f29cb2018-01-31 16:09:31 +010080 video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
81 num_cpu_cores, &stats_proxy_,
82 config_.encoder_settings,
83 config_.pre_encode_callback,
Niels Möllerd1f7eb62018-03-28 16:40:58 +020084 rtc::MakeUnique<OveruseFrameDetector>(&stats_proxy_));
Sebastian Jansson06b83aa2018-02-28 13:03:46 +010085 // TODO(srte): Initialization should not be done posted on a task queue.
86 // Note that the posted task must not outlive this scope since the closure
87 // references local variables.
88 worker_queue_->PostTask(rtc::NewClosure(
89 [this, call_stats, transport, bitrate_allocator, send_delay_stats,
90 event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states,
Sebastian Jansson25e51102018-03-01 15:56:47 +010091 &fec_controller, retransmission_limiter]() {
Sebastian Jansson06b83aa2018-02-28 13:03:46 +010092 send_stream_.reset(new VideoSendStreamImpl(
93 &stats_proxy_, worker_queue_, call_stats, transport,
94 bitrate_allocator, send_delay_stats, video_stream_encoder_.get(),
95 event_log, &config_, encoder_config.max_bitrate_bps,
96 encoder_config.bitrate_priority, suspended_ssrcs,
97 suspended_payload_states, encoder_config.content_type,
Sebastian Jansson25e51102018-03-01 15:56:47 +010098 std::move(fec_controller), retransmission_limiter));
Sebastian Jansson06b83aa2018-02-28 13:03:46 +010099 },
100 [this]() { thread_sync_event_.Set(); }));
perkj26091b12016-09-01 01:17:40 -0700101
102 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
103 // |module_process_thread| must be registered and deregistered on the thread
104 // it was created on.
105 thread_sync_event_.Wait(rtc::Event::kForever);
106 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800107 // TODO(sprang): Enable this also for regular video calls if it works well.
108 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
109 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700110 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800111 }
Ying Wang38a31b02017-12-21 12:26:19 +0000112
perkj26091b12016-09-01 01:17:40 -0700113 ReconfigureVideoEncoder(std::move(encoder_config));
114}
115
116VideoSendStream::~VideoSendStream() {
117 RTC_DCHECK_RUN_ON(&thread_checker_);
118 RTC_DCHECK(!send_stream_);
119}
120
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800121void VideoSendStream::UpdateActiveSimulcastLayers(
122 const std::vector<bool> active_layers) {
123 RTC_DCHECK_RUN_ON(&thread_checker_);
124 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
125 VideoSendStreamImpl* send_stream = send_stream_.get();
126 worker_queue_->PostTask([this, send_stream, active_layers] {
127 send_stream->UpdateActiveSimulcastLayers(active_layers);
128 thread_sync_event_.Set();
129 });
130
131 thread_sync_event_.Wait(rtc::Event::kForever);
132}
133
perkj26091b12016-09-01 01:17:40 -0700134void VideoSendStream::Start() {
135 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100136 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700137 VideoSendStreamImpl* send_stream = send_stream_.get();
138 worker_queue_->PostTask([this, send_stream] {
139 send_stream->Start();
140 thread_sync_event_.Set();
141 });
142
143 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700144 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
145 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700146 thread_sync_event_.Wait(rtc::Event::kForever);
147}
148
149void VideoSendStream::Stop() {
150 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100151 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700152 VideoSendStreamImpl* send_stream = send_stream_.get();
153 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
154}
155
perkja49cbd32016-09-16 07:53:41 -0700156void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700157 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
158 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700159 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700160 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700161}
162
163void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700164 // TODO(perkj): Some test cases in VideoSendStreamTest call
165 // ReconfigureVideoEncoder from the network thread.
166 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800167 RTC_DCHECK(content_type_ == config.content_type);
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +0100168 video_stream_encoder_->ConfigureEncoder(
169 std::move(config),
170 config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp),
171 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700172}
173
174VideoSendStream::Stats VideoSendStream::GetStats() {
175 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
176 // a network thread. See comment in Call::GetStats().
177 // RTC_DCHECK_RUN_ON(&thread_checker_);
178 return stats_proxy_.GetStats();
179}
180
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100181rtc::Optional<float> VideoSendStream::GetPacingFactorOverride() const {
182 return send_stream_->configured_pacing_factor_;
183}
184
perkj26091b12016-09-01 01:17:40 -0700185void VideoSendStream::SignalNetworkState(NetworkState state) {
186 RTC_DCHECK_RUN_ON(&thread_checker_);
187 VideoSendStreamImpl* send_stream = send_stream_.get();
188 worker_queue_->PostTask(
189 [send_stream, state] { send_stream->SignalNetworkState(state); });
190}
191
Åsa Persson4bece9a2017-10-06 10:04:04 +0200192void VideoSendStream::StopPermanentlyAndGetRtpStates(
193 VideoSendStream::RtpStateMap* rtp_state_map,
194 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700195 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700196 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700197 send_stream_->DeRegisterProcessThread();
Sebastian Jansson1b2e90b2018-03-05 19:09:11 +0100198 worker_queue_->PostTask([this, rtp_state_map, payload_state_map]() {
199 send_stream_->Stop();
200 *rtp_state_map = send_stream_->GetRtpStates();
201 *payload_state_map = send_stream_->GetRtpPayloadStates();
202 send_stream_.reset();
203 thread_sync_event_.Set();
204 });
perkj26091b12016-09-01 01:17:40 -0700205 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700206}
207
nisse284542b2017-01-10 08:58:32 -0800208void VideoSendStream::SetTransportOverhead(
209 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800210 RTC_DCHECK_RUN_ON(&thread_checker_);
211 VideoSendStreamImpl* send_stream = send_stream_.get();
212 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
213 send_stream->SetTransportOverhead(transport_overhead_per_packet);
214 });
215}
216
perkj26091b12016-09-01 01:17:40 -0700217bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
218 // Called on a network thread.
219 return send_stream_->DeliverRtcp(packet, length);
220}
221
palmkviste75f2042016-09-28 06:19:48 -0700222void VideoSendStream::EnableEncodedFrameRecording(
223 const std::vector<rtc::PlatformFile>& files,
224 size_t byte_limit) {
225 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
226}
227
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000228} // namespace internal
229} // namespace webrtc