blob: 88362f628822229b19526326f65076e353322f68 [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öller4db138e2018-04-19 09:04:13 +020080 RTC_DCHECK(config_.encoder_settings.encoder_factory);
81
Niels Möller73f29cb2018-01-31 16:09:31 +010082 video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
83 num_cpu_cores, &stats_proxy_,
84 config_.encoder_settings,
85 config_.pre_encode_callback,
Niels Möllerd1f7eb62018-03-28 16:40:58 +020086 rtc::MakeUnique<OveruseFrameDetector>(&stats_proxy_));
Sebastian Jansson06b83aa2018-02-28 13:03:46 +010087 // TODO(srte): Initialization should not be done posted on a task queue.
88 // Note that the posted task must not outlive this scope since the closure
89 // references local variables.
90 worker_queue_->PostTask(rtc::NewClosure(
91 [this, call_stats, transport, bitrate_allocator, send_delay_stats,
92 event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states,
Sebastian Jansson25e51102018-03-01 15:56:47 +010093 &fec_controller, retransmission_limiter]() {
Sebastian Jansson06b83aa2018-02-28 13:03:46 +010094 send_stream_.reset(new VideoSendStreamImpl(
95 &stats_proxy_, worker_queue_, call_stats, transport,
96 bitrate_allocator, send_delay_stats, video_stream_encoder_.get(),
97 event_log, &config_, encoder_config.max_bitrate_bps,
98 encoder_config.bitrate_priority, suspended_ssrcs,
99 suspended_payload_states, encoder_config.content_type,
Sebastian Jansson25e51102018-03-01 15:56:47 +0100100 std::move(fec_controller), retransmission_limiter));
Sebastian Jansson06b83aa2018-02-28 13:03:46 +0100101 },
102 [this]() { thread_sync_event_.Set(); }));
perkj26091b12016-09-01 01:17:40 -0700103
104 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
105 // |module_process_thread| must be registered and deregistered on the thread
106 // it was created on.
107 thread_sync_event_.Wait(rtc::Event::kForever);
108 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800109 // TODO(sprang): Enable this also for regular video calls if it works well.
110 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
111 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700112 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800113 }
Ying Wang38a31b02017-12-21 12:26:19 +0000114
perkj26091b12016-09-01 01:17:40 -0700115 ReconfigureVideoEncoder(std::move(encoder_config));
116}
117
118VideoSendStream::~VideoSendStream() {
119 RTC_DCHECK_RUN_ON(&thread_checker_);
120 RTC_DCHECK(!send_stream_);
121}
122
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800123void VideoSendStream::UpdateActiveSimulcastLayers(
124 const std::vector<bool> active_layers) {
125 RTC_DCHECK_RUN_ON(&thread_checker_);
126 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
127 VideoSendStreamImpl* send_stream = send_stream_.get();
128 worker_queue_->PostTask([this, send_stream, active_layers] {
129 send_stream->UpdateActiveSimulcastLayers(active_layers);
130 thread_sync_event_.Set();
131 });
132
133 thread_sync_event_.Wait(rtc::Event::kForever);
134}
135
perkj26091b12016-09-01 01:17:40 -0700136void VideoSendStream::Start() {
137 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100138 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700139 VideoSendStreamImpl* send_stream = send_stream_.get();
140 worker_queue_->PostTask([this, send_stream] {
141 send_stream->Start();
142 thread_sync_event_.Set();
143 });
144
145 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700146 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
147 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700148 thread_sync_event_.Wait(rtc::Event::kForever);
149}
150
151void VideoSendStream::Stop() {
152 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100153 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700154 VideoSendStreamImpl* send_stream = send_stream_.get();
155 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
156}
157
perkja49cbd32016-09-16 07:53:41 -0700158void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700159 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
160 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700161 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700162 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700163}
164
165void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700166 // TODO(perkj): Some test cases in VideoSendStreamTest call
167 // ReconfigureVideoEncoder from the network thread.
168 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800169 RTC_DCHECK(content_type_ == config.content_type);
Ilya Nikolaevskiy1d037ae2018-03-15 15:46:17 +0100170 video_stream_encoder_->ConfigureEncoder(
171 std::move(config),
Niels Möllerf1338562018-04-26 09:51:47 +0200172 config_.rtp.max_packet_size - CalculateMaxHeaderSize(config_.rtp));
perkj26091b12016-09-01 01:17:40 -0700173}
174
175VideoSendStream::Stats VideoSendStream::GetStats() {
176 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
177 // a network thread. See comment in Call::GetStats().
178 // RTC_DCHECK_RUN_ON(&thread_checker_);
179 return stats_proxy_.GetStats();
180}
181
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100182rtc::Optional<float> VideoSendStream::GetPacingFactorOverride() const {
183 return send_stream_->configured_pacing_factor_;
184}
185
perkj26091b12016-09-01 01:17:40 -0700186void VideoSendStream::SignalNetworkState(NetworkState state) {
187 RTC_DCHECK_RUN_ON(&thread_checker_);
188 VideoSendStreamImpl* send_stream = send_stream_.get();
189 worker_queue_->PostTask(
190 [send_stream, state] { send_stream->SignalNetworkState(state); });
191}
192
Åsa Persson4bece9a2017-10-06 10:04:04 +0200193void VideoSendStream::StopPermanentlyAndGetRtpStates(
194 VideoSendStream::RtpStateMap* rtp_state_map,
195 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700196 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700197 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700198 send_stream_->DeRegisterProcessThread();
Sebastian Jansson1b2e90b2018-03-05 19:09:11 +0100199 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 });
perkj26091b12016-09-01 01:17:40 -0700206 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700207}
208
nisse284542b2017-01-10 08:58:32 -0800209void VideoSendStream::SetTransportOverhead(
210 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800211 RTC_DCHECK_RUN_ON(&thread_checker_);
212 VideoSendStreamImpl* send_stream = send_stream_.get();
213 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
214 send_stream->SetTransportOverhead(transport_overhead_per_packet);
215 });
216}
217
perkj26091b12016-09-01 01:17:40 -0700218bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
219 // Called on a network thread.
220 return send_stream_->DeliverRtcp(packet, length);
221}
222
palmkviste75f2042016-09-28 06:19:48 -0700223void VideoSendStream::EnableEncodedFrameRecording(
224 const std::vector<rtc::PlatformFile>& files,
225 size_t byte_limit) {
226 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
227}
228
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000229} // namespace internal
230} // namespace webrtc