webrtcvideoengine2.cc revision 1ecbe45c7e4c9142896cb2810d699558518f4f28
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/webrtcvideoframe.h"
40#include "talk/media/webrtc/webrtcvoiceengine.h"
41#include "webrtc/base/buffer.h"
42#include "webrtc/base/logging.h"
43#include "webrtc/base/stringutils.h"
44#include "webrtc/call.h"
45#include "webrtc/video_encoder.h"
46
47#define UNIMPLEMENTED                                                 \
48  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
49  ASSERT(false)
50
51namespace cricket {
52namespace {
53
54static bool CodecNameMatches(const std::string& name1,
55                             const std::string& name2) {
56  return _stricmp(name1.c_str(), name2.c_str()) == 0;
57}
58
59// True if codec is supported by a software implementation that's always
60// available.
61static bool CodecIsInternallySupported(const std::string& codec_name) {
62  return CodecNameMatches(codec_name, kVp8CodecName);
63}
64
65static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
66  std::stringstream out;
67  out << '{';
68  for (size_t i = 0; i < codecs.size(); ++i) {
69    out << codecs[i].ToString();
70    if (i != codecs.size() - 1) {
71      out << ", ";
72    }
73  }
74  out << '}';
75  return out.str();
76}
77
78static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
79  bool has_video = false;
80  for (size_t i = 0; i < codecs.size(); ++i) {
81    if (!codecs[i].ValidateCodecFormat()) {
82      return false;
83    }
84    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
85      has_video = true;
86    }
87  }
88  if (!has_video) {
89    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
90                  << CodecVectorToString(codecs);
91    return false;
92  }
93  return true;
94}
95
96static std::string RtpExtensionsToString(
97    const std::vector<RtpHeaderExtension>& extensions) {
98  std::stringstream out;
99  out << '{';
100  for (size_t i = 0; i < extensions.size(); ++i) {
101    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
102    if (i != extensions.size() - 1) {
103      out << ", ";
104    }
105  }
106  out << '}';
107  return out.str();
108}
109
110}  // namespace
111
112// This constant is really an on/off, lower-level configurable NACK history
113// duration hasn't been implemented.
114static const int kNackHistoryMs = 1000;
115
116static const int kDefaultQpMax = 56;
117
118static const int kDefaultRtcpReceiverReportSsrc = 1;
119
120// External video encoders are given payloads 120-127. This also means that we
121// only support up to 8 external payload types.
122static const int kExternalVideoPayloadTypeBase = 120;
123#ifndef NDEBUG
124static const size_t kMaxExternalVideoCodecs = 8;
125#endif
126
127struct VideoCodecPref {
128  int payload_type;
129  int width;
130  int height;
131  const char* name;
132  int rtx_payload_type;
133} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96};
134
135const char kH264CodecName[] = "H264";
136
137VideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1};
138VideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1};
139
140static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
141                                   const VideoCodec& requested_codec,
142                                   VideoCodec* matching_codec) {
143  for (size_t i = 0; i < codecs.size(); ++i) {
144    if (requested_codec.Matches(codecs[i])) {
145      *matching_codec = codecs[i];
146      return true;
147    }
148  }
149  return false;
150}
151
152static void AddDefaultFeedbackParams(VideoCodec* codec) {
153  const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
154  codec->AddFeedbackParam(kFir);
155  const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
156  codec->AddFeedbackParam(kNack);
157  const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
158  codec->AddFeedbackParam(kPli);
159  const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
160  codec->AddFeedbackParam(kRemb);
161}
162
163static bool IsNackEnabled(const VideoCodec& codec) {
164  return codec.HasFeedbackParam(
165      FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
166}
167
168static bool IsRembEnabled(const VideoCodec& codec) {
169  return codec.HasFeedbackParam(
170      FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
171}
172
173static VideoCodec DefaultVideoCodec() {
174  VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
175                           kDefaultVideoCodecPref.name,
176                           kDefaultVideoCodecPref.width,
177                           kDefaultVideoCodecPref.height,
178                           kDefaultFramerate,
179                           0);
180  AddDefaultFeedbackParams(&default_codec);
181  return default_codec;
182}
183
184static VideoCodec DefaultRedCodec() {
185  return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0);
186}
187
188static VideoCodec DefaultUlpfecCodec() {
189  return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0);
190}
191
192static std::vector<VideoCodec> DefaultVideoCodecs() {
193  std::vector<VideoCodec> codecs;
194  codecs.push_back(DefaultVideoCodec());
195  codecs.push_back(DefaultRedCodec());
196  codecs.push_back(DefaultUlpfecCodec());
197  if (kDefaultVideoCodecPref.rtx_payload_type != -1) {
198    codecs.push_back(
199        VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type,
200                                   kDefaultVideoCodecPref.payload_type));
201  }
202  return codecs;
203}
204
205static bool ValidateRtpHeaderExtensionIds(
206    const std::vector<RtpHeaderExtension>& extensions) {
207  std::set<int> extensions_used;
208  for (size_t i = 0; i < extensions.size(); ++i) {
209    if (extensions[i].id < 0 || extensions[i].id >= 15 ||
210        !extensions_used.insert(extensions[i].id).second) {
211      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
212      return false;
213    }
214  }
215  return true;
216}
217
218static std::vector<webrtc::RtpExtension> FilterRtpExtensions(
219    const std::vector<RtpHeaderExtension>& extensions) {
220  std::vector<webrtc::RtpExtension> webrtc_extensions;
221  for (size_t i = 0; i < extensions.size(); ++i) {
222    // Unsupported extensions will be ignored.
223    if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) {
224      webrtc_extensions.push_back(webrtc::RtpExtension(
225          extensions[i].uri, extensions[i].id));
226    } else {
227      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
228    }
229  }
230  return webrtc_extensions;
231}
232
233WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
234}
235
236std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
237    const VideoCodec& codec,
238    const VideoOptions& options,
239    size_t num_streams) {
240  if (num_streams != 1) {
241    LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
242    return std::vector<webrtc::VideoStream>();
243  }
244
245  webrtc::VideoStream stream;
246  stream.width = codec.width;
247  stream.height = codec.height;
248  stream.max_framerate =
249      codec.framerate != 0 ? codec.framerate : kDefaultFramerate;
250
251  int min_bitrate = kMinVideoBitrate;
252  codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
253  int max_bitrate = kMaxVideoBitrate;
254  codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
255  stream.min_bitrate_bps = min_bitrate * 1000;
256  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
257
258  int max_qp = kDefaultQpMax;
259  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
260  stream.max_qp = max_qp;
261  std::vector<webrtc::VideoStream> streams;
262  streams.push_back(stream);
263  return streams;
264}
265
266void* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
267    const VideoCodec& codec,
268    const VideoOptions& options) {
269  if (CodecNameMatches(codec.name, kVp8CodecName)) {
270    webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
271        webrtc::VideoEncoder::GetDefaultVp8Settings());
272    options.video_noise_reduction.Get(&settings->denoisingOn);
273    return settings;
274  }
275  return NULL;
276}
277
278void WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
279    const VideoCodec& codec,
280    void* encoder_settings) {
281  if (encoder_settings == NULL) {
282    return;
283  }
284  if (CodecNameMatches(codec.name, kVp8CodecName)) {
285    delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
286  }
287}
288
289DefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
290    : default_recv_ssrc_(0), default_renderer_(NULL) {}
291
292UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
293    VideoMediaChannel* channel,
294    uint32_t ssrc) {
295  if (default_recv_ssrc_ != 0) {  // Already one default stream.
296    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
297    return kDropPacket;
298  }
299
300  StreamParams sp;
301  sp.ssrcs.push_back(ssrc);
302  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
303  if (!channel->AddRecvStream(sp)) {
304    LOG(LS_WARNING) << "Could not create default receive stream.";
305  }
306
307  channel->SetRenderer(ssrc, default_renderer_);
308  default_recv_ssrc_ = ssrc;
309  return kDeliverPacket;
310}
311
312WebRtcCallFactory::~WebRtcCallFactory() {
313}
314webrtc::Call* WebRtcCallFactory::CreateCall(
315    const webrtc::Call::Config& config) {
316  return webrtc::Call::Create(config);
317}
318
319VideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
320  return default_renderer_;
321}
322
323void DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
324    VideoMediaChannel* channel,
325    VideoRenderer* renderer) {
326  default_renderer_ = renderer;
327  if (default_recv_ssrc_ != 0) {
328    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
329  }
330}
331
332WebRtcVideoEngine2::WebRtcVideoEngine2()
333    : worker_thread_(NULL),
334      voice_engine_(NULL),
335      default_codec_format_(kDefaultVideoCodecPref.width,
336                            kDefaultVideoCodecPref.height,
337                            FPS_TO_INTERVAL(kDefaultFramerate),
338                            FOURCC_ANY),
339      initialized_(false),
340      cpu_monitor_(new rtc::CpuMonitor(NULL)),
341      call_factory_(&default_call_factory_),
342      external_decoder_factory_(NULL),
343      external_encoder_factory_(NULL) {
344  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
345  video_codecs_ = GetSupportedCodecs();
346  rtp_header_extensions_.push_back(
347      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
348                         kRtpTimestampOffsetHeaderExtensionDefaultId));
349  rtp_header_extensions_.push_back(
350      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
351                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
352}
353
354WebRtcVideoEngine2::~WebRtcVideoEngine2() {
355  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
356
357  if (initialized_) {
358    Terminate();
359  }
360}
361
362void WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) {
363  assert(!initialized_);
364  call_factory_ = call_factory;
365}
366
367bool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) {
368  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
369  worker_thread_ = worker_thread;
370  ASSERT(worker_thread_ != NULL);
371
372  cpu_monitor_->set_thread(worker_thread_);
373  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
374    LOG(LS_ERROR) << "Failed to start CPU monitor.";
375    cpu_monitor_.reset();
376  }
377
378  initialized_ = true;
379  return true;
380}
381
382void WebRtcVideoEngine2::Terminate() {
383  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
384
385  cpu_monitor_->Stop();
386
387  initialized_ = false;
388}
389
390int WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
391
392bool WebRtcVideoEngine2::SetDefaultEncoderConfig(
393    const VideoEncoderConfig& config) {
394  const VideoCodec& codec = config.max_codec;
395  // TODO(pbos): Make use of external encoder factory.
396  if (!CodecIsInternallySupported(codec.name)) {
397    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:"
398                  << codec.ToString();
399    return false;
400  }
401
402  default_codec_format_ =
403      VideoFormat(codec.width,
404                  codec.height,
405                  VideoFormat::FpsToInterval(codec.framerate),
406                  FOURCC_ANY);
407  video_codecs_.clear();
408  video_codecs_.push_back(codec);
409  return true;
410}
411
412VideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const {
413  return VideoEncoderConfig(DefaultVideoCodec());
414}
415
416WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
417    const VideoOptions& options,
418    VoiceMediaChannel* voice_channel) {
419  assert(initialized_);
420  LOG(LS_INFO) << "CreateChannel: "
421               << (voice_channel != NULL ? "With" : "Without")
422               << " voice channel.";
423  WebRtcVideoChannel2* channel =
424      new WebRtcVideoChannel2(call_factory_,
425                              voice_channel,
426                              external_encoder_factory_,
427                              external_decoder_factory_,
428                              GetVideoEncoderFactory());
429  if (!channel->Init()) {
430    delete channel;
431    return NULL;
432  }
433  channel->SetOptions(options);
434  channel->SetRecvCodecs(video_codecs_);
435  return channel;
436}
437
438const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
439  return video_codecs_;
440}
441
442const std::vector<RtpHeaderExtension>&
443WebRtcVideoEngine2::rtp_header_extensions() const {
444  return rtp_header_extensions_;
445}
446
447void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
448  // TODO(pbos): Set up logging.
449  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
450  // if min_sev == -1, we keep the current log level.
451  if (min_sev < 0) {
452    assert(min_sev == -1);
453    return;
454  }
455}
456
457void WebRtcVideoEngine2::SetExternalDecoderFactory(
458    WebRtcVideoDecoderFactory* decoder_factory) {
459  assert(!initialized_);
460  external_decoder_factory_ = decoder_factory;
461}
462
463void WebRtcVideoEngine2::SetExternalEncoderFactory(
464    WebRtcVideoEncoderFactory* encoder_factory) {
465  assert(!initialized_);
466  external_encoder_factory_ = encoder_factory;
467
468  video_codecs_ = GetSupportedCodecs();
469}
470
471bool WebRtcVideoEngine2::EnableTimedRender() {
472  // TODO(pbos): Figure out whether this can be removed.
473  return true;
474}
475
476// Checks to see whether we comprehend and could receive a particular codec
477bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
478  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
479  // if supported by the encoder factory. Add a corresponding test that fails
480  // with this code (that doesn't ask the factory).
481  for (size_t j = 0; j < video_codecs_.size(); ++j) {
482    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
483    if (codec.Matches(in)) {
484      return true;
485    }
486  }
487  return false;
488}
489
490// Tells whether the |requested| codec can be transmitted or not. If it can be
491// transmitted |out| is set with the best settings supported. Aspect ratio will
492// be set as close to |current|'s as possible. If not set |requested|'s
493// dimensions will be used for aspect ratio matching.
494bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
495                                      const VideoCodec& current,
496                                      VideoCodec* out) {
497  assert(out != NULL);
498
499  if (requested.width != requested.height &&
500      (requested.height == 0 || requested.width == 0)) {
501    // 0xn and nx0 are invalid resolutions.
502    return false;
503  }
504
505  VideoCodec matching_codec;
506  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
507    // Codec not supported.
508    return false;
509  }
510
511  out->id = requested.id;
512  out->name = requested.name;
513  out->preference = requested.preference;
514  out->params = requested.params;
515  out->framerate =
516      rtc::_min(requested.framerate, matching_codec.framerate);
517  out->params = requested.params;
518  out->feedback_params = requested.feedback_params;
519  out->width = requested.width;
520  out->height = requested.height;
521  if (requested.width == 0 && requested.height == 0) {
522    return true;
523  }
524
525  while (out->width > matching_codec.width) {
526    out->width /= 2;
527    out->height /= 2;
528  }
529
530  return out->width > 0 && out->height > 0;
531}
532
533bool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
534  if (initialized_) {
535    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
536    return false;
537  }
538  voice_engine_ = voice_engine;
539  return true;
540}
541
542// Ignore spammy trace messages, mostly from the stats API when we haven't
543// gotten RTCP info yet from the remote side.
544bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
545  static const char* const kTracesToIgnore[] = {NULL};
546  for (const char* const* p = kTracesToIgnore; *p; ++p) {
547    if (trace.find(*p) == 0) {
548      return true;
549    }
550  }
551  return false;
552}
553
554WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
555  return &default_video_encoder_factory_;
556}
557
558std::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const {
559  std::vector<VideoCodec> supported_codecs = DefaultVideoCodecs();
560
561  if (external_encoder_factory_ == NULL) {
562    return supported_codecs;
563  }
564
565  assert(external_encoder_factory_->codecs().size() <= kMaxExternalVideoCodecs);
566  const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
567      external_encoder_factory_->codecs();
568  for (size_t i = 0; i < codecs.size(); ++i) {
569    // Don't add internally-supported codecs twice.
570    if (CodecIsInternallySupported(codecs[i].name)) {
571      continue;
572    }
573
574    VideoCodec codec(kExternalVideoPayloadTypeBase + static_cast<int>(i),
575                     codecs[i].name,
576                     codecs[i].max_width,
577                     codecs[i].max_height,
578                     codecs[i].max_fps,
579                     0);
580
581    AddDefaultFeedbackParams(&codec);
582    supported_codecs.push_back(codec);
583  }
584  return supported_codecs;
585}
586
587// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
588// to avoid having to copy the rendered VideoFrame prematurely.
589// This implementation is only safe to use in a const context and should never
590// be written to.
591class WebRtcVideoRenderFrame : public VideoFrame {
592 public:
593  explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
594      : frame_(frame) {}
595
596  virtual bool InitToBlack(int w,
597                           int h,
598                           size_t pixel_width,
599                           size_t pixel_height,
600                           int64 elapsed_time,
601                           int64 time_stamp) OVERRIDE {
602    UNIMPLEMENTED;
603    return false;
604  }
605
606  virtual bool Reset(uint32 fourcc,
607                     int w,
608                     int h,
609                     int dw,
610                     int dh,
611                     uint8* sample,
612                     size_t sample_size,
613                     size_t pixel_width,
614                     size_t pixel_height,
615                     int64 elapsed_time,
616                     int64 time_stamp,
617                     int rotation) OVERRIDE {
618    UNIMPLEMENTED;
619    return false;
620  }
621
622  virtual size_t GetWidth() const OVERRIDE {
623    return static_cast<size_t>(frame_->width());
624  }
625  virtual size_t GetHeight() const OVERRIDE {
626    return static_cast<size_t>(frame_->height());
627  }
628
629  virtual const uint8* GetYPlane() const OVERRIDE {
630    return frame_->buffer(webrtc::kYPlane);
631  }
632  virtual const uint8* GetUPlane() const OVERRIDE {
633    return frame_->buffer(webrtc::kUPlane);
634  }
635  virtual const uint8* GetVPlane() const OVERRIDE {
636    return frame_->buffer(webrtc::kVPlane);
637  }
638
639  virtual uint8* GetYPlane() OVERRIDE {
640    UNIMPLEMENTED;
641    return NULL;
642  }
643  virtual uint8* GetUPlane() OVERRIDE {
644    UNIMPLEMENTED;
645    return NULL;
646  }
647  virtual uint8* GetVPlane() OVERRIDE {
648    UNIMPLEMENTED;
649    return NULL;
650  }
651
652  virtual int32 GetYPitch() const OVERRIDE {
653    return frame_->stride(webrtc::kYPlane);
654  }
655  virtual int32 GetUPitch() const OVERRIDE {
656    return frame_->stride(webrtc::kUPlane);
657  }
658  virtual int32 GetVPitch() const OVERRIDE {
659    return frame_->stride(webrtc::kVPlane);
660  }
661
662  virtual void* GetNativeHandle() const OVERRIDE { return NULL; }
663
664  virtual size_t GetPixelWidth() const OVERRIDE { return 1; }
665  virtual size_t GetPixelHeight() const OVERRIDE { return 1; }
666
667  virtual int64 GetElapsedTime() const OVERRIDE {
668    // Convert millisecond render time to ns timestamp.
669    return frame_->render_time_ms() * rtc::kNumNanosecsPerMillisec;
670  }
671  virtual int64 GetTimeStamp() const OVERRIDE {
672    // Convert 90K rtp timestamp to ns timestamp.
673    return (frame_->timestamp() / 90) * rtc::kNumNanosecsPerMillisec;
674  }
675  virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; }
676  virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; }
677
678  virtual int GetRotation() const OVERRIDE {
679    UNIMPLEMENTED;
680    return ROTATION_0;
681  }
682
683  virtual VideoFrame* Copy() const OVERRIDE {
684    UNIMPLEMENTED;
685    return NULL;
686  }
687
688  virtual bool MakeExclusive() OVERRIDE {
689    UNIMPLEMENTED;
690    return false;
691  }
692
693  virtual size_t CopyToBuffer(uint8* buffer, size_t size) const {
694    UNIMPLEMENTED;
695    return 0;
696  }
697
698  // TODO(fbarchard): Refactor into base class and share with LMI
699  virtual size_t ConvertToRgbBuffer(uint32 to_fourcc,
700                                    uint8* buffer,
701                                    size_t size,
702                                    int stride_rgb) const OVERRIDE {
703    size_t width = GetWidth();
704    size_t height = GetHeight();
705    size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height;
706    if (size < needed) {
707      LOG(LS_WARNING) << "RGB buffer is not large enough";
708      return needed;
709    }
710
711    if (libyuv::ConvertFromI420(GetYPlane(),
712                                GetYPitch(),
713                                GetUPlane(),
714                                GetUPitch(),
715                                GetVPlane(),
716                                GetVPitch(),
717                                buffer,
718                                stride_rgb,
719                                static_cast<int>(width),
720                                static_cast<int>(height),
721                                to_fourcc)) {
722      LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc;
723      return 0;  // 0 indicates error
724    }
725    return needed;
726  }
727
728 protected:
729  virtual VideoFrame* CreateEmptyFrame(int w,
730                                       int h,
731                                       size_t pixel_width,
732                                       size_t pixel_height,
733                                       int64 elapsed_time,
734                                       int64 time_stamp) const OVERRIDE {
735    WebRtcVideoFrame* frame = new WebRtcVideoFrame();
736    frame->InitToBlack(
737        w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
738    return frame;
739  }
740
741 private:
742  const webrtc::I420VideoFrame* const frame_;
743};
744
745WebRtcVideoChannel2::WebRtcVideoChannel2(
746    WebRtcCallFactory* call_factory,
747    VoiceMediaChannel* voice_channel,
748    WebRtcVideoEncoderFactory* external_encoder_factory,
749    WebRtcVideoDecoderFactory* external_decoder_factory,
750    WebRtcVideoEncoderFactory2* encoder_factory)
751    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
752      external_encoder_factory_(external_encoder_factory),
753      external_decoder_factory_(external_decoder_factory),
754      encoder_factory_(encoder_factory) {
755  // TODO(pbos): Connect the video and audio with |voice_channel|.
756  webrtc::Call::Config config(this);
757  config.overuse_callback = this;
758  call_.reset(call_factory->CreateCall(config));
759
760  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
761  sending_ = false;
762  default_send_ssrc_ = 0;
763
764  SetDefaultOptions();
765}
766
767void WebRtcVideoChannel2::SetDefaultOptions() {
768  options_.cpu_overuse_detection.Set(false);
769  options_.suspend_below_min_bitrate.Set(false);
770  options_.use_payload_padding.Set(false);
771  options_.video_noise_reduction.Set(true);
772}
773
774WebRtcVideoChannel2::~WebRtcVideoChannel2() {
775  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
776           send_streams_.begin();
777       it != send_streams_.end();
778       ++it) {
779    delete it->second;
780  }
781
782  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
783           receive_streams_.begin();
784       it != receive_streams_.end();
785       ++it) {
786    delete it->second;
787  }
788}
789
790bool WebRtcVideoChannel2::Init() { return true; }
791
792bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
793  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
794  if (!ValidateCodecFormats(codecs)) {
795    return false;
796  }
797
798  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
799  if (mapped_codecs.empty()) {
800    LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
801    return false;
802  }
803
804  // TODO(pbos): Add a decoder factory which controls supported codecs.
805  // Blocked on webrtc:2854.
806  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
807    if (!CodecNameMatches(mapped_codecs[i].codec.name, kVp8CodecName)) {
808      LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
809                    << mapped_codecs[i].codec.name << "'";
810      return false;
811    }
812  }
813
814  recv_codecs_ = mapped_codecs;
815
816  rtc::CritScope stream_lock(&stream_crit_);
817  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
818           receive_streams_.begin();
819       it != receive_streams_.end();
820       ++it) {
821    it->second->SetRecvCodecs(recv_codecs_);
822  }
823
824  return true;
825}
826
827bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
828  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
829  if (!ValidateCodecFormats(codecs)) {
830    return false;
831  }
832
833  const std::vector<VideoCodecSettings> supported_codecs =
834      FilterSupportedCodecs(MapCodecs(codecs));
835
836  if (supported_codecs.empty()) {
837    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
838    return false;
839  }
840
841  send_codec_.Set(supported_codecs.front());
842  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
843
844  rtc::CritScope stream_lock(&stream_crit_);
845  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
846           send_streams_.begin();
847       it != send_streams_.end();
848       ++it) {
849    assert(it->second != NULL);
850    it->second->SetCodec(supported_codecs.front());
851  }
852
853  return true;
854}
855
856bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
857  VideoCodecSettings codec_settings;
858  if (!send_codec_.Get(&codec_settings)) {
859    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
860    return false;
861  }
862  *codec = codec_settings.codec;
863  return true;
864}
865
866bool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
867                                              const VideoFormat& format) {
868  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
869                  << format.ToString();
870  rtc::CritScope stream_lock(&stream_crit_);
871  if (send_streams_.find(ssrc) == send_streams_.end()) {
872    return false;
873  }
874  return send_streams_[ssrc]->SetVideoFormat(format);
875}
876
877bool WebRtcVideoChannel2::SetRender(bool render) {
878  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
879  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
880  return true;
881}
882
883bool WebRtcVideoChannel2::SetSend(bool send) {
884  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
885  if (send && !send_codec_.IsSet()) {
886    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
887    return false;
888  }
889  if (send) {
890    StartAllSendStreams();
891  } else {
892    StopAllSendStreams();
893  }
894  sending_ = send;
895  return true;
896}
897
898bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
899  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
900  if (sp.ssrcs.empty()) {
901    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
902    return false;
903  }
904
905  uint32 ssrc = sp.first_ssrc();
906  assert(ssrc != 0);
907  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
908  // ssrc.
909  rtc::CritScope stream_lock(&stream_crit_);
910  if (send_streams_.find(ssrc) != send_streams_.end()) {
911    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
912    return false;
913  }
914
915  std::vector<uint32> primary_ssrcs;
916  sp.GetPrimarySsrcs(&primary_ssrcs);
917  std::vector<uint32> rtx_ssrcs;
918  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
919  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
920    LOG(LS_ERROR)
921        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
922        << sp.ToString();
923    return false;
924  }
925
926  WebRtcVideoSendStream* stream =
927      new WebRtcVideoSendStream(call_.get(),
928                                external_encoder_factory_,
929                                encoder_factory_,
930                                options_,
931                                send_codec_,
932                                sp,
933                                send_rtp_extensions_);
934
935  send_streams_[ssrc] = stream;
936
937  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
938    rtcp_receiver_report_ssrc_ = ssrc;
939  }
940  if (default_send_ssrc_ == 0) {
941    default_send_ssrc_ = ssrc;
942  }
943  if (sending_) {
944    stream->Start();
945  }
946
947  return true;
948}
949
950bool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
951  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
952
953  if (ssrc == 0) {
954    if (default_send_ssrc_ == 0) {
955      LOG(LS_ERROR) << "No default send stream active.";
956      return false;
957    }
958
959    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
960    ssrc = default_send_ssrc_;
961  }
962
963  WebRtcVideoSendStream* removed_stream;
964  {
965    rtc::CritScope stream_lock(&stream_crit_);
966    std::map<uint32, WebRtcVideoSendStream*>::iterator it =
967        send_streams_.find(ssrc);
968    if (it == send_streams_.end()) {
969      return false;
970    }
971
972    removed_stream = it->second;
973    send_streams_.erase(it);
974  }
975
976  delete removed_stream;
977
978  if (ssrc == default_send_ssrc_) {
979    default_send_ssrc_ = 0;
980  }
981
982  return true;
983}
984
985bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
986  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
987  assert(sp.ssrcs.size() > 0);
988
989  uint32 ssrc = sp.first_ssrc();
990  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
991
992  // TODO(pbos): Check if any of the SSRCs overlap.
993  rtc::CritScope stream_lock(&stream_crit_);
994  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
995    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
996    return false;
997  }
998
999  webrtc::VideoReceiveStream::Config config;
1000  ConfigureReceiverRtp(&config, sp);
1001  receive_streams_[ssrc] =
1002      new WebRtcVideoReceiveStream(call_.get(), config, recv_codecs_);
1003
1004  return true;
1005}
1006
1007void WebRtcVideoChannel2::ConfigureReceiverRtp(
1008    webrtc::VideoReceiveStream::Config* config,
1009    const StreamParams& sp) const {
1010  uint32 ssrc = sp.first_ssrc();
1011
1012  config->rtp.remote_ssrc = ssrc;
1013  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
1014
1015  config->rtp.extensions = recv_rtp_extensions_;
1016
1017  // TODO(pbos): This protection is against setting the same local ssrc as
1018  // remote which is not permitted by the lower-level API. RTCP requires a
1019  // corresponding sender SSRC. Figure out what to do when we don't have
1020  // (receive-only) or know a good local SSRC.
1021  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
1022    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
1023      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
1024    } else {
1025      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
1026    }
1027  }
1028
1029  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
1030    if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) {
1031      config->rtp.fec = recv_codecs_[i].fec;
1032      uint32 rtx_ssrc;
1033      if (recv_codecs_[i].rtx_payload_type != -1 &&
1034          sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
1035        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc;
1036        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type =
1037            recv_codecs_[i].rtx_payload_type;
1038      }
1039      break;
1040    }
1041  }
1042
1043}
1044
1045bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
1046  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1047  if (ssrc == 0) {
1048    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
1049    return false;
1050  }
1051
1052  rtc::CritScope stream_lock(&stream_crit_);
1053  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
1054      receive_streams_.find(ssrc);
1055  if (stream == receive_streams_.end()) {
1056    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1057    return false;
1058  }
1059  delete stream->second;
1060  receive_streams_.erase(stream);
1061
1062  return true;
1063}
1064
1065bool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1066  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1067               << (renderer ? "(ptr)" : "NULL");
1068  if (ssrc == 0) {
1069    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1070    return true;
1071  }
1072
1073  rtc::CritScope stream_lock(&stream_crit_);
1074  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1075      receive_streams_.find(ssrc);
1076  if (it == receive_streams_.end()) {
1077    return false;
1078  }
1079
1080  it->second->SetRenderer(renderer);
1081  return true;
1082}
1083
1084bool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1085  if (ssrc == 0) {
1086    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1087    return *renderer != NULL;
1088  }
1089
1090  rtc::CritScope stream_lock(&stream_crit_);
1091  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1092      receive_streams_.find(ssrc);
1093  if (it == receive_streams_.end()) {
1094    return false;
1095  }
1096  *renderer = it->second->GetRenderer();
1097  return true;
1098}
1099
1100bool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
1101                                   VideoMediaInfo* info) {
1102  info->Clear();
1103  FillSenderStats(info);
1104  FillReceiverStats(info);
1105  FillBandwidthEstimationStats(info);
1106  return true;
1107}
1108
1109void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1110  rtc::CritScope stream_lock(&stream_crit_);
1111  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1112           send_streams_.begin();
1113       it != send_streams_.end();
1114       ++it) {
1115    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1116  }
1117}
1118
1119void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1120  rtc::CritScope stream_lock(&stream_crit_);
1121  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1122           receive_streams_.begin();
1123       it != receive_streams_.end();
1124       ++it) {
1125    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1126  }
1127}
1128
1129void WebRtcVideoChannel2::FillBandwidthEstimationStats(
1130    VideoMediaInfo* video_media_info) {
1131  // TODO(pbos): Implement.
1132}
1133
1134bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1135  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1136               << (capturer != NULL ? "(capturer)" : "NULL");
1137  assert(ssrc != 0);
1138  rtc::CritScope stream_lock(&stream_crit_);
1139  if (send_streams_.find(ssrc) == send_streams_.end()) {
1140    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1141    return false;
1142  }
1143  return send_streams_[ssrc]->SetCapturer(capturer);
1144}
1145
1146bool WebRtcVideoChannel2::SendIntraFrame() {
1147  // TODO(pbos): Implement.
1148  LOG(LS_VERBOSE) << "SendIntraFrame().";
1149  return true;
1150}
1151
1152bool WebRtcVideoChannel2::RequestIntraFrame() {
1153  // TODO(pbos): Implement.
1154  LOG(LS_VERBOSE) << "SendIntraFrame().";
1155  return true;
1156}
1157
1158void WebRtcVideoChannel2::OnPacketReceived(
1159    rtc::Buffer* packet,
1160    const rtc::PacketTime& packet_time) {
1161  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
1162      call_->Receiver()->DeliverPacket(
1163          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
1164  switch (delivery_result) {
1165    case webrtc::PacketReceiver::DELIVERY_OK:
1166      return;
1167    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
1168      return;
1169    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
1170      break;
1171  }
1172
1173  uint32 ssrc = 0;
1174  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
1175    return;
1176  }
1177
1178  // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload.
1179  // Also figure out whether RTX needs to be handled.
1180  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1181    case UnsignalledSsrcHandler::kDropPacket:
1182      return;
1183    case UnsignalledSsrcHandler::kDeliverPacket:
1184      break;
1185  }
1186
1187  if (call_->Receiver()->DeliverPacket(
1188          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1189      webrtc::PacketReceiver::DELIVERY_OK) {
1190    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1191    return;
1192  }
1193}
1194
1195void WebRtcVideoChannel2::OnRtcpReceived(
1196    rtc::Buffer* packet,
1197    const rtc::PacketTime& packet_time) {
1198  if (call_->Receiver()->DeliverPacket(
1199          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1200      webrtc::PacketReceiver::DELIVERY_OK) {
1201    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1202  }
1203}
1204
1205void WebRtcVideoChannel2::OnReadyToSend(bool ready) {
1206  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
1207  call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
1208                                  : webrtc::Call::kNetworkDown);
1209}
1210
1211bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1212  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1213                  << (mute ? "mute" : "unmute");
1214  assert(ssrc != 0);
1215  rtc::CritScope stream_lock(&stream_crit_);
1216  if (send_streams_.find(ssrc) == send_streams_.end()) {
1217    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1218    return false;
1219  }
1220
1221  send_streams_[ssrc]->MuteStream(mute);
1222  return true;
1223}
1224
1225bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1226    const std::vector<RtpHeaderExtension>& extensions) {
1227  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1228               << RtpExtensionsToString(extensions);
1229  if (!ValidateRtpHeaderExtensionIds(extensions))
1230    return false;
1231
1232  recv_rtp_extensions_ = FilterRtpExtensions(extensions);
1233  rtc::CritScope stream_lock(&stream_crit_);
1234  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1235           receive_streams_.begin();
1236       it != receive_streams_.end();
1237       ++it) {
1238    it->second->SetRtpExtensions(recv_rtp_extensions_);
1239  }
1240  return true;
1241}
1242
1243bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1244    const std::vector<RtpHeaderExtension>& extensions) {
1245  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1246               << RtpExtensionsToString(extensions);
1247  if (!ValidateRtpHeaderExtensionIds(extensions))
1248    return false;
1249
1250  send_rtp_extensions_ = FilterRtpExtensions(extensions);
1251  rtc::CritScope stream_lock(&stream_crit_);
1252  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1253           send_streams_.begin();
1254       it != send_streams_.end();
1255       ++it) {
1256    it->second->SetRtpExtensions(send_rtp_extensions_);
1257  }
1258  return true;
1259}
1260
1261bool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
1262  // TODO(pbos): Implement.
1263  LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
1264  return true;
1265}
1266
1267bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
1268  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
1269  options_.SetAll(options);
1270  rtc::CritScope stream_lock(&stream_crit_);
1271  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1272           send_streams_.begin();
1273       it != send_streams_.end();
1274       ++it) {
1275    it->second->SetOptions(options_);
1276  }
1277  return true;
1278}
1279
1280void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1281  MediaChannel::SetInterface(iface);
1282  // Set the RTP recv/send buffer to a bigger size
1283  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1284                          rtc::Socket::OPT_RCVBUF,
1285                          kVideoRtpBufferSize);
1286
1287  // TODO(sriniv): Remove or re-enable this.
1288  // As part of b/8030474, send-buffer is size now controlled through
1289  // portallocator flags.
1290  // network_interface_->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        int width = format_.width;
1481        int height = format_.height;
1482        int half_width = (width + 1) / 2;
1483        black_frame.CreateEmptyFrame(
1484            width, height, width, half_width, half_width);
1485        SetWebRtcFrameToBlack(&black_frame);
1486        SetDimensions(width, height, false);
1487        stream_->Input()->SwapFrame(&black_frame);
1488      }
1489
1490      capturer_ = NULL;
1491      return true;
1492    }
1493
1494    capturer_ = capturer;
1495  }
1496  // Lock cannot be held while connecting the capturer to prevent lock-order
1497  // violations.
1498  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1499  return true;
1500}
1501
1502bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1503    const VideoFormat& format) {
1504  if ((format.width == 0 || format.height == 0) &&
1505      format.width != format.height) {
1506    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1507                     "both, 0x0 drops frames).";
1508    return false;
1509  }
1510
1511  rtc::CritScope cs(&lock_);
1512  if (format.width == 0 && format.height == 0) {
1513    LOG(LS_INFO)
1514        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
1515        << parameters_.config.rtp.ssrcs[0] << ".";
1516  } else {
1517    // TODO(pbos): Fix me, this only affects the last stream!
1518    parameters_.encoder_config.streams.back().max_framerate =
1519        VideoFormat::IntervalToFps(format.interval);
1520    SetDimensions(format.width, format.height, false);
1521  }
1522
1523  format_ = format;
1524  return true;
1525}
1526
1527void WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1528  rtc::CritScope cs(&lock_);
1529  muted_ = mute;
1530}
1531
1532bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1533  cricket::VideoCapturer* capturer;
1534  {
1535    rtc::CritScope cs(&lock_);
1536    if (capturer_ == NULL) {
1537      return false;
1538    }
1539    capturer = capturer_;
1540    capturer_ = NULL;
1541  }
1542  capturer->SignalVideoFrame.disconnect(this);
1543  return true;
1544}
1545
1546void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
1547    const VideoOptions& options) {
1548  rtc::CritScope cs(&lock_);
1549  VideoCodecSettings codec_settings;
1550  if (parameters_.codec_settings.Get(&codec_settings)) {
1551    SetCodecAndOptions(codec_settings, options);
1552  } else {
1553    parameters_.options = options;
1554  }
1555}
1556
1557void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
1558    const VideoCodecSettings& codec_settings) {
1559  rtc::CritScope cs(&lock_);
1560  SetCodecAndOptions(codec_settings, parameters_.options);
1561}
1562
1563webrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
1564  if (CodecNameMatches(name, kVp8CodecName)) {
1565    return webrtc::kVideoCodecVP8;
1566  } else if (CodecNameMatches(name, kH264CodecName)) {
1567    return webrtc::kVideoCodecH264;
1568  }
1569  return webrtc::kVideoCodecUnknown;
1570}
1571
1572WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
1573WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
1574    const VideoCodec& codec) {
1575  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
1576
1577  // Do not re-create encoders of the same type.
1578  if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) {
1579    return allocated_encoder_;
1580  }
1581
1582  if (external_encoder_factory_ != NULL) {
1583    webrtc::VideoEncoder* encoder =
1584        external_encoder_factory_->CreateVideoEncoder(type);
1585    if (encoder != NULL) {
1586      return AllocatedEncoder(encoder, type, true);
1587    }
1588  }
1589
1590  if (type == webrtc::kVideoCodecVP8) {
1591    return AllocatedEncoder(
1592        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false);
1593  }
1594
1595  // This shouldn't happen, we should not be trying to create something we don't
1596  // support.
1597  assert(false);
1598  return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false);
1599}
1600
1601void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
1602    AllocatedEncoder* encoder) {
1603  if (encoder->external) {
1604    external_encoder_factory_->DestroyVideoEncoder(encoder->encoder);
1605  } else {
1606    delete encoder->encoder;
1607  }
1608}
1609
1610void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
1611    const VideoCodecSettings& codec_settings,
1612    const VideoOptions& options) {
1613  std::vector<webrtc::VideoStream> video_streams =
1614      encoder_factory_->CreateVideoStreams(
1615          codec_settings.codec, options, parameters_.config.rtp.ssrcs.size());
1616  if (video_streams.empty()) {
1617    return;
1618  }
1619  parameters_.encoder_config.streams = video_streams;
1620  format_ = VideoFormat(codec_settings.codec.width,
1621                        codec_settings.codec.height,
1622                        VideoFormat::FpsToInterval(30),
1623                        FOURCC_I420);
1624
1625  AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
1626  parameters_.config.encoder_settings.encoder = new_encoder.encoder;
1627  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
1628  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
1629  parameters_.config.rtp.fec = codec_settings.fec;
1630
1631  // Set RTX payload type if RTX is enabled.
1632  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
1633    parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1634
1635    options.use_payload_padding.Get(
1636        &parameters_.config.rtp.rtx.pad_with_redundant_payloads);
1637  }
1638
1639  if (IsNackEnabled(codec_settings.codec)) {
1640    parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs;
1641  }
1642
1643  options.suspend_below_min_bitrate.Get(
1644      &parameters_.config.suspend_below_min_bitrate);
1645
1646  parameters_.codec_settings.Set(codec_settings);
1647  parameters_.options = options;
1648
1649  RecreateWebRtcStream();
1650  if (allocated_encoder_.encoder != new_encoder.encoder) {
1651    DestroyVideoEncoder(&allocated_encoder_);
1652    allocated_encoder_ = new_encoder;
1653  }
1654}
1655
1656void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1657    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1658  rtc::CritScope cs(&lock_);
1659  parameters_.config.rtp.extensions = rtp_extensions;
1660  RecreateWebRtcStream();
1661}
1662
1663void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
1664    int width,
1665    int height,
1666    bool override_max) {
1667  assert(!parameters_.encoder_config.streams.empty());
1668  LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
1669
1670  VideoCodecSettings codec_settings;
1671  parameters_.codec_settings.Get(&codec_settings);
1672  // Restrict dimensions according to codec max.
1673  if (!override_max) {
1674    if (codec_settings.codec.width < width)
1675      width = codec_settings.codec.width;
1676    if (codec_settings.codec.height < height)
1677      height = codec_settings.codec.height;
1678  }
1679
1680  if (parameters_.encoder_config.streams.back().width == width &&
1681      parameters_.encoder_config.streams.back().height == height) {
1682    return;
1683  }
1684
1685  webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config;
1686  encoder_config.encoder_specific_settings =
1687      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1688                                                   parameters_.options);
1689
1690  VideoCodec codec = codec_settings.codec;
1691  codec.width = width;
1692  codec.height = height;
1693
1694  encoder_config.streams = encoder_factory_->CreateVideoStreams(
1695      codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
1696
1697  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
1698
1699  encoder_factory_->DestroyVideoEncoderSettings(
1700      codec_settings.codec,
1701      encoder_config.encoder_specific_settings);
1702
1703  encoder_config.encoder_specific_settings = NULL;
1704
1705  if (!stream_reconfigured) {
1706    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
1707                    << width << "x" << height;
1708    return;
1709  }
1710
1711  parameters_.encoder_config = encoder_config;
1712}
1713
1714void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
1715  rtc::CritScope cs(&lock_);
1716  assert(stream_ != NULL);
1717  stream_->Start();
1718  sending_ = true;
1719}
1720
1721void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
1722  rtc::CritScope cs(&lock_);
1723  if (stream_ != NULL) {
1724    stream_->Stop();
1725  }
1726  sending_ = false;
1727}
1728
1729VideoSenderInfo
1730WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
1731  VideoSenderInfo info;
1732  rtc::CritScope cs(&lock_);
1733  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
1734    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
1735  }
1736
1737  if (stream_ == NULL) {
1738    return info;
1739  }
1740
1741  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
1742  info.framerate_input = stats.input_frame_rate;
1743  info.framerate_sent = stats.encode_frame_rate;
1744
1745  for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
1746           stats.substreams.begin();
1747       it != stats.substreams.end();
1748       ++it) {
1749    // TODO(pbos): Wire up additional stats, such as padding bytes.
1750    webrtc::StreamStats stream_stats = it->second;
1751    info.bytes_sent += stream_stats.rtp_stats.bytes +
1752                       stream_stats.rtp_stats.header_bytes +
1753                       stream_stats.rtp_stats.padding_bytes;
1754    info.packets_sent += stream_stats.rtp_stats.packets;
1755    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
1756  }
1757
1758  if (!stats.substreams.empty()) {
1759    // TODO(pbos): Report fraction lost per SSRC.
1760    webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
1761    info.fraction_lost =
1762        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
1763        (1 << 8);
1764  }
1765
1766  if (capturer_ != NULL && !capturer_->IsMuted()) {
1767    VideoFormat last_captured_frame_format;
1768    capturer_->GetStats(&info.adapt_frame_drops,
1769                        &info.effects_frame_drops,
1770                        &info.capturer_frame_time,
1771                        &last_captured_frame_format);
1772    info.input_frame_width = last_captured_frame_format.width;
1773    info.input_frame_height = last_captured_frame_format.height;
1774    info.send_frame_width =
1775        static_cast<int>(parameters_.encoder_config.streams.front().width);
1776    info.send_frame_height =
1777        static_cast<int>(parameters_.encoder_config.streams.front().height);
1778  }
1779
1780  // TODO(pbos): Support or remove the following stats.
1781  info.packets_cached = -1;
1782  info.rtt_ms = -1;
1783
1784  return info;
1785}
1786
1787void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest(
1788    CoordinatedVideoAdapter::AdaptRequest adapt_request) {
1789  rtc::CritScope cs(&lock_);
1790  bool adapt_cpu;
1791  parameters_.options.cpu_overuse_detection.Get(&adapt_cpu);
1792  if (!adapt_cpu) {
1793    return;
1794  }
1795  if (capturer_ == NULL || capturer_->video_adapter() == NULL) {
1796    return;
1797  }
1798
1799  capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request);
1800}
1801
1802void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
1803  if (stream_ != NULL) {
1804    call_->DestroyVideoSendStream(stream_);
1805  }
1806
1807  VideoCodecSettings codec_settings;
1808  parameters_.codec_settings.Get(&codec_settings);
1809  parameters_.encoder_config.encoder_specific_settings =
1810      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1811                                                   parameters_.options);
1812
1813  stream_ = call_->CreateVideoSendStream(parameters_.config,
1814                                         parameters_.encoder_config);
1815
1816  encoder_factory_->DestroyVideoEncoderSettings(
1817      codec_settings.codec,
1818      parameters_.encoder_config.encoder_specific_settings);
1819
1820  parameters_.encoder_config.encoder_specific_settings = NULL;
1821
1822  if (sending_) {
1823    stream_->Start();
1824  }
1825}
1826
1827WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
1828    webrtc::Call* call,
1829    const webrtc::VideoReceiveStream::Config& config,
1830    const std::vector<VideoCodecSettings>& recv_codecs)
1831    : call_(call),
1832      stream_(NULL),
1833      config_(config),
1834      renderer_(NULL),
1835      last_width_(-1),
1836      last_height_(-1) {
1837  config_.renderer = this;
1838  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
1839  SetRecvCodecs(recv_codecs);
1840}
1841
1842WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
1843  call_->DestroyVideoReceiveStream(stream_);
1844}
1845
1846void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
1847    const std::vector<VideoCodecSettings>& recv_codecs) {
1848  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
1849  // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
1850  // DecoderFactory similar to send side. Pending webrtc:2854.
1851  // Also set up default codecs if there's nothing in recv_codecs_.
1852  webrtc::VideoCodec codec;
1853  memset(&codec, 0, sizeof(codec));
1854
1855  codec.plType = kDefaultVideoCodecPref.payload_type;
1856  strcpy(codec.plName, kDefaultVideoCodecPref.name);
1857  codec.codecType = webrtc::kVideoCodecVP8;
1858  codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
1859  codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
1860  codec.codecSpecific.VP8.denoisingOn = true;
1861  codec.codecSpecific.VP8.errorConcealmentOn = false;
1862  codec.codecSpecific.VP8.automaticResizeOn = false;
1863  codec.codecSpecific.VP8.frameDroppingOn = true;
1864  codec.codecSpecific.VP8.keyFrameInterval = 3000;
1865  // Bitrates don't matter and are ignored for the receiver. This is put in to
1866  // have the current underlying implementation accept the VideoCodec.
1867  codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
1868  config_.codecs.clear();
1869  config_.codecs.push_back(codec);
1870
1871  config_.rtp.fec = recv_codecs.front().fec;
1872
1873  config_.rtp.nack.rtp_history_ms =
1874      IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
1875  config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
1876
1877  RecreateWebRtcStream();
1878}
1879
1880void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
1881    const std::vector<webrtc::RtpExtension>& extensions) {
1882  config_.rtp.extensions = extensions;
1883  RecreateWebRtcStream();
1884}
1885
1886void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
1887  if (stream_ != NULL) {
1888    call_->DestroyVideoReceiveStream(stream_);
1889  }
1890  stream_ = call_->CreateVideoReceiveStream(config_);
1891  stream_->Start();
1892}
1893
1894void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
1895    const webrtc::I420VideoFrame& frame,
1896    int time_to_render_ms) {
1897  rtc::CritScope crit(&renderer_lock_);
1898  if (renderer_ == NULL) {
1899    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
1900    return;
1901  }
1902
1903  if (frame.width() != last_width_ || frame.height() != last_height_) {
1904    SetSize(frame.width(), frame.height());
1905  }
1906
1907  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
1908                  << ")";
1909
1910  const WebRtcVideoRenderFrame render_frame(&frame);
1911  renderer_->RenderFrame(&render_frame);
1912}
1913
1914void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
1915    cricket::VideoRenderer* renderer) {
1916  rtc::CritScope crit(&renderer_lock_);
1917  renderer_ = renderer;
1918  if (renderer_ != NULL && last_width_ != -1) {
1919    SetSize(last_width_, last_height_);
1920  }
1921}
1922
1923VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
1924  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
1925  // design.
1926  rtc::CritScope crit(&renderer_lock_);
1927  return renderer_;
1928}
1929
1930void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
1931                                                            int height) {
1932  rtc::CritScope crit(&renderer_lock_);
1933  if (!renderer_->SetSize(width, height, 0)) {
1934    LOG(LS_ERROR) << "Could not set renderer size.";
1935  }
1936  last_width_ = width;
1937  last_height_ = height;
1938}
1939
1940VideoReceiverInfo
1941WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
1942  VideoReceiverInfo info;
1943  info.add_ssrc(config_.rtp.remote_ssrc);
1944  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
1945  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
1946                    stats.rtp_stats.padding_bytes;
1947  info.packets_rcvd = stats.rtp_stats.packets;
1948
1949  info.framerate_rcvd = stats.network_frame_rate;
1950  info.framerate_decoded = stats.decode_frame_rate;
1951  info.framerate_output = stats.render_frame_rate;
1952
1953  rtc::CritScope frame_cs(&renderer_lock_);
1954  info.frame_width = last_width_;
1955  info.frame_height = last_height_;
1956
1957  // TODO(pbos): Support or remove the following stats.
1958  info.packets_concealed = -1;
1959
1960  return info;
1961}
1962
1963WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
1964    : rtx_payload_type(-1) {}
1965
1966std::vector<WebRtcVideoChannel2::VideoCodecSettings>
1967WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
1968  assert(!codecs.empty());
1969
1970  std::vector<VideoCodecSettings> video_codecs;
1971  std::map<int, bool> payload_used;
1972  std::map<int, VideoCodec::CodecType> payload_codec_type;
1973  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
1974
1975  webrtc::FecConfig fec_settings;
1976
1977  for (size_t i = 0; i < codecs.size(); ++i) {
1978    const VideoCodec& in_codec = codecs[i];
1979    int payload_type = in_codec.id;
1980
1981    if (payload_used[payload_type]) {
1982      LOG(LS_ERROR) << "Payload type already registered: "
1983                    << in_codec.ToString();
1984      return std::vector<VideoCodecSettings>();
1985    }
1986    payload_used[payload_type] = true;
1987    payload_codec_type[payload_type] = in_codec.GetCodecType();
1988
1989    switch (in_codec.GetCodecType()) {
1990      case VideoCodec::CODEC_RED: {
1991        // RED payload type, should not have duplicates.
1992        assert(fec_settings.red_payload_type == -1);
1993        fec_settings.red_payload_type = in_codec.id;
1994        continue;
1995      }
1996
1997      case VideoCodec::CODEC_ULPFEC: {
1998        // ULPFEC payload type, should not have duplicates.
1999        assert(fec_settings.ulpfec_payload_type == -1);
2000        fec_settings.ulpfec_payload_type = in_codec.id;
2001        continue;
2002      }
2003
2004      case VideoCodec::CODEC_RTX: {
2005        int associated_payload_type;
2006        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
2007                               &associated_payload_type)) {
2008          LOG(LS_ERROR) << "RTX codec without associated payload type: "
2009                        << in_codec.ToString();
2010          return std::vector<VideoCodecSettings>();
2011        }
2012        rtx_mapping[associated_payload_type] = in_codec.id;
2013        continue;
2014      }
2015
2016      case VideoCodec::CODEC_VIDEO:
2017        break;
2018    }
2019
2020    video_codecs.push_back(VideoCodecSettings());
2021    video_codecs.back().codec = in_codec;
2022  }
2023
2024  // One of these codecs should have been a video codec. Only having FEC
2025  // parameters into this code is a logic error.
2026  assert(!video_codecs.empty());
2027
2028  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
2029       it != rtx_mapping.end();
2030       ++it) {
2031    if (!payload_used[it->first]) {
2032      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
2033      return std::vector<VideoCodecSettings>();
2034    }
2035    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
2036      LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
2037      return std::vector<VideoCodecSettings>();
2038    }
2039  }
2040
2041  // TODO(pbos): Write tests that figure out that I have not verified that RTX
2042  // codecs aren't mapped to bogus payloads.
2043  for (size_t i = 0; i < video_codecs.size(); ++i) {
2044    video_codecs[i].fec = fec_settings;
2045    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
2046      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
2047    }
2048  }
2049
2050  return video_codecs;
2051}
2052
2053std::vector<WebRtcVideoChannel2::VideoCodecSettings>
2054WebRtcVideoChannel2::FilterSupportedCodecs(
2055    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
2056  std::vector<VideoCodecSettings> supported_codecs;
2057  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
2058    const VideoCodecSettings& codec = mapped_codecs[i];
2059    if (CodecIsInternallySupported(codec.codec.name)) {
2060      supported_codecs.push_back(codec);
2061    }
2062
2063    if (external_encoder_factory_ == NULL) {
2064      continue;
2065    }
2066    const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
2067        external_encoder_factory_->codecs();
2068    for (size_t c = 0; c < external_codecs.size(); ++c) {
2069      if (CodecNameMatches(codec.codec.name, external_codecs[c].name)) {
2070        supported_codecs.push_back(codec);
2071        break;
2072      }
2073    }
2074  }
2075  return supported_codecs;
2076}
2077
2078}  // namespace cricket
2079
2080#endif  // HAVE_WEBRTC_VIDEO
2081