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