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
11 #include "webrtc/video/video_send_stream.h"
12
13 #include <algorithm>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17
18 #include "webrtc/base/checks.h"
19 #include "webrtc/base/logging.h"
20 #include "webrtc/base/trace_event.h"
21 #include "webrtc/call/congestion_controller.h"
22 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
23 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
24 #include "webrtc/modules/pacing/packet_router.h"
25 #include "webrtc/video/call_stats.h"
26 #include "webrtc/video/encoder_state_feedback.h"
27 #include "webrtc/video/payload_router.h"
28 #include "webrtc/video/video_capture_input.h"
29 #include "webrtc/video/vie_channel.h"
30 #include "webrtc/video/vie_encoder.h"
31 #include "webrtc/video_send_stream.h"
32
33 namespace webrtc {
34
35 class PacedSender;
36 class RtcpIntraFrameObserver;
37 class TransportFeedbackObserver;
38
39 std::string
ToString() const40 VideoSendStream::Config::EncoderSettings::ToString() const {
41 std::stringstream ss;
42 ss << "{payload_name: " << payload_name;
43 ss << ", payload_type: " << payload_type;
44 ss << ", encoder: " << (encoder != nullptr ? "(VideoEncoder)" : "nullptr");
45 ss << '}';
46 return ss.str();
47 }
48
ToString() const49 std::string VideoSendStream::Config::Rtp::Rtx::ToString()
50 const {
51 std::stringstream ss;
52 ss << "{ssrcs: [";
53 for (size_t i = 0; i < ssrcs.size(); ++i) {
54 ss << ssrcs[i];
55 if (i != ssrcs.size() - 1)
56 ss << ", ";
57 }
58 ss << ']';
59
60 ss << ", payload_type: " << payload_type;
61 ss << '}';
62 return ss.str();
63 }
64
ToString() const65 std::string VideoSendStream::Config::Rtp::ToString() const {
66 std::stringstream ss;
67 ss << "{ssrcs: [";
68 for (size_t i = 0; i < ssrcs.size(); ++i) {
69 ss << ssrcs[i];
70 if (i != ssrcs.size() - 1)
71 ss << ", ";
72 }
73 ss << ']';
74 ss << ", max_packet_size: " << max_packet_size;
75 ss << ", extensions: [";
76 for (size_t i = 0; i < extensions.size(); ++i) {
77 ss << extensions[i].ToString();
78 if (i != extensions.size() - 1)
79 ss << ", ";
80 }
81 ss << ']';
82
83 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}';
84 ss << ", fec: " << fec.ToString();
85 ss << ", rtx: " << rtx.ToString();
86 ss << ", c_name: " << c_name;
87 ss << '}';
88 return ss.str();
89 }
90
ToString() const91 std::string VideoSendStream::Config::ToString() const {
92 std::stringstream ss;
93 ss << "{encoder_settings: " << encoder_settings.ToString();
94 ss << ", rtp: " << rtp.ToString();
95 ss << ", pre_encode_callback: "
96 << (pre_encode_callback != nullptr ? "(I420FrameCallback)" : "nullptr");
97 ss << ", post_encode_callback: " << (post_encode_callback != nullptr
98 ? "(EncodedFrameObserver)"
99 : "nullptr");
100 ss << ", local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)"
101 : "nullptr");
102 ss << ", render_delay_ms: " << render_delay_ms;
103 ss << ", target_delay_ms: " << target_delay_ms;
104 ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on"
105 : "off");
106 ss << '}';
107 return ss.str();
108 }
109
110 namespace internal {
VideoSendStream(int num_cpu_cores,ProcessThread * module_process_thread,CallStats * call_stats,CongestionController * congestion_controller,BitrateAllocator * bitrate_allocator,const VideoSendStream::Config & config,const VideoEncoderConfig & encoder_config,const std::map<uint32_t,RtpState> & suspended_ssrcs)111 VideoSendStream::VideoSendStream(
112 int num_cpu_cores,
113 ProcessThread* module_process_thread,
114 CallStats* call_stats,
115 CongestionController* congestion_controller,
116 BitrateAllocator* bitrate_allocator,
117 const VideoSendStream::Config& config,
118 const VideoEncoderConfig& encoder_config,
119 const std::map<uint32_t, RtpState>& suspended_ssrcs)
120 : stats_proxy_(Clock::GetRealTimeClock(),
121 config,
122 encoder_config.content_type),
123 transport_adapter_(config.send_transport),
124 encoded_frame_proxy_(config.post_encode_callback),
125 config_(config),
126 suspended_ssrcs_(suspended_ssrcs),
127 module_process_thread_(module_process_thread),
128 call_stats_(call_stats),
129 congestion_controller_(congestion_controller),
130 encoder_feedback_(new EncoderStateFeedback()),
131 use_config_bitrate_(true) {
132 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString();
133 RTC_DCHECK(!config_.rtp.ssrcs.empty());
134
135 // Set up Call-wide sequence numbers, if configured for this send stream.
136 TransportFeedbackObserver* transport_feedback_observer = nullptr;
137 for (const RtpExtension& extension : config.rtp.extensions) {
138 if (extension.name == RtpExtension::kTransportSequenceNumber) {
139 transport_feedback_observer =
140 congestion_controller_->GetTransportFeedbackObserver();
141 break;
142 }
143 }
144
145 const std::vector<uint32_t>& ssrcs = config.rtp.ssrcs;
146
147 vie_encoder_.reset(new ViEEncoder(
148 num_cpu_cores, module_process_thread_, &stats_proxy_,
149 config.pre_encode_callback, congestion_controller_->pacer(),
150 bitrate_allocator));
151 RTC_CHECK(vie_encoder_->Init());
152
153 vie_channel_.reset(new ViEChannel(
154 num_cpu_cores, config.send_transport, module_process_thread_,
155 encoder_feedback_->GetRtcpIntraFrameObserver(),
156 congestion_controller_->GetBitrateController()->
157 CreateRtcpBandwidthObserver(),
158 transport_feedback_observer,
159 congestion_controller_->GetRemoteBitrateEstimator(false),
160 call_stats_->rtcp_rtt_stats(), congestion_controller_->pacer(),
161 congestion_controller_->packet_router(), ssrcs.size(), true));
162 RTC_CHECK(vie_channel_->Init() == 0);
163
164 call_stats_->RegisterStatsObserver(vie_channel_->GetStatsObserver());
165
166 vie_encoder_->StartThreadsAndSetSharedMembers(
167 vie_channel_->send_payload_router(),
168 vie_channel_->vcm_protection_callback());
169
170 std::vector<uint32_t> first_ssrc(1, ssrcs[0]);
171 vie_encoder_->SetSsrcs(first_ssrc);
172
173 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
174 const std::string& extension = config_.rtp.extensions[i].name;
175 int id = config_.rtp.extensions[i].id;
176 // One-byte-extension local identifiers are in the range 1-14 inclusive.
177 RTC_DCHECK_GE(id, 1);
178 RTC_DCHECK_LE(id, 14);
179 if (extension == RtpExtension::kTOffset) {
180 RTC_CHECK_EQ(0, vie_channel_->SetSendTimestampOffsetStatus(true, id));
181 } else if (extension == RtpExtension::kAbsSendTime) {
182 RTC_CHECK_EQ(0, vie_channel_->SetSendAbsoluteSendTimeStatus(true, id));
183 } else if (extension == RtpExtension::kVideoRotation) {
184 RTC_CHECK_EQ(0, vie_channel_->SetSendVideoRotationStatus(true, id));
185 } else if (extension == RtpExtension::kTransportSequenceNumber) {
186 RTC_CHECK_EQ(0, vie_channel_->SetSendTransportSequenceNumber(true, id));
187 } else {
188 RTC_NOTREACHED() << "Registering unsupported RTP extension.";
189 }
190 }
191
192 congestion_controller_->SetChannelRembStatus(true, false,
193 vie_channel_->rtp_rtcp());
194
195 // Enable NACK, FEC or both.
196 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0;
197 const bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1;
198 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future.
199 vie_channel_->SetProtectionMode(enable_protection_nack, enable_protection_fec,
200 config_.rtp.fec.red_payload_type,
201 config_.rtp.fec.ulpfec_payload_type);
202 vie_encoder_->SetProtectionMethod(enable_protection_nack,
203 enable_protection_fec);
204
205 ConfigureSsrcs();
206
207 vie_channel_->SetRTCPCName(config_.rtp.c_name.c_str());
208
209 input_.reset(new internal::VideoCaptureInput(
210 module_process_thread_, vie_encoder_.get(), config_.local_renderer,
211 &stats_proxy_, this, config_.encoding_time_observer));
212
213 // 28 to match packet overhead in ModuleRtpRtcpImpl.
214 RTC_DCHECK_LE(config_.rtp.max_packet_size, static_cast<size_t>(0xFFFF - 28));
215 vie_channel_->SetMTU(static_cast<uint16_t>(config_.rtp.max_packet_size + 28));
216
217 RTC_DCHECK(config.encoder_settings.encoder != nullptr);
218 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0);
219 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127);
220 RTC_CHECK_EQ(0, vie_encoder_->RegisterExternalEncoder(
221 config.encoder_settings.encoder,
222 config.encoder_settings.payload_type,
223 config.encoder_settings.internal_source));
224
225 RTC_CHECK(ReconfigureVideoEncoder(encoder_config));
226
227 vie_channel_->RegisterSendSideDelayObserver(&stats_proxy_);
228
229 if (config_.post_encode_callback)
230 vie_encoder_->RegisterPostEncodeImageCallback(&encoded_frame_proxy_);
231
232 if (config_.suspend_below_min_bitrate)
233 vie_encoder_->SuspendBelowMinBitrate();
234
235 congestion_controller_->AddEncoder(vie_encoder_.get());
236 encoder_feedback_->AddEncoder(ssrcs, vie_encoder_.get());
237
238 vie_channel_->RegisterSendChannelRtcpStatisticsCallback(&stats_proxy_);
239 vie_channel_->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_);
240 vie_channel_->RegisterRtcpPacketTypeCounterObserver(&stats_proxy_);
241 vie_channel_->RegisterSendBitrateObserver(&stats_proxy_);
242 vie_channel_->RegisterSendFrameCountObserver(&stats_proxy_);
243 }
244
~VideoSendStream()245 VideoSendStream::~VideoSendStream() {
246 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString();
247 vie_channel_->RegisterSendFrameCountObserver(nullptr);
248 vie_channel_->RegisterSendBitrateObserver(nullptr);
249 vie_channel_->RegisterRtcpPacketTypeCounterObserver(nullptr);
250 vie_channel_->RegisterSendChannelRtpStatisticsCallback(nullptr);
251 vie_channel_->RegisterSendChannelRtcpStatisticsCallback(nullptr);
252
253 // Remove capture input (thread) so that it's not running after the current
254 // channel is deleted.
255 input_.reset();
256
257 vie_encoder_->DeRegisterExternalEncoder(
258 config_.encoder_settings.payload_type);
259
260 call_stats_->DeregisterStatsObserver(vie_channel_->GetStatsObserver());
261 congestion_controller_->SetChannelRembStatus(false, false,
262 vie_channel_->rtp_rtcp());
263
264 // Remove the feedback, stop all encoding threads and processing. This must be
265 // done before deleting the channel.
266 congestion_controller_->RemoveEncoder(vie_encoder_.get());
267 encoder_feedback_->RemoveEncoder(vie_encoder_.get());
268 vie_encoder_->StopThreadsAndRemoveSharedMembers();
269
270 uint32_t remote_ssrc = vie_channel_->GetRemoteSSRC();
271 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream(
272 remote_ssrc);
273 }
274
Input()275 VideoCaptureInput* VideoSendStream::Input() {
276 return input_.get();
277 }
278
Start()279 void VideoSendStream::Start() {
280 transport_adapter_.Enable();
281 vie_encoder_->Pause();
282 if (vie_channel_->StartSend() == 0) {
283 // Was not already started, trigger a keyframe.
284 vie_encoder_->SendKeyFrame();
285 }
286 vie_encoder_->Restart();
287 vie_channel_->StartReceive();
288 }
289
Stop()290 void VideoSendStream::Stop() {
291 // TODO(pbos): Make sure the encoder stops here.
292 vie_channel_->StopSend();
293 vie_channel_->StopReceive();
294 transport_adapter_.Disable();
295 }
296
ReconfigureVideoEncoder(const VideoEncoderConfig & config)297 bool VideoSendStream::ReconfigureVideoEncoder(
298 const VideoEncoderConfig& config) {
299 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder");
300 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString();
301 const std::vector<VideoStream>& streams = config.streams;
302 RTC_DCHECK(!streams.empty());
303 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size());
304
305 VideoCodec video_codec;
306 memset(&video_codec, 0, sizeof(video_codec));
307 if (config_.encoder_settings.payload_name == "VP8") {
308 video_codec.codecType = kVideoCodecVP8;
309 } else if (config_.encoder_settings.payload_name == "VP9") {
310 video_codec.codecType = kVideoCodecVP9;
311 } else if (config_.encoder_settings.payload_name == "H264") {
312 video_codec.codecType = kVideoCodecH264;
313 } else {
314 video_codec.codecType = kVideoCodecGeneric;
315 }
316
317 switch (config.content_type) {
318 case VideoEncoderConfig::ContentType::kRealtimeVideo:
319 video_codec.mode = kRealtimeVideo;
320 break;
321 case VideoEncoderConfig::ContentType::kScreen:
322 video_codec.mode = kScreensharing;
323 if (config.streams.size() == 1 &&
324 config.streams[0].temporal_layer_thresholds_bps.size() == 1) {
325 video_codec.targetBitrate =
326 config.streams[0].temporal_layer_thresholds_bps[0] / 1000;
327 }
328 break;
329 }
330
331 if (video_codec.codecType == kVideoCodecVP8) {
332 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
333 } else if (video_codec.codecType == kVideoCodecVP9) {
334 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
335 } else if (video_codec.codecType == kVideoCodecH264) {
336 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
337 }
338
339 if (video_codec.codecType == kVideoCodecVP8) {
340 if (config.encoder_specific_settings != nullptr) {
341 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
342 config.encoder_specific_settings);
343 }
344 video_codec.codecSpecific.VP8.numberOfTemporalLayers =
345 static_cast<unsigned char>(
346 streams.back().temporal_layer_thresholds_bps.size() + 1);
347 } else if (video_codec.codecType == kVideoCodecVP9) {
348 if (config.encoder_specific_settings != nullptr) {
349 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>(
350 config.encoder_specific_settings);
351 if (video_codec.mode == kScreensharing) {
352 video_codec.codecSpecific.VP9.flexibleMode = true;
353 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
354 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1);
355 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2);
356 }
357 }
358 video_codec.codecSpecific.VP9.numberOfTemporalLayers =
359 static_cast<unsigned char>(
360 streams.back().temporal_layer_thresholds_bps.size() + 1);
361 } else if (video_codec.codecType == kVideoCodecH264) {
362 if (config.encoder_specific_settings != nullptr) {
363 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>(
364 config.encoder_specific_settings);
365 }
366 } else {
367 // TODO(pbos): Support encoder_settings codec-agnostically.
368 RTC_DCHECK(config.encoder_specific_settings == nullptr)
369 << "Encoder-specific settings for codec type not wired up.";
370 }
371
372 strncpy(video_codec.plName,
373 config_.encoder_settings.payload_name.c_str(),
374 kPayloadNameSize - 1);
375 video_codec.plName[kPayloadNameSize - 1] = '\0';
376 video_codec.plType = config_.encoder_settings.payload_type;
377 video_codec.numberOfSimulcastStreams =
378 static_cast<unsigned char>(streams.size());
379 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
380 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
381 if (video_codec.codecType == kVideoCodecVP9) {
382 // If the vector is empty, bitrates will be configured automatically.
383 RTC_DCHECK(config.spatial_layers.empty() ||
384 config.spatial_layers.size() ==
385 video_codec.codecSpecific.VP9.numberOfSpatialLayers);
386 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers,
387 kMaxSimulcastStreams);
388 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
389 video_codec.spatialLayers[i] = config.spatial_layers[i];
390 }
391 for (size_t i = 0; i < streams.size(); ++i) {
392 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
393 RTC_DCHECK_GT(streams[i].width, 0u);
394 RTC_DCHECK_GT(streams[i].height, 0u);
395 RTC_DCHECK_GT(streams[i].max_framerate, 0);
396 // Different framerates not supported per stream at the moment.
397 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
398 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
399 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
400 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
401 RTC_DCHECK_GE(streams[i].max_qp, 0);
402
403 sim_stream->width = static_cast<uint16_t>(streams[i].width);
404 sim_stream->height = static_cast<uint16_t>(streams[i].height);
405 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
406 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
407 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
408 sim_stream->qpMax = streams[i].max_qp;
409 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
410 streams[i].temporal_layer_thresholds_bps.size() + 1);
411
412 video_codec.width = std::max(video_codec.width,
413 static_cast<uint16_t>(streams[i].width));
414 video_codec.height = std::max(
415 video_codec.height, static_cast<uint16_t>(streams[i].height));
416 video_codec.minBitrate =
417 std::min(static_cast<uint16_t>(video_codec.minBitrate),
418 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
419 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
420 video_codec.qpMax = std::max(video_codec.qpMax,
421 static_cast<unsigned int>(streams[i].max_qp));
422 }
423
424 // Set to zero to not update the bitrate controller from ViEEncoder, as
425 // the bitrate controller is already set from Call.
426 video_codec.startBitrate = 0;
427
428 RTC_DCHECK_GT(streams[0].max_framerate, 0);
429 video_codec.maxFramerate = streams[0].max_framerate;
430
431 if (!SetSendCodec(video_codec))
432 return false;
433
434 // Clear stats for disabled layers.
435 for (size_t i = video_codec.numberOfSimulcastStreams;
436 i < config_.rtp.ssrcs.size(); ++i) {
437 stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
438 }
439
440 stats_proxy_.SetContentType(config.content_type);
441
442 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
443 vie_encoder_->SetMinTransmitBitrate(config.min_transmit_bitrate_bps / 1000);
444
445 encoder_config_ = config;
446 use_config_bitrate_ = false;
447 return true;
448 }
449
DeliverRtcp(const uint8_t * packet,size_t length)450 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
451 return vie_channel_->ReceivedRTCPPacket(packet, length) == 0;
452 }
453
GetStats()454 VideoSendStream::Stats VideoSendStream::GetStats() {
455 return stats_proxy_.GetStats();
456 }
457
OveruseDetected()458 void VideoSendStream::OveruseDetected() {
459 if (config_.overuse_callback)
460 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse);
461 }
462
NormalUsage()463 void VideoSendStream::NormalUsage() {
464 if (config_.overuse_callback)
465 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse);
466 }
467
ConfigureSsrcs()468 void VideoSendStream::ConfigureSsrcs() {
469 vie_channel_->SetSSRC(config_.rtp.ssrcs.front(), kViEStreamTypeNormal, 0);
470 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
471 uint32_t ssrc = config_.rtp.ssrcs[i];
472 vie_channel_->SetSSRC(ssrc, kViEStreamTypeNormal,
473 static_cast<unsigned char>(i));
474 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
475 if (it != suspended_ssrcs_.end())
476 vie_channel_->SetRtpStateForSsrc(ssrc, it->second);
477 }
478
479 if (config_.rtp.rtx.ssrcs.empty()) {
480 return;
481 }
482
483 // Set up RTX.
484 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size());
485 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
486 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
487 vie_channel_->SetSSRC(config_.rtp.rtx.ssrcs[i], kViEStreamTypeRtx,
488 static_cast<unsigned char>(i));
489 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
490 if (it != suspended_ssrcs_.end())
491 vie_channel_->SetRtpStateForSsrc(ssrc, it->second);
492 }
493
494 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0);
495 vie_channel_->SetRtxSendPayloadType(config_.rtp.rtx.payload_type,
496 config_.encoder_settings.payload_type);
497 }
498
GetRtpStates() const499 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
500 std::map<uint32_t, RtpState> rtp_states;
501 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
502 uint32_t ssrc = config_.rtp.ssrcs[i];
503 rtp_states[ssrc] = vie_channel_->GetRtpStateForSsrc(ssrc);
504 }
505
506 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
507 uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
508 rtp_states[ssrc] = vie_channel_->GetRtpStateForSsrc(ssrc);
509 }
510
511 return rtp_states;
512 }
513
SignalNetworkState(NetworkState state)514 void VideoSendStream::SignalNetworkState(NetworkState state) {
515 // When network goes up, enable RTCP status before setting transmission state.
516 // When it goes down, disable RTCP afterwards. This ensures that any packets
517 // sent due to the network state changed will not be dropped.
518 if (state == kNetworkUp)
519 vie_channel_->SetRTCPMode(config_.rtp.rtcp_mode);
520 vie_encoder_->SetNetworkTransmissionState(state == kNetworkUp);
521 if (state == kNetworkDown)
522 vie_channel_->SetRTCPMode(RtcpMode::kOff);
523 }
524
GetRtt() const525 int64_t VideoSendStream::GetRtt() const {
526 webrtc::RtcpStatistics rtcp_stats;
527 uint16_t frac_lost;
528 uint32_t cumulative_lost;
529 uint32_t extended_max_sequence_number;
530 uint32_t jitter;
531 int64_t rtt_ms;
532 if (vie_channel_->GetSendRtcpStatistics(&frac_lost, &cumulative_lost,
533 &extended_max_sequence_number,
534 &jitter, &rtt_ms) == 0) {
535 return rtt_ms;
536 }
537 return -1;
538 }
539
GetPaddingNeededBps() const540 int VideoSendStream::GetPaddingNeededBps() const {
541 return vie_encoder_->GetPaddingNeededBps();
542 }
543
SetSendCodec(VideoCodec video_codec)544 bool VideoSendStream::SetSendCodec(VideoCodec video_codec) {
545 static const int kEncoderMinBitrate = 30;
546 if (video_codec.maxBitrate == 0) {
547 // Unset max bitrate -> cap to one bit per pixel.
548 video_codec.maxBitrate =
549 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
550 1000;
551 }
552
553 if (video_codec.minBitrate < kEncoderMinBitrate)
554 video_codec.minBitrate = kEncoderMinBitrate;
555 if (video_codec.maxBitrate < kEncoderMinBitrate)
556 video_codec.maxBitrate = kEncoderMinBitrate;
557
558 // Stop the media flow while reconfiguring.
559 vie_encoder_->Pause();
560
561 if (vie_encoder_->SetEncoder(video_codec) != 0) {
562 LOG(LS_ERROR) << "Failed to set encoder.";
563 return false;
564 }
565
566 if (vie_channel_->SetSendCodec(video_codec, false) != 0) {
567 LOG(LS_ERROR) << "Failed to set send codec.";
568 return false;
569 }
570
571 // Not all configured SSRCs have to be utilized (simulcast senders don't have
572 // to send on all SSRCs at once etc.)
573 std::vector<uint32_t> used_ssrcs = config_.rtp.ssrcs;
574 used_ssrcs.resize(static_cast<size_t>(video_codec.numberOfSimulcastStreams));
575 vie_encoder_->SetSsrcs(used_ssrcs);
576
577 // Restart the media flow
578 vie_encoder_->Restart();
579
580 return true;
581 }
582
583 } // namespace internal
584 } // namespace webrtc
585