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