• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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