Home | History | Annotate | Download | only in video
      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
     40 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 
     49 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 
     65 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 
     91 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 {
    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 
    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 
    275 VideoCaptureInput* VideoSendStream::Input() {
    276   return input_.get();
    277 }
    278 
    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 
    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 
    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 
    450 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
    451   return vie_channel_->ReceivedRTCPPacket(packet, length) == 0;
    452 }
    453 
    454 VideoSendStream::Stats VideoSendStream::GetStats() {
    455   return stats_proxy_.GetStats();
    456 }
    457 
    458 void VideoSendStream::OveruseDetected() {
    459   if (config_.overuse_callback)
    460     config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse);
    461 }
    462 
    463 void VideoSendStream::NormalUsage() {
    464   if (config_.overuse_callback)
    465     config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse);
    466 }
    467 
    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 
    499 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 
    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 
    525 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 
    540 int VideoSendStream::GetPaddingNeededBps() const {
    541   return vie_encoder_->GetPaddingNeededBps();
    542 }
    543 
    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