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
33namespace webrtc {
34
35class PacedSender;
36class RtcpIntraFrameObserver;
37class TransportFeedbackObserver;
38
39std::string
40VideoSendStream::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
49std::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
65std::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
91std::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
110namespace internal {
111VideoSendStream::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
245VideoSendStream::~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
275VideoCaptureInput* VideoSendStream::Input() {
276  return input_.get();
277}
278
279void 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
290void 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
297bool 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
450bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
451  return vie_channel_->ReceivedRTCPPacket(packet, length) == 0;
452}
453
454VideoSendStream::Stats VideoSendStream::GetStats() {
455  return stats_proxy_.GetStats();
456}
457
458void VideoSendStream::OveruseDetected() {
459  if (config_.overuse_callback)
460    config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse);
461}
462
463void VideoSendStream::NormalUsage() {
464  if (config_.overuse_callback)
465    config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse);
466}
467
468void 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
499std::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
514void 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
525int64_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
540int VideoSendStream::GetPaddingNeededBps() const {
541  return vie_encoder_->GetPaddingNeededBps();
542}
543
544bool 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