webrtcvideoengine2.cc revision f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50e
1/*
2 * libjingle
3 * Copyright 2014 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifdef HAVE_WEBRTC_VIDEO
29#include "talk/media/webrtc/webrtcvideoengine2.h"
30
31#include <algorithm>
32#include <set>
33#include <string>
34
35#include "libyuv/convert_from.h"
36#include "talk/media/base/videocapturer.h"
37#include "talk/media/base/videorenderer.h"
38#include "talk/media/webrtc/constants.h"
39#include "talk/media/webrtc/simulcast.h"
40#include "talk/media/webrtc/webrtcvideocapturer.h"
41#include "talk/media/webrtc/webrtcvideoengine.h"
42#include "talk/media/webrtc/webrtcvideoframe.h"
43#include "talk/media/webrtc/webrtcvoiceengine.h"
44#include "webrtc/base/buffer.h"
45#include "webrtc/base/logging.h"
46#include "webrtc/base/stringutils.h"
47#include "webrtc/call.h"
48#include "webrtc/video_decoder.h"
49#include "webrtc/video_encoder.h"
50
51#define UNIMPLEMENTED                                                 \
52  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
53  ASSERT(false)
54
55namespace cricket {
56namespace {
57static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
58  std::stringstream out;
59  out << '{';
60  for (size_t i = 0; i < codecs.size(); ++i) {
61    out << codecs[i].ToString();
62    if (i != codecs.size() - 1) {
63      out << ", ";
64    }
65  }
66  out << '}';
67  return out.str();
68}
69
70static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
71  bool has_video = false;
72  for (size_t i = 0; i < codecs.size(); ++i) {
73    if (!codecs[i].ValidateCodecFormat()) {
74      return false;
75    }
76    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
77      has_video = true;
78    }
79  }
80  if (!has_video) {
81    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
82                  << CodecVectorToString(codecs);
83    return false;
84  }
85  return true;
86}
87
88static std::string RtpExtensionsToString(
89    const std::vector<RtpHeaderExtension>& extensions) {
90  std::stringstream out;
91  out << '{';
92  for (size_t i = 0; i < extensions.size(); ++i) {
93    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
94    if (i != extensions.size() - 1) {
95      out << ", ";
96    }
97  }
98  out << '}';
99  return out.str();
100}
101
102// Merges two fec configs and logs an error if a conflict arises
103// such that merging in diferent order would trigger a diferent output.
104static void MergeFecConfig(const webrtc::FecConfig& other,
105                           webrtc::FecConfig* output) {
106  if (other.ulpfec_payload_type != -1) {
107    if (output->ulpfec_payload_type != -1 &&
108        output->ulpfec_payload_type != other.ulpfec_payload_type) {
109      LOG(LS_WARNING) << "Conflict merging ulpfec_payload_type configs: "
110                      << output->ulpfec_payload_type << " and "
111                      << other.ulpfec_payload_type;
112    }
113    output->ulpfec_payload_type = other.ulpfec_payload_type;
114  }
115  if (other.red_payload_type != -1) {
116    if (output->red_payload_type != -1 &&
117        output->red_payload_type != other.red_payload_type) {
118      LOG(LS_WARNING) << "Conflict merging red_payload_type configs: "
119                      << output->red_payload_type << " and "
120                      << other.red_payload_type;
121    }
122    output->red_payload_type = other.red_payload_type;
123  }
124}
125}  // namespace
126
127// This constant is really an on/off, lower-level configurable NACK history
128// duration hasn't been implemented.
129static const int kNackHistoryMs = 1000;
130
131static const int kDefaultQpMax = 56;
132
133static const int kDefaultRtcpReceiverReportSsrc = 1;
134
135// External video encoders are given payloads 120-127. This also means that we
136// only support up to 8 external payload types.
137static const int kExternalVideoPayloadTypeBase = 120;
138#ifndef NDEBUG
139static const size_t kMaxExternalVideoCodecs = 8;
140#endif
141
142const char kH264CodecName[] = "H264";
143
144static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
145                                   const VideoCodec& requested_codec,
146                                   VideoCodec* matching_codec) {
147  for (size_t i = 0; i < codecs.size(); ++i) {
148    if (requested_codec.Matches(codecs[i])) {
149      *matching_codec = codecs[i];
150      return true;
151    }
152  }
153  return false;
154}
155
156static bool ValidateRtpHeaderExtensionIds(
157    const std::vector<RtpHeaderExtension>& extensions) {
158  std::set<int> extensions_used;
159  for (size_t i = 0; i < extensions.size(); ++i) {
160    if (extensions[i].id < 0 || extensions[i].id >= 15 ||
161        !extensions_used.insert(extensions[i].id).second) {
162      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
163      return false;
164    }
165  }
166  return true;
167}
168
169static bool CompareRtpHeaderExtensionIds(
170    const webrtc::RtpExtension& extension1,
171    const webrtc::RtpExtension& extension2) {
172  // Sorting on ID is sufficient, more than one extension per ID is unsupported.
173  return extension1.id > extension2.id;
174}
175
176static std::vector<webrtc::RtpExtension> FilterRtpExtensions(
177    const std::vector<RtpHeaderExtension>& extensions) {
178  std::vector<webrtc::RtpExtension> webrtc_extensions;
179  for (size_t i = 0; i < extensions.size(); ++i) {
180    // Unsupported extensions will be ignored.
181    if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) {
182      webrtc_extensions.push_back(webrtc::RtpExtension(
183          extensions[i].uri, extensions[i].id));
184    } else {
185      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
186    }
187  }
188
189  // Sort filtered headers to make sure that they can later be compared
190  // regardless of in which order they were entered.
191  std::sort(webrtc_extensions.begin(), webrtc_extensions.end(),
192            CompareRtpHeaderExtensionIds);
193  return webrtc_extensions;
194}
195
196static bool RtpExtensionsHaveChanged(
197    const std::vector<webrtc::RtpExtension>& before,
198    const std::vector<webrtc::RtpExtension>& after) {
199  if (before.size() != after.size())
200    return true;
201  for (size_t i = 0; i < before.size(); ++i) {
202    if (before[i].id != after[i].id)
203      return true;
204    if (before[i].name != after[i].name)
205      return true;
206  }
207  return false;
208}
209
210WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
211}
212
213std::vector<webrtc::VideoStream>
214WebRtcVideoEncoderFactory2::CreateSimulcastVideoStreams(
215    const VideoCodec& codec,
216    const VideoOptions& options,
217    size_t num_streams) {
218  // Use default factory for non-simulcast.
219  int max_qp = kDefaultQpMax;
220  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
221
222  int min_bitrate_kbps;
223  if (!codec.GetParam(kCodecParamMinBitrate, &min_bitrate_kbps) ||
224      min_bitrate_kbps < kMinVideoBitrate) {
225    min_bitrate_kbps = kMinVideoBitrate;
226  }
227
228  int max_bitrate_kbps;
229  if (!codec.GetParam(kCodecParamMaxBitrate, &max_bitrate_kbps)) {
230    max_bitrate_kbps = 0;
231  }
232
233  return GetSimulcastConfig(
234      num_streams,
235      GetSimulcastBitrateMode(options),
236      codec.width,
237      codec.height,
238      max_bitrate_kbps * 1000,
239      max_qp,
240      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate);
241}
242
243std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
244    const VideoCodec& codec,
245    const VideoOptions& options,
246    size_t num_streams) {
247  if (num_streams != 1)
248    return CreateSimulcastVideoStreams(codec, options, num_streams);
249
250  webrtc::VideoStream stream;
251  stream.width = codec.width;
252  stream.height = codec.height;
253  stream.max_framerate =
254      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
255
256  stream.min_bitrate_bps = kMinVideoBitrate * 1000;
257  stream.target_bitrate_bps = stream.max_bitrate_bps = kMaxVideoBitrate * 1000;
258
259  int max_qp = kDefaultQpMax;
260  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
261  stream.max_qp = max_qp;
262  std::vector<webrtc::VideoStream> streams;
263  streams.push_back(stream);
264  return streams;
265}
266
267void* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
268    const VideoCodec& codec,
269    const VideoOptions& options) {
270  if (CodecNameMatches(codec.name, kVp8CodecName)) {
271    webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
272        webrtc::VideoEncoder::GetDefaultVp8Settings());
273    options.video_noise_reduction.Get(&settings->denoisingOn);
274    return settings;
275  }
276  if (CodecNameMatches(codec.name, kVp9CodecName)) {
277    webrtc::VideoCodecVP9* settings = new webrtc::VideoCodecVP9(
278        webrtc::VideoEncoder::GetDefaultVp9Settings());
279    options.video_noise_reduction.Get(&settings->denoisingOn);
280    return settings;
281  }
282  return NULL;
283}
284
285void WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
286    const VideoCodec& codec,
287    void* encoder_settings) {
288  if (encoder_settings == NULL) {
289    return;
290  }
291  if (CodecNameMatches(codec.name, kVp8CodecName)) {
292    delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
293  }
294  if (CodecNameMatches(codec.name, kVp9CodecName)) {
295    delete reinterpret_cast<webrtc::VideoCodecVP9*>(encoder_settings);
296  }
297}
298
299DefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
300    : default_recv_ssrc_(0), default_renderer_(NULL) {}
301
302UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
303    VideoMediaChannel* channel,
304    uint32_t ssrc) {
305  if (default_recv_ssrc_ != 0) {  // Already one default stream.
306    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
307    return kDropPacket;
308  }
309
310  StreamParams sp;
311  sp.ssrcs.push_back(ssrc);
312  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
313  if (!channel->AddRecvStream(sp)) {
314    LOG(LS_WARNING) << "Could not create default receive stream.";
315  }
316
317  channel->SetRenderer(ssrc, default_renderer_);
318  default_recv_ssrc_ = ssrc;
319  return kDeliverPacket;
320}
321
322WebRtcCallFactory::~WebRtcCallFactory() {
323}
324webrtc::Call* WebRtcCallFactory::CreateCall(
325    const webrtc::Call::Config& config) {
326  return webrtc::Call::Create(config);
327}
328
329VideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
330  return default_renderer_;
331}
332
333void DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
334    VideoMediaChannel* channel,
335    VideoRenderer* renderer) {
336  default_renderer_ = renderer;
337  if (default_recv_ssrc_ != 0) {
338    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
339  }
340}
341
342WebRtcVideoEngine2::WebRtcVideoEngine2()
343    : worker_thread_(NULL),
344      voice_engine_(NULL),
345      default_codec_format_(kDefaultVideoMaxWidth,
346                            kDefaultVideoMaxHeight,
347                            FPS_TO_INTERVAL(kDefaultVideoMaxFramerate),
348                            FOURCC_ANY),
349      initialized_(false),
350      cpu_monitor_(new rtc::CpuMonitor(NULL)),
351      call_factory_(&default_call_factory_),
352      external_decoder_factory_(NULL),
353      external_encoder_factory_(NULL) {
354  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
355  video_codecs_ = GetSupportedCodecs();
356  rtp_header_extensions_.push_back(
357      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
358                         kRtpTimestampOffsetHeaderExtensionDefaultId));
359  rtp_header_extensions_.push_back(
360      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
361                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
362}
363
364WebRtcVideoEngine2::~WebRtcVideoEngine2() {
365  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
366
367  if (initialized_) {
368    Terminate();
369  }
370}
371
372void WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) {
373  assert(!initialized_);
374  call_factory_ = call_factory;
375}
376
377bool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) {
378  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
379  worker_thread_ = worker_thread;
380  ASSERT(worker_thread_ != NULL);
381
382  cpu_monitor_->set_thread(worker_thread_);
383  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
384    LOG(LS_ERROR) << "Failed to start CPU monitor.";
385    cpu_monitor_.reset();
386  }
387
388  initialized_ = true;
389  return true;
390}
391
392void WebRtcVideoEngine2::Terminate() {
393  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
394
395  if (cpu_monitor_.get() != NULL)
396    cpu_monitor_->Stop();
397
398  initialized_ = false;
399}
400
401int WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
402
403bool WebRtcVideoEngine2::SetDefaultEncoderConfig(
404    const VideoEncoderConfig& config) {
405  const VideoCodec& codec = config.max_codec;
406  bool supports_codec = false;
407  for (size_t i = 0; i < video_codecs_.size(); ++i) {
408    if (CodecNameMatches(video_codecs_[i].name, codec.name)) {
409      video_codecs_[i] = codec;
410      supports_codec = true;
411      break;
412    }
413  }
414
415  if (!supports_codec) {
416    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported: "
417                  << codec.ToString();
418    return false;
419  }
420
421  default_codec_format_ =
422      VideoFormat(codec.width,
423                  codec.height,
424                  VideoFormat::FpsToInterval(codec.framerate),
425                  FOURCC_ANY);
426  return true;
427}
428
429WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
430    const VideoOptions& options,
431    VoiceMediaChannel* voice_channel) {
432  assert(initialized_);
433  LOG(LS_INFO) << "CreateChannel: "
434               << (voice_channel != NULL ? "With" : "Without")
435               << " voice channel. Options: " << options.ToString();
436  WebRtcVideoChannel2* channel =
437      new WebRtcVideoChannel2(call_factory_,
438                              voice_engine_,
439                              voice_channel,
440                              options,
441                              external_encoder_factory_,
442                              external_decoder_factory_,
443                              GetVideoEncoderFactory());
444  if (!channel->Init()) {
445    delete channel;
446    return NULL;
447  }
448  channel->SetRecvCodecs(video_codecs_);
449  return channel;
450}
451
452const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
453  return video_codecs_;
454}
455
456const std::vector<RtpHeaderExtension>&
457WebRtcVideoEngine2::rtp_header_extensions() const {
458  return rtp_header_extensions_;
459}
460
461void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
462  // TODO(pbos): Set up logging.
463  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
464  // if min_sev == -1, we keep the current log level.
465  if (min_sev < 0) {
466    assert(min_sev == -1);
467    return;
468  }
469}
470
471void WebRtcVideoEngine2::SetExternalDecoderFactory(
472    WebRtcVideoDecoderFactory* decoder_factory) {
473  assert(!initialized_);
474  external_decoder_factory_ = decoder_factory;
475}
476
477void WebRtcVideoEngine2::SetExternalEncoderFactory(
478    WebRtcVideoEncoderFactory* encoder_factory) {
479  assert(!initialized_);
480  if (external_encoder_factory_ == encoder_factory)
481    return;
482
483  // No matter what happens we shouldn't hold on to a stale
484  // WebRtcSimulcastEncoderFactory.
485  simulcast_encoder_factory_.reset();
486
487  if (encoder_factory &&
488      WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
489          encoder_factory->codecs())) {
490    simulcast_encoder_factory_.reset(
491        new WebRtcSimulcastEncoderFactory(encoder_factory));
492    encoder_factory = simulcast_encoder_factory_.get();
493  }
494  external_encoder_factory_ = encoder_factory;
495
496  video_codecs_ = GetSupportedCodecs();
497}
498
499bool WebRtcVideoEngine2::EnableTimedRender() {
500  // TODO(pbos): Figure out whether this can be removed.
501  return true;
502}
503
504// Checks to see whether we comprehend and could receive a particular codec
505bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
506  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
507  // if supported by the encoder factory. Add a corresponding test that fails
508  // with this code (that doesn't ask the factory).
509  for (size_t j = 0; j < video_codecs_.size(); ++j) {
510    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
511    if (codec.Matches(in)) {
512      return true;
513    }
514  }
515  return false;
516}
517
518// Tells whether the |requested| codec can be transmitted or not. If it can be
519// transmitted |out| is set with the best settings supported. Aspect ratio will
520// be set as close to |current|'s as possible. If not set |requested|'s
521// dimensions will be used for aspect ratio matching.
522bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
523                                      const VideoCodec& current,
524                                      VideoCodec* out) {
525  assert(out != NULL);
526
527  if (requested.width != requested.height &&
528      (requested.height == 0 || requested.width == 0)) {
529    // 0xn and nx0 are invalid resolutions.
530    return false;
531  }
532
533  VideoCodec matching_codec;
534  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
535    // Codec not supported.
536    return false;
537  }
538
539  out->id = requested.id;
540  out->name = requested.name;
541  out->preference = requested.preference;
542  out->params = requested.params;
543  out->framerate =
544      rtc::_min(requested.framerate, matching_codec.framerate);
545  out->params = requested.params;
546  out->feedback_params = requested.feedback_params;
547  out->width = requested.width;
548  out->height = requested.height;
549  if (requested.width == 0 && requested.height == 0) {
550    return true;
551  }
552
553  while (out->width > matching_codec.width) {
554    out->width /= 2;
555    out->height /= 2;
556  }
557
558  return out->width > 0 && out->height > 0;
559}
560
561bool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
562  if (initialized_) {
563    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
564    return false;
565  }
566  voice_engine_ = voice_engine;
567  return true;
568}
569
570// Ignore spammy trace messages, mostly from the stats API when we haven't
571// gotten RTCP info yet from the remote side.
572bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
573  static const char* const kTracesToIgnore[] = {NULL};
574  for (const char* const* p = kTracesToIgnore; *p; ++p) {
575    if (trace.find(*p) == 0) {
576      return true;
577    }
578  }
579  return false;
580}
581
582WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
583  return &default_video_encoder_factory_;
584}
585
586std::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const {
587  std::vector<VideoCodec> supported_codecs = DefaultVideoCodecList();
588
589  if (external_encoder_factory_ == NULL) {
590    return supported_codecs;
591  }
592
593  assert(external_encoder_factory_->codecs().size() <= kMaxExternalVideoCodecs);
594  const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
595      external_encoder_factory_->codecs();
596  for (size_t i = 0; i < codecs.size(); ++i) {
597    // Don't add internally-supported codecs twice.
598    if (CodecIsInternallySupported(codecs[i].name)) {
599      continue;
600    }
601
602    VideoCodec codec(kExternalVideoPayloadTypeBase + static_cast<int>(i),
603                     codecs[i].name,
604                     codecs[i].max_width,
605                     codecs[i].max_height,
606                     codecs[i].max_fps,
607                     0);
608
609    AddDefaultFeedbackParams(&codec);
610    supported_codecs.push_back(codec);
611  }
612  return supported_codecs;
613}
614
615WebRtcVideoChannel2::WebRtcVideoChannel2(
616    WebRtcCallFactory* call_factory,
617    WebRtcVoiceEngine* voice_engine,
618    VoiceMediaChannel* voice_channel,
619    const VideoOptions& options,
620    WebRtcVideoEncoderFactory* external_encoder_factory,
621    WebRtcVideoDecoderFactory* external_decoder_factory,
622    WebRtcVideoEncoderFactory2* encoder_factory)
623    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
624      voice_channel_(voice_channel),
625      external_encoder_factory_(external_encoder_factory),
626      external_decoder_factory_(external_decoder_factory),
627      encoder_factory_(encoder_factory) {
628  SetDefaultOptions();
629  options_.SetAll(options);
630  webrtc::Call::Config config(this);
631  config.overuse_callback = this;
632  if (voice_engine != NULL) {
633    config.voice_engine = voice_engine->voe()->engine();
634  }
635
636  call_.reset(call_factory->CreateCall(config));
637
638  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
639  sending_ = false;
640  default_send_ssrc_ = 0;
641}
642
643void WebRtcVideoChannel2::SetDefaultOptions() {
644  options_.cpu_overuse_detection.Set(false);
645  options_.dscp.Set(false);
646  options_.suspend_below_min_bitrate.Set(false);
647  options_.video_noise_reduction.Set(true);
648  options_.screencast_min_bitrate.Set(0);
649}
650
651WebRtcVideoChannel2::~WebRtcVideoChannel2() {
652  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
653           send_streams_.begin();
654       it != send_streams_.end();
655       ++it) {
656    delete it->second;
657  }
658
659  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
660           receive_streams_.begin();
661       it != receive_streams_.end();
662       ++it) {
663    delete it->second;
664  }
665}
666
667bool WebRtcVideoChannel2::Init() { return true; }
668
669bool WebRtcVideoChannel2::CodecIsExternallySupported(
670    const std::string& name) const {
671  if (external_encoder_factory_ == NULL) {
672    return false;
673  }
674
675  const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
676      external_encoder_factory_->codecs();
677  for (size_t c = 0; c < external_codecs.size(); ++c) {
678    if (CodecNameMatches(name, external_codecs[c].name)) {
679      return true;
680    }
681  }
682  return false;
683}
684
685std::vector<WebRtcVideoChannel2::VideoCodecSettings>
686WebRtcVideoChannel2::FilterSupportedCodecs(
687    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs)
688    const {
689  std::vector<VideoCodecSettings> supported_codecs;
690  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
691    const VideoCodecSettings& codec = mapped_codecs[i];
692    if (CodecIsInternallySupported(codec.codec.name) ||
693        CodecIsExternallySupported(codec.codec.name)) {
694      supported_codecs.push_back(codec);
695    }
696  }
697  return supported_codecs;
698}
699
700bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
701  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
702  if (!ValidateCodecFormats(codecs)) {
703    return false;
704  }
705
706  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
707  if (mapped_codecs.empty()) {
708    LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs.";
709    return false;
710  }
711
712  const std::vector<VideoCodecSettings> supported_codecs =
713      FilterSupportedCodecs(mapped_codecs);
714
715  if (mapped_codecs.size() != supported_codecs.size()) {
716    LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs.";
717    return false;
718  }
719
720  recv_codecs_ = supported_codecs;
721
722  rtc::CritScope stream_lock(&stream_crit_);
723  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
724           receive_streams_.begin();
725       it != receive_streams_.end();
726       ++it) {
727    it->second->SetRecvCodecs(recv_codecs_);
728  }
729
730  return true;
731}
732
733bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
734  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
735  if (!ValidateCodecFormats(codecs)) {
736    return false;
737  }
738
739  const std::vector<VideoCodecSettings> supported_codecs =
740      FilterSupportedCodecs(MapCodecs(codecs));
741
742  if (supported_codecs.empty()) {
743    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
744    return false;
745  }
746
747  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
748
749  VideoCodecSettings old_codec;
750  if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) {
751    // Using same codec, avoid reconfiguring.
752    return true;
753  }
754
755  send_codec_.Set(supported_codecs.front());
756
757  rtc::CritScope stream_lock(&stream_crit_);
758  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
759           send_streams_.begin();
760       it != send_streams_.end();
761       ++it) {
762    assert(it->second != NULL);
763    it->second->SetCodec(supported_codecs.front());
764  }
765
766  VideoCodec codec = supported_codecs.front().codec;
767  int bitrate_kbps;
768  if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
769      bitrate_kbps > 0) {
770    bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000;
771  } else {
772    bitrate_config_.min_bitrate_bps = 0;
773  }
774  if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
775      bitrate_kbps > 0) {
776    bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000;
777  } else {
778    // Do not reconfigure start bitrate unless it's specified and positive.
779    bitrate_config_.start_bitrate_bps = -1;
780  }
781  if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
782      bitrate_kbps > 0) {
783    bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000;
784  } else {
785    bitrate_config_.max_bitrate_bps = -1;
786  }
787  call_->SetBitrateConfig(bitrate_config_);
788
789  return true;
790}
791
792bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
793  VideoCodecSettings codec_settings;
794  if (!send_codec_.Get(&codec_settings)) {
795    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
796    return false;
797  }
798  *codec = codec_settings.codec;
799  return true;
800}
801
802bool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
803                                              const VideoFormat& format) {
804  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
805                  << format.ToString();
806  rtc::CritScope stream_lock(&stream_crit_);
807  if (send_streams_.find(ssrc) == send_streams_.end()) {
808    return false;
809  }
810  return send_streams_[ssrc]->SetVideoFormat(format);
811}
812
813bool WebRtcVideoChannel2::SetRender(bool render) {
814  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
815  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
816  return true;
817}
818
819bool WebRtcVideoChannel2::SetSend(bool send) {
820  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
821  if (send && !send_codec_.IsSet()) {
822    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
823    return false;
824  }
825  if (send) {
826    StartAllSendStreams();
827  } else {
828    StopAllSendStreams();
829  }
830  sending_ = send;
831  return true;
832}
833
834bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
835  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
836  if (sp.ssrcs.empty()) {
837    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
838    return false;
839  }
840
841  uint32 ssrc = sp.first_ssrc();
842  assert(ssrc != 0);
843  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
844  // ssrc.
845  rtc::CritScope stream_lock(&stream_crit_);
846  if (send_streams_.find(ssrc) != send_streams_.end()) {
847    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
848    return false;
849  }
850
851  std::vector<uint32> primary_ssrcs;
852  sp.GetPrimarySsrcs(&primary_ssrcs);
853  std::vector<uint32> rtx_ssrcs;
854  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
855  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
856    LOG(LS_ERROR)
857        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
858        << sp.ToString();
859    return false;
860  }
861
862  WebRtcVideoSendStream* stream =
863      new WebRtcVideoSendStream(call_.get(),
864                                external_encoder_factory_,
865                                encoder_factory_,
866                                options_,
867                                send_codec_,
868                                sp,
869                                send_rtp_extensions_);
870
871  send_streams_[ssrc] = stream;
872
873  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
874    rtcp_receiver_report_ssrc_ = ssrc;
875  }
876  if (default_send_ssrc_ == 0) {
877    default_send_ssrc_ = ssrc;
878  }
879  if (sending_) {
880    stream->Start();
881  }
882
883  return true;
884}
885
886bool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
887  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
888
889  if (ssrc == 0) {
890    if (default_send_ssrc_ == 0) {
891      LOG(LS_ERROR) << "No default send stream active.";
892      return false;
893    }
894
895    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
896    ssrc = default_send_ssrc_;
897  }
898
899  WebRtcVideoSendStream* removed_stream;
900  {
901    rtc::CritScope stream_lock(&stream_crit_);
902    std::map<uint32, WebRtcVideoSendStream*>::iterator it =
903        send_streams_.find(ssrc);
904    if (it == send_streams_.end()) {
905      return false;
906    }
907
908    removed_stream = it->second;
909    send_streams_.erase(it);
910  }
911
912  delete removed_stream;
913
914  if (ssrc == default_send_ssrc_) {
915    default_send_ssrc_ = 0;
916  }
917
918  return true;
919}
920
921bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
922  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
923  assert(sp.ssrcs.size() > 0);
924
925  uint32 ssrc = sp.first_ssrc();
926  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
927
928  // TODO(pbos): Check if any of the SSRCs overlap.
929  rtc::CritScope stream_lock(&stream_crit_);
930  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
931    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
932    return false;
933  }
934
935  webrtc::VideoReceiveStream::Config config;
936  ConfigureReceiverRtp(&config, sp);
937
938  // Set up A/V sync if there is a VoiceChannel.
939  // TODO(pbos): The A/V is synched by the receiving channel. So we need to know
940  // the SSRC of the remote audio channel in order to sync the correct webrtc
941  // VoiceEngine channel. For now sync the first channel in non-conference to
942  // match existing behavior in WebRtcVideoEngine.
943  if (voice_channel_ != NULL && receive_streams_.empty() &&
944      !options_.conference_mode.GetWithDefaultIfUnset(false)) {
945    config.audio_channel_id =
946        static_cast<WebRtcVoiceMediaChannel*>(voice_channel_)->voe_channel();
947  }
948
949  receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
950      call_.get(), external_decoder_factory_, config, recv_codecs_);
951
952  return true;
953}
954
955void WebRtcVideoChannel2::ConfigureReceiverRtp(
956    webrtc::VideoReceiveStream::Config* config,
957    const StreamParams& sp) const {
958  uint32 ssrc = sp.first_ssrc();
959
960  config->rtp.remote_ssrc = ssrc;
961  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
962
963  config->rtp.extensions = recv_rtp_extensions_;
964
965  // TODO(pbos): This protection is against setting the same local ssrc as
966  // remote which is not permitted by the lower-level API. RTCP requires a
967  // corresponding sender SSRC. Figure out what to do when we don't have
968  // (receive-only) or know a good local SSRC.
969  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
970    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
971      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
972    } else {
973      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
974    }
975  }
976
977  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
978    MergeFecConfig(recv_codecs_[i].fec, &config->rtp.fec);
979  }
980
981  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
982    uint32 rtx_ssrc;
983    if (recv_codecs_[i].rtx_payload_type != -1 &&
984        sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
985      webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx =
986          config->rtp.rtx[recv_codecs_[i].codec.id];
987      rtx.ssrc = rtx_ssrc;
988      rtx.payload_type = recv_codecs_[i].rtx_payload_type;
989    }
990  }
991}
992
993bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
994  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
995  if (ssrc == 0) {
996    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
997    return false;
998  }
999
1000  rtc::CritScope stream_lock(&stream_crit_);
1001  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
1002      receive_streams_.find(ssrc);
1003  if (stream == receive_streams_.end()) {
1004    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1005    return false;
1006  }
1007  delete stream->second;
1008  receive_streams_.erase(stream);
1009
1010  return true;
1011}
1012
1013bool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1014  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1015               << (renderer ? "(ptr)" : "NULL");
1016  if (ssrc == 0) {
1017    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1018    return true;
1019  }
1020
1021  rtc::CritScope stream_lock(&stream_crit_);
1022  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1023      receive_streams_.find(ssrc);
1024  if (it == receive_streams_.end()) {
1025    return false;
1026  }
1027
1028  it->second->SetRenderer(renderer);
1029  return true;
1030}
1031
1032bool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1033  if (ssrc == 0) {
1034    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1035    return *renderer != NULL;
1036  }
1037
1038  rtc::CritScope stream_lock(&stream_crit_);
1039  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1040      receive_streams_.find(ssrc);
1041  if (it == receive_streams_.end()) {
1042    return false;
1043  }
1044  *renderer = it->second->GetRenderer();
1045  return true;
1046}
1047
1048bool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
1049                                   VideoMediaInfo* info) {
1050  info->Clear();
1051  FillSenderStats(info);
1052  FillReceiverStats(info);
1053  webrtc::Call::Stats stats = call_->GetStats();
1054  FillBandwidthEstimationStats(stats, info);
1055  if (stats.rtt_ms != -1) {
1056    for (size_t i = 0; i < info->senders.size(); ++i) {
1057      info->senders[i].rtt_ms = stats.rtt_ms;
1058    }
1059  }
1060  return true;
1061}
1062
1063void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1064  rtc::CritScope stream_lock(&stream_crit_);
1065  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1066           send_streams_.begin();
1067       it != send_streams_.end();
1068       ++it) {
1069    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1070  }
1071}
1072
1073void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1074  rtc::CritScope stream_lock(&stream_crit_);
1075  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1076           receive_streams_.begin();
1077       it != receive_streams_.end();
1078       ++it) {
1079    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1080  }
1081}
1082
1083void WebRtcVideoChannel2::FillBandwidthEstimationStats(
1084    const webrtc::Call::Stats& stats,
1085    VideoMediaInfo* video_media_info) {
1086  BandwidthEstimationInfo bwe_info;
1087  bwe_info.available_send_bandwidth = stats.send_bandwidth_bps;
1088  bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps;
1089  bwe_info.bucket_delay = stats.pacer_delay_ms;
1090
1091  // Get send stream bitrate stats.
1092  rtc::CritScope stream_lock(&stream_crit_);
1093  for (std::map<uint32, WebRtcVideoSendStream*>::iterator stream =
1094           send_streams_.begin();
1095       stream != send_streams_.end();
1096       ++stream) {
1097    stream->second->FillBandwidthEstimationInfo(&bwe_info);
1098  }
1099  video_media_info->bw_estimations.push_back(bwe_info);
1100}
1101
1102bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1103  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1104               << (capturer != NULL ? "(capturer)" : "NULL");
1105  assert(ssrc != 0);
1106  rtc::CritScope stream_lock(&stream_crit_);
1107  if (send_streams_.find(ssrc) == send_streams_.end()) {
1108    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1109    return false;
1110  }
1111  return send_streams_[ssrc]->SetCapturer(capturer);
1112}
1113
1114bool WebRtcVideoChannel2::SendIntraFrame() {
1115  // TODO(pbos): Implement.
1116  LOG(LS_VERBOSE) << "SendIntraFrame().";
1117  return true;
1118}
1119
1120bool WebRtcVideoChannel2::RequestIntraFrame() {
1121  // TODO(pbos): Implement.
1122  LOG(LS_VERBOSE) << "SendIntraFrame().";
1123  return true;
1124}
1125
1126void WebRtcVideoChannel2::OnPacketReceived(
1127    rtc::Buffer* packet,
1128    const rtc::PacketTime& packet_time) {
1129  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
1130      call_->Receiver()->DeliverPacket(
1131          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
1132  switch (delivery_result) {
1133    case webrtc::PacketReceiver::DELIVERY_OK:
1134      return;
1135    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
1136      return;
1137    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
1138      break;
1139  }
1140
1141  uint32 ssrc = 0;
1142  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
1143    return;
1144  }
1145
1146  // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload.
1147  // Also figure out whether RTX needs to be handled.
1148  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1149    case UnsignalledSsrcHandler::kDropPacket:
1150      return;
1151    case UnsignalledSsrcHandler::kDeliverPacket:
1152      break;
1153  }
1154
1155  if (call_->Receiver()->DeliverPacket(
1156          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1157      webrtc::PacketReceiver::DELIVERY_OK) {
1158    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1159    return;
1160  }
1161}
1162
1163void WebRtcVideoChannel2::OnRtcpReceived(
1164    rtc::Buffer* packet,
1165    const rtc::PacketTime& packet_time) {
1166  if (call_->Receiver()->DeliverPacket(
1167          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1168      webrtc::PacketReceiver::DELIVERY_OK) {
1169    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1170  }
1171}
1172
1173void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
1174  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
1175  call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
1176                                  : webrtc::Call::kNetworkDown);
1177}
1178
1179bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1180  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1181                  << (mute ? "mute" : "unmute");
1182  assert(ssrc != 0);
1183  rtc::CritScope stream_lock(&stream_crit_);
1184  if (send_streams_.find(ssrc) == send_streams_.end()) {
1185    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1186    return false;
1187  }
1188
1189  send_streams_[ssrc]->MuteStream(mute);
1190  return true;
1191}
1192
1193bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1194    const std::vector<RtpHeaderExtension>& extensions) {
1195  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1196               << RtpExtensionsToString(extensions);
1197  if (!ValidateRtpHeaderExtensionIds(extensions))
1198    return false;
1199
1200  std::vector<webrtc::RtpExtension> filtered_extensions =
1201      FilterRtpExtensions(extensions);
1202  if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions))
1203    return true;
1204
1205  recv_rtp_extensions_ = filtered_extensions;
1206
1207  rtc::CritScope stream_lock(&stream_crit_);
1208  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1209           receive_streams_.begin();
1210       it != receive_streams_.end();
1211       ++it) {
1212    it->second->SetRtpExtensions(recv_rtp_extensions_);
1213  }
1214  return true;
1215}
1216
1217bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1218    const std::vector<RtpHeaderExtension>& extensions) {
1219  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1220               << RtpExtensionsToString(extensions);
1221  if (!ValidateRtpHeaderExtensionIds(extensions))
1222    return false;
1223
1224  std::vector<webrtc::RtpExtension> filtered_extensions =
1225      FilterRtpExtensions(extensions);
1226  if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions))
1227    return true;
1228
1229  send_rtp_extensions_ = filtered_extensions;
1230
1231  rtc::CritScope stream_lock(&stream_crit_);
1232  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1233           send_streams_.begin();
1234       it != send_streams_.end();
1235       ++it) {
1236    it->second->SetRtpExtensions(send_rtp_extensions_);
1237  }
1238  return true;
1239}
1240
1241bool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) {
1242  LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps.";
1243  if (max_bitrate_bps <= 0) {
1244    // Unsetting max bitrate.
1245    max_bitrate_bps = -1;
1246  }
1247  bitrate_config_.start_bitrate_bps = -1;
1248  bitrate_config_.max_bitrate_bps = max_bitrate_bps;
1249  if (max_bitrate_bps > 0 &&
1250      bitrate_config_.min_bitrate_bps > max_bitrate_bps) {
1251    bitrate_config_.min_bitrate_bps = max_bitrate_bps;
1252  }
1253  call_->SetBitrateConfig(bitrate_config_);
1254  return true;
1255}
1256
1257bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
1258  LOG(LS_INFO) << "SetOptions: " << options.ToString();
1259  VideoOptions old_options = options_;
1260  options_.SetAll(options);
1261  if (options_ == old_options) {
1262    // No new options to set.
1263    return true;
1264  }
1265  rtc::DiffServCodePoint dscp = options_.dscp.GetWithDefaultIfUnset(false)
1266                                    ? rtc::DSCP_AF41
1267                                    : rtc::DSCP_DEFAULT;
1268  MediaChannel::SetDscp(dscp);
1269  rtc::CritScope stream_lock(&stream_crit_);
1270  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1271           send_streams_.begin();
1272       it != send_streams_.end();
1273       ++it) {
1274    it->second->SetOptions(options_);
1275  }
1276  return true;
1277}
1278
1279void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1280  MediaChannel::SetInterface(iface);
1281  // Set the RTP recv/send buffer to a bigger size
1282  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1283                          rtc::Socket::OPT_RCVBUF,
1284                          kVideoRtpBufferSize);
1285
1286  // Speculative change to increase the outbound socket buffer size.
1287  // In b/15152257, we are seeing a significant number of packets discarded
1288  // due to lack of socket buffer space, although it's not yet clear what the
1289  // ideal value should be.
1290  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1291                          rtc::Socket::OPT_SNDBUF,
1292                          kVideoRtpBufferSize);
1293}
1294
1295void WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1296  // TODO(pbos): Implement.
1297}
1298
1299void WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
1300  // Ignored.
1301}
1302
1303void WebRtcVideoChannel2::OnLoadUpdate(Load load) {
1304  rtc::CritScope stream_lock(&stream_crit_);
1305  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1306           send_streams_.begin();
1307       it != send_streams_.end();
1308       ++it) {
1309    it->second->OnCpuResolutionRequest(load == kOveruse
1310                                           ? CoordinatedVideoAdapter::DOWNGRADE
1311                                           : CoordinatedVideoAdapter::UPGRADE);
1312  }
1313}
1314
1315bool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
1316  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1317  return MediaChannel::SendPacket(&packet);
1318}
1319
1320bool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1321  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1322  return MediaChannel::SendRtcp(&packet);
1323}
1324
1325void WebRtcVideoChannel2::StartAllSendStreams() {
1326  rtc::CritScope stream_lock(&stream_crit_);
1327  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1328           send_streams_.begin();
1329       it != send_streams_.end();
1330       ++it) {
1331    it->second->Start();
1332  }
1333}
1334
1335void WebRtcVideoChannel2::StopAllSendStreams() {
1336  rtc::CritScope stream_lock(&stream_crit_);
1337  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1338           send_streams_.begin();
1339       it != send_streams_.end();
1340       ++it) {
1341    it->second->Stop();
1342  }
1343}
1344
1345WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
1346    VideoSendStreamParameters(
1347        const webrtc::VideoSendStream::Config& config,
1348        const VideoOptions& options,
1349        const Settable<VideoCodecSettings>& codec_settings)
1350    : config(config), options(options), codec_settings(codec_settings) {
1351}
1352
1353WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1354    webrtc::Call* call,
1355    WebRtcVideoEncoderFactory* external_encoder_factory,
1356    WebRtcVideoEncoderFactory2* encoder_factory,
1357    const VideoOptions& options,
1358    const Settable<VideoCodecSettings>& codec_settings,
1359    const StreamParams& sp,
1360    const std::vector<webrtc::RtpExtension>& rtp_extensions)
1361    : call_(call),
1362      external_encoder_factory_(external_encoder_factory),
1363      encoder_factory_(encoder_factory),
1364      stream_(NULL),
1365      parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
1366      allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false),
1367      capturer_(NULL),
1368      sending_(false),
1369      muted_(false) {
1370  parameters_.config.rtp.max_packet_size = kVideoMtu;
1371
1372  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
1373  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
1374                 &parameters_.config.rtp.rtx.ssrcs);
1375  parameters_.config.rtp.c_name = sp.cname;
1376  parameters_.config.rtp.extensions = rtp_extensions;
1377
1378  VideoCodecSettings params;
1379  if (codec_settings.Get(&params)) {
1380    SetCodec(params);
1381  }
1382}
1383
1384WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1385  DisconnectCapturer();
1386  if (stream_ != NULL) {
1387    call_->DestroyVideoSendStream(stream_);
1388  }
1389  DestroyVideoEncoder(&allocated_encoder_);
1390}
1391
1392static void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
1393  assert(video_frame != NULL);
1394  memset(video_frame->buffer(webrtc::kYPlane),
1395         16,
1396         video_frame->allocated_size(webrtc::kYPlane));
1397  memset(video_frame->buffer(webrtc::kUPlane),
1398         128,
1399         video_frame->allocated_size(webrtc::kUPlane));
1400  memset(video_frame->buffer(webrtc::kVPlane),
1401         128,
1402         video_frame->allocated_size(webrtc::kVPlane));
1403}
1404
1405static void CreateBlackFrame(webrtc::I420VideoFrame* video_frame,
1406                             int width,
1407                             int height) {
1408  video_frame->CreateEmptyFrame(
1409      width, height, width, (width + 1) / 2, (width + 1) / 2);
1410  SetWebRtcFrameToBlack(video_frame);
1411}
1412
1413static void ConvertToI420VideoFrame(const VideoFrame& frame,
1414                                    webrtc::I420VideoFrame* i420_frame) {
1415  i420_frame->CreateFrame(
1416      static_cast<int>(frame.GetYPitch() * frame.GetHeight()),
1417      frame.GetYPlane(),
1418      static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)),
1419      frame.GetUPlane(),
1420      static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)),
1421      frame.GetVPlane(),
1422      static_cast<int>(frame.GetWidth()),
1423      static_cast<int>(frame.GetHeight()),
1424      static_cast<int>(frame.GetYPitch()),
1425      static_cast<int>(frame.GetUPitch()),
1426      static_cast<int>(frame.GetVPitch()));
1427}
1428
1429void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1430    VideoCapturer* capturer,
1431    const VideoFrame* frame) {
1432  LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
1433                  << frame->GetHeight();
1434  // Lock before copying, can be called concurrently when swapping input source.
1435  rtc::CritScope frame_cs(&frame_lock_);
1436  ConvertToI420VideoFrame(*frame, &video_frame_);
1437
1438  rtc::CritScope cs(&lock_);
1439  if (stream_ == NULL) {
1440    LOG(LS_WARNING) << "Capturer inputting frames before send codecs are "
1441                       "configured, dropping.";
1442    return;
1443  }
1444  if (format_.width == 0) {  // Dropping frames.
1445    assert(format_.height == 0);
1446    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1447    return;
1448  }
1449  if (muted_) {
1450    // Create a black frame to transmit instead.
1451    CreateBlackFrame(&video_frame_,
1452                     static_cast<int>(frame->GetWidth()),
1453                     static_cast<int>(frame->GetHeight()));
1454  }
1455  // Reconfigure codec if necessary.
1456  SetDimensions(
1457      video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
1458
1459  LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
1460                  << video_frame_.height() << " -> (codec) "
1461                  << parameters_.encoder_config.streams.back().width << "x"
1462                  << parameters_.encoder_config.streams.back().height;
1463  stream_->Input()->SwapFrame(&video_frame_);
1464}
1465
1466bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1467    VideoCapturer* capturer) {
1468  if (!DisconnectCapturer() && capturer == NULL) {
1469    return false;
1470  }
1471
1472  {
1473    rtc::CritScope cs(&lock_);
1474
1475    if (capturer == NULL) {
1476      if (stream_ != NULL) {
1477        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
1478        webrtc::I420VideoFrame black_frame;
1479
1480        // TODO(pbos): Base width/height on last_dimensions_. This will however
1481        // fail the test AddRemoveCapturer which needs to be fixed to permit
1482        // sending black frames in the same size that was previously sent.
1483        int width = format_.width;
1484        int height = format_.height;
1485        int half_width = (width + 1) / 2;
1486        black_frame.CreateEmptyFrame(
1487            width, height, width, half_width, half_width);
1488        SetWebRtcFrameToBlack(&black_frame);
1489        SetDimensions(width, height, last_dimensions_.is_screencast);
1490        stream_->Input()->SwapFrame(&black_frame);
1491      }
1492
1493      capturer_ = NULL;
1494      return true;
1495    }
1496
1497    capturer_ = capturer;
1498  }
1499  // Lock cannot be held while connecting the capturer to prevent lock-order
1500  // violations.
1501  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1502  return true;
1503}
1504
1505bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1506    const VideoFormat& format) {
1507  if ((format.width == 0 || format.height == 0) &&
1508      format.width != format.height) {
1509    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1510                     "both, 0x0 drops frames).";
1511    return false;
1512  }
1513
1514  rtc::CritScope cs(&lock_);
1515  if (format.width == 0 && format.height == 0) {
1516    LOG(LS_INFO)
1517        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
1518        << parameters_.config.rtp.ssrcs[0] << ".";
1519  } else {
1520    // TODO(pbos): Fix me, this only affects the last stream!
1521    parameters_.encoder_config.streams.back().max_framerate =
1522        VideoFormat::IntervalToFps(format.interval);
1523    SetDimensions(format.width, format.height, false);
1524  }
1525
1526  format_ = format;
1527  return true;
1528}
1529
1530void WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1531  rtc::CritScope cs(&lock_);
1532  muted_ = mute;
1533}
1534
1535bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1536  cricket::VideoCapturer* capturer;
1537  {
1538    rtc::CritScope cs(&lock_);
1539    if (capturer_ == NULL) {
1540      return false;
1541    }
1542    capturer = capturer_;
1543    capturer_ = NULL;
1544  }
1545  capturer->SignalVideoFrame.disconnect(this);
1546  return true;
1547}
1548
1549void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
1550    const VideoOptions& options) {
1551  rtc::CritScope cs(&lock_);
1552  VideoCodecSettings codec_settings;
1553  if (parameters_.codec_settings.Get(&codec_settings)) {
1554    SetCodecAndOptions(codec_settings, options);
1555  } else {
1556    parameters_.options = options;
1557  }
1558}
1559
1560void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
1561    const VideoCodecSettings& codec_settings) {
1562  rtc::CritScope cs(&lock_);
1563  SetCodecAndOptions(codec_settings, parameters_.options);
1564}
1565
1566webrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
1567  if (CodecNameMatches(name, kVp8CodecName)) {
1568    return webrtc::kVideoCodecVP8;
1569  } else if (CodecNameMatches(name, kVp9CodecName)) {
1570    return webrtc::kVideoCodecVP9;
1571  } else if (CodecNameMatches(name, kH264CodecName)) {
1572    return webrtc::kVideoCodecH264;
1573  }
1574  return webrtc::kVideoCodecUnknown;
1575}
1576
1577WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
1578WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
1579    const VideoCodec& codec) {
1580  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
1581
1582  // Do not re-create encoders of the same type.
1583  if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) {
1584    return allocated_encoder_;
1585  }
1586
1587  if (external_encoder_factory_ != NULL) {
1588    webrtc::VideoEncoder* encoder =
1589        external_encoder_factory_->CreateVideoEncoder(type);
1590    if (encoder != NULL) {
1591      return AllocatedEncoder(encoder, type, true);
1592    }
1593  }
1594
1595  if (type == webrtc::kVideoCodecVP8) {
1596    return AllocatedEncoder(
1597        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false);
1598  } else if (type == webrtc::kVideoCodecVP9) {
1599    return AllocatedEncoder(
1600        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp9), type, false);
1601  }
1602
1603  // This shouldn't happen, we should not be trying to create something we don't
1604  // support.
1605  assert(false);
1606  return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false);
1607}
1608
1609void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
1610    AllocatedEncoder* encoder) {
1611  if (encoder->external) {
1612    external_encoder_factory_->DestroyVideoEncoder(encoder->encoder);
1613  } else {
1614    delete encoder->encoder;
1615  }
1616}
1617
1618void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
1619    const VideoCodecSettings& codec_settings,
1620    const VideoOptions& options) {
1621  if (last_dimensions_.width == -1) {
1622    last_dimensions_.width = codec_settings.codec.width;
1623    last_dimensions_.height = codec_settings.codec.height;
1624    last_dimensions_.is_screencast = false;
1625  }
1626  parameters_.encoder_config =
1627      CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
1628  if (parameters_.encoder_config.streams.empty()) {
1629    return;
1630  }
1631
1632  format_ = VideoFormat(codec_settings.codec.width,
1633                        codec_settings.codec.height,
1634                        VideoFormat::FpsToInterval(30),
1635                        FOURCC_I420);
1636
1637  AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
1638  parameters_.config.encoder_settings.encoder = new_encoder.encoder;
1639  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
1640  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
1641  parameters_.config.rtp.fec = codec_settings.fec;
1642
1643  // Set RTX payload type if RTX is enabled.
1644  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
1645    parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1646  }
1647
1648  if (IsNackEnabled(codec_settings.codec)) {
1649    parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs;
1650  }
1651
1652  options.suspend_below_min_bitrate.Get(
1653      &parameters_.config.suspend_below_min_bitrate);
1654
1655  parameters_.codec_settings.Set(codec_settings);
1656  parameters_.options = options;
1657
1658  RecreateWebRtcStream();
1659  if (allocated_encoder_.encoder != new_encoder.encoder) {
1660    DestroyVideoEncoder(&allocated_encoder_);
1661    allocated_encoder_ = new_encoder;
1662  }
1663}
1664
1665void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1666    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1667  rtc::CritScope cs(&lock_);
1668  parameters_.config.rtp.extensions = rtp_extensions;
1669  RecreateWebRtcStream();
1670}
1671
1672webrtc::VideoEncoderConfig
1673WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
1674    const Dimensions& dimensions,
1675    const VideoCodec& codec) const {
1676  webrtc::VideoEncoderConfig encoder_config;
1677  if (dimensions.is_screencast) {
1678    int screencast_min_bitrate_kbps;
1679    parameters_.options.screencast_min_bitrate.Get(
1680        &screencast_min_bitrate_kbps);
1681    encoder_config.min_transmit_bitrate_bps =
1682        screencast_min_bitrate_kbps * 1000;
1683    encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare;
1684  } else {
1685    encoder_config.min_transmit_bitrate_bps = 0;
1686    encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo;
1687  }
1688
1689  // Restrict dimensions according to codec max.
1690  int width = dimensions.width;
1691  int height = dimensions.height;
1692  if (!dimensions.is_screencast) {
1693    if (codec.width < width)
1694      width = codec.width;
1695    if (codec.height < height)
1696      height = codec.height;
1697  }
1698
1699  VideoCodec clamped_codec = codec;
1700  clamped_codec.width = width;
1701  clamped_codec.height = height;
1702
1703  encoder_config.streams = encoder_factory_->CreateVideoStreams(
1704      clamped_codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
1705
1706  // Conference mode screencast uses 2 temporal layers split at 100kbit.
1707  if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) &&
1708      dimensions.is_screencast && encoder_config.streams.size() == 1) {
1709    ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
1710
1711    // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked
1712    // on the VideoCodec struct as target and max bitrates, respectively.
1713    // See eg. webrtc::VP8EncoderImpl::SetRates().
1714    encoder_config.streams[0].target_bitrate_bps =
1715        config.tl0_bitrate_kbps * 1000;
1716    encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
1717    encoder_config.streams[0].temporal_layer_thresholds_bps.clear();
1718    encoder_config.streams[0].temporal_layer_thresholds_bps.push_back(
1719        config.tl0_bitrate_kbps * 1000);
1720  }
1721  return encoder_config;
1722}
1723
1724void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
1725    int width,
1726    int height,
1727    bool is_screencast) {
1728  if (last_dimensions_.width == width && last_dimensions_.height == height &&
1729      last_dimensions_.is_screencast == is_screencast) {
1730    // Configured using the same parameters, do not reconfigure.
1731    return;
1732  }
1733  LOG(LS_INFO) << "SetDimensions: " << width << "x" << height
1734               << (is_screencast ? " (screencast)" : " (not screencast)");
1735
1736  last_dimensions_.width = width;
1737  last_dimensions_.height = height;
1738  last_dimensions_.is_screencast = is_screencast;
1739
1740  assert(!parameters_.encoder_config.streams.empty());
1741
1742  VideoCodecSettings codec_settings;
1743  parameters_.codec_settings.Get(&codec_settings);
1744
1745  webrtc::VideoEncoderConfig encoder_config =
1746      CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
1747
1748  encoder_config.encoder_specific_settings =
1749      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1750                                                   parameters_.options);
1751
1752  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
1753
1754  encoder_factory_->DestroyVideoEncoderSettings(
1755      codec_settings.codec,
1756      encoder_config.encoder_specific_settings);
1757
1758  encoder_config.encoder_specific_settings = NULL;
1759
1760  if (!stream_reconfigured) {
1761    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
1762                    << width << "x" << height;
1763    return;
1764  }
1765
1766  parameters_.encoder_config = encoder_config;
1767}
1768
1769void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
1770  rtc::CritScope cs(&lock_);
1771  assert(stream_ != NULL);
1772  stream_->Start();
1773  sending_ = true;
1774}
1775
1776void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
1777  rtc::CritScope cs(&lock_);
1778  if (stream_ != NULL) {
1779    stream_->Stop();
1780  }
1781  sending_ = false;
1782}
1783
1784VideoSenderInfo
1785WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
1786  VideoSenderInfo info;
1787  rtc::CritScope cs(&lock_);
1788  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
1789    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
1790  }
1791
1792  if (stream_ == NULL) {
1793    return info;
1794  }
1795
1796  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
1797  info.framerate_input = stats.input_frame_rate;
1798  info.framerate_sent = stats.encode_frame_rate;
1799
1800  info.send_frame_width = 0;
1801  info.send_frame_height = 0;
1802  for (std::map<uint32_t, webrtc::SsrcStats>::iterator it =
1803           stats.substreams.begin();
1804       it != stats.substreams.end();
1805       ++it) {
1806    // TODO(pbos): Wire up additional stats, such as padding bytes.
1807    webrtc::SsrcStats stream_stats = it->second;
1808    info.bytes_sent += stream_stats.rtp_stats.bytes +
1809                       stream_stats.rtp_stats.header_bytes +
1810                       stream_stats.rtp_stats.padding_bytes;
1811    info.packets_sent += stream_stats.rtp_stats.packets;
1812    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
1813    if (stream_stats.sent_width > info.send_frame_width)
1814      info.send_frame_width = stream_stats.sent_width;
1815    if (stream_stats.sent_height > info.send_frame_height)
1816      info.send_frame_height = stream_stats.sent_height;
1817  }
1818
1819  if (!stats.substreams.empty()) {
1820    // TODO(pbos): Report fraction lost per SSRC.
1821    webrtc::SsrcStats first_stream_stats = stats.substreams.begin()->second;
1822    info.fraction_lost =
1823        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
1824        (1 << 8);
1825  }
1826
1827  if (capturer_ != NULL && !capturer_->IsMuted()) {
1828    VideoFormat last_captured_frame_format;
1829    capturer_->GetStats(&info.adapt_frame_drops,
1830                        &info.effects_frame_drops,
1831                        &info.capturer_frame_time,
1832                        &last_captured_frame_format);
1833    info.input_frame_width = last_captured_frame_format.width;
1834    info.input_frame_height = last_captured_frame_format.height;
1835  }
1836
1837  // TODO(pbos): Support or remove the following stats.
1838  info.packets_cached = -1;
1839
1840  return info;
1841}
1842
1843void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
1844    BandwidthEstimationInfo* bwe_info) {
1845  rtc::CritScope cs(&lock_);
1846  if (stream_ == NULL) {
1847    return;
1848  }
1849  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
1850  for (std::map<uint32_t, webrtc::SsrcStats>::iterator it =
1851           stats.substreams.begin();
1852       it != stats.substreams.end();
1853       ++it) {
1854    bwe_info->transmit_bitrate += it->second.total_bitrate_bps;
1855    bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps;
1856  }
1857  bwe_info->actual_enc_bitrate = stats.media_bitrate_bps;
1858}
1859
1860void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest(
1861    CoordinatedVideoAdapter::AdaptRequest adapt_request) {
1862  rtc::CritScope cs(&lock_);
1863  bool adapt_cpu;
1864  parameters_.options.cpu_overuse_detection.Get(&adapt_cpu);
1865  if (!adapt_cpu) {
1866    return;
1867  }
1868  if (capturer_ == NULL || capturer_->video_adapter() == NULL) {
1869    return;
1870  }
1871
1872  capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request);
1873}
1874
1875void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
1876  if (stream_ != NULL) {
1877    call_->DestroyVideoSendStream(stream_);
1878  }
1879
1880  VideoCodecSettings codec_settings;
1881  parameters_.codec_settings.Get(&codec_settings);
1882  parameters_.encoder_config.encoder_specific_settings =
1883      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1884                                                   parameters_.options);
1885
1886  stream_ = call_->CreateVideoSendStream(parameters_.config,
1887                                         parameters_.encoder_config);
1888
1889  encoder_factory_->DestroyVideoEncoderSettings(
1890      codec_settings.codec,
1891      parameters_.encoder_config.encoder_specific_settings);
1892
1893  parameters_.encoder_config.encoder_specific_settings = NULL;
1894
1895  if (sending_) {
1896    stream_->Start();
1897  }
1898}
1899
1900WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
1901    webrtc::Call* call,
1902    WebRtcVideoDecoderFactory* external_decoder_factory,
1903    const webrtc::VideoReceiveStream::Config& config,
1904    const std::vector<VideoCodecSettings>& recv_codecs)
1905    : call_(call),
1906      stream_(NULL),
1907      config_(config),
1908      external_decoder_factory_(external_decoder_factory),
1909      renderer_(NULL),
1910      last_width_(-1),
1911      last_height_(-1) {
1912  config_.renderer = this;
1913  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
1914  SetRecvCodecs(recv_codecs);
1915}
1916
1917WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
1918  call_->DestroyVideoReceiveStream(stream_);
1919  ClearDecoders(&allocated_decoders_);
1920}
1921
1922WebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder
1923WebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder(
1924    std::vector<AllocatedDecoder>* old_decoders,
1925    const VideoCodec& codec) {
1926  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
1927
1928  for (size_t i = 0; i < old_decoders->size(); ++i) {
1929    if ((*old_decoders)[i].type == type) {
1930      AllocatedDecoder decoder = (*old_decoders)[i];
1931      (*old_decoders)[i] = old_decoders->back();
1932      old_decoders->pop_back();
1933      return decoder;
1934    }
1935  }
1936
1937  if (external_decoder_factory_ != NULL) {
1938    webrtc::VideoDecoder* decoder =
1939        external_decoder_factory_->CreateVideoDecoder(type);
1940    if (decoder != NULL) {
1941      return AllocatedDecoder(decoder, type, true);
1942    }
1943  }
1944
1945  if (type == webrtc::kVideoCodecVP8) {
1946    return AllocatedDecoder(
1947        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false);
1948  }
1949
1950  // This shouldn't happen, we should not be trying to create something we don't
1951  // support.
1952  assert(false);
1953  return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false);
1954}
1955
1956void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
1957    const std::vector<VideoCodecSettings>& recv_codecs) {
1958  std::vector<AllocatedDecoder> old_decoders = allocated_decoders_;
1959  allocated_decoders_.clear();
1960  config_.decoders.clear();
1961  for (size_t i = 0; i < recv_codecs.size(); ++i) {
1962    AllocatedDecoder allocated_decoder =
1963        CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec);
1964    allocated_decoders_.push_back(allocated_decoder);
1965
1966    webrtc::VideoReceiveStream::Decoder decoder;
1967    decoder.decoder = allocated_decoder.decoder;
1968    decoder.payload_type = recv_codecs[i].codec.id;
1969    decoder.payload_name = recv_codecs[i].codec.name;
1970    config_.decoders.push_back(decoder);
1971  }
1972
1973  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
1974  config_.rtp.fec = recv_codecs.front().fec;
1975  config_.rtp.nack.rtp_history_ms =
1976      IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
1977  config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
1978
1979  ClearDecoders(&old_decoders);
1980  RecreateWebRtcStream();
1981}
1982
1983void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
1984    const std::vector<webrtc::RtpExtension>& extensions) {
1985  config_.rtp.extensions = extensions;
1986  RecreateWebRtcStream();
1987}
1988
1989void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
1990  if (stream_ != NULL) {
1991    call_->DestroyVideoReceiveStream(stream_);
1992  }
1993  stream_ = call_->CreateVideoReceiveStream(config_);
1994  stream_->Start();
1995}
1996
1997void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders(
1998    std::vector<AllocatedDecoder>* allocated_decoders) {
1999  for (size_t i = 0; i < allocated_decoders->size(); ++i) {
2000    if ((*allocated_decoders)[i].external) {
2001      external_decoder_factory_->DestroyVideoDecoder(
2002          (*allocated_decoders)[i].decoder);
2003    } else {
2004      delete (*allocated_decoders)[i].decoder;
2005    }
2006  }
2007  allocated_decoders->clear();
2008}
2009
2010void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
2011    const webrtc::I420VideoFrame& frame,
2012    int time_to_render_ms) {
2013  rtc::CritScope crit(&renderer_lock_);
2014  if (renderer_ == NULL) {
2015    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
2016    return;
2017  }
2018
2019  if (frame.width() != last_width_ || frame.height() != last_height_) {
2020    SetSize(frame.width(), frame.height());
2021  }
2022
2023  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
2024                  << ")";
2025
2026  const WebRtcVideoRenderFrame render_frame(&frame);
2027  renderer_->RenderFrame(&render_frame);
2028}
2029
2030void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
2031    cricket::VideoRenderer* renderer) {
2032  rtc::CritScope crit(&renderer_lock_);
2033  renderer_ = renderer;
2034  if (renderer_ != NULL && last_width_ != -1) {
2035    SetSize(last_width_, last_height_);
2036  }
2037}
2038
2039VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
2040  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
2041  // design.
2042  rtc::CritScope crit(&renderer_lock_);
2043  return renderer_;
2044}
2045
2046void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
2047                                                            int height) {
2048  rtc::CritScope crit(&renderer_lock_);
2049  if (!renderer_->SetSize(width, height, 0)) {
2050    LOG(LS_ERROR) << "Could not set renderer size.";
2051  }
2052  last_width_ = width;
2053  last_height_ = height;
2054}
2055
2056VideoReceiverInfo
2057WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
2058  VideoReceiverInfo info;
2059  info.add_ssrc(config_.rtp.remote_ssrc);
2060  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
2061  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
2062                    stats.rtp_stats.padding_bytes;
2063  info.packets_rcvd = stats.rtp_stats.packets;
2064
2065  info.framerate_rcvd = stats.network_frame_rate;
2066  info.framerate_decoded = stats.decode_frame_rate;
2067  info.framerate_output = stats.render_frame_rate;
2068
2069  rtc::CritScope frame_cs(&renderer_lock_);
2070  info.frame_width = last_width_;
2071  info.frame_height = last_height_;
2072
2073  // TODO(pbos): Support or remove the following stats.
2074  info.packets_concealed = -1;
2075
2076  return info;
2077}
2078
2079WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
2080    : rtx_payload_type(-1) {}
2081
2082bool WebRtcVideoChannel2::VideoCodecSettings::operator==(
2083    const WebRtcVideoChannel2::VideoCodecSettings& other) const {
2084  return codec == other.codec &&
2085         fec.ulpfec_payload_type == other.fec.ulpfec_payload_type &&
2086         fec.red_payload_type == other.fec.red_payload_type &&
2087         rtx_payload_type == other.rtx_payload_type;
2088}
2089
2090std::vector<WebRtcVideoChannel2::VideoCodecSettings>
2091WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
2092  assert(!codecs.empty());
2093
2094  std::vector<VideoCodecSettings> video_codecs;
2095  std::map<int, bool> payload_used;
2096  std::map<int, VideoCodec::CodecType> payload_codec_type;
2097  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
2098
2099  webrtc::FecConfig fec_settings;
2100
2101  for (size_t i = 0; i < codecs.size(); ++i) {
2102    const VideoCodec& in_codec = codecs[i];
2103    int payload_type = in_codec.id;
2104
2105    if (payload_used[payload_type]) {
2106      LOG(LS_ERROR) << "Payload type already registered: "
2107                    << in_codec.ToString();
2108      return std::vector<VideoCodecSettings>();
2109    }
2110    payload_used[payload_type] = true;
2111    payload_codec_type[payload_type] = in_codec.GetCodecType();
2112
2113    switch (in_codec.GetCodecType()) {
2114      case VideoCodec::CODEC_RED: {
2115        // RED payload type, should not have duplicates.
2116        assert(fec_settings.red_payload_type == -1);
2117        fec_settings.red_payload_type = in_codec.id;
2118        continue;
2119      }
2120
2121      case VideoCodec::CODEC_ULPFEC: {
2122        // ULPFEC payload type, should not have duplicates.
2123        assert(fec_settings.ulpfec_payload_type == -1);
2124        fec_settings.ulpfec_payload_type = in_codec.id;
2125        continue;
2126      }
2127
2128      case VideoCodec::CODEC_RTX: {
2129        int associated_payload_type;
2130        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
2131                               &associated_payload_type)) {
2132          LOG(LS_ERROR) << "RTX codec without associated payload type: "
2133                        << in_codec.ToString();
2134          return std::vector<VideoCodecSettings>();
2135        }
2136        rtx_mapping[associated_payload_type] = in_codec.id;
2137        continue;
2138      }
2139
2140      case VideoCodec::CODEC_VIDEO:
2141        break;
2142    }
2143
2144    video_codecs.push_back(VideoCodecSettings());
2145    video_codecs.back().codec = in_codec;
2146  }
2147
2148  // One of these codecs should have been a video codec. Only having FEC
2149  // parameters into this code is a logic error.
2150  assert(!video_codecs.empty());
2151
2152  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
2153       it != rtx_mapping.end();
2154       ++it) {
2155    if (!payload_used[it->first]) {
2156      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
2157      return std::vector<VideoCodecSettings>();
2158    }
2159    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
2160      LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
2161      return std::vector<VideoCodecSettings>();
2162    }
2163  }
2164
2165  // TODO(pbos): Write tests that figure out that I have not verified that RTX
2166  // codecs aren't mapped to bogus payloads.
2167  for (size_t i = 0; i < video_codecs.size(); ++i) {
2168    video_codecs[i].fec = fec_settings;
2169    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
2170      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
2171    }
2172  }
2173
2174  return video_codecs;
2175}
2176
2177}  // namespace cricket
2178
2179#endif  // HAVE_WEBRTC_VIDEO
2180