Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / media / webrtc / webrtcvideoengine.cc
1 /*
2  * libjingle
3  * Copyright 2004 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/webrtcvideoengine.h"
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <math.h>
36 #include <set>
37
38 #include "talk/base/basictypes.h"
39 #include "talk/base/buffer.h"
40 #include "talk/base/byteorder.h"
41 #include "talk/base/common.h"
42 #include "talk/base/cpumonitor.h"
43 #include "talk/base/logging.h"
44 #include "talk/base/stringutils.h"
45 #include "talk/base/thread.h"
46 #include "talk/base/timeutils.h"
47 #include "talk/media/base/constants.h"
48 #include "talk/media/base/rtputils.h"
49 #include "talk/media/base/streamparams.h"
50 #include "talk/media/base/videoadapter.h"
51 #include "talk/media/base/videocapturer.h"
52 #include "talk/media/base/videorenderer.h"
53 #include "talk/media/devices/filevideocapturer.h"
54 #include "talk/media/webrtc/webrtcpassthroughrender.h"
55 #include "talk/media/webrtc/webrtctexturevideoframe.h"
56 #include "talk/media/webrtc/webrtcvideocapturer.h"
57 #include "talk/media/webrtc/webrtcvideodecoderfactory.h"
58 #include "talk/media/webrtc/webrtcvideoencoderfactory.h"
59 #include "talk/media/webrtc/webrtcvideoframe.h"
60 #include "talk/media/webrtc/webrtcvie.h"
61 #include "talk/media/webrtc/webrtcvoe.h"
62 #include "talk/media/webrtc/webrtcvoiceengine.h"
63 #include "webrtc/experiments.h"
64 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
65
66 #if !defined(LIBPEERCONNECTION_LIB)
67 #include "talk/media/webrtc/webrtcmediaengine.h"
68
69 WRME_EXPORT
70 cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
71     webrtc::AudioDeviceModule* adm, webrtc::AudioDeviceModule* adm_sc,
72     cricket::WebRtcVideoEncoderFactory* encoder_factory,
73     cricket::WebRtcVideoDecoderFactory* decoder_factory) {
74   return new cricket::WebRtcMediaEngine(adm, adm_sc, encoder_factory,
75                                         decoder_factory);
76 }
77
78 WRME_EXPORT
79 void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
80   delete static_cast<cricket::WebRtcMediaEngine*>(media_engine);
81 }
82 #endif
83
84
85 namespace cricket {
86
87
88 static const int kDefaultLogSeverity = talk_base::LS_WARNING;
89
90 static const int kMinVideoBitrate = 50;
91 static const int kStartVideoBitrate = 300;
92 static const int kMaxVideoBitrate = 2000;
93
94 // Controlled by exp, try a super low minimum bitrate for poor connections.
95 static const int kLowerMinBitrate = 30;
96
97 static const int kVideoMtu = 1200;
98
99 static const int kVideoRtpBufferSize = 65536;
100
101 static const char kVp8PayloadName[] = "VP8";
102 static const char kRedPayloadName[] = "red";
103 static const char kFecPayloadName[] = "ulpfec";
104
105 static const int kDefaultNumberOfTemporalLayers = 1;  // 1:1
106
107 static const int kMaxExternalVideoCodecs = 8;
108 static const int kExternalVideoPayloadTypeBase = 120;
109
110 static bool BitrateIsSet(int value) {
111   return value > kAutoBandwidth;
112 }
113
114 static int GetBitrate(int value, int deflt) {
115   return BitrateIsSet(value) ? value : deflt;
116 }
117
118 // Static allocation of payload type values for external video codec.
119 static int GetExternalVideoPayloadType(int index) {
120   ASSERT(index >= 0 && index < kMaxExternalVideoCodecs);
121   return kExternalVideoPayloadTypeBase + index;
122 }
123
124 static void LogMultiline(talk_base::LoggingSeverity sev, char* text) {
125   const char* delim = "\r\n";
126   // TODO(fbarchard): Fix strtok lint warning.
127   for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
128     LOG_V(sev) << tok;
129   }
130 }
131
132 // Severity is an integer because it comes is assumed to be from command line.
133 static int SeverityToFilter(int severity) {
134   int filter = webrtc::kTraceNone;
135   switch (severity) {
136     case talk_base::LS_VERBOSE:
137       filter |= webrtc::kTraceAll;
138     case talk_base::LS_INFO:
139       filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo);
140     case talk_base::LS_WARNING:
141       filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning);
142     case talk_base::LS_ERROR:
143       filter |= (webrtc::kTraceError | webrtc::kTraceCritical);
144   }
145   return filter;
146 }
147
148 static const int kCpuMonitorPeriodMs = 2000;  // 2 seconds.
149
150 static const bool kNotSending = false;
151
152 // Default video dscp value.
153 // See http://tools.ietf.org/html/rfc2474 for details
154 // See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
155 static const talk_base::DiffServCodePoint kVideoDscpValue =
156     talk_base::DSCP_AF41;
157
158 static bool IsNackEnabled(const VideoCodec& codec) {
159   return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
160                                               kParamValueEmpty));
161 }
162
163 // Returns true if Receiver Estimated Max Bitrate is enabled.
164 static bool IsRembEnabled(const VideoCodec& codec) {
165   return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamRemb,
166                                               kParamValueEmpty));
167 }
168
169 struct FlushBlackFrameData : public talk_base::MessageData {
170   FlushBlackFrameData(uint32 s, int64 t) : ssrc(s), timestamp(t) {
171   }
172   uint32 ssrc;
173   int64 timestamp;
174 };
175
176 class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
177  public:
178   WebRtcRenderAdapter(VideoRenderer* renderer, int channel_id)
179       : renderer_(renderer),
180         channel_id_(channel_id),
181         width_(0),
182         height_(0),
183         first_frame_arrived_(false),
184         capture_start_rtp_time_stamp_(0),
185         capture_start_ntp_time_ms_(0) {
186   }
187
188   virtual ~WebRtcRenderAdapter() {
189   }
190
191   void SetRenderer(VideoRenderer* renderer) {
192     talk_base::CritScope cs(&crit_);
193     renderer_ = renderer;
194     // FrameSizeChange may have already been called when renderer was not set.
195     // If so we should call SetSize here.
196     // TODO(ronghuawu): Add unit test for this case. Didn't do it now
197     // because the WebRtcRenderAdapter is currently hiding in cc file. No
198     // good way to get access to it from the unit test.
199     if (width_ > 0 && height_ > 0 && renderer_ != NULL) {
200       if (!renderer_->SetSize(width_, height_, 0)) {
201         LOG(LS_ERROR)
202             << "WebRtcRenderAdapter (channel " << channel_id_
203             << ") SetRenderer failed to SetSize to: "
204             << width_ << "x" << height_;
205       }
206     }
207   }
208
209   // Implementation of webrtc::ExternalRenderer.
210   virtual int FrameSizeChange(unsigned int width, unsigned int height,
211                               unsigned int /*number_of_streams*/) {
212     talk_base::CritScope cs(&crit_);
213     width_ = width;
214     height_ = height;
215     LOG(LS_INFO) << "WebRtcRenderAdapter (channel " << channel_id_
216                  << ") frame size changed to: "
217                  << width << "x" << height;
218     if (renderer_ == NULL) {
219       LOG(LS_VERBOSE) << "WebRtcRenderAdapter (channel " << channel_id_
220                       << ") the renderer has not been set. "
221                       << "SetSize will be called later in SetRenderer.";
222       return 0;
223     }
224     return renderer_->SetSize(width_, height_, 0) ? 0 : -1;
225   }
226
227   virtual int DeliverFrame(unsigned char* buffer,
228                            int buffer_size,
229                            uint32_t rtp_time_stamp,
230 #ifdef USE_WEBRTC_DEV_BRANCH
231                            int64_t ntp_time_ms,
232 #endif
233                            int64_t render_time,
234                            void* handle) {
235     talk_base::CritScope cs(&crit_);
236     if (!first_frame_arrived_) {
237       first_frame_arrived_ = true;
238       capture_start_rtp_time_stamp_ = rtp_time_stamp;
239     }
240
241     const int kVideoCodecClockratekHz = cricket::kVideoCodecClockrate / 1000;
242
243 #ifdef USE_WEBRTC_DEV_BRANCH
244     if (ntp_time_ms > 0) {
245       uint32 elapsed_time_ms =
246           (rtp_time_stamp - capture_start_rtp_time_stamp_) /
247           kVideoCodecClockratekHz;
248       capture_start_ntp_time_ms_ = ntp_time_ms - elapsed_time_ms;
249     }
250 #endif
251     frame_rate_tracker_.Update(1);
252     if (renderer_ == NULL) {
253       return 0;
254     }
255     // Convert 90K rtp timestamp to ns timestamp.
256     int64 rtp_time_stamp_in_ns = (rtp_time_stamp / kVideoCodecClockratekHz) *
257         talk_base::kNumNanosecsPerMillisec;
258     // Convert milisecond render time to ns timestamp.
259     int64 render_time_stamp_in_ns = render_time *
260         talk_base::kNumNanosecsPerMillisec;
261     // Send the rtp timestamp to renderer as the VideoFrame timestamp.
262     // and the render timestamp as the VideoFrame elapsed_time.
263     if (handle == NULL) {
264       return DeliverBufferFrame(buffer, buffer_size, render_time_stamp_in_ns,
265                                 rtp_time_stamp_in_ns);
266     } else {
267       return DeliverTextureFrame(handle, render_time_stamp_in_ns,
268                                  rtp_time_stamp_in_ns);
269     }
270   }
271
272   virtual bool IsTextureSupported() { return true; }
273
274   int DeliverBufferFrame(unsigned char* buffer, int buffer_size,
275                          int64 elapsed_time, int64 rtp_time_stamp_in_ns) {
276     WebRtcVideoFrame video_frame;
277     video_frame.Alias(buffer, buffer_size, width_, height_,
278                       1, 1, elapsed_time, rtp_time_stamp_in_ns, 0);
279
280     // Sanity check on decoded frame size.
281     if (buffer_size != static_cast<int>(VideoFrame::SizeOf(width_, height_))) {
282       LOG(LS_WARNING) << "WebRtcRenderAdapter (channel " << channel_id_
283                       << ") received a strange frame size: "
284                       << buffer_size;
285     }
286
287     int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1;
288     return ret;
289   }
290
291   int DeliverTextureFrame(void* handle,
292                           int64 elapsed_time,
293                           int64 rtp_time_stamp_in_ns) {
294     WebRtcTextureVideoFrame video_frame(
295         static_cast<webrtc::NativeHandle*>(handle), width_, height_,
296         elapsed_time, rtp_time_stamp_in_ns);
297     return renderer_->RenderFrame(&video_frame);
298   }
299
300   unsigned int width() {
301     talk_base::CritScope cs(&crit_);
302     return width_;
303   }
304
305   unsigned int height() {
306     talk_base::CritScope cs(&crit_);
307     return height_;
308   }
309
310   int framerate() {
311     talk_base::CritScope cs(&crit_);
312     return static_cast<int>(frame_rate_tracker_.units_second());
313   }
314
315   VideoRenderer* renderer() {
316     talk_base::CritScope cs(&crit_);
317     return renderer_;
318   }
319
320   int64 capture_start_ntp_time_ms() {
321     talk_base::CritScope cs(&crit_);
322     return capture_start_ntp_time_ms_;
323   }
324
325  private:
326   talk_base::CriticalSection crit_;
327   VideoRenderer* renderer_;
328   int channel_id_;
329   unsigned int width_;
330   unsigned int height_;
331   talk_base::RateTracker frame_rate_tracker_;
332   bool first_frame_arrived_;
333   uint32 capture_start_rtp_time_stamp_;
334   int64 capture_start_ntp_time_ms_;
335 };
336
337 class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
338  public:
339   explicit WebRtcDecoderObserver(int video_channel)
340        : video_channel_(video_channel),
341          framerate_(0),
342          bitrate_(0),
343          decode_ms_(0),
344          max_decode_ms_(0),
345          current_delay_ms_(0),
346          target_delay_ms_(0),
347          jitter_buffer_ms_(0),
348          min_playout_delay_ms_(0),
349          render_delay_ms_(0) {
350   }
351
352   // virtual functions from VieDecoderObserver.
353   virtual void IncomingCodecChanged(const int videoChannel,
354                                     const webrtc::VideoCodec& videoCodec) {}
355   virtual void IncomingRate(const int videoChannel,
356                             const unsigned int framerate,
357                             const unsigned int bitrate) {
358     talk_base::CritScope cs(&crit_);
359     ASSERT(video_channel_ == videoChannel);
360     framerate_ = framerate;
361     bitrate_ = bitrate;
362   }
363
364   virtual void DecoderTiming(int decode_ms,
365                              int max_decode_ms,
366                              int current_delay_ms,
367                              int target_delay_ms,
368                              int jitter_buffer_ms,
369                              int min_playout_delay_ms,
370                              int render_delay_ms) {
371     talk_base::CritScope cs(&crit_);
372     decode_ms_ = decode_ms;
373     max_decode_ms_ = max_decode_ms;
374     current_delay_ms_ = current_delay_ms;
375     target_delay_ms_ = target_delay_ms;
376     jitter_buffer_ms_ = jitter_buffer_ms;
377     min_playout_delay_ms_ = min_playout_delay_ms;
378     render_delay_ms_ = render_delay_ms;
379   }
380
381   virtual void RequestNewKeyFrame(const int videoChannel) {}
382
383   // Populate |rinfo| based on previously-set data in |*this|.
384   void ExportTo(VideoReceiverInfo* rinfo) {
385     talk_base::CritScope cs(&crit_);
386     rinfo->framerate_rcvd = framerate_;
387     rinfo->decode_ms = decode_ms_;
388     rinfo->max_decode_ms = max_decode_ms_;
389     rinfo->current_delay_ms = current_delay_ms_;
390     rinfo->target_delay_ms = target_delay_ms_;
391     rinfo->jitter_buffer_ms = jitter_buffer_ms_;
392     rinfo->min_playout_delay_ms = min_playout_delay_ms_;
393     rinfo->render_delay_ms = render_delay_ms_;
394   }
395
396  private:
397   mutable talk_base::CriticalSection crit_;
398   int video_channel_;
399   int framerate_;
400   int bitrate_;
401   int decode_ms_;
402   int max_decode_ms_;
403   int current_delay_ms_;
404   int target_delay_ms_;
405   int jitter_buffer_ms_;
406   int min_playout_delay_ms_;
407   int render_delay_ms_;
408 };
409
410 class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver {
411  public:
412   explicit WebRtcEncoderObserver(int video_channel)
413       : video_channel_(video_channel),
414         framerate_(0),
415         bitrate_(0),
416         suspended_(false) {
417   }
418
419   // virtual functions from VieEncoderObserver.
420   virtual void OutgoingRate(const int videoChannel,
421                             const unsigned int framerate,
422                             const unsigned int bitrate) {
423     talk_base::CritScope cs(&crit_);
424     ASSERT(video_channel_ == videoChannel);
425     framerate_ = framerate;
426     bitrate_ = bitrate;
427   }
428
429   virtual void SuspendChange(int video_channel, bool is_suspended) {
430     talk_base::CritScope cs(&crit_);
431     ASSERT(video_channel_ == video_channel);
432     suspended_ = is_suspended;
433   }
434
435   int framerate() const {
436     talk_base::CritScope cs(&crit_);
437     return framerate_;
438   }
439   int bitrate() const {
440     talk_base::CritScope cs(&crit_);
441     return bitrate_;
442   }
443   bool suspended() const {
444     talk_base::CritScope cs(&crit_);
445     return suspended_;
446   }
447
448  private:
449   mutable talk_base::CriticalSection crit_;
450   int video_channel_;
451   int framerate_;
452   int bitrate_;
453   bool suspended_;
454 };
455
456 class WebRtcLocalStreamInfo {
457  public:
458   WebRtcLocalStreamInfo()
459       : width_(0), height_(0), elapsed_time_(-1), time_stamp_(-1) {}
460   size_t width() const {
461     talk_base::CritScope cs(&crit_);
462     return width_;
463   }
464   size_t height() const {
465     talk_base::CritScope cs(&crit_);
466     return height_;
467   }
468   int64 elapsed_time() const {
469     talk_base::CritScope cs(&crit_);
470     return elapsed_time_;
471   }
472   int64 time_stamp() const {
473     talk_base::CritScope cs(&crit_);
474     return time_stamp_;
475   }
476   int framerate() {
477     talk_base::CritScope cs(&crit_);
478     return static_cast<int>(rate_tracker_.units_second());
479   }
480   void GetLastFrameInfo(
481       size_t* width, size_t* height, int64* elapsed_time) const {
482     talk_base::CritScope cs(&crit_);
483     *width = width_;
484     *height = height_;
485     *elapsed_time = elapsed_time_;
486   }
487
488   void UpdateFrame(const VideoFrame* frame) {
489     talk_base::CritScope cs(&crit_);
490
491     width_ = frame->GetWidth();
492     height_ = frame->GetHeight();
493     elapsed_time_ = frame->GetElapsedTime();
494     time_stamp_ = frame->GetTimeStamp();
495
496     rate_tracker_.Update(1);
497   }
498
499  private:
500   mutable talk_base::CriticalSection crit_;
501   size_t width_;
502   size_t height_;
503   int64 elapsed_time_;
504   int64 time_stamp_;
505   talk_base::RateTracker rate_tracker_;
506
507   DISALLOW_COPY_AND_ASSIGN(WebRtcLocalStreamInfo);
508 };
509
510 // WebRtcVideoChannelRecvInfo is a container class with members such as renderer
511 // and a decoder observer that is used by receive channels.
512 // It must exist as long as the receive channel is connected to renderer or a
513 // decoder observer in this class and methods in the class should only be called
514 // from the worker thread.
515 class WebRtcVideoChannelRecvInfo  {
516  public:
517   typedef std::map<int, webrtc::VideoDecoder*> DecoderMap;  // key: payload type
518   explicit WebRtcVideoChannelRecvInfo(int channel_id)
519       : channel_id_(channel_id),
520         render_adapter_(NULL, channel_id),
521         decoder_observer_(channel_id) {
522   }
523   int channel_id() { return channel_id_; }
524   void SetRenderer(VideoRenderer* renderer) {
525     render_adapter_.SetRenderer(renderer);
526   }
527   WebRtcRenderAdapter* render_adapter() { return &render_adapter_; }
528   WebRtcDecoderObserver* decoder_observer() { return &decoder_observer_; }
529   void RegisterDecoder(int pl_type, webrtc::VideoDecoder* decoder) {
530     ASSERT(!IsDecoderRegistered(pl_type));
531     registered_decoders_[pl_type] = decoder;
532   }
533   bool IsDecoderRegistered(int pl_type) {
534     return registered_decoders_.count(pl_type) != 0;
535   }
536   const DecoderMap& registered_decoders() {
537     return registered_decoders_;
538   }
539   void ClearRegisteredDecoders() {
540     registered_decoders_.clear();
541   }
542
543  private:
544   int channel_id_;  // Webrtc video channel number.
545   // Renderer for this channel.
546   WebRtcRenderAdapter render_adapter_;
547   WebRtcDecoderObserver decoder_observer_;
548   DecoderMap registered_decoders_;
549 };
550
551 class WebRtcOveruseObserver : public webrtc::CpuOveruseObserver {
552  public:
553   explicit WebRtcOveruseObserver(CoordinatedVideoAdapter* video_adapter)
554       : video_adapter_(video_adapter),
555         enabled_(false) {
556   }
557
558   // TODO(mflodman): Consider sending resolution as part of event, to let
559   // adapter know what resolution the request is based on. Helps eliminate stale
560   // data, race conditions.
561   virtual void OveruseDetected() OVERRIDE {
562     talk_base::CritScope cs(&crit_);
563     if (!enabled_) {
564       return;
565     }
566
567     video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
568   }
569
570   virtual void NormalUsage() OVERRIDE {
571     talk_base::CritScope cs(&crit_);
572     if (!enabled_) {
573       return;
574     }
575
576     video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE);
577   }
578
579   void Enable(bool enable) {
580     talk_base::CritScope cs(&crit_);
581     enabled_ = enable;
582   }
583
584   bool enabled() const { return enabled_; }
585
586  private:
587   CoordinatedVideoAdapter* video_adapter_;
588   bool enabled_;
589   talk_base::CriticalSection crit_;
590 };
591
592
593 class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
594  public:
595   typedef std::map<int, webrtc::VideoEncoder*> EncoderMap;  // key: payload type
596   WebRtcVideoChannelSendInfo(int channel_id, int capture_id,
597                              webrtc::ViEExternalCapture* external_capture,
598                              talk_base::CpuMonitor* cpu_monitor)
599       : channel_id_(channel_id),
600         capture_id_(capture_id),
601         sending_(false),
602         muted_(false),
603         video_capturer_(NULL),
604         encoder_observer_(channel_id),
605         external_capture_(external_capture),
606         capturer_updated_(false),
607         interval_(0),
608         cpu_monitor_(cpu_monitor),
609         overuse_observer_enabled_(false) {
610   }
611
612   int channel_id() const { return channel_id_; }
613   int capture_id() const { return capture_id_; }
614   void set_sending(bool sending) { sending_ = sending; }
615   bool sending() const { return sending_; }
616   void set_muted(bool on) {
617     // TODO(asapersson): add support.
618     // video_adapter_.SetBlackOutput(on);
619     muted_ = on;
620   }
621   bool muted() {return muted_; }
622
623   WebRtcEncoderObserver* encoder_observer() { return &encoder_observer_; }
624   webrtc::ViEExternalCapture* external_capture() { return external_capture_; }
625   const VideoFormat& video_format() const {
626     return video_format_;
627   }
628   void set_video_format(const VideoFormat& video_format) {
629     video_format_ = video_format;
630     if (video_format_ != cricket::VideoFormat()) {
631       interval_ = video_format_.interval;
632     }
633     CoordinatedVideoAdapter* adapter = video_adapter();
634     if (adapter) {
635       adapter->OnOutputFormatRequest(video_format_);
636     }
637   }
638   void set_interval(int64 interval) {
639     if (video_format() == cricket::VideoFormat()) {
640       interval_ = interval;
641     }
642   }
643   int64 interval() { return interval_; }
644
645   int CurrentAdaptReason() const {
646     const CoordinatedVideoAdapter* adapter = video_adapter();
647     if (!adapter) {
648       return CoordinatedVideoAdapter::ADAPTREASON_NONE;
649     }
650     return video_adapter()->adapt_reason();
651   }
652
653   StreamParams* stream_params() { return stream_params_.get(); }
654   void set_stream_params(const StreamParams& sp) {
655     stream_params_.reset(new StreamParams(sp));
656   }
657   void ClearStreamParams() { stream_params_.reset(); }
658   bool has_ssrc(uint32 local_ssrc) const {
659     return !stream_params_ ? false :
660         stream_params_->has_ssrc(local_ssrc);
661   }
662   WebRtcLocalStreamInfo* local_stream_info() {
663     return &local_stream_info_;
664   }
665   VideoCapturer* video_capturer() {
666     return video_capturer_;
667   }
668   void set_video_capturer(VideoCapturer* video_capturer,
669                           ViEWrapper* vie_wrapper) {
670     if (video_capturer == video_capturer_) {
671       return;
672     }
673
674     CoordinatedVideoAdapter* old_video_adapter = video_adapter();
675     if (old_video_adapter) {
676       // Disconnect signals from old video adapter.
677       SignalCpuAdaptationUnable.disconnect(old_video_adapter);
678       if (cpu_monitor_) {
679         cpu_monitor_->SignalUpdate.disconnect(old_video_adapter);
680       }
681     }
682
683     capturer_updated_ = true;
684     video_capturer_ = video_capturer;
685
686     vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_, NULL);
687     if (!video_capturer) {
688       overuse_observer_.reset();
689       return;
690     }
691
692     CoordinatedVideoAdapter* adapter = video_adapter();
693     ASSERT(adapter && "Video adapter should not be null here.");
694
695     UpdateAdapterCpuOptions();
696
697     overuse_observer_.reset(new WebRtcOveruseObserver(adapter));
698     vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_,
699                                                     overuse_observer_.get());
700     // (Dis)connect the video adapter from the cpu monitor as appropriate.
701     SetCpuOveruseDetection(overuse_observer_enabled_);
702
703     SignalCpuAdaptationUnable.repeat(adapter->SignalCpuAdaptationUnable);
704   }
705
706   CoordinatedVideoAdapter* video_adapter() {
707     if (!video_capturer_) {
708       return NULL;
709     }
710     return video_capturer_->video_adapter();
711   }
712   const CoordinatedVideoAdapter* video_adapter() const {
713     if (!video_capturer_) {
714       return NULL;
715     }
716     return video_capturer_->video_adapter();
717   }
718
719   void ApplyCpuOptions(const VideoOptions& video_options) {
720     // Use video_options_.SetAll() instead of assignment so that unset value in
721     // video_options will not overwrite the previous option value.
722     video_options_.SetAll(video_options);
723     UpdateAdapterCpuOptions();
724   }
725
726   void UpdateAdapterCpuOptions() {
727     if (!video_capturer_) {
728       return;
729     }
730
731     bool cpu_adapt, cpu_smoothing, adapt_third;
732     float low, med, high;
733
734     // TODO(thorcarpenter): Have VideoAdapter be responsible for setting
735     // all these video options.
736     CoordinatedVideoAdapter* video_adapter = video_capturer_->video_adapter();
737     if (video_options_.adapt_input_to_cpu_usage.Get(&cpu_adapt) ||
738         overuse_observer_enabled_) {
739       video_adapter->set_cpu_adaptation(cpu_adapt || overuse_observer_enabled_);
740     }
741     if (video_options_.adapt_cpu_with_smoothing.Get(&cpu_smoothing)) {
742       video_adapter->set_cpu_smoothing(cpu_smoothing);
743     }
744     if (video_options_.process_adaptation_threshhold.Get(&med)) {
745       video_adapter->set_process_threshold(med);
746     }
747     if (video_options_.system_low_adaptation_threshhold.Get(&low)) {
748       video_adapter->set_low_system_threshold(low);
749     }
750     if (video_options_.system_high_adaptation_threshhold.Get(&high)) {
751       video_adapter->set_high_system_threshold(high);
752     }
753     if (video_options_.video_adapt_third.Get(&adapt_third)) {
754       video_adapter->set_scale_third(adapt_third);
755     }
756   }
757
758   void SetCpuOveruseDetection(bool enable) {
759     overuse_observer_enabled_ = enable;
760
761     if (overuse_observer_) {
762       overuse_observer_->Enable(enable);
763     }
764
765     // The video adapter is signaled by overuse detection if enabled; otherwise
766     // it will be signaled by cpu monitor.
767     CoordinatedVideoAdapter* adapter = video_adapter();
768     if (adapter) {
769       bool cpu_adapt = false;
770       video_options_.adapt_input_to_cpu_usage.Get(&cpu_adapt);
771       adapter->set_cpu_adaptation(
772           adapter->cpu_adaptation() || cpu_adapt || enable);
773       if (cpu_monitor_) {
774         if (enable) {
775           cpu_monitor_->SignalUpdate.disconnect(adapter);
776         } else {
777           cpu_monitor_->SignalUpdate.connect(
778               adapter, &CoordinatedVideoAdapter::OnCpuLoadUpdated);
779         }
780       }
781     }
782   }
783
784   void ProcessFrame(const VideoFrame& original_frame, bool mute,
785                     VideoFrame** processed_frame) {
786     if (!mute) {
787       *processed_frame = original_frame.Copy();
788     } else {
789       WebRtcVideoFrame* black_frame = new WebRtcVideoFrame();
790       black_frame->InitToBlack(static_cast<int>(original_frame.GetWidth()),
791                                static_cast<int>(original_frame.GetHeight()),
792                                1, 1,
793                                original_frame.GetElapsedTime(),
794                                original_frame.GetTimeStamp());
795       *processed_frame = black_frame;
796     }
797     local_stream_info_.UpdateFrame(*processed_frame);
798   }
799   void RegisterEncoder(int pl_type, webrtc::VideoEncoder* encoder) {
800     ASSERT(!IsEncoderRegistered(pl_type));
801     registered_encoders_[pl_type] = encoder;
802   }
803   bool IsEncoderRegistered(int pl_type) {
804     return registered_encoders_.count(pl_type) != 0;
805   }
806   const EncoderMap& registered_encoders() {
807     return registered_encoders_;
808   }
809   void ClearRegisteredEncoders() {
810     registered_encoders_.clear();
811   }
812
813   sigslot::repeater0<> SignalCpuAdaptationUnable;
814
815  private:
816   int channel_id_;
817   int capture_id_;
818   bool sending_;
819   bool muted_;
820   VideoCapturer* video_capturer_;
821   WebRtcEncoderObserver encoder_observer_;
822   webrtc::ViEExternalCapture* external_capture_;
823   EncoderMap registered_encoders_;
824
825   VideoFormat video_format_;
826
827   talk_base::scoped_ptr<StreamParams> stream_params_;
828
829   WebRtcLocalStreamInfo local_stream_info_;
830
831   bool capturer_updated_;
832
833   int64 interval_;
834
835   talk_base::CpuMonitor* cpu_monitor_;
836   talk_base::scoped_ptr<WebRtcOveruseObserver> overuse_observer_;
837   bool overuse_observer_enabled_;
838
839   VideoOptions video_options_;
840 };
841
842 const WebRtcVideoEngine::VideoCodecPref
843     WebRtcVideoEngine::kVideoCodecPrefs[] = {
844     {kVp8PayloadName, 100, -1, 0},
845     {kRedPayloadName, 116, -1, 1},
846     {kFecPayloadName, 117, -1, 2},
847     {kRtxCodecName, 96, 100, 3},
848 };
849
850 // The formats are sorted by the descending order of width. We use the order to
851 // find the next format for CPU and bandwidth adaptation.
852 const VideoFormatPod WebRtcVideoEngine::kVideoFormats[] = {
853   {1280, 800, FPS_TO_INTERVAL(30), FOURCC_ANY},
854   {1280, 720, FPS_TO_INTERVAL(30), FOURCC_ANY},
855   {960, 600, FPS_TO_INTERVAL(30), FOURCC_ANY},
856   {960, 540, FPS_TO_INTERVAL(30), FOURCC_ANY},
857   {640, 400, FPS_TO_INTERVAL(30), FOURCC_ANY},
858   {640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY},
859   {640, 480, FPS_TO_INTERVAL(30), FOURCC_ANY},
860   {480, 300, FPS_TO_INTERVAL(30), FOURCC_ANY},
861   {480, 270, FPS_TO_INTERVAL(30), FOURCC_ANY},
862   {480, 360, FPS_TO_INTERVAL(30), FOURCC_ANY},
863   {320, 200, FPS_TO_INTERVAL(30), FOURCC_ANY},
864   {320, 180, FPS_TO_INTERVAL(30), FOURCC_ANY},
865   {320, 240, FPS_TO_INTERVAL(30), FOURCC_ANY},
866   {240, 150, FPS_TO_INTERVAL(30), FOURCC_ANY},
867   {240, 135, FPS_TO_INTERVAL(30), FOURCC_ANY},
868   {240, 180, FPS_TO_INTERVAL(30), FOURCC_ANY},
869   {160, 100, FPS_TO_INTERVAL(30), FOURCC_ANY},
870   {160, 90, FPS_TO_INTERVAL(30), FOURCC_ANY},
871   {160, 120, FPS_TO_INTERVAL(30), FOURCC_ANY},
872 };
873
874 const VideoFormatPod WebRtcVideoEngine::kDefaultVideoFormat =
875   {640, 400, FPS_TO_INTERVAL(30), FOURCC_ANY};
876
877 static void UpdateVideoCodec(const cricket::VideoFormat& video_format,
878                              webrtc::VideoCodec* target_codec) {
879   if ((target_codec == NULL) || (video_format == cricket::VideoFormat())) {
880     return;
881   }
882   target_codec->width = video_format.width;
883   target_codec->height = video_format.height;
884   target_codec->maxFramerate = cricket::VideoFormat::IntervalToFps(
885       video_format.interval);
886 }
887
888 static bool GetCpuOveruseOptions(const VideoOptions& options,
889                                  webrtc::CpuOveruseOptions* overuse_options) {
890   int underuse_threshold = 0;
891   int overuse_threshold = 0;
892   if (!options.cpu_underuse_threshold.Get(&underuse_threshold) ||
893       !options.cpu_overuse_threshold.Get(&overuse_threshold)) {
894     return false;
895   }
896   if (underuse_threshold <= 0 || overuse_threshold <= 0) {
897     return false;
898   }
899   // Valid thresholds.
900   bool encode_usage =
901       options.cpu_overuse_encode_usage.GetWithDefaultIfUnset(false);
902   overuse_options->enable_capture_jitter_method = !encode_usage;
903   overuse_options->enable_encode_usage_method = encode_usage;
904   if (encode_usage) {
905     // Use method based on encode usage.
906     overuse_options->low_encode_usage_threshold_percent = underuse_threshold;
907     overuse_options->high_encode_usage_threshold_percent = overuse_threshold;
908   } else {
909     // Use default method based on capture jitter.
910     overuse_options->low_capture_jitter_threshold_ms =
911         static_cast<float>(underuse_threshold);
912     overuse_options->high_capture_jitter_threshold_ms =
913         static_cast<float>(overuse_threshold);
914   }
915   return true;
916 }
917
918 WebRtcVideoEngine::WebRtcVideoEngine() {
919   Construct(new ViEWrapper(), new ViETraceWrapper(), NULL,
920       new talk_base::CpuMonitor(NULL));
921 }
922
923 WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
924                                      ViEWrapper* vie_wrapper,
925                                      talk_base::CpuMonitor* cpu_monitor) {
926   Construct(vie_wrapper, new ViETraceWrapper(), voice_engine, cpu_monitor);
927 }
928
929 WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
930                                      ViEWrapper* vie_wrapper,
931                                      ViETraceWrapper* tracing,
932                                      talk_base::CpuMonitor* cpu_monitor) {
933   Construct(vie_wrapper, tracing, voice_engine, cpu_monitor);
934 }
935
936 void WebRtcVideoEngine::Construct(ViEWrapper* vie_wrapper,
937                                   ViETraceWrapper* tracing,
938                                   WebRtcVoiceEngine* voice_engine,
939                                   talk_base::CpuMonitor* cpu_monitor) {
940   LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine";
941   worker_thread_ = NULL;
942   vie_wrapper_.reset(vie_wrapper);
943   vie_wrapper_base_initialized_ = false;
944   tracing_.reset(tracing);
945   voice_engine_ = voice_engine;
946   initialized_ = false;
947   SetTraceFilter(SeverityToFilter(kDefaultLogSeverity));
948   render_module_.reset(new WebRtcPassthroughRender());
949   local_renderer_w_ = local_renderer_h_ = 0;
950   local_renderer_ = NULL;
951   capture_started_ = false;
952   decoder_factory_ = NULL;
953   encoder_factory_ = NULL;
954   cpu_monitor_.reset(cpu_monitor);
955
956   SetTraceOptions("");
957   if (tracing_->SetTraceCallback(this) != 0) {
958     LOG_RTCERR1(SetTraceCallback, this);
959   }
960
961   // Set default quality levels for our supported codecs. We override them here
962   // if we know your cpu performance is low, and they can be updated explicitly
963   // by calling SetDefaultCodec.  For example by a flute preference setting, or
964   // by the server with a jec in response to our reported system info.
965   VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
966                        kVideoCodecPrefs[0].name,
967                        kDefaultVideoFormat.width,
968                        kDefaultVideoFormat.height,
969                        VideoFormat::IntervalToFps(kDefaultVideoFormat.interval),
970                        0);
971   if (!SetDefaultCodec(max_codec)) {
972     LOG(LS_ERROR) << "Failed to initialize list of supported codec types";
973   }
974
975
976   // Load our RTP Header extensions.
977   rtp_header_extensions_.push_back(
978       RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
979                          kRtpTimestampOffsetHeaderExtensionDefaultId));
980   rtp_header_extensions_.push_back(
981       RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
982                          kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
983 }
984
985 WebRtcVideoEngine::~WebRtcVideoEngine() {
986   LOG(LS_INFO) << "WebRtcVideoEngine::~WebRtcVideoEngine";
987   if (initialized_) {
988     Terminate();
989   }
990   if (encoder_factory_) {
991     encoder_factory_->RemoveObserver(this);
992   }
993   tracing_->SetTraceCallback(NULL);
994   // Test to see if the media processor was deregistered properly.
995   ASSERT(SignalMediaFrame.is_empty());
996 }
997
998 bool WebRtcVideoEngine::Init(talk_base::Thread* worker_thread) {
999   LOG(LS_INFO) << "WebRtcVideoEngine::Init";
1000   worker_thread_ = worker_thread;
1001   ASSERT(worker_thread_ != NULL);
1002
1003   cpu_monitor_->set_thread(worker_thread_);
1004   if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
1005     LOG(LS_ERROR) << "Failed to start CPU monitor.";
1006     cpu_monitor_.reset();
1007   }
1008
1009   bool result = InitVideoEngine();
1010   if (result) {
1011     LOG(LS_INFO) << "VideoEngine Init done";
1012   } else {
1013     LOG(LS_ERROR) << "VideoEngine Init failed, releasing";
1014     Terminate();
1015   }
1016   return result;
1017 }
1018
1019 bool WebRtcVideoEngine::InitVideoEngine() {
1020   LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine";
1021
1022   // Init WebRTC VideoEngine.
1023   if (!vie_wrapper_base_initialized_) {
1024     if (vie_wrapper_->base()->Init() != 0) {
1025       LOG_RTCERR0(Init);
1026       return false;
1027     }
1028     vie_wrapper_base_initialized_ = true;
1029   }
1030
1031   // Log the VoiceEngine version info.
1032   char buffer[1024] = "";
1033   if (vie_wrapper_->base()->GetVersion(buffer) != 0) {
1034     LOG_RTCERR0(GetVersion);
1035     return false;
1036   }
1037
1038   LOG(LS_INFO) << "WebRtc VideoEngine Version:";
1039   LogMultiline(talk_base::LS_INFO, buffer);
1040
1041   // Hook up to VoiceEngine for sync purposes, if supplied.
1042   if (!voice_engine_) {
1043     LOG(LS_WARNING) << "NULL voice engine";
1044   } else if ((vie_wrapper_->base()->SetVoiceEngine(
1045       voice_engine_->voe()->engine())) != 0) {
1046     LOG_RTCERR0(SetVoiceEngine);
1047     return false;
1048   }
1049
1050   // Register our custom render module.
1051   if (vie_wrapper_->render()->RegisterVideoRenderModule(
1052       *render_module_.get()) != 0) {
1053     LOG_RTCERR0(RegisterVideoRenderModule);
1054     return false;
1055   }
1056
1057   initialized_ = true;
1058   return true;
1059 }
1060
1061 void WebRtcVideoEngine::Terminate() {
1062   LOG(LS_INFO) << "WebRtcVideoEngine::Terminate";
1063   initialized_ = false;
1064
1065   if (vie_wrapper_->render()->DeRegisterVideoRenderModule(
1066       *render_module_.get()) != 0) {
1067     LOG_RTCERR0(DeRegisterVideoRenderModule);
1068   }
1069
1070   if (vie_wrapper_->base()->SetVoiceEngine(NULL) != 0) {
1071     LOG_RTCERR0(SetVoiceEngine);
1072   }
1073
1074   cpu_monitor_->Stop();
1075 }
1076
1077 int WebRtcVideoEngine::GetCapabilities() {
1078   return VIDEO_RECV | VIDEO_SEND;
1079 }
1080
1081 bool WebRtcVideoEngine::SetOptions(const VideoOptions &options) {
1082   return true;
1083 }
1084
1085 bool WebRtcVideoEngine::SetDefaultEncoderConfig(
1086     const VideoEncoderConfig& config) {
1087   return SetDefaultCodec(config.max_codec);
1088 }
1089
1090 VideoEncoderConfig WebRtcVideoEngine::GetDefaultEncoderConfig() const {
1091   ASSERT(!video_codecs_.empty());
1092   VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
1093                        kVideoCodecPrefs[0].name,
1094                        video_codecs_[0].width,
1095                        video_codecs_[0].height,
1096                        video_codecs_[0].framerate,
1097                        0);
1098   return VideoEncoderConfig(max_codec);
1099 }
1100
1101 // SetDefaultCodec may be called while the capturer is running. For example, a
1102 // test call is started in a page with QVGA default codec, and then a real call
1103 // is started in another page with VGA default codec. This is the corner case
1104 // and happens only when a session is started. We ignore this case currently.
1105 bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) {
1106   if (!RebuildCodecList(codec)) {
1107     LOG(LS_WARNING) << "Failed to RebuildCodecList";
1108     return false;
1109   }
1110
1111   ASSERT(!video_codecs_.empty());
1112   default_codec_format_ = VideoFormat(
1113       video_codecs_[0].width,
1114       video_codecs_[0].height,
1115       VideoFormat::FpsToInterval(video_codecs_[0].framerate),
1116       FOURCC_ANY);
1117   return true;
1118 }
1119
1120 WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel(
1121     VoiceMediaChannel* voice_channel) {
1122   WebRtcVideoMediaChannel* channel =
1123       new WebRtcVideoMediaChannel(this, voice_channel);
1124   if (!channel->Init()) {
1125     delete channel;
1126     channel = NULL;
1127   }
1128   return channel;
1129 }
1130
1131 bool WebRtcVideoEngine::SetLocalRenderer(VideoRenderer* renderer) {
1132   local_renderer_w_ = local_renderer_h_ = 0;
1133   local_renderer_ = renderer;
1134   return true;
1135 }
1136
1137 const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const {
1138   return video_codecs_;
1139 }
1140
1141 const std::vector<RtpHeaderExtension>&
1142 WebRtcVideoEngine::rtp_header_extensions() const {
1143   return rtp_header_extensions_;
1144 }
1145
1146 void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) {
1147   // if min_sev == -1, we keep the current log level.
1148   if (min_sev >= 0) {
1149     SetTraceFilter(SeverityToFilter(min_sev));
1150   }
1151   SetTraceOptions(filter);
1152 }
1153
1154 int WebRtcVideoEngine::GetLastEngineError() {
1155   return vie_wrapper_->error();
1156 }
1157
1158 // Checks to see whether we comprehend and could receive a particular codec
1159 bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) {
1160   for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
1161     const VideoFormat fmt(kVideoFormats[i]);
1162     if ((in.width == 0 && in.height == 0) ||
1163         (fmt.width == in.width && fmt.height == in.height)) {
1164       if (encoder_factory_) {
1165         const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1166             encoder_factory_->codecs();
1167         for (size_t j = 0; j < codecs.size(); ++j) {
1168           VideoCodec codec(GetExternalVideoPayloadType(static_cast<int>(j)),
1169                            codecs[j].name, 0, 0, 0, 0);
1170           if (codec.Matches(in))
1171             return true;
1172         }
1173       }
1174       for (size_t j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) {
1175         VideoCodec codec(kVideoCodecPrefs[j].payload_type,
1176                          kVideoCodecPrefs[j].name, 0, 0, 0, 0);
1177         if (codec.Matches(in)) {
1178           return true;
1179         }
1180       }
1181     }
1182   }
1183   return false;
1184 }
1185
1186 // Given the requested codec, returns true if we can send that codec type and
1187 // updates out with the best quality we could send for that codec. If current is
1188 // not empty, we constrain out so that its aspect ratio matches current's.
1189 bool WebRtcVideoEngine::CanSendCodec(const VideoCodec& requested,
1190                                      const VideoCodec& current,
1191                                      VideoCodec* out) {
1192   if (!out) {
1193     return false;
1194   }
1195
1196   std::vector<VideoCodec>::const_iterator local_max;
1197   for (local_max = video_codecs_.begin();
1198        local_max < video_codecs_.end();
1199        ++local_max) {
1200     // First match codecs by payload type
1201     if (!requested.Matches(*local_max)) {
1202       continue;
1203     }
1204
1205     out->id = requested.id;
1206     out->name = requested.name;
1207     out->preference = requested.preference;
1208     out->params = requested.params;
1209     out->framerate = talk_base::_min(requested.framerate, local_max->framerate);
1210     out->width = 0;
1211     out->height = 0;
1212     out->params = requested.params;
1213     out->feedback_params = requested.feedback_params;
1214
1215     if (0 == requested.width && 0 == requested.height) {
1216       // Special case with resolution 0. The channel should not send frames.
1217       return true;
1218     } else if (0 == requested.width || 0 == requested.height) {
1219       // 0xn and nx0 are invalid resolutions.
1220       return false;
1221     }
1222
1223     // Pick the best quality that is within their and our bounds and has the
1224     // correct aspect ratio.
1225     for (int j = 0; j < ARRAY_SIZE(kVideoFormats); ++j) {
1226       const VideoFormat format(kVideoFormats[j]);
1227
1228       // Skip any format that is larger than the local or remote maximums, or
1229       // smaller than the current best match
1230       if (format.width > requested.width || format.height > requested.height ||
1231           format.width > local_max->width ||
1232           (format.width < out->width && format.height < out->height)) {
1233         continue;
1234       }
1235
1236       bool better = false;
1237
1238       // Check any further constraints on this prospective format
1239       if (!out->width || !out->height) {
1240         // If we don't have any matches yet, this is the best so far.
1241         better = true;
1242       } else if (current.width && current.height) {
1243         // current is set so format must match its ratio exactly.
1244         better =
1245             (format.width * current.height == format.height * current.width);
1246       } else {
1247         // Prefer closer aspect ratios i.e
1248         // format.aspect - requested.aspect < out.aspect - requested.aspect
1249         better = abs(format.width * requested.height * out->height -
1250                      requested.width * format.height * out->height) <
1251                  abs(out->width * format.height * requested.height -
1252                      requested.width * format.height * out->height);
1253       }
1254
1255       if (better) {
1256         out->width = format.width;
1257         out->height = format.height;
1258       }
1259     }
1260     if (out->width > 0) {
1261       return true;
1262     }
1263   }
1264   return false;
1265 }
1266
1267 static void ConvertToCricketVideoCodec(
1268     const webrtc::VideoCodec& in_codec, VideoCodec* out_codec) {
1269   out_codec->id = in_codec.plType;
1270   out_codec->name = in_codec.plName;
1271   out_codec->width = in_codec.width;
1272   out_codec->height = in_codec.height;
1273   out_codec->framerate = in_codec.maxFramerate;
1274   if (BitrateIsSet(in_codec.minBitrate)) {
1275     out_codec->SetParam(kCodecParamMinBitrate, in_codec.minBitrate);
1276   }
1277   if (BitrateIsSet(in_codec.maxBitrate)) {
1278     out_codec->SetParam(kCodecParamMaxBitrate, in_codec.maxBitrate);
1279   }
1280   if (BitrateIsSet(in_codec.startBitrate)) {
1281     out_codec->SetParam(kCodecParamStartBitrate, in_codec.startBitrate);
1282   }
1283   if (in_codec.qpMax) {
1284     out_codec->SetParam(kCodecParamMaxQuantization, in_codec.qpMax);
1285   }
1286 }
1287
1288 bool WebRtcVideoEngine::ConvertFromCricketVideoCodec(
1289     const VideoCodec& in_codec, webrtc::VideoCodec* out_codec) {
1290   bool found = false;
1291   int ncodecs = vie_wrapper_->codec()->NumberOfCodecs();
1292   for (int i = 0; i < ncodecs; ++i) {
1293     if (vie_wrapper_->codec()->GetCodec(i, *out_codec) == 0 &&
1294         _stricmp(in_codec.name.c_str(), out_codec->plName) == 0) {
1295       found = true;
1296       break;
1297     }
1298   }
1299
1300   // If not found, check if this is supported by external encoder factory.
1301   if (!found && encoder_factory_) {
1302     const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1303         encoder_factory_->codecs();
1304     for (size_t i = 0; i < codecs.size(); ++i) {
1305       if (_stricmp(in_codec.name.c_str(), codecs[i].name.c_str()) == 0) {
1306         out_codec->codecType = codecs[i].type;
1307         out_codec->plType = GetExternalVideoPayloadType(static_cast<int>(i));
1308         talk_base::strcpyn(out_codec->plName, sizeof(out_codec->plName),
1309                            codecs[i].name.c_str(), codecs[i].name.length());
1310         found = true;
1311         break;
1312       }
1313     }
1314   }
1315
1316   // Is this an RTX codec? Handled separately here since webrtc doesn't handle
1317   // them as webrtc::VideoCodec internally.
1318   if (!found && _stricmp(in_codec.name.c_str(), kRtxCodecName) == 0) {
1319     talk_base::strcpyn(out_codec->plName, sizeof(out_codec->plName),
1320                        in_codec.name.c_str(), in_codec.name.length());
1321     out_codec->plType = in_codec.id;
1322     found = true;
1323   }
1324
1325   if (!found) {
1326     LOG(LS_ERROR) << "invalid codec type";
1327     return false;
1328   }
1329
1330   if (in_codec.id != 0)
1331     out_codec->plType = in_codec.id;
1332
1333   if (in_codec.width != 0)
1334     out_codec->width = in_codec.width;
1335
1336   if (in_codec.height != 0)
1337     out_codec->height = in_codec.height;
1338
1339   if (in_codec.framerate != 0)
1340     out_codec->maxFramerate = in_codec.framerate;
1341
1342   // Convert bitrate parameters.
1343   int max_bitrate = -1;
1344   int min_bitrate = -1;
1345   int start_bitrate = -1;
1346
1347   in_codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
1348   in_codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
1349   in_codec.GetParam(kCodecParamStartBitrate, &start_bitrate);
1350
1351
1352   out_codec->minBitrate = min_bitrate;
1353   out_codec->startBitrate = start_bitrate;
1354   out_codec->maxBitrate = max_bitrate;
1355
1356   // Convert general codec parameters.
1357   int max_quantization = 0;
1358   if (in_codec.GetParam(kCodecParamMaxQuantization, &max_quantization)) {
1359     if (max_quantization < 0) {
1360       return false;
1361     }
1362     out_codec->qpMax = max_quantization;
1363   }
1364   return true;
1365 }
1366
1367 void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) {
1368   talk_base::CritScope cs(&channels_crit_);
1369   channels_.push_back(channel);
1370 }
1371
1372 void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) {
1373   talk_base::CritScope cs(&channels_crit_);
1374   channels_.erase(std::remove(channels_.begin(), channels_.end(), channel),
1375                   channels_.end());
1376 }
1377
1378 bool WebRtcVideoEngine::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
1379   if (initialized_) {
1380     LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
1381     return false;
1382   }
1383   voice_engine_ = voice_engine;
1384   return true;
1385 }
1386
1387 bool WebRtcVideoEngine::EnableTimedRender() {
1388   if (initialized_) {
1389     LOG(LS_WARNING) << "EnableTimedRender can not be called after Init";
1390     return false;
1391   }
1392   render_module_.reset(webrtc::VideoRender::CreateVideoRender(0, NULL,
1393       false, webrtc::kRenderExternal));
1394   return true;
1395 }
1396
1397 void WebRtcVideoEngine::SetTraceFilter(int filter) {
1398   tracing_->SetTraceFilter(filter);
1399 }
1400
1401 // See https://sites.google.com/a/google.com/wavelet/
1402 //     Home/Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters
1403 // for all supported command line setttings.
1404 void WebRtcVideoEngine::SetTraceOptions(const std::string& options) {
1405   // Set WebRTC trace file.
1406   std::vector<std::string> opts;
1407   talk_base::tokenize(options, ' ', '"', '"', &opts);
1408   std::vector<std::string>::iterator tracefile =
1409       std::find(opts.begin(), opts.end(), "tracefile");
1410   if (tracefile != opts.end() && ++tracefile != opts.end()) {
1411     // Write WebRTC debug output (at same loglevel) to file
1412     if (tracing_->SetTraceFile(tracefile->c_str()) == -1) {
1413       LOG_RTCERR1(SetTraceFile, *tracefile);
1414     }
1415   }
1416 }
1417
1418 static void AddDefaultFeedbackParams(VideoCodec* codec) {
1419   const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
1420   codec->AddFeedbackParam(kFir);
1421   const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
1422   codec->AddFeedbackParam(kNack);
1423   const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
1424   codec->AddFeedbackParam(kPli);
1425   const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
1426   codec->AddFeedbackParam(kRemb);
1427 }
1428
1429 // Rebuilds the codec list to be only those that are less intensive
1430 // than the specified codec. Prefers internal codec over external with
1431 // higher preference field.
1432 bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
1433   if (!FindCodec(in_codec))
1434     return false;
1435
1436   video_codecs_.clear();
1437
1438   bool found = false;
1439   std::set<std::string> internal_codec_names;
1440   for (size_t i = 0; i < ARRAY_SIZE(kVideoCodecPrefs); ++i) {
1441     const VideoCodecPref& pref(kVideoCodecPrefs[i]);
1442     if (!found)
1443       found = (in_codec.name == pref.name);
1444     if (found) {
1445       VideoCodec codec(pref.payload_type, pref.name,
1446                        in_codec.width, in_codec.height, in_codec.framerate,
1447                        static_cast<int>(ARRAY_SIZE(kVideoCodecPrefs) - i));
1448       if (_stricmp(kVp8PayloadName, codec.name.c_str()) == 0) {
1449         AddDefaultFeedbackParams(&codec);
1450       }
1451       if (pref.associated_payload_type != -1) {
1452         codec.SetParam(kCodecParamAssociatedPayloadType,
1453                        pref.associated_payload_type);
1454       }
1455       video_codecs_.push_back(codec);
1456       internal_codec_names.insert(codec.name);
1457     }
1458   }
1459   if (encoder_factory_) {
1460     const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1461         encoder_factory_->codecs();
1462     for (size_t i = 0; i < codecs.size(); ++i) {
1463       bool is_internal_codec = internal_codec_names.find(codecs[i].name) !=
1464           internal_codec_names.end();
1465       if (!is_internal_codec) {
1466         if (!found)
1467           found = (in_codec.name == codecs[i].name);
1468         VideoCodec codec(
1469             GetExternalVideoPayloadType(static_cast<int>(i)),
1470             codecs[i].name,
1471             codecs[i].max_width,
1472             codecs[i].max_height,
1473             codecs[i].max_fps,
1474             // Use negative preference on external codec to ensure the internal
1475             // codec is preferred.
1476             static_cast<int>(0 - i));
1477         AddDefaultFeedbackParams(&codec);
1478         video_codecs_.push_back(codec);
1479       }
1480     }
1481   }
1482   ASSERT(found);
1483   return true;
1484 }
1485
1486 // Ignore spammy trace messages, mostly from the stats API when we haven't
1487 // gotten RTCP info yet from the remote side.
1488 bool WebRtcVideoEngine::ShouldIgnoreTrace(const std::string& trace) {
1489   static const char* const kTracesToIgnore[] = {
1490     NULL
1491   };
1492   for (const char* const* p = kTracesToIgnore; *p; ++p) {
1493     if (trace.find(*p) == 0) {
1494       return true;
1495     }
1496   }
1497   return false;
1498 }
1499
1500 int WebRtcVideoEngine::GetNumOfChannels() {
1501   talk_base::CritScope cs(&channels_crit_);
1502   return static_cast<int>(channels_.size());
1503 }
1504
1505 void WebRtcVideoEngine::Print(webrtc::TraceLevel level, const char* trace,
1506                               int length) {
1507   talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE;
1508   if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
1509     sev = talk_base::LS_ERROR;
1510   else if (level == webrtc::kTraceWarning)
1511     sev = talk_base::LS_WARNING;
1512   else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
1513     sev = talk_base::LS_INFO;
1514   else if (level == webrtc::kTraceTerseInfo)
1515     sev = talk_base::LS_INFO;
1516
1517   // Skip past boilerplate prefix text
1518   if (length < 72) {
1519     std::string msg(trace, length);
1520     LOG(LS_ERROR) << "Malformed webrtc log message: ";
1521     LOG_V(sev) << msg;
1522   } else {
1523     std::string msg(trace + 71, length - 72);
1524     if (!ShouldIgnoreTrace(msg) &&
1525         (!voice_engine_ || !voice_engine_->ShouldIgnoreTrace(msg))) {
1526       LOG_V(sev) << "webrtc: " << msg;
1527     }
1528   }
1529 }
1530
1531 webrtc::VideoDecoder* WebRtcVideoEngine::CreateExternalDecoder(
1532     webrtc::VideoCodecType type) {
1533   if (decoder_factory_ == NULL) {
1534     return NULL;
1535   }
1536   return decoder_factory_->CreateVideoDecoder(type);
1537 }
1538
1539 void WebRtcVideoEngine::DestroyExternalDecoder(webrtc::VideoDecoder* decoder) {
1540   ASSERT(decoder_factory_ != NULL);
1541   if (decoder_factory_ == NULL)
1542     return;
1543   decoder_factory_->DestroyVideoDecoder(decoder);
1544 }
1545
1546 webrtc::VideoEncoder* WebRtcVideoEngine::CreateExternalEncoder(
1547     webrtc::VideoCodecType type) {
1548   if (encoder_factory_ == NULL) {
1549     return NULL;
1550   }
1551   return encoder_factory_->CreateVideoEncoder(type);
1552 }
1553
1554 void WebRtcVideoEngine::DestroyExternalEncoder(webrtc::VideoEncoder* encoder) {
1555   ASSERT(encoder_factory_ != NULL);
1556   if (encoder_factory_ == NULL)
1557     return;
1558   encoder_factory_->DestroyVideoEncoder(encoder);
1559 }
1560
1561 bool WebRtcVideoEngine::IsExternalEncoderCodecType(
1562     webrtc::VideoCodecType type) const {
1563   if (!encoder_factory_)
1564     return false;
1565   const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1566       encoder_factory_->codecs();
1567   std::vector<WebRtcVideoEncoderFactory::VideoCodec>::const_iterator it;
1568   for (it = codecs.begin(); it != codecs.end(); ++it) {
1569     if (it->type == type)
1570       return true;
1571   }
1572   return false;
1573 }
1574
1575 void WebRtcVideoEngine::SetExternalDecoderFactory(
1576     WebRtcVideoDecoderFactory* decoder_factory) {
1577   decoder_factory_ = decoder_factory;
1578 }
1579
1580 void WebRtcVideoEngine::SetExternalEncoderFactory(
1581     WebRtcVideoEncoderFactory* encoder_factory) {
1582   if (encoder_factory_ == encoder_factory)
1583     return;
1584
1585   if (encoder_factory_) {
1586     encoder_factory_->RemoveObserver(this);
1587   }
1588   encoder_factory_ = encoder_factory;
1589   if (encoder_factory_) {
1590     encoder_factory_->AddObserver(this);
1591   }
1592
1593   // Invoke OnCodecAvailable() here in case the list of codecs is already
1594   // available when the encoder factory is installed. If not the encoder
1595   // factory will invoke the callback later when the codecs become available.
1596   OnCodecsAvailable();
1597 }
1598
1599 void WebRtcVideoEngine::OnCodecsAvailable() {
1600   // Rebuild codec list while reapplying the current default codec format.
1601   VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
1602                        kVideoCodecPrefs[0].name,
1603                        video_codecs_[0].width,
1604                        video_codecs_[0].height,
1605                        video_codecs_[0].framerate,
1606                        0);
1607   if (!RebuildCodecList(max_codec)) {
1608     LOG(LS_ERROR) << "Failed to initialize list of supported codec types";
1609   }
1610 }
1611
1612 // WebRtcVideoMediaChannel
1613
1614 WebRtcVideoMediaChannel::WebRtcVideoMediaChannel(
1615     WebRtcVideoEngine* engine,
1616     VoiceMediaChannel* channel)
1617     : engine_(engine),
1618       voice_channel_(channel),
1619       vie_channel_(-1),
1620       nack_enabled_(true),
1621       remb_enabled_(false),
1622       render_started_(false),
1623       first_receive_ssrc_(0),
1624       num_unsignalled_recv_channels_(0),
1625       send_rtx_type_(-1),
1626       send_red_type_(-1),
1627       send_fec_type_(-1),
1628       sending_(false),
1629       ratio_w_(0),
1630       ratio_h_(0) {
1631   engine->RegisterChannel(this);
1632 }
1633
1634 bool WebRtcVideoMediaChannel::Init() {
1635   const uint32 ssrc_key = 0;
1636   return CreateChannel(ssrc_key, MD_SENDRECV, &vie_channel_);
1637 }
1638
1639 WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() {
1640   const bool send = false;
1641   SetSend(send);
1642   const bool render = false;
1643   SetRender(render);
1644
1645   while (!send_channels_.empty()) {
1646     if (!DeleteSendChannel(send_channels_.begin()->first)) {
1647       LOG(LS_ERROR) << "Unable to delete channel with ssrc key "
1648                     << send_channels_.begin()->first;
1649       ASSERT(false);
1650       break;
1651     }
1652   }
1653
1654   // Remove all receive streams and the default channel.
1655   while (!recv_channels_.empty()) {
1656     RemoveRecvStreamInternal(recv_channels_.begin()->first);
1657   }
1658
1659   // Unregister the channel from the engine.
1660   engine()->UnregisterChannel(this);
1661   if (worker_thread()) {
1662     worker_thread()->Clear(this);
1663   }
1664 }
1665
1666 bool WebRtcVideoMediaChannel::SetRecvCodecs(
1667     const std::vector<VideoCodec>& codecs) {
1668   receive_codecs_.clear();
1669   associated_payload_types_.clear();
1670   for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
1671       iter != codecs.end(); ++iter) {
1672     if (engine()->FindCodec(*iter)) {
1673       webrtc::VideoCodec wcodec;
1674       if (engine()->ConvertFromCricketVideoCodec(*iter, &wcodec)) {
1675         receive_codecs_.push_back(wcodec);
1676         int apt;
1677         if (iter->GetParam(cricket::kCodecParamAssociatedPayloadType, &apt)) {
1678           associated_payload_types_[wcodec.plType] = apt;
1679         }
1680       }
1681     } else {
1682       LOG(LS_INFO) << "Unknown codec " << iter->name;
1683       return false;
1684     }
1685   }
1686
1687   for (RecvChannelMap::iterator it = recv_channels_.begin();
1688       it != recv_channels_.end(); ++it) {
1689     if (!SetReceiveCodecs(it->second))
1690       return false;
1691   }
1692   return true;
1693 }
1694
1695 bool WebRtcVideoMediaChannel::SetSendCodecs(
1696     const std::vector<VideoCodec>& codecs) {
1697   // Match with local video codec list.
1698   std::vector<webrtc::VideoCodec> send_codecs;
1699   VideoCodec checked_codec;
1700   VideoCodec current;  // defaults to 0x0
1701   if (sending_) {
1702     ConvertToCricketVideoCodec(*send_codec_, &current);
1703   }
1704   std::map<int, int> primary_rtx_pt_mapping;
1705   bool nack_enabled = nack_enabled_;
1706   bool remb_enabled = remb_enabled_;
1707   for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
1708       iter != codecs.end(); ++iter) {
1709     if (_stricmp(iter->name.c_str(), kRedPayloadName) == 0) {
1710       send_red_type_ = iter->id;
1711     } else if (_stricmp(iter->name.c_str(), kFecPayloadName) == 0) {
1712       send_fec_type_ = iter->id;
1713     } else if (_stricmp(iter->name.c_str(), kRtxCodecName) == 0) {
1714       int rtx_type = iter->id;
1715       int rtx_primary_type = -1;
1716       if (iter->GetParam(kCodecParamAssociatedPayloadType, &rtx_primary_type)) {
1717         primary_rtx_pt_mapping[rtx_primary_type] = rtx_type;
1718       }
1719     } else if (engine()->CanSendCodec(*iter, current, &checked_codec)) {
1720       webrtc::VideoCodec wcodec;
1721       if (engine()->ConvertFromCricketVideoCodec(checked_codec, &wcodec)) {
1722         if (send_codecs.empty()) {
1723           nack_enabled = IsNackEnabled(checked_codec);
1724           remb_enabled = IsRembEnabled(checked_codec);
1725         }
1726         send_codecs.push_back(wcodec);
1727       }
1728     } else {
1729       LOG(LS_WARNING) << "Unknown codec " << iter->name;
1730     }
1731   }
1732
1733   // Fail if we don't have a match.
1734   if (send_codecs.empty()) {
1735     LOG(LS_WARNING) << "No matching codecs available";
1736     return false;
1737   }
1738
1739   // Recv protection.
1740   // Do not update if the status is same as previously configured.
1741   if (nack_enabled_ != nack_enabled) {
1742     for (RecvChannelMap::iterator it = recv_channels_.begin();
1743         it != recv_channels_.end(); ++it) {
1744       int channel_id = it->second->channel_id();
1745       if (!SetNackFec(channel_id, send_red_type_, send_fec_type_,
1746                       nack_enabled)) {
1747         return false;
1748       }
1749       if (engine_->vie()->rtp()->SetRembStatus(channel_id,
1750                                                kNotSending,
1751                                                remb_enabled_) != 0) {
1752         LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_);
1753         return false;
1754       }
1755     }
1756     nack_enabled_ = nack_enabled;
1757   }
1758
1759   // Send settings.
1760   // Do not update if the status is same as previously configured.
1761   if (remb_enabled_ != remb_enabled) {
1762     for (SendChannelMap::iterator iter = send_channels_.begin();
1763          iter != send_channels_.end(); ++iter) {
1764       int channel_id = iter->second->channel_id();
1765       if (!SetNackFec(channel_id, send_red_type_, send_fec_type_,
1766                       nack_enabled_)) {
1767         return false;
1768       }
1769       if (engine_->vie()->rtp()->SetRembStatus(channel_id,
1770                                                remb_enabled,
1771                                                remb_enabled) != 0) {
1772         LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled, remb_enabled);
1773         return false;
1774       }
1775     }
1776     remb_enabled_ = remb_enabled;
1777   }
1778
1779   // Select the first matched codec.
1780   webrtc::VideoCodec& codec(send_codecs[0]);
1781
1782   // Set RTX payload type if primary now active. This value will be used  in
1783   // SetSendCodec.
1784   std::map<int, int>::const_iterator rtx_it =
1785     primary_rtx_pt_mapping.find(static_cast<int>(codec.plType));
1786   if (rtx_it != primary_rtx_pt_mapping.end()) {
1787     send_rtx_type_ = rtx_it->second;
1788   }
1789
1790   if (BitrateIsSet(codec.minBitrate) && BitrateIsSet(codec.maxBitrate) &&
1791       codec.minBitrate > codec.maxBitrate) {
1792     // TODO(pthatcher): This behavior contradicts other behavior in
1793     // this file which will cause min > max to push the min down to
1794     // the max.  There are unit tests for both behaviors.  We should
1795     // pick one and do that.
1796     LOG(LS_INFO) << "Rejecting codec with min bitrate ("
1797                  << codec.minBitrate << ") larger than max ("
1798                  << codec.maxBitrate << "). ";
1799     return false;
1800   }
1801
1802   if (!SetSendCodec(codec)) {
1803     return false;
1804   }
1805
1806   LogSendCodecChange("SetSendCodecs()");
1807
1808   return true;
1809 }
1810
1811 bool WebRtcVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) {
1812   if (!send_codec_) {
1813     return false;
1814   }
1815   ConvertToCricketVideoCodec(*send_codec_, send_codec);
1816   return true;
1817 }
1818
1819 bool WebRtcVideoMediaChannel::SetSendStreamFormat(uint32 ssrc,
1820                                                   const VideoFormat& format) {
1821   WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
1822   if (!send_channel) {
1823     LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use.";
1824     return false;
1825   }
1826   send_channel->set_video_format(format);
1827   return true;
1828 }
1829
1830 bool WebRtcVideoMediaChannel::SetRender(bool render) {
1831   if (render == render_started_) {
1832     return true;  // no action required
1833   }
1834
1835   bool ret = true;
1836   for (RecvChannelMap::iterator it = recv_channels_.begin();
1837       it != recv_channels_.end(); ++it) {
1838     if (render) {
1839       if (engine()->vie()->render()->StartRender(
1840           it->second->channel_id()) != 0) {
1841         LOG_RTCERR1(StartRender, it->second->channel_id());
1842         ret = false;
1843       }
1844     } else {
1845       if (engine()->vie()->render()->StopRender(
1846           it->second->channel_id()) != 0) {
1847         LOG_RTCERR1(StopRender, it->second->channel_id());
1848         ret = false;
1849       }
1850     }
1851   }
1852   if (ret) {
1853     render_started_ = render;
1854   }
1855
1856   return ret;
1857 }
1858
1859 bool WebRtcVideoMediaChannel::SetSend(bool send) {
1860   if (!HasReadySendChannels() && send) {
1861     LOG(LS_ERROR) << "No stream added";
1862     return false;
1863   }
1864   if (send == sending()) {
1865     return true;  // No action required.
1866   }
1867
1868   if (send) {
1869     // We've been asked to start sending.
1870     // SetSendCodecs must have been called already.
1871     if (!send_codec_) {
1872       return false;
1873     }
1874     // Start send now.
1875     if (!StartSend()) {
1876       return false;
1877     }
1878   } else {
1879     // We've been asked to stop sending.
1880     if (!StopSend()) {
1881       return false;
1882     }
1883   }
1884   sending_ = send;
1885
1886   return true;
1887 }
1888
1889 bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) {
1890   if (sp.first_ssrc() == 0) {
1891     LOG(LS_ERROR) << "AddSendStream with 0 ssrc is not supported.";
1892     return false;
1893   }
1894
1895   LOG(LS_INFO) << "AddSendStream " << sp.ToString();
1896
1897   if (!IsOneSsrcStream(sp) && !IsSimulcastStream(sp)) {
1898     LOG(LS_ERROR) << "AddSendStream: bad local stream parameters";
1899     return false;
1900   }
1901
1902   uint32 ssrc_key;
1903   if (!CreateSendChannelKey(sp.first_ssrc(), &ssrc_key)) {
1904     LOG(LS_ERROR) << "Trying to register duplicate ssrc: " << sp.first_ssrc();
1905     return false;
1906   }
1907   // If the default channel is already used for sending create a new channel
1908   // otherwise use the default channel for sending.
1909   int channel_id = -1;
1910   if (send_channels_[0]->stream_params() == NULL) {
1911     channel_id = vie_channel_;
1912   } else {
1913     if (!CreateChannel(ssrc_key, MD_SEND, &channel_id)) {
1914       LOG(LS_ERROR) << "AddSendStream: unable to create channel";
1915       return false;
1916     }
1917   }
1918   WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
1919   // Set the send (local) SSRC.
1920   // If there are multiple send SSRCs, we can only set the first one here, and
1921   // the rest of the SSRC(s) need to be set after SetSendCodec has been called
1922   // (with a codec requires multiple SSRC(s)).
1923   if (engine()->vie()->rtp()->SetLocalSSRC(channel_id,
1924                                            sp.first_ssrc()) != 0) {
1925     LOG_RTCERR2(SetLocalSSRC, channel_id, sp.first_ssrc());
1926     return false;
1927   }
1928
1929   // Set the corresponding RTX SSRC.
1930   if (!SetLocalRtxSsrc(channel_id, sp, sp.first_ssrc(), 0)) {
1931     return false;
1932   }
1933
1934   // Set RTCP CName.
1935   if (engine()->vie()->rtp()->SetRTCPCName(channel_id,
1936                                            sp.cname.c_str()) != 0) {
1937     LOG_RTCERR2(SetRTCPCName, channel_id, sp.cname.c_str());
1938     return false;
1939   }
1940
1941   // At this point the channel's local SSRC has been updated. If the channel is
1942   // the default channel make sure that all the receive channels are updated as
1943   // well. Receive channels have to have the same SSRC as the default channel in
1944   // order to send receiver reports with this SSRC.
1945   if (IsDefaultChannel(channel_id)) {
1946     for (RecvChannelMap::const_iterator it = recv_channels_.begin();
1947          it != recv_channels_.end(); ++it) {
1948       WebRtcVideoChannelRecvInfo* info = it->second;
1949       int channel_id = info->channel_id();
1950       if (engine()->vie()->rtp()->SetLocalSSRC(channel_id,
1951                                                sp.first_ssrc()) != 0) {
1952         LOG_RTCERR1(SetLocalSSRC, it->first);
1953         return false;
1954       }
1955     }
1956   }
1957
1958   send_channel->set_stream_params(sp);
1959
1960   // Reset send codec after stream parameters changed.
1961   if (send_codec_) {
1962     if (!SetSendCodec(send_channel, *send_codec_)) {
1963       return false;
1964     }
1965     LogSendCodecChange("SetSendStreamFormat()");
1966   }
1967
1968   if (sending_) {
1969     return StartSend(send_channel);
1970   }
1971   return true;
1972 }
1973
1974 bool WebRtcVideoMediaChannel::RemoveSendStream(uint32 ssrc) {
1975   if (ssrc == 0) {
1976     LOG(LS_ERROR) << "RemoveSendStream with 0 ssrc is not supported.";
1977     return false;
1978   }
1979
1980   uint32 ssrc_key;
1981   if (!GetSendChannelKey(ssrc, &ssrc_key)) {
1982     LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1983                     << " which doesn't exist.";
1984     return false;
1985   }
1986   WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
1987   int channel_id = send_channel->channel_id();
1988   if (IsDefaultChannel(channel_id) && (send_channel->stream_params() == NULL)) {
1989     // Default channel will still exist. However, if stream_params() is NULL
1990     // there is no stream to remove.
1991     return false;
1992   }
1993   if (sending_) {
1994     StopSend(send_channel);
1995   }
1996
1997   const WebRtcVideoChannelSendInfo::EncoderMap& encoder_map =
1998       send_channel->registered_encoders();
1999   for (WebRtcVideoChannelSendInfo::EncoderMap::const_iterator it =
2000       encoder_map.begin(); it != encoder_map.end(); ++it) {
2001     if (engine()->vie()->ext_codec()->DeRegisterExternalSendCodec(
2002         channel_id, it->first) != 0) {
2003       LOG_RTCERR1(DeregisterEncoderObserver, channel_id);
2004     }
2005     engine()->DestroyExternalEncoder(it->second);
2006   }
2007   send_channel->ClearRegisteredEncoders();
2008
2009   // The receive channels depend on the default channel, recycle it instead.
2010   if (IsDefaultChannel(channel_id)) {
2011     SetCapturer(GetDefaultChannelSsrc(), NULL);
2012     send_channel->ClearStreamParams();
2013   } else {
2014     return DeleteSendChannel(ssrc_key);
2015   }
2016   return true;
2017 }
2018
2019 bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
2020   if (sp.first_ssrc() == 0) {
2021     LOG(LS_ERROR) << "AddRecvStream with 0 ssrc is not supported.";
2022     return false;
2023   }
2024
2025   // TODO(zhurunz) Remove this once BWE works properly across different send
2026   // and receive channels.
2027   // Reuse default channel for recv stream in 1:1 call.
2028   if (!InConferenceMode() && first_receive_ssrc_ == 0) {
2029     LOG(LS_INFO) << "Recv stream " << sp.first_ssrc()
2030                  << " reuse default channel #"
2031                  << vie_channel_;
2032     first_receive_ssrc_ = sp.first_ssrc();
2033     if (render_started_) {
2034       if (engine()->vie()->render()->StartRender(vie_channel_) !=0) {
2035         LOG_RTCERR1(StartRender, vie_channel_);
2036       }
2037     }
2038     return true;
2039   }
2040
2041   int channel_id = -1;
2042   RecvChannelMap::iterator channel_iterator =
2043       recv_channels_.find(sp.first_ssrc());
2044   if (channel_iterator == recv_channels_.end() &&
2045       first_receive_ssrc_ != sp.first_ssrc()) {
2046     // TODO(perkj): Implement recv media from multiple media SSRCs per stream.
2047     // NOTE: We have two SSRCs per stream when RTX is enabled.
2048     if (!IsOneSsrcStream(sp)) {
2049       LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one primary SSRC per"
2050                     << " stream and one FID SSRC per primary SSRC.";
2051       return false;
2052     }
2053
2054     // Create a new channel for receiving video data.
2055     // In order to get the bandwidth estimation work fine for
2056     // receive only channels, we connect all receiving channels
2057     // to our master send channel.
2058     if (!CreateChannel(sp.first_ssrc(), MD_RECV, &channel_id)) {
2059       return false;
2060     }
2061   } else {
2062     // Already exists.
2063     if (first_receive_ssrc_ == sp.first_ssrc()) {
2064       return false;
2065     }
2066     // Early receive added channel.
2067     channel_id = (*channel_iterator).second->channel_id();
2068   }
2069   channel_iterator = recv_channels_.find(sp.first_ssrc());
2070
2071   // Set the corresponding RTX SSRC.
2072   uint32 rtx_ssrc;
2073   bool has_rtx = sp.GetFidSsrc(sp.first_ssrc(), &rtx_ssrc);
2074   if (has_rtx) {
2075     LOG(LS_INFO) << "Setting rtx ssrc " << rtx_ssrc << " for stream "
2076                  << sp.first_ssrc();
2077     if (engine()->vie()->rtp()->SetRemoteSSRCType(
2078         channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) {
2079       LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx,
2080                   rtx_ssrc);
2081       return false;
2082     }
2083     rtx_to_primary_ssrc_[rtx_ssrc] = sp.first_ssrc();
2084   }
2085
2086   // Get the default renderer.
2087   VideoRenderer* default_renderer = NULL;
2088   if (InConferenceMode()) {
2089     // The recv_channels_ size start out being 1, so if it is two here this
2090     // is the first receive channel created (vie_channel_ is not used for
2091     // receiving in a conference call). This means that the renderer stored
2092     // inside vie_channel_ should be used for the just created channel.
2093     if (recv_channels_.size() == 2 &&
2094         recv_channels_.find(0) != recv_channels_.end()) {
2095       GetRenderer(0, &default_renderer);
2096     }
2097   }
2098
2099   // The first recv stream reuses the default renderer (if a default renderer
2100   // has been set).
2101   if (default_renderer) {
2102     SetRenderer(sp.first_ssrc(), default_renderer);
2103   }
2104
2105   LOG(LS_INFO) << "New video stream " << sp.first_ssrc()
2106                << " registered to VideoEngine channel #"
2107                << channel_id << " and connected to channel #" << vie_channel_;
2108
2109   return true;
2110 }
2111
2112 bool WebRtcVideoMediaChannel::RemoveRecvStream(uint32 ssrc) {
2113   if (ssrc == 0) {
2114     LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
2115     return false;
2116   }
2117   return RemoveRecvStreamInternal(ssrc);
2118 }
2119
2120 bool WebRtcVideoMediaChannel::RemoveRecvStreamInternal(uint32 ssrc) {
2121   RecvChannelMap::iterator it = recv_channels_.find(ssrc);
2122   if (it == recv_channels_.end()) {
2123     // TODO(perkj): Remove this once BWE works properly across different send
2124     // and receive channels.
2125     // The default channel is reused for recv stream in 1:1 call.
2126     if (first_receive_ssrc_ == ssrc) {
2127       first_receive_ssrc_ = 0;
2128       // Need to stop the renderer and remove it since the render window can be
2129       // deleted after this.
2130       if (render_started_) {
2131         if (engine()->vie()->render()->StopRender(vie_channel_) !=0) {
2132           LOG_RTCERR1(StopRender, it->second->channel_id());
2133         }
2134       }
2135       recv_channels_[0]->SetRenderer(NULL);
2136       return true;
2137     }
2138     return false;
2139   }
2140   WebRtcVideoChannelRecvInfo* info = it->second;
2141
2142   // Remove any RTX SSRC mappings to this stream.
2143   SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.begin();
2144   while (rtx_it != rtx_to_primary_ssrc_.end()) {
2145     if (rtx_it->second == ssrc) {
2146       rtx_to_primary_ssrc_.erase(rtx_it++);
2147     } else {
2148       ++rtx_it;
2149     }
2150   }
2151
2152   int channel_id = info->channel_id();
2153   if (engine()->vie()->render()->RemoveRenderer(channel_id) != 0) {
2154     LOG_RTCERR1(RemoveRenderer, channel_id);
2155   }
2156
2157   if (engine()->vie()->network()->DeregisterSendTransport(channel_id) !=0) {
2158     LOG_RTCERR1(DeRegisterSendTransport, channel_id);
2159   }
2160
2161   if (engine()->vie()->codec()->DeregisterDecoderObserver(
2162       channel_id) != 0) {
2163     LOG_RTCERR1(DeregisterDecoderObserver, channel_id);
2164   }
2165
2166   const WebRtcVideoChannelRecvInfo::DecoderMap& decoder_map =
2167       info->registered_decoders();
2168   for (WebRtcVideoChannelRecvInfo::DecoderMap::const_iterator it =
2169        decoder_map.begin(); it != decoder_map.end(); ++it) {
2170     if (engine()->vie()->ext_codec()->DeRegisterExternalReceiveCodec(
2171         channel_id, it->first) != 0) {
2172       LOG_RTCERR1(DeregisterDecoderObserver, channel_id);
2173     }
2174     engine()->DestroyExternalDecoder(it->second);
2175   }
2176   info->ClearRegisteredDecoders();
2177
2178   LOG(LS_INFO) << "Removing video stream " << ssrc
2179                << " with VideoEngine channel #"
2180                << channel_id;
2181   bool ret = true;
2182   if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) {
2183     LOG_RTCERR1(DeleteChannel, channel_id);
2184     ret = false;
2185   }
2186   // Delete the WebRtcVideoChannelRecvInfo pointed to by it->second.
2187   delete info;
2188   recv_channels_.erase(it);
2189   return ret;
2190 }
2191
2192 bool WebRtcVideoMediaChannel::StartSend() {
2193   bool success = true;
2194   for (SendChannelMap::iterator iter = send_channels_.begin();
2195        iter != send_channels_.end(); ++iter) {
2196     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2197     if (!StartSend(send_channel)) {
2198       success = false;
2199     }
2200   }
2201   return success;
2202 }
2203
2204 bool WebRtcVideoMediaChannel::StartSend(
2205     WebRtcVideoChannelSendInfo* send_channel) {
2206   const int channel_id = send_channel->channel_id();
2207   if (engine()->vie()->base()->StartSend(channel_id) != 0) {
2208     LOG_RTCERR1(StartSend, channel_id);
2209     return false;
2210   }
2211
2212   send_channel->set_sending(true);
2213   return true;
2214 }
2215
2216 bool WebRtcVideoMediaChannel::StopSend() {
2217   bool success = true;
2218   for (SendChannelMap::iterator iter = send_channels_.begin();
2219        iter != send_channels_.end(); ++iter) {
2220     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2221     if (!StopSend(send_channel)) {
2222       success = false;
2223     }
2224   }
2225   return success;
2226 }
2227
2228 bool WebRtcVideoMediaChannel::StopSend(
2229     WebRtcVideoChannelSendInfo* send_channel) {
2230   const int channel_id = send_channel->channel_id();
2231   if (engine()->vie()->base()->StopSend(channel_id) != 0) {
2232     LOG_RTCERR1(StopSend, channel_id);
2233     return false;
2234   }
2235   send_channel->set_sending(false);
2236   return true;
2237 }
2238
2239 bool WebRtcVideoMediaChannel::SendIntraFrame() {
2240   bool success = true;
2241   for (SendChannelMap::iterator iter = send_channels_.begin();
2242        iter != send_channels_.end();
2243        ++iter) {
2244     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2245     const int channel_id = send_channel->channel_id();
2246     if (engine()->vie()->codec()->SendKeyFrame(channel_id) != 0) {
2247       LOG_RTCERR1(SendKeyFrame, channel_id);
2248       success = false;
2249     }
2250   }
2251   return success;
2252 }
2253
2254 bool WebRtcVideoMediaChannel::HasReadySendChannels() {
2255   return !send_channels_.empty() &&
2256       ((send_channels_.size() > 1) ||
2257        (send_channels_[0]->stream_params() != NULL));
2258 }
2259
2260 bool WebRtcVideoMediaChannel::GetSendChannelKey(uint32 local_ssrc,
2261                                                 uint32* key) {
2262   *key = 0;
2263   // If a send channel is not ready to send it will not have local_ssrc
2264   // registered to it.
2265   if (!HasReadySendChannels()) {
2266     return false;
2267   }
2268   // The default channel is stored with key 0. The key therefore does not match
2269   // the SSRC associated with the default channel. Check if the SSRC provided
2270   // corresponds to the default channel's SSRC.
2271   if (local_ssrc == GetDefaultChannelSsrc()) {
2272     return true;
2273   }
2274   if (send_channels_.find(local_ssrc) == send_channels_.end()) {
2275     for (SendChannelMap::iterator iter = send_channels_.begin();
2276          iter != send_channels_.end(); ++iter) {
2277       WebRtcVideoChannelSendInfo* send_channel = iter->second;
2278       if (send_channel->has_ssrc(local_ssrc)) {
2279         *key = iter->first;
2280         return true;
2281       }
2282     }
2283     return false;
2284   }
2285   // The key was found in the above std::map::find call. This means that the
2286   // ssrc is the key.
2287   *key = local_ssrc;
2288   return true;
2289 }
2290
2291 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
2292     uint32 local_ssrc) {
2293   uint32 key;
2294   if (!GetSendChannelKey(local_ssrc, &key)) {
2295     return NULL;
2296   }
2297   return send_channels_[key];
2298 }
2299
2300 bool WebRtcVideoMediaChannel::CreateSendChannelKey(uint32 local_ssrc,
2301                                                    uint32* key) {
2302   if (GetSendChannelKey(local_ssrc, key)) {
2303     // If there is a key corresponding to |local_ssrc|, the SSRC is already in
2304     // use. SSRCs need to be unique in a session and at this point a duplicate
2305     // SSRC has been detected.
2306     return false;
2307   }
2308   if (send_channels_[0]->stream_params() == NULL) {
2309     // key should be 0 here as the default channel should be re-used whenever it
2310     // is not used.
2311     *key = 0;
2312     return true;
2313   }
2314   // SSRC is currently not in use and the default channel is already in use. Use
2315   // the SSRC as key since it is supposed to be unique in a session.
2316   *key = local_ssrc;
2317   return true;
2318 }
2319
2320 int WebRtcVideoMediaChannel::GetSendChannelNum(VideoCapturer* capturer) {
2321   int num = 0;
2322   for (SendChannelMap::iterator iter = send_channels_.begin();
2323        iter != send_channels_.end(); ++iter) {
2324     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2325     if (send_channel->video_capturer() == capturer) {
2326       ++num;
2327     }
2328   }
2329   return num;
2330 }
2331
2332 uint32 WebRtcVideoMediaChannel::GetDefaultChannelSsrc() {
2333   WebRtcVideoChannelSendInfo* send_channel = send_channels_[0];
2334   const StreamParams* sp = send_channel->stream_params();
2335   if (sp == NULL) {
2336     // This happens if no send stream is currently registered.
2337     return 0;
2338   }
2339   return sp->first_ssrc();
2340 }
2341
2342 bool WebRtcVideoMediaChannel::DeleteSendChannel(uint32 ssrc_key) {
2343   if (send_channels_.find(ssrc_key) == send_channels_.end()) {
2344     return false;
2345   }
2346   WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
2347   MaybeDisconnectCapturer(send_channel->video_capturer());
2348   send_channel->set_video_capturer(NULL, engine()->vie());
2349
2350   int channel_id = send_channel->channel_id();
2351   int capture_id = send_channel->capture_id();
2352   if (engine()->vie()->codec()->DeregisterEncoderObserver(
2353           channel_id) != 0) {
2354     LOG_RTCERR1(DeregisterEncoderObserver, channel_id);
2355   }
2356
2357   // Destroy the external capture interface.
2358   if (engine()->vie()->capture()->DisconnectCaptureDevice(
2359           channel_id) != 0) {
2360     LOG_RTCERR1(DisconnectCaptureDevice, channel_id);
2361   }
2362   if (engine()->vie()->capture()->ReleaseCaptureDevice(
2363           capture_id) != 0) {
2364     LOG_RTCERR1(ReleaseCaptureDevice, capture_id);
2365   }
2366
2367   // The default channel is stored in both |send_channels_| and
2368   // |recv_channels_|. To make sure it is only deleted once from vie let the
2369   // delete call happen when tearing down |recv_channels_| and not here.
2370   if (!IsDefaultChannel(channel_id)) {
2371     engine_->vie()->base()->DeleteChannel(channel_id);
2372   }
2373   delete send_channel;
2374   send_channels_.erase(ssrc_key);
2375   return true;
2376 }
2377
2378 bool WebRtcVideoMediaChannel::RemoveCapturer(uint32 ssrc) {
2379   WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2380   if (!send_channel) {
2381     return false;
2382   }
2383   VideoCapturer* capturer = send_channel->video_capturer();
2384   if (capturer == NULL) {
2385     return false;
2386   }
2387   MaybeDisconnectCapturer(capturer);
2388   send_channel->set_video_capturer(NULL, engine()->vie());
2389   const int64 timestamp = send_channel->local_stream_info()->time_stamp();
2390   if (send_codec_) {
2391     QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate);
2392   }
2393   return true;
2394 }
2395
2396 bool WebRtcVideoMediaChannel::SetRenderer(uint32 ssrc,
2397                                           VideoRenderer* renderer) {
2398   if (recv_channels_.find(ssrc) == recv_channels_.end()) {
2399     // TODO(perkj): Remove this once BWE works properly across different send
2400     // and receive channels.
2401     // The default channel is reused for recv stream in 1:1 call.
2402     if (first_receive_ssrc_ == ssrc &&
2403         recv_channels_.find(0) != recv_channels_.end()) {
2404       LOG(LS_INFO) << "SetRenderer " << ssrc
2405                    << " reuse default channel #"
2406                    << vie_channel_;
2407       recv_channels_[0]->SetRenderer(renderer);
2408       return true;
2409     }
2410     return false;
2411   }
2412
2413   recv_channels_[ssrc]->SetRenderer(renderer);
2414   return true;
2415 }
2416
2417 bool WebRtcVideoMediaChannel::GetStats(const StatsOptions& options,
2418                                        VideoMediaInfo* info) {
2419   // Get sender statistics and build VideoSenderInfo.
2420   unsigned int total_bitrate_sent = 0;
2421   unsigned int video_bitrate_sent = 0;
2422   unsigned int fec_bitrate_sent = 0;
2423   unsigned int nack_bitrate_sent = 0;
2424   unsigned int estimated_send_bandwidth = 0;
2425   unsigned int target_enc_bitrate = 0;
2426   if (send_codec_) {
2427     for (SendChannelMap::const_iterator iter = send_channels_.begin();
2428          iter != send_channels_.end(); ++iter) {
2429       WebRtcVideoChannelSendInfo* send_channel = iter->second;
2430       const int channel_id = send_channel->channel_id();
2431       VideoSenderInfo sinfo;
2432       const StreamParams* send_params = send_channel->stream_params();
2433       if (send_params == NULL) {
2434         // This should only happen if the default vie channel is not in use.
2435         // This can happen if no streams have ever been added or the stream
2436         // corresponding to the default channel has been removed. Note that
2437         // there may be non-default vie channels in use when this happen so
2438         // asserting send_channels_.size() == 1 is not correct and neither is
2439         // breaking out of the loop.
2440         ASSERT(channel_id == vie_channel_);
2441         continue;
2442       }
2443       unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
2444       if (engine_->vie()->rtp()->GetRTPStatistics(channel_id, bytes_sent,
2445                                                   packets_sent, bytes_recv,
2446                                                   packets_recv) != 0) {
2447         LOG_RTCERR1(GetRTPStatistics, vie_channel_);
2448         continue;
2449       }
2450       WebRtcLocalStreamInfo* channel_stream_info =
2451           send_channel->local_stream_info();
2452
2453       for (size_t i = 0; i < send_params->ssrcs.size(); ++i) {
2454         sinfo.add_ssrc(send_params->ssrcs[i]);
2455       }
2456       sinfo.codec_name = send_codec_->plName;
2457       sinfo.bytes_sent = bytes_sent;
2458       sinfo.packets_sent = packets_sent;
2459       sinfo.packets_cached = -1;
2460       sinfo.packets_lost = -1;
2461       sinfo.fraction_lost = -1;
2462       sinfo.rtt_ms = -1;
2463
2464       VideoCapturer* video_capturer = send_channel->video_capturer();
2465       if (video_capturer) {
2466         VideoFormat last_captured_frame_format;
2467         video_capturer->GetStats(&sinfo.adapt_frame_drops,
2468                                  &sinfo.effects_frame_drops,
2469                                  &sinfo.capturer_frame_time,
2470                                  &last_captured_frame_format);
2471         sinfo.input_frame_width = last_captured_frame_format.width;
2472         sinfo.input_frame_height = last_captured_frame_format.height;
2473       } else {
2474         sinfo.input_frame_width = 0;
2475         sinfo.input_frame_height = 0;
2476       }
2477
2478       webrtc::VideoCodec vie_codec;
2479       if (!video_capturer || video_capturer->IsMuted()) {
2480         sinfo.send_frame_width = 0;
2481         sinfo.send_frame_height = 0;
2482       } else if (engine()->vie()->codec()->GetSendCodec(channel_id,
2483                                                         vie_codec) == 0) {
2484         sinfo.send_frame_width = vie_codec.width;
2485         sinfo.send_frame_height = vie_codec.height;
2486       } else {
2487         sinfo.send_frame_width = -1;
2488         sinfo.send_frame_height = -1;
2489         LOG_RTCERR1(GetSendCodec, channel_id);
2490       }
2491       sinfo.framerate_input = channel_stream_info->framerate();
2492       sinfo.framerate_sent = send_channel->encoder_observer()->framerate();
2493       sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate();
2494       if (send_codec_) {
2495         sinfo.preferred_bitrate = GetBitrate(
2496             send_codec_->maxBitrate, kMaxVideoBitrate);
2497       }
2498       sinfo.adapt_reason = send_channel->CurrentAdaptReason();
2499       sinfo.capture_jitter_ms = -1;
2500       sinfo.avg_encode_ms = -1;
2501       sinfo.encode_usage_percent = -1;
2502       sinfo.capture_queue_delay_ms_per_s = -1;
2503
2504       int capture_jitter_ms = 0;
2505       int avg_encode_time_ms = 0;
2506       int encode_usage_percent = 0;
2507       int capture_queue_delay_ms_per_s = 0;
2508       if (engine()->vie()->base()->CpuOveruseMeasures(
2509           channel_id,
2510           &capture_jitter_ms,
2511           &avg_encode_time_ms,
2512           &encode_usage_percent,
2513           &capture_queue_delay_ms_per_s) == 0) {
2514         sinfo.capture_jitter_ms = capture_jitter_ms;
2515         sinfo.avg_encode_ms = avg_encode_time_ms;
2516         sinfo.encode_usage_percent = encode_usage_percent;
2517         sinfo.capture_queue_delay_ms_per_s = capture_queue_delay_ms_per_s;
2518       }
2519
2520       webrtc::RtcpPacketTypeCounter rtcp_sent;
2521       webrtc::RtcpPacketTypeCounter rtcp_received;
2522       if (engine()->vie()->rtp()->GetRtcpPacketTypeCounters(
2523           channel_id, &rtcp_sent, &rtcp_received) == 0) {
2524         sinfo.firs_rcvd = rtcp_received.fir_packets;
2525         sinfo.plis_rcvd = rtcp_received.pli_packets;
2526         sinfo.nacks_rcvd = rtcp_received.nack_packets;
2527       } else {
2528         sinfo.firs_rcvd = -1;
2529         sinfo.plis_rcvd = -1;
2530         sinfo.nacks_rcvd = -1;
2531         LOG_RTCERR1(GetRtcpPacketTypeCounters, channel_id);
2532       }
2533
2534       // Get received RTCP statistics for the sender (reported by the remote
2535       // client in a RTCP packet), if available.
2536       // It's not a fatal error if we can't, since RTCP may not have arrived
2537       // yet.
2538       webrtc::RtcpStatistics outgoing_stream_rtcp_stats;
2539       int outgoing_stream_rtt_ms;
2540
2541       if (engine_->vie()->rtp()->GetSendChannelRtcpStatistics(
2542           channel_id,
2543           outgoing_stream_rtcp_stats,
2544           outgoing_stream_rtt_ms) == 0) {
2545         // Convert Q8 to float.
2546         sinfo.packets_lost = outgoing_stream_rtcp_stats.cumulative_lost;
2547         sinfo.fraction_lost = static_cast<float>(
2548             outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8);
2549         sinfo.rtt_ms = outgoing_stream_rtt_ms;
2550       }
2551       info->senders.push_back(sinfo);
2552
2553       unsigned int channel_total_bitrate_sent = 0;
2554       unsigned int channel_video_bitrate_sent = 0;
2555       unsigned int channel_fec_bitrate_sent = 0;
2556       unsigned int channel_nack_bitrate_sent = 0;
2557       if (engine_->vie()->rtp()->GetBandwidthUsage(
2558           channel_id, channel_total_bitrate_sent, channel_video_bitrate_sent,
2559           channel_fec_bitrate_sent, channel_nack_bitrate_sent) == 0) {
2560         total_bitrate_sent += channel_total_bitrate_sent;
2561         video_bitrate_sent += channel_video_bitrate_sent;
2562         fec_bitrate_sent += channel_fec_bitrate_sent;
2563         nack_bitrate_sent += channel_nack_bitrate_sent;
2564       } else {
2565         LOG_RTCERR1(GetBandwidthUsage, channel_id);
2566       }
2567
2568       unsigned int target_enc_stream_bitrate = 0;
2569       if (engine_->vie()->codec()->GetCodecTargetBitrate(
2570           channel_id, &target_enc_stream_bitrate) == 0) {
2571         target_enc_bitrate += target_enc_stream_bitrate;
2572       } else {
2573         LOG_RTCERR1(GetCodecTargetBitrate, channel_id);
2574       }
2575     }
2576     if (!send_channels_.empty()) {
2577       // GetEstimatedSendBandwidth returns the estimated bandwidth for all video
2578       // engine channels in a channel group. Any valid channel id will do as it
2579       // is only used to access the right group of channels.
2580       const int channel_id = send_channels_.begin()->second->channel_id();
2581       // Get the send bandwidth available for this MediaChannel.
2582       if (engine_->vie()->rtp()->GetEstimatedSendBandwidth(
2583           channel_id, &estimated_send_bandwidth) != 0) {
2584         LOG_RTCERR1(GetEstimatedSendBandwidth, channel_id);
2585       }
2586     }
2587   } else {
2588     LOG(LS_WARNING) << "GetStats: sender information not ready.";
2589   }
2590
2591   // Get the SSRC and stats for each receiver, based on our own calculations.
2592   for (RecvChannelMap::const_iterator it = recv_channels_.begin();
2593        it != recv_channels_.end(); ++it) {
2594     WebRtcVideoChannelRecvInfo* channel = it->second;
2595
2596     unsigned int ssrc;
2597     // Get receiver statistics and build VideoReceiverInfo, if we have data.
2598     // Skip the default channel (ssrc == 0).
2599     if (engine_->vie()->rtp()->GetRemoteSSRC(
2600             channel->channel_id(), ssrc) != 0 ||
2601         ssrc == 0)
2602       continue;
2603
2604     webrtc::StreamDataCounters sent;
2605     webrtc::StreamDataCounters received;
2606     if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(),
2607                                                 sent, received) != 0) {
2608       LOG_RTCERR1(GetRTPStatistics, channel->channel_id());
2609       return false;
2610     }
2611     VideoReceiverInfo rinfo;
2612     rinfo.add_ssrc(ssrc);
2613     rinfo.bytes_rcvd = received.bytes;
2614     rinfo.packets_rcvd = received.packets;
2615     rinfo.packets_lost = -1;
2616     rinfo.packets_concealed = -1;
2617     rinfo.fraction_lost = -1;  // from SentRTCP
2618     rinfo.frame_width = channel->render_adapter()->width();
2619     rinfo.frame_height = channel->render_adapter()->height();
2620     int fps = channel->render_adapter()->framerate();
2621     rinfo.framerate_decoded = fps;
2622     rinfo.framerate_output = fps;
2623     rinfo.capture_start_ntp_time_ms =
2624         channel->render_adapter()->capture_start_ntp_time_ms();
2625     channel->decoder_observer()->ExportTo(&rinfo);
2626
2627     webrtc::RtcpPacketTypeCounter rtcp_sent;
2628     webrtc::RtcpPacketTypeCounter rtcp_received;
2629     if (engine()->vie()->rtp()->GetRtcpPacketTypeCounters(
2630         channel->channel_id(), &rtcp_sent, &rtcp_received) == 0) {
2631       rinfo.firs_sent = rtcp_sent.fir_packets;
2632       rinfo.plis_sent = rtcp_sent.pli_packets;
2633       rinfo.nacks_sent = rtcp_sent.nack_packets;
2634     } else {
2635       rinfo.firs_sent = -1;
2636       rinfo.plis_sent = -1;
2637       rinfo.nacks_sent = -1;
2638       LOG_RTCERR1(GetRtcpPacketTypeCounters, channel->channel_id());
2639     }
2640
2641     // Get our locally created statistics of the received RTP stream.
2642     webrtc::RtcpStatistics incoming_stream_rtcp_stats;
2643     int incoming_stream_rtt_ms;
2644     if (engine_->vie()->rtp()->GetReceiveChannelRtcpStatistics(
2645         channel->channel_id(),
2646         incoming_stream_rtcp_stats,
2647         incoming_stream_rtt_ms) == 0) {
2648       // Convert Q8 to float.
2649       rinfo.packets_lost = incoming_stream_rtcp_stats.cumulative_lost;
2650       rinfo.fraction_lost = static_cast<float>(
2651           incoming_stream_rtcp_stats.fraction_lost) / (1 << 8);
2652     }
2653     info->receivers.push_back(rinfo);
2654   }
2655   unsigned int estimated_recv_bandwidth = 0;
2656   if (!recv_channels_.empty()) {
2657     // GetEstimatedReceiveBandwidth returns the estimated bandwidth for all
2658     // video engine channels in a channel group. Any valid channel id will do as
2659     // it is only used to access the right group of channels.
2660     const int channel_id = recv_channels_.begin()->second->channel_id();
2661     // Gets the estimated receive bandwidth for the MediaChannel.
2662     if (engine_->vie()->rtp()->GetEstimatedReceiveBandwidth(
2663         channel_id, &estimated_recv_bandwidth) != 0) {
2664       LOG_RTCERR1(GetEstimatedReceiveBandwidth, channel_id);
2665     }
2666   }
2667
2668   // Build BandwidthEstimationInfo.
2669   // TODO(zhurunz): Add real unittest for this.
2670   BandwidthEstimationInfo bwe;
2671
2672   // TODO(jiayl): remove the condition when the necessary changes are available
2673   // outside the dev branch.
2674   if (options.include_received_propagation_stats) {
2675     webrtc::ReceiveBandwidthEstimatorStats additional_stats;
2676     // Only call for the default channel because the returned stats are
2677     // collected for all the channels using the same estimator.
2678     if (engine_->vie()->rtp()->GetReceiveBandwidthEstimatorStats(
2679         recv_channels_[0]->channel_id(), &additional_stats) == 0) {
2680       bwe.total_received_propagation_delta_ms =
2681           additional_stats.total_propagation_time_delta_ms;
2682       bwe.recent_received_propagation_delta_ms.swap(
2683           additional_stats.recent_propagation_time_delta_ms);
2684       bwe.recent_received_packet_group_arrival_time_ms.swap(
2685           additional_stats.recent_arrival_time_ms);
2686     }
2687   }
2688
2689   engine_->vie()->rtp()->GetPacerQueuingDelayMs(
2690       recv_channels_[0]->channel_id(), &bwe.bucket_delay);
2691
2692   // Calculations done above per send/receive stream.
2693   bwe.actual_enc_bitrate = video_bitrate_sent;
2694   bwe.transmit_bitrate = total_bitrate_sent;
2695   bwe.retransmit_bitrate = nack_bitrate_sent;
2696   bwe.available_send_bandwidth = estimated_send_bandwidth;
2697   bwe.available_recv_bandwidth = estimated_recv_bandwidth;
2698   bwe.target_enc_bitrate = target_enc_bitrate;
2699
2700   info->bw_estimations.push_back(bwe);
2701
2702   return true;
2703 }
2704
2705 bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc,
2706                                           VideoCapturer* capturer) {
2707   ASSERT(ssrc != 0);
2708   if (!capturer) {
2709     return RemoveCapturer(ssrc);
2710   }
2711   WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2712   if (!send_channel) {
2713     return false;
2714   }
2715   VideoCapturer* old_capturer = send_channel->video_capturer();
2716   MaybeDisconnectCapturer(old_capturer);
2717
2718   send_channel->set_video_capturer(capturer, engine()->vie());
2719   MaybeConnectCapturer(capturer);
2720   if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
2721     capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
2722   }
2723   const int64 timestamp = send_channel->local_stream_info()->time_stamp();
2724   if (send_codec_) {
2725     QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate);
2726   }
2727   return true;
2728 }
2729
2730 bool WebRtcVideoMediaChannel::RequestIntraFrame() {
2731   // There is no API exposed to application to request a key frame
2732   // ViE does this internally when there are errors from decoder
2733   return false;
2734 }
2735
2736 void WebRtcVideoMediaChannel::OnPacketReceived(
2737     talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
2738   // Pick which channel to send this packet to. If this packet doesn't match
2739   // any multiplexed streams, just send it to the default channel. Otherwise,
2740   // send it to the specific decoder instance for that stream.
2741   uint32 ssrc = 0;
2742   if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc))
2743     return;
2744   int processing_channel = GetRecvChannelNum(ssrc);
2745   if (processing_channel == -1) {
2746     // Allocate an unsignalled recv channel for processing in conference mode.
2747     if (!InConferenceMode()) {
2748       // If we can't find or allocate one, use the default.
2749       processing_channel = video_channel();
2750     } else if (!CreateUnsignalledRecvChannel(ssrc, &processing_channel)) {
2751       // If we can't create an unsignalled recv channel, drop the packet in
2752       // conference mode.
2753       return;
2754     }
2755   }
2756
2757   engine()->vie()->network()->ReceivedRTPPacket(
2758       processing_channel,
2759       packet->data(),
2760       static_cast<int>(packet->length()),
2761       webrtc::PacketTime(packet_time.timestamp, packet_time.not_before));
2762 }
2763
2764 void WebRtcVideoMediaChannel::OnRtcpReceived(
2765     talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
2766 // Sending channels need all RTCP packets with feedback information.
2767 // Even sender reports can contain attached report blocks.
2768 // Receiving channels need sender reports in order to create
2769 // correct receiver reports.
2770
2771   uint32 ssrc = 0;
2772   if (!GetRtcpSsrc(packet->data(), packet->length(), &ssrc)) {
2773     LOG(LS_WARNING) << "Failed to parse SSRC from received RTCP packet";
2774     return;
2775   }
2776   int type = 0;
2777   if (!GetRtcpType(packet->data(), packet->length(), &type)) {
2778     LOG(LS_WARNING) << "Failed to parse type from received RTCP packet";
2779     return;
2780   }
2781
2782   // If it is a sender report, find the channel that is listening.
2783   if (type == kRtcpTypeSR) {
2784     int which_channel = GetRecvChannelNum(ssrc);
2785     if (which_channel != -1 && !IsDefaultChannel(which_channel)) {
2786       engine_->vie()->network()->ReceivedRTCPPacket(
2787           which_channel,
2788           packet->data(),
2789           static_cast<int>(packet->length()));
2790     }
2791   }
2792   // SR may continue RR and any RR entry may correspond to any one of the send
2793   // channels. So all RTCP packets must be forwarded all send channels. ViE
2794   // will filter out RR internally.
2795   for (SendChannelMap::iterator iter = send_channels_.begin();
2796        iter != send_channels_.end(); ++iter) {
2797     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2798     int channel_id = send_channel->channel_id();
2799     engine_->vie()->network()->ReceivedRTCPPacket(
2800         channel_id,
2801         packet->data(),
2802         static_cast<int>(packet->length()));
2803   }
2804 }
2805
2806 void WebRtcVideoMediaChannel::OnReadyToSend(bool ready) {
2807   SetNetworkTransmissionState(ready);
2808 }
2809
2810 bool WebRtcVideoMediaChannel::MuteStream(uint32 ssrc, bool muted) {
2811   WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2812   if (!send_channel) {
2813     LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use.";
2814     return false;
2815   }
2816   send_channel->set_muted(muted);
2817   return true;
2818 }
2819
2820 bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions(
2821     const std::vector<RtpHeaderExtension>& extensions) {
2822   if (receive_extensions_ == extensions) {
2823     return true;
2824   }
2825
2826   const RtpHeaderExtension* offset_extension =
2827       FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension);
2828   const RtpHeaderExtension* send_time_extension =
2829       FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
2830
2831   // Loop through all receive channels and enable/disable the extensions.
2832   for (RecvChannelMap::iterator channel_it = recv_channels_.begin();
2833        channel_it != recv_channels_.end(); ++channel_it) {
2834     int channel_id = channel_it->second->channel_id();
2835     if (!SetHeaderExtension(
2836         &webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, channel_id,
2837         offset_extension)) {
2838       return false;
2839     }
2840     if (!SetHeaderExtension(
2841         &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id,
2842         send_time_extension)) {
2843       return false;
2844     }
2845   }
2846
2847   receive_extensions_ = extensions;
2848   return true;
2849 }
2850
2851 bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions(
2852     const std::vector<RtpHeaderExtension>& extensions) {
2853   if (send_extensions_ == extensions) {
2854     return true;
2855   }
2856
2857   const RtpHeaderExtension* offset_extension =
2858       FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension);
2859   const RtpHeaderExtension* send_time_extension =
2860       FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
2861
2862   // Loop through all send channels and enable/disable the extensions.
2863   for (SendChannelMap::iterator channel_it = send_channels_.begin();
2864        channel_it != send_channels_.end(); ++channel_it) {
2865     int channel_id = channel_it->second->channel_id();
2866     if (!SetHeaderExtension(
2867         &webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, channel_id,
2868         offset_extension)) {
2869       return false;
2870     }
2871     if (!SetHeaderExtension(
2872         &webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, channel_id,
2873         send_time_extension)) {
2874       return false;
2875     }
2876   }
2877
2878   if (send_time_extension) {
2879     // For video RTP packets, we would like to update AbsoluteSendTimeHeader
2880     // Extension closer to the network, @ socket level before sending.
2881     // Pushing the extension id to socket layer.
2882     MediaChannel::SetOption(NetworkInterface::ST_RTP,
2883                             talk_base::Socket::OPT_RTP_SENDTIME_EXTN_ID,
2884                             send_time_extension->id);
2885   }
2886
2887   send_extensions_ = extensions;
2888   return true;
2889 }
2890
2891 int WebRtcVideoMediaChannel::GetRtpSendTimeExtnId() const {
2892   const RtpHeaderExtension* send_time_extension = FindHeaderExtension(
2893       send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension);
2894   if (send_time_extension) {
2895     return send_time_extension->id;
2896   }
2897   return -1;
2898 }
2899
2900 bool WebRtcVideoMediaChannel::SetStartSendBandwidth(int bps) {
2901   LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetStartSendBandwidth";
2902
2903   if (!send_codec_) {
2904     LOG(LS_INFO) << "The send codec has not been set up yet";
2905     return true;
2906   }
2907
2908   // On success, SetSendCodec() will reset |send_start_bitrate_| to |bps/1000|,
2909   // by calling MaybeChangeBitrates.  That method will also clamp the
2910   // start bitrate between min and max, consistent with the override behavior
2911   // in SetMaxSendBandwidth.
2912   webrtc::VideoCodec new_codec = *send_codec_;
2913   if (BitrateIsSet(bps)) {
2914     new_codec.startBitrate = bps / 1000;
2915   }
2916   return SetSendCodec(new_codec);
2917 }
2918
2919 bool WebRtcVideoMediaChannel::SetMaxSendBandwidth(int bps) {
2920   LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetMaxSendBandwidth";
2921
2922   if (!send_codec_) {
2923     LOG(LS_INFO) << "The send codec has not been set up yet";
2924     return true;
2925   }
2926
2927   webrtc::VideoCodec new_codec = *send_codec_;
2928   if (BitrateIsSet(bps)) {
2929     new_codec.maxBitrate = bps / 1000;
2930   }
2931   if (!SetSendCodec(new_codec)) {
2932     return false;
2933   }
2934   LogSendCodecChange("SetMaxSendBandwidth()");
2935
2936   return true;
2937 }
2938
2939 bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
2940   // Always accept options that are unchanged.
2941   if (options_ == options) {
2942     return true;
2943   }
2944
2945   // Trigger SetSendCodec to set correct noise reduction state if the option has
2946   // changed.
2947   bool denoiser_changed = options.video_noise_reduction.IsSet() &&
2948       (options_.video_noise_reduction != options.video_noise_reduction);
2949
2950   bool leaky_bucket_changed = options.video_leaky_bucket.IsSet() &&
2951       (options_.video_leaky_bucket != options.video_leaky_bucket);
2952
2953   bool buffer_latency_changed = options.buffered_mode_latency.IsSet() &&
2954       (options_.buffered_mode_latency != options.buffered_mode_latency);
2955
2956   bool cpu_overuse_detection_changed = options.cpu_overuse_detection.IsSet() &&
2957       (options_.cpu_overuse_detection != options.cpu_overuse_detection);
2958
2959   bool dscp_option_changed = (options_.dscp != options.dscp);
2960
2961   bool suspend_below_min_bitrate_changed =
2962       options.suspend_below_min_bitrate.IsSet() &&
2963       (options_.suspend_below_min_bitrate != options.suspend_below_min_bitrate);
2964
2965   bool conference_mode_turned_off = false;
2966   if (options_.conference_mode.IsSet() && options.conference_mode.IsSet() &&
2967       options_.conference_mode.GetWithDefaultIfUnset(false) &&
2968       !options.conference_mode.GetWithDefaultIfUnset(false)) {
2969     conference_mode_turned_off = true;
2970   }
2971
2972   bool improved_wifi_bwe_changed =
2973       options.use_improved_wifi_bandwidth_estimator.IsSet() &&
2974       options_.use_improved_wifi_bandwidth_estimator !=
2975           options.use_improved_wifi_bandwidth_estimator;
2976
2977
2978   // Save the options, to be interpreted where appropriate.
2979   // Use options_.SetAll() instead of assignment so that unset value in options
2980   // will not overwrite the previous option value.
2981   options_.SetAll(options);
2982
2983   // Set CPU options for all send channels.
2984   for (SendChannelMap::iterator iter = send_channels_.begin();
2985        iter != send_channels_.end(); ++iter) {
2986     WebRtcVideoChannelSendInfo* send_channel = iter->second;
2987     send_channel->ApplyCpuOptions(options_);
2988   }
2989
2990   if (send_codec_) {
2991     bool reset_send_codec_needed = denoiser_changed;
2992     webrtc::VideoCodec new_codec = *send_codec_;
2993
2994     // TODO(pthatcher): Remove this.  We don't need 4 ways to set bitrates.
2995     bool lower_min_bitrate;
2996     if (options.lower_min_bitrate.Get(&lower_min_bitrate)) {
2997       new_codec.minBitrate = kLowerMinBitrate;
2998       reset_send_codec_needed = true;
2999     }
3000
3001     if (conference_mode_turned_off) {
3002       // This is a special case for turning conference mode off.
3003       // Max bitrate should go back to the default maximum value instead
3004       // of the current maximum.
3005       new_codec.maxBitrate = kAutoBandwidth;
3006       reset_send_codec_needed = true;
3007     }
3008
3009     // TODO(pthatcher): Remove this.  We don't need 4 ways to set bitrates.
3010     int new_start_bitrate;
3011     if (options.video_start_bitrate.Get(&new_start_bitrate)) {
3012       new_codec.startBitrate = new_start_bitrate;
3013       reset_send_codec_needed = true;
3014     }
3015
3016
3017     LOG(LS_INFO) << "Reset send codec needed is enabled? "
3018                  << reset_send_codec_needed;
3019     if (reset_send_codec_needed) {
3020       if (!SetSendCodec(new_codec)) {
3021         return false;
3022       }
3023       LogSendCodecChange("SetOptions()");
3024     }
3025   }
3026
3027   if (leaky_bucket_changed) {
3028     bool enable_leaky_bucket =
3029         options_.video_leaky_bucket.GetWithDefaultIfUnset(false);
3030     LOG(LS_INFO) << "Leaky bucket is enabled? " << enable_leaky_bucket;
3031     for (SendChannelMap::iterator it = send_channels_.begin();
3032         it != send_channels_.end(); ++it) {
3033       if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(
3034           it->second->channel_id(), enable_leaky_bucket) != 0) {
3035         LOG_RTCERR2(SetTransmissionSmoothingStatus, it->second->channel_id(),
3036                     enable_leaky_bucket);
3037       }
3038     }
3039   }
3040   if (buffer_latency_changed) {
3041     int buffer_latency =
3042         options_.buffered_mode_latency.GetWithDefaultIfUnset(
3043             cricket::kBufferedModeDisabled);
3044     LOG(LS_INFO) << "Buffer latency is " << buffer_latency;
3045     for (SendChannelMap::iterator it = send_channels_.begin();
3046         it != send_channels_.end(); ++it) {
3047       if (engine()->vie()->rtp()->SetSenderBufferingMode(
3048           it->second->channel_id(), buffer_latency) != 0) {
3049         LOG_RTCERR2(SetSenderBufferingMode, it->second->channel_id(),
3050                     buffer_latency);
3051       }
3052     }
3053     for (RecvChannelMap::iterator it = recv_channels_.begin();
3054         it != recv_channels_.end(); ++it) {
3055       if (engine()->vie()->rtp()->SetReceiverBufferingMode(
3056           it->second->channel_id(), buffer_latency) != 0) {
3057         LOG_RTCERR2(SetReceiverBufferingMode, it->second->channel_id(),
3058                     buffer_latency);
3059       }
3060     }
3061   }
3062   if (cpu_overuse_detection_changed) {
3063     bool cpu_overuse_detection =
3064         options_.cpu_overuse_detection.GetWithDefaultIfUnset(false);
3065     LOG(LS_INFO) << "CPU overuse detection is enabled? "
3066                  << cpu_overuse_detection;
3067     for (SendChannelMap::iterator iter = send_channels_.begin();
3068          iter != send_channels_.end(); ++iter) {
3069       WebRtcVideoChannelSendInfo* send_channel = iter->second;
3070       send_channel->SetCpuOveruseDetection(cpu_overuse_detection);
3071     }
3072   }
3073   if (dscp_option_changed) {
3074     talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
3075     if (options_.dscp.GetWithDefaultIfUnset(false))
3076       dscp = kVideoDscpValue;
3077     LOG(LS_INFO) << "DSCP is " << dscp;
3078     if (MediaChannel::SetDscp(dscp) != 0) {
3079       LOG(LS_WARNING) << "Failed to set DSCP settings for video channel";
3080     }
3081   }
3082   if (suspend_below_min_bitrate_changed) {
3083     if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
3084       LOG(LS_INFO) << "Suspend below min bitrate enabled.";
3085       for (SendChannelMap::iterator it = send_channels_.begin();
3086            it != send_channels_.end(); ++it) {
3087         engine()->vie()->codec()->SuspendBelowMinBitrate(
3088             it->second->channel_id());
3089       }
3090     } else {
3091       LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled";
3092     }
3093   }
3094   if (improved_wifi_bwe_changed) {
3095     LOG(LS_INFO) << "Improved WIFI BWE called.";
3096     webrtc::Config config;
3097     config.Set(new webrtc::AimdRemoteRateControl(
3098         options_.use_improved_wifi_bandwidth_estimator
3099           .GetWithDefaultIfUnset(false)));
3100     for (SendChannelMap::iterator it = send_channels_.begin();
3101             it != send_channels_.end(); ++it) {
3102       engine()->vie()->network()->SetBandwidthEstimationConfig(
3103           it->second->channel_id(), config);
3104     }
3105   }
3106   webrtc::CpuOveruseOptions overuse_options;
3107   if (GetCpuOveruseOptions(options_, &overuse_options)) {
3108     for (SendChannelMap::iterator it = send_channels_.begin();
3109          it != send_channels_.end(); ++it) {
3110       if (engine()->vie()->base()->SetCpuOveruseOptions(
3111           it->second->channel_id(), overuse_options) != 0) {
3112         LOG_RTCERR1(SetCpuOveruseOptions, it->second->channel_id());
3113       }
3114     }
3115   }
3116   return true;
3117 }
3118
3119 void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) {
3120   MediaChannel::SetInterface(iface);
3121   // Set the RTP recv/send buffer to a bigger size
3122   MediaChannel::SetOption(NetworkInterface::ST_RTP,
3123                           talk_base::Socket::OPT_RCVBUF,
3124                           kVideoRtpBufferSize);
3125
3126     // TODO(sriniv): Remove or re-enable this.
3127     // As part of b/8030474, send-buffer is size now controlled through
3128     // portallocator flags.
3129     // network_interface_->SetOption(NetworkInterface::ST_RTP,
3130     //                              talk_base::Socket::OPT_SNDBUF,
3131     //                              kVideoRtpBufferSize);
3132 }
3133
3134 void WebRtcVideoMediaChannel::UpdateAspectRatio(int ratio_w, int ratio_h) {
3135   ASSERT(ratio_w != 0);
3136   ASSERT(ratio_h != 0);
3137   ratio_w_ = ratio_w;
3138   ratio_h_ = ratio_h;
3139   // For now assume that all streams want the same aspect ratio.
3140   // TODO(hellner): remove the need for this assumption.
3141   for (SendChannelMap::iterator iter = send_channels_.begin();
3142        iter != send_channels_.end(); ++iter) {
3143     WebRtcVideoChannelSendInfo* send_channel = iter->second;
3144     VideoCapturer* capturer = send_channel->video_capturer();
3145     if (capturer) {
3146       capturer->UpdateAspectRatio(ratio_w, ratio_h);
3147     }
3148   }
3149 }
3150
3151 bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc,
3152                                           VideoRenderer** renderer) {
3153   RecvChannelMap::const_iterator it = recv_channels_.find(ssrc);
3154   if (it == recv_channels_.end()) {
3155     if (first_receive_ssrc_ == ssrc &&
3156         recv_channels_.find(0) != recv_channels_.end()) {
3157       LOG(LS_INFO) << " GetRenderer " << ssrc
3158                    << " reuse default renderer #"
3159                    << vie_channel_;
3160       *renderer = recv_channels_[0]->render_adapter()->renderer();
3161       return true;
3162     }
3163     return false;
3164   }
3165
3166   *renderer = it->second->render_adapter()->renderer();
3167   return true;
3168 }
3169
3170 bool WebRtcVideoMediaChannel::GetVideoAdapter(
3171     uint32 ssrc, CoordinatedVideoAdapter** video_adapter) {
3172   SendChannelMap::iterator it = send_channels_.find(ssrc);
3173   if (it == send_channels_.end()) {
3174     return false;
3175   }
3176   *video_adapter = it->second->video_adapter();
3177   return true;
3178 }
3179
3180 void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
3181                                         const VideoFrame* frame) {
3182   // If the |capturer| is registered to any send channel, then send the frame
3183   // to those send channels.
3184   bool capturer_is_channel_owned = false;
3185   for (SendChannelMap::iterator iter = send_channels_.begin();
3186        iter != send_channels_.end(); ++iter) {
3187     WebRtcVideoChannelSendInfo* send_channel = iter->second;
3188     if (send_channel->video_capturer() == capturer) {
3189       SendFrame(send_channel, frame, capturer->IsScreencast());
3190       capturer_is_channel_owned = true;
3191     }
3192   }
3193   if (capturer_is_channel_owned) {
3194     return;
3195   }
3196
3197   // TODO(hellner): Remove below for loop once the captured frame no longer
3198   // come from the engine, i.e. the engine no longer owns a capturer.
3199   for (SendChannelMap::iterator iter = send_channels_.begin();
3200        iter != send_channels_.end(); ++iter) {
3201     WebRtcVideoChannelSendInfo* send_channel = iter->second;
3202     if (send_channel->video_capturer() == NULL) {
3203       SendFrame(send_channel, frame, capturer->IsScreencast());
3204     }
3205   }
3206 }
3207
3208 bool WebRtcVideoMediaChannel::SendFrame(
3209     WebRtcVideoChannelSendInfo* send_channel,
3210     const VideoFrame* frame,
3211     bool is_screencast) {
3212   if (!send_channel) {
3213     return false;
3214   }
3215   if (!send_codec_) {
3216     // Send codec has not been set. No reason to process the frame any further.
3217     return false;
3218   }
3219   const VideoFormat& video_format = send_channel->video_format();
3220   // If the frame should be dropped.
3221   const bool video_format_set = video_format != cricket::VideoFormat();
3222   if (video_format_set &&
3223       (video_format.width == 0 && video_format.height == 0)) {
3224     return true;
3225   }
3226
3227   // Checks if we need to reset vie send codec.
3228   if (!MaybeResetVieSendCodec(send_channel,
3229                               static_cast<int>(frame->GetWidth()),
3230                               static_cast<int>(frame->GetHeight()),
3231                               is_screencast, NULL)) {
3232     LOG(LS_ERROR) << "MaybeResetVieSendCodec failed with "
3233                   << frame->GetWidth() << "x" << frame->GetHeight();
3234     return false;
3235   }
3236   const VideoFrame* frame_out = frame;
3237   talk_base::scoped_ptr<VideoFrame> processed_frame;
3238   // Disable muting for screencast.
3239   const bool mute = (send_channel->muted() && !is_screencast);
3240   send_channel->ProcessFrame(*frame_out, mute, processed_frame.use());
3241   if (processed_frame) {
3242     frame_out = processed_frame.get();
3243   }
3244
3245   webrtc::ViEVideoFrameI420 frame_i420;
3246   // TODO(ronghuawu): Update the webrtc::ViEVideoFrameI420
3247   // to use const unsigned char*
3248   frame_i420.y_plane = const_cast<unsigned char*>(frame_out->GetYPlane());
3249   frame_i420.u_plane = const_cast<unsigned char*>(frame_out->GetUPlane());
3250   frame_i420.v_plane = const_cast<unsigned char*>(frame_out->GetVPlane());
3251   frame_i420.y_pitch = frame_out->GetYPitch();
3252   frame_i420.u_pitch = frame_out->GetUPitch();
3253   frame_i420.v_pitch = frame_out->GetVPitch();
3254   frame_i420.width = static_cast<uint16>(frame_out->GetWidth());
3255   frame_i420.height = static_cast<uint16>(frame_out->GetHeight());
3256
3257   int64 timestamp_ntp_ms = 0;
3258   // TODO(justinlin): Reenable after Windows issues with clock drift are fixed.
3259   // Currently reverted to old behavior of discarding capture timestamp.
3260 #if 0
3261   static const int kTimestampDeltaInSecondsForWarning = 2;
3262
3263   // If the frame timestamp is 0, we will use the deliver time.
3264   const int64 frame_timestamp = frame->GetTimeStamp();
3265   if (frame_timestamp != 0) {
3266     if (abs(time(NULL) - frame_timestamp / talk_base::kNumNanosecsPerSec) >
3267             kTimestampDeltaInSecondsForWarning) {
3268       LOG(LS_WARNING) << "Frame timestamp differs by more than "
3269                       << kTimestampDeltaInSecondsForWarning << " seconds from "
3270                       << "current Unix timestamp.";
3271     }
3272
3273     timestamp_ntp_ms =
3274         talk_base::UnixTimestampNanosecsToNtpMillisecs(frame_timestamp);
3275   }
3276 #endif
3277
3278   return send_channel->external_capture()->IncomingFrameI420(
3279       frame_i420, timestamp_ntp_ms) == 0;
3280 }
3281
3282 bool WebRtcVideoMediaChannel::CreateChannel(uint32 ssrc_key,
3283                                             MediaDirection direction,
3284                                             int* channel_id) {
3285   // There are 3 types of channels. Sending only, receiving only and
3286   // sending and receiving. The sending and receiving channel is the
3287   // default channel and there is only one. All other channels that are created
3288   // are associated with the default channel which must exist. The default
3289   // channel id is stored in |vie_channel_|. All channels need to know about
3290   // the default channel to properly handle remb which is why there are
3291   // different ViE create channel calls.
3292   // For this channel the local and remote ssrc key is 0. However, it may
3293   // have a non-zero local and/or remote ssrc depending on if it is currently
3294   // sending and/or receiving.
3295   if ((vie_channel_ == -1 || direction == MD_SENDRECV) &&
3296       (!send_channels_.empty() || !recv_channels_.empty())) {
3297     ASSERT(false);
3298     return false;
3299   }
3300
3301   *channel_id = -1;
3302   if (direction == MD_RECV) {
3303     // All rec channels are associated with the default channel |vie_channel_|
3304     if (engine_->vie()->base()->CreateReceiveChannel(*channel_id,
3305                                                      vie_channel_) != 0) {
3306       LOG_RTCERR2(CreateReceiveChannel, *channel_id, vie_channel_);
3307       return false;
3308     }
3309   } else if (direction == MD_SEND) {
3310     if (engine_->vie()->base()->CreateChannel(*channel_id,
3311                                               vie_channel_) != 0) {
3312       LOG_RTCERR2(CreateChannel, *channel_id, vie_channel_);
3313       return false;
3314     }
3315   } else {
3316     ASSERT(direction == MD_SENDRECV);
3317     if (engine_->vie()->base()->CreateChannel(*channel_id) != 0) {
3318       LOG_RTCERR1(CreateChannel, *channel_id);
3319       return false;
3320     }
3321   }
3322   if (!ConfigureChannel(*channel_id, direction, ssrc_key)) {
3323     engine_->vie()->base()->DeleteChannel(*channel_id);
3324     *channel_id = -1;
3325     return false;
3326   }
3327
3328   return true;
3329 }
3330
3331 bool WebRtcVideoMediaChannel::CreateUnsignalledRecvChannel(
3332     uint32 ssrc_key, int* out_channel_id) {
3333   int unsignalled_recv_channel_limit =
3334       options_.unsignalled_recv_stream_limit.GetWithDefaultIfUnset(
3335           kNumDefaultUnsignalledVideoRecvStreams);
3336   if (num_unsignalled_recv_channels_ >= unsignalled_recv_channel_limit) {
3337     return false;
3338   }
3339   if (!CreateChannel(ssrc_key, MD_RECV, out_channel_id)) {
3340     return false;
3341   }
3342   // TODO(tvsriram): Support dynamic sizing of unsignalled recv channels.
3343   num_unsignalled_recv_channels_++;
3344   return true;
3345 }
3346
3347 bool WebRtcVideoMediaChannel::ConfigureChannel(int channel_id,
3348                                                MediaDirection direction,
3349                                                uint32 ssrc_key) {
3350   const bool receiving = (direction == MD_RECV) || (direction == MD_SENDRECV);
3351   const bool sending = (direction == MD_SEND) || (direction == MD_SENDRECV);
3352   // Register external transport.
3353   if (engine_->vie()->network()->RegisterSendTransport(
3354       channel_id, *this) != 0) {
3355     LOG_RTCERR1(RegisterSendTransport, channel_id);
3356     return false;
3357   }
3358
3359   // Set MTU.
3360   if (engine_->vie()->network()->SetMTU(channel_id, kVideoMtu) != 0) {
3361     LOG_RTCERR2(SetMTU, channel_id, kVideoMtu);
3362     return false;
3363   }
3364   // Turn on RTCP and loss feedback reporting.
3365   if (engine()->vie()->rtp()->SetRTCPStatus(
3366       channel_id, webrtc::kRtcpCompound_RFC4585) != 0) {
3367     LOG_RTCERR2(SetRTCPStatus, channel_id, webrtc::kRtcpCompound_RFC4585);
3368     return false;
3369   }
3370   // Enable pli as key frame request method.
3371   if (engine_->vie()->rtp()->SetKeyFrameRequestMethod(
3372       channel_id, webrtc::kViEKeyFrameRequestPliRtcp) != 0) {
3373     LOG_RTCERR2(SetKeyFrameRequestMethod,
3374                 channel_id, webrtc::kViEKeyFrameRequestPliRtcp);
3375     return false;
3376   }
3377   if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) {
3378     // Logged in SetNackFec. Don't spam the logs.
3379     return false;
3380   }
3381   // Note that receiving must always be configured before sending to ensure
3382   // that send and receive channel is configured correctly (ConfigureReceiving
3383   // assumes no sending).
3384   if (receiving) {
3385     if (!ConfigureReceiving(channel_id, ssrc_key)) {
3386       return false;
3387     }
3388   }
3389   if (sending) {
3390     if (!ConfigureSending(channel_id, ssrc_key)) {
3391       return false;
3392     }
3393   }
3394
3395   // Start receiving for both receive and send channels so that we get incoming
3396   // RTP (if receiving) as well as RTCP feedback (if sending).
3397   if (engine()->vie()->base()->StartReceive(channel_id) != 0) {
3398     LOG_RTCERR1(StartReceive, channel_id);
3399     return false;
3400   }
3401
3402   return true;
3403 }
3404
3405 bool WebRtcVideoMediaChannel::ConfigureReceiving(int channel_id,
3406                                                  uint32 remote_ssrc_key) {
3407   // Make sure that an SSRC/key isn't registered more than once.
3408   if (recv_channels_.find(remote_ssrc_key) != recv_channels_.end()) {
3409     return false;
3410   }
3411   // Connect the voice channel, if there is one.
3412   // TODO(perkj): The A/V is synched by the receiving channel. So we need to
3413   // know the SSRC of the remote audio channel in order to fetch the correct
3414   // webrtc VoiceEngine channel. For now- only sync the default channel used
3415   // in 1-1 calls.
3416   if (remote_ssrc_key == 0 && voice_channel_) {
3417     WebRtcVoiceMediaChannel* voice_channel =
3418         static_cast<WebRtcVoiceMediaChannel*>(voice_channel_);
3419     if (engine_->vie()->base()->ConnectAudioChannel(
3420         vie_channel_, voice_channel->voe_channel()) != 0) {
3421       LOG_RTCERR2(ConnectAudioChannel, channel_id,
3422                   voice_channel->voe_channel());
3423       LOG(LS_WARNING) << "A/V not synchronized";
3424       // Not a fatal error.
3425     }
3426   }
3427
3428   talk_base::scoped_ptr<WebRtcVideoChannelRecvInfo> channel_info(
3429       new WebRtcVideoChannelRecvInfo(channel_id));
3430
3431   // Install a render adapter.
3432   if (engine_->vie()->render()->AddRenderer(channel_id,
3433       webrtc::kVideoI420, channel_info->render_adapter()) != 0) {
3434     LOG_RTCERR3(AddRenderer, channel_id, webrtc::kVideoI420,
3435                 channel_info->render_adapter());
3436     return false;
3437   }
3438
3439
3440   if (engine_->vie()->rtp()->SetRembStatus(channel_id,
3441                                            kNotSending,
3442                                            remb_enabled_) != 0) {
3443     LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_);
3444     return false;
3445   }
3446
3447   if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus,
3448       channel_id, receive_extensions_, kRtpTimestampOffsetHeaderExtension)) {
3449     return false;
3450   }
3451   if (!SetHeaderExtension(
3452       &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id,
3453       receive_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) {
3454     return false;
3455   }
3456
3457   if (remote_ssrc_key != 0) {
3458     // Use the same SSRC as our default channel
3459     // (so the RTCP reports are correct).
3460     unsigned int send_ssrc = 0;
3461     webrtc::ViERTP_RTCP* rtp = engine()->vie()->rtp();
3462     if (rtp->GetLocalSSRC(vie_channel_, send_ssrc) == -1) {
3463       LOG_RTCERR2(GetLocalSSRC, vie_channel_, send_ssrc);
3464       return false;
3465     }
3466     if (rtp->SetLocalSSRC(channel_id, send_ssrc) == -1) {
3467       LOG_RTCERR2(SetLocalSSRC, channel_id, send_ssrc);
3468       return false;
3469     }
3470   }  // Else this is the the default channel and we don't change the SSRC.
3471
3472   // Disable color enhancement since it is a bit too aggressive.
3473   if (engine()->vie()->image()->EnableColorEnhancement(channel_id,
3474                                                        false) != 0) {
3475     LOG_RTCERR1(EnableColorEnhancement, channel_id);
3476     return false;
3477   }
3478
3479   if (!SetReceiveCodecs(channel_info.get())) {
3480     return false;
3481   }
3482
3483   int buffer_latency =
3484       options_.buffered_mode_latency.GetWithDefaultIfUnset(
3485           cricket::kBufferedModeDisabled);
3486   if (buffer_latency != cricket::kBufferedModeDisabled) {
3487     if (engine()->vie()->rtp()->SetReceiverBufferingMode(
3488         channel_id, buffer_latency) != 0) {
3489       LOG_RTCERR2(SetReceiverBufferingMode, channel_id, buffer_latency);
3490     }
3491   }
3492
3493   if (render_started_) {
3494     if (engine_->vie()->render()->StartRender(channel_id) != 0) {
3495       LOG_RTCERR1(StartRender, channel_id);
3496       return false;
3497     }
3498   }
3499
3500   // Register decoder observer for incoming framerate and bitrate.
3501   if (engine()->vie()->codec()->RegisterDecoderObserver(
3502       channel_id, *channel_info->decoder_observer()) != 0) {
3503     LOG_RTCERR1(RegisterDecoderObserver, channel_info->decoder_observer());
3504     return false;
3505   }
3506
3507   recv_channels_[remote_ssrc_key] = channel_info.release();
3508   return true;
3509 }
3510
3511 bool WebRtcVideoMediaChannel::ConfigureSending(int channel_id,
3512                                                uint32 local_ssrc_key) {
3513   // The ssrc key can be zero or correspond to an SSRC.
3514   // Make sure the default channel isn't configured more than once.
3515   if (local_ssrc_key == 0 && send_channels_.find(0) != send_channels_.end()) {
3516     return false;
3517   }
3518   // Make sure that the SSRC is not already in use.
3519   uint32 dummy_key;
3520   if (GetSendChannelKey(local_ssrc_key, &dummy_key)) {
3521     return false;
3522   }
3523   int vie_capture = 0;
3524   webrtc::ViEExternalCapture* external_capture = NULL;
3525   // Register external capture.
3526   if (engine()->vie()->capture()->AllocateExternalCaptureDevice(
3527       vie_capture, external_capture) != 0) {
3528     LOG_RTCERR0(AllocateExternalCaptureDevice);
3529     return false;
3530   }
3531
3532   // Connect external capture.
3533   if (engine()->vie()->capture()->ConnectCaptureDevice(
3534       vie_capture, channel_id) != 0) {
3535     LOG_RTCERR2(ConnectCaptureDevice, vie_capture, channel_id);
3536     return false;
3537   }
3538   talk_base::scoped_ptr<WebRtcVideoChannelSendInfo> send_channel(
3539       new WebRtcVideoChannelSendInfo(channel_id, vie_capture,
3540                                      external_capture,
3541                                      engine()->cpu_monitor()));
3542   send_channel->ApplyCpuOptions(options_);
3543   send_channel->SignalCpuAdaptationUnable.connect(this,
3544       &WebRtcVideoMediaChannel::OnCpuAdaptationUnable);
3545
3546   if (options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)) {
3547     send_channel->SetCpuOveruseDetection(true);
3548   }
3549
3550   webrtc::CpuOveruseOptions overuse_options;
3551   if (GetCpuOveruseOptions(options_, &overuse_options)) {
3552     if (engine()->vie()->base()->SetCpuOveruseOptions(channel_id,
3553                                                       overuse_options) != 0) {
3554       LOG_RTCERR1(SetCpuOveruseOptions, channel_id);
3555     }
3556   }
3557
3558   // Register encoder observer for outgoing framerate and bitrate.
3559   if (engine()->vie()->codec()->RegisterEncoderObserver(
3560       channel_id, *send_channel->encoder_observer()) != 0) {
3561     LOG_RTCERR1(RegisterEncoderObserver, send_channel->encoder_observer());
3562     return false;
3563   }
3564
3565   if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus,
3566       channel_id, send_extensions_, kRtpTimestampOffsetHeaderExtension)) {
3567     return false;
3568   }
3569
3570   if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus,
3571       channel_id, send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) {
3572     return false;
3573   }
3574
3575   if (options_.video_leaky_bucket.GetWithDefaultIfUnset(false)) {
3576     if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id,
3577                                                                true) != 0) {
3578       LOG_RTCERR2(SetTransmissionSmoothingStatus, channel_id, true);
3579       return false;
3580     }
3581   }
3582
3583   int buffer_latency =
3584       options_.buffered_mode_latency.GetWithDefaultIfUnset(
3585           cricket::kBufferedModeDisabled);
3586   if (buffer_latency != cricket::kBufferedModeDisabled) {
3587     if (engine()->vie()->rtp()->SetSenderBufferingMode(
3588         channel_id, buffer_latency) != 0) {
3589       LOG_RTCERR2(SetSenderBufferingMode, channel_id, buffer_latency);
3590     }
3591   }
3592
3593   if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
3594     engine()->vie()->codec()->SuspendBelowMinBitrate(channel_id);
3595   }
3596
3597   // The remb status direction correspond to the RTP stream (and not the RTCP
3598   // stream). I.e. if send remb is enabled it means it is receiving remote
3599   // rembs and should use them to estimate bandwidth. Receive remb mean that
3600   // remb packets will be generated and that the channel should be included in
3601   // it. If remb is enabled all channels are allowed to contribute to the remb
3602   // but only receive channels will ever end up actually contributing. This
3603   // keeps the logic simple.
3604   if (engine_->vie()->rtp()->SetRembStatus(channel_id,
3605                                            remb_enabled_,
3606                                            remb_enabled_) != 0) {
3607     LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled_, remb_enabled_);
3608     return false;
3609   }
3610   if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) {
3611     // Logged in SetNackFec. Don't spam the logs.
3612     return false;
3613   }
3614
3615   send_channels_[local_ssrc_key] = send_channel.release();
3616
3617   return true;
3618 }
3619
3620 bool WebRtcVideoMediaChannel::SetNackFec(int channel_id,
3621                                          int red_payload_type,
3622                                          int fec_payload_type,
3623                                          bool nack_enabled) {
3624   bool enable = (red_payload_type != -1 && fec_payload_type != -1 &&
3625       !InConferenceMode());
3626   if (enable) {
3627     if (engine_->vie()->rtp()->SetHybridNACKFECStatus(
3628         channel_id, nack_enabled, red_payload_type, fec_payload_type) != 0) {
3629       LOG_RTCERR4(SetHybridNACKFECStatus,
3630                   channel_id, nack_enabled, red_payload_type, fec_payload_type);
3631       return false;
3632     }
3633     LOG(LS_INFO) << "Hybrid NACK/FEC enabled for channel " << channel_id;
3634   } else {
3635     if (engine_->vie()->rtp()->SetNACKStatus(channel_id, nack_enabled) != 0) {
3636       LOG_RTCERR1(SetNACKStatus, channel_id);
3637       return false;
3638     }
3639     std::string enabled = nack_enabled ? "enabled" : "disabled";
3640     LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id;
3641   }
3642   return true;
3643 }
3644
3645 bool WebRtcVideoMediaChannel::SetSendCodec(const webrtc::VideoCodec& codec) {
3646   bool ret_val = true;
3647   for (SendChannelMap::iterator iter = send_channels_.begin();
3648        iter != send_channels_.end(); ++iter) {
3649     WebRtcVideoChannelSendInfo* send_channel = iter->second;
3650     ret_val = SetSendCodec(send_channel, codec) && ret_val;
3651   }
3652   if (ret_val) {
3653     // All SetSendCodec calls were successful. Update the global state
3654     // accordingly.
3655     send_codec_.reset(new webrtc::VideoCodec(codec));
3656   } else {
3657     // At least one SetSendCodec call failed, rollback.
3658     for (SendChannelMap::iterator iter = send_channels_.begin();
3659          iter != send_channels_.end(); ++iter) {
3660       WebRtcVideoChannelSendInfo* send_channel = iter->second;
3661       if (send_codec_) {
3662         SetSendCodec(send_channel, *send_codec_);
3663       }
3664     }
3665   }
3666   return ret_val;
3667 }
3668
3669 bool WebRtcVideoMediaChannel::SetSendCodec(
3670     WebRtcVideoChannelSendInfo* send_channel,
3671     const webrtc::VideoCodec& codec) {
3672   if (!send_channel) {
3673     return false;
3674   }
3675
3676   const int channel_id = send_channel->channel_id();
3677   // Make a copy of the codec
3678   webrtc::VideoCodec target_codec = codec;
3679
3680   // Set the default number of temporal layers for VP8.
3681   if (webrtc::kVideoCodecVP8 == codec.codecType) {
3682     target_codec.codecSpecific.VP8.numberOfTemporalLayers =
3683         kDefaultNumberOfTemporalLayers;
3684
3685     // Turn off the VP8 error resilience
3686     target_codec.codecSpecific.VP8.resilience = webrtc::kResilienceOff;
3687
3688     bool enable_denoising =
3689         options_.video_noise_reduction.GetWithDefaultIfUnset(false);
3690     target_codec.codecSpecific.VP8.denoisingOn = enable_denoising;
3691   }
3692
3693   // Register external encoder if codec type is supported by encoder factory.
3694   if (engine()->IsExternalEncoderCodecType(codec.codecType) &&
3695       !send_channel->IsEncoderRegistered(target_codec.plType)) {
3696     webrtc::VideoEncoder* encoder =
3697         engine()->CreateExternalEncoder(codec.codecType);
3698     if (encoder) {
3699       if (engine()->vie()->ext_codec()->RegisterExternalSendCodec(
3700           channel_id, target_codec.plType, encoder, false) == 0) {
3701         send_channel->RegisterEncoder(target_codec.plType, encoder);
3702       } else {
3703         LOG_RTCERR2(RegisterExternalSendCodec, channel_id, target_codec.plName);
3704         engine()->DestroyExternalEncoder(encoder);
3705       }
3706     }
3707   }
3708
3709   // Resolution and framerate may vary for different send channels.
3710   const VideoFormat& video_format = send_channel->video_format();
3711   UpdateVideoCodec(video_format, &target_codec);
3712
3713   if (target_codec.width == 0 && target_codec.height == 0) {
3714     const uint32 ssrc = send_channel->stream_params()->first_ssrc();
3715     LOG(LS_INFO) << "0x0 resolution selected. Captured frames will be dropped "
3716                  << "for ssrc: " << ssrc << ".";
3717   } else {
3718     MaybeChangeBitrates(channel_id, &target_codec);
3719     webrtc::VideoCodec current_codec;
3720     if (!engine()->vie()->codec()->GetSendCodec(channel_id, current_codec)) {
3721       // Compare against existing configured send codec.
3722       if (current_codec == target_codec) {
3723         // Codec is already configured on channel. no need to apply.
3724         return true;
3725       }
3726     }
3727
3728     if (0 != engine()->vie()->codec()->SetSendCodec(channel_id, target_codec)) {
3729       LOG_RTCERR2(SetSendCodec, channel_id, target_codec.plName);
3730       return false;
3731     }
3732
3733     // NOTE: SetRtxSendPayloadType must be called after all simulcast SSRCs
3734     // are configured. Otherwise ssrc's configured after this point will use
3735     // the primary PT for RTX.
3736     if (send_rtx_type_ != -1 &&
3737         engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id,
3738                                                       send_rtx_type_) != 0) {
3739         LOG_RTCERR2(SetRtxSendPayloadType, channel_id, send_rtx_type_);
3740         return false;
3741     }
3742   }
3743   send_channel->set_interval(
3744       cricket::VideoFormat::FpsToInterval(target_codec.maxFramerate));
3745   return true;
3746 }
3747
3748
3749 static std::string ToString(webrtc::VideoCodecComplexity complexity) {
3750   switch (complexity) {
3751     case webrtc::kComplexityNormal:
3752       return "normal";
3753     case webrtc::kComplexityHigh:
3754       return "high";
3755     case webrtc::kComplexityHigher:
3756       return "higher";
3757     case webrtc::kComplexityMax:
3758       return "max";
3759     default:
3760       return "unknown";
3761   }
3762 }
3763
3764 static std::string ToString(webrtc::VP8ResilienceMode resilience) {
3765   switch (resilience) {
3766     case webrtc::kResilienceOff:
3767       return "off";
3768     case webrtc::kResilientStream:
3769       return "stream";
3770     case webrtc::kResilientFrames:
3771       return "frames";
3772     default:
3773       return "unknown";
3774   }
3775 }
3776
3777 void WebRtcVideoMediaChannel::LogSendCodecChange(const std::string& reason) {
3778   webrtc::VideoCodec vie_codec;
3779   if (engine()->vie()->codec()->GetSendCodec(vie_channel_, vie_codec) != 0) {
3780     LOG_RTCERR1(GetSendCodec, vie_channel_);
3781     return;
3782   }
3783
3784   LOG(LS_INFO) << reason << " : selected video codec "
3785                << vie_codec.plName << "/"
3786                << vie_codec.width << "x" << vie_codec.height << "x"
3787                << static_cast<int>(vie_codec.maxFramerate) << "fps"
3788                << "@" << vie_codec.maxBitrate << "kbps"
3789                << " (min=" << vie_codec.minBitrate << "kbps,"
3790                << " start=" << vie_codec.startBitrate << "kbps)";
3791   LOG(LS_INFO) << "Video max quantization: " << vie_codec.qpMax;
3792   if (webrtc::kVideoCodecVP8 == vie_codec.codecType) {
3793     LOG(LS_INFO) << "VP8 number of temporal layers: "
3794                  << static_cast<int>(
3795                      vie_codec.codecSpecific.VP8.numberOfTemporalLayers);
3796     LOG(LS_INFO) << "VP8 options : "
3797                  << "picture loss indication = "
3798                  << vie_codec.codecSpecific.VP8.pictureLossIndicationOn
3799                  << ", feedback mode = "
3800                  << vie_codec.codecSpecific.VP8.feedbackModeOn
3801                  << ", complexity = "
3802                  << ToString(vie_codec.codecSpecific.VP8.complexity)
3803                  << ", resilience = "
3804                  << ToString(vie_codec.codecSpecific.VP8.resilience)
3805                  << ", denoising = "
3806                  << vie_codec.codecSpecific.VP8.denoisingOn
3807                  << ", error concealment = "
3808                  << vie_codec.codecSpecific.VP8.errorConcealmentOn
3809                  << ", automatic resize = "
3810                  << vie_codec.codecSpecific.VP8.automaticResizeOn
3811                  << ", frame dropping = "
3812                  << vie_codec.codecSpecific.VP8.frameDroppingOn
3813                  << ", key frame interval = "
3814                  << vie_codec.codecSpecific.VP8.keyFrameInterval;
3815   }
3816
3817   if (send_rtx_type_ != -1) {
3818     LOG(LS_INFO) << "RTX payload type: " << send_rtx_type_;
3819   }
3820 }
3821
3822 bool WebRtcVideoMediaChannel::SetReceiveCodecs(
3823     WebRtcVideoChannelRecvInfo* info) {
3824   int red_type = -1;
3825   int fec_type = -1;
3826   int channel_id = info->channel_id();
3827   // Build a map from payload types to video codecs so that we easily can find
3828   // out if associated payload types are referring to valid codecs.
3829   std::map<int, webrtc::VideoCodec*> pt_to_codec;
3830   for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
3831        it != receive_codecs_.end(); ++it) {
3832     pt_to_codec[it->plType] = &(*it);
3833   }
3834   for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
3835        it != receive_codecs_.end(); ++it) {
3836     if (it->codecType == webrtc::kVideoCodecRED) {
3837       red_type = it->plType;
3838     } else if (it->codecType == webrtc::kVideoCodecULPFEC) {
3839       fec_type = it->plType;
3840     }
3841     // If this is an RTX codec we have to verify that it is associated with
3842     // a valid video codec which we have RTX support for.
3843     if (_stricmp(it->plName, kRtxCodecName) == 0) {
3844       std::map<int, int>::iterator apt_it = associated_payload_types_.find(
3845           it->plType);
3846       bool valid_apt = false;
3847       if (apt_it != associated_payload_types_.end()) {
3848         std::map<int, webrtc::VideoCodec*>::iterator codec_it =
3849             pt_to_codec.find(apt_it->second);
3850         // We currently only support RTX associated with VP8 due to limitations
3851         // in webrtc where only one RTX payload type can be registered.
3852         valid_apt = codec_it != pt_to_codec.end() &&
3853             _stricmp(codec_it->second->plName, kVp8PayloadName) == 0;
3854       }
3855       if (!valid_apt) {
3856         LOG(LS_ERROR) << "The RTX codec isn't associated with a known and "
3857                          "supported payload type";
3858         return false;
3859       }
3860       if (engine()->vie()->rtp()->SetRtxReceivePayloadType(
3861           channel_id, it->plType) != 0) {
3862         LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, it->plType);
3863         return false;
3864       }
3865       continue;
3866     }
3867     if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) {
3868       LOG_RTCERR2(SetReceiveCodec, channel_id, it->plName);
3869       return false;
3870     }
3871     if (!info->IsDecoderRegistered(it->plType) &&
3872         it->codecType != webrtc::kVideoCodecRED &&
3873         it->codecType != webrtc::kVideoCodecULPFEC) {
3874       webrtc::VideoDecoder* decoder =
3875           engine()->CreateExternalDecoder(it->codecType);
3876       if (decoder) {
3877         if (engine()->vie()->ext_codec()->RegisterExternalReceiveCodec(
3878             channel_id, it->plType, decoder) == 0) {
3879           info->RegisterDecoder(it->plType, decoder);
3880         } else {
3881           LOG_RTCERR2(RegisterExternalReceiveCodec, channel_id, it->plName);
3882           engine()->DestroyExternalDecoder(decoder);
3883         }
3884       }
3885     }
3886   }
3887   return true;
3888 }
3889
3890 int WebRtcVideoMediaChannel::GetRecvChannelNum(uint32 ssrc) {
3891   if (ssrc == first_receive_ssrc_) {
3892     return vie_channel_;
3893   }
3894   int recv_channel = -1;
3895   RecvChannelMap::iterator it = recv_channels_.find(ssrc);
3896   if (it == recv_channels_.end()) {
3897     // Check if we have an RTX stream registered on this SSRC.
3898     SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.find(ssrc);
3899     if (rtx_it != rtx_to_primary_ssrc_.end()) {
3900       it = recv_channels_.find(rtx_it->second);
3901       assert(it != recv_channels_.end());
3902       recv_channel = it->second->channel_id();
3903     }
3904   } else {
3905     recv_channel = it->second->channel_id();
3906   }
3907   return recv_channel;
3908 }
3909
3910 // If the new frame size is different from the send codec size we set on vie,
3911 // we need to reset the send codec on vie.
3912 // The new send codec size should not exceed send_codec_ which is controlled
3913 // only by the 'jec' logic.
3914 // TODO(pthatcher): Get rid of this function, so we only ever set up
3915 // codecs in a single place.
3916 bool WebRtcVideoMediaChannel::MaybeResetVieSendCodec(
3917     WebRtcVideoChannelSendInfo* send_channel,
3918     int new_width,
3919     int new_height,
3920     bool is_screencast,
3921     bool* reset) {
3922   if (reset) {
3923     *reset = false;
3924   }
3925   ASSERT(send_codec_.get() != NULL);
3926
3927   webrtc::VideoCodec target_codec = *send_codec_;
3928   const VideoFormat& video_format = send_channel->video_format();
3929   UpdateVideoCodec(video_format, &target_codec);
3930
3931   // Vie send codec size should not exceed target_codec.
3932   int target_width = new_width;
3933   int target_height = new_height;
3934   if (!is_screencast &&
3935       (new_width > target_codec.width || new_height > target_codec.height)) {
3936     target_width = target_codec.width;
3937     target_height = target_codec.height;
3938   }
3939
3940   // Get current vie codec.
3941   webrtc::VideoCodec vie_codec;
3942   const int channel_id = send_channel->channel_id();
3943   if (engine()->vie()->codec()->GetSendCodec(channel_id, vie_codec) != 0) {
3944     LOG_RTCERR1(GetSendCodec, channel_id);
3945     return false;
3946   }
3947   const int cur_width = vie_codec.width;
3948   const int cur_height = vie_codec.height;
3949
3950   // Only reset send codec when there is a size change. Additionally,
3951   // automatic resize needs to be turned off when screencasting and on when
3952   // not screencasting.
3953   // Don't allow automatic resizing for screencasting.
3954   bool automatic_resize = !is_screencast;
3955   // Turn off VP8 frame dropping when screensharing as the current model does
3956   // not work well at low fps.
3957   bool vp8_frame_dropping = !is_screencast;
3958   // Disable denoising for screencasting.
3959   bool enable_denoising =
3960       options_.video_noise_reduction.GetWithDefaultIfUnset(false);
3961   int screencast_min_bitrate =
3962       options_.screencast_min_bitrate.GetWithDefaultIfUnset(0);
3963   bool leaky_bucket = options_.video_leaky_bucket.GetWithDefaultIfUnset(false);
3964   bool denoising = !is_screencast && enable_denoising;
3965   bool reset_send_codec =
3966       target_width != cur_width || target_height != cur_height ||
3967       automatic_resize != vie_codec.codecSpecific.VP8.automaticResizeOn ||
3968       denoising != vie_codec.codecSpecific.VP8.denoisingOn ||
3969       vp8_frame_dropping != vie_codec.codecSpecific.VP8.frameDroppingOn;
3970
3971   if (reset_send_codec) {
3972     // Set the new codec on vie.
3973     vie_codec.width = target_width;
3974     vie_codec.height = target_height;
3975     vie_codec.maxFramerate = target_codec.maxFramerate;
3976     vie_codec.startBitrate = target_codec.startBitrate;
3977     vie_codec.minBitrate = target_codec.minBitrate;
3978     vie_codec.maxBitrate = target_codec.maxBitrate;
3979     vie_codec.targetBitrate = 0;
3980     vie_codec.codecSpecific.VP8.automaticResizeOn = automatic_resize;
3981     vie_codec.codecSpecific.VP8.denoisingOn = denoising;
3982     vie_codec.codecSpecific.VP8.frameDroppingOn = vp8_frame_dropping;
3983     MaybeChangeBitrates(channel_id, &vie_codec);
3984
3985     if (engine()->vie()->codec()->SetSendCodec(channel_id, vie_codec) != 0) {
3986       LOG_RTCERR1(SetSendCodec, channel_id);
3987       return false;
3988     }
3989
3990     if (is_screencast) {
3991       engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id,
3992                                                     screencast_min_bitrate);
3993       // If screencast and min bitrate set, force enable pacer.
3994       if (screencast_min_bitrate > 0) {
3995         engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id,
3996                                                                true);
3997       }
3998     } else {
3999       // In case of switching from screencast to regular capture, set
4000       // min bitrate padding and pacer back to defaults.
4001       engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id, 0);
4002       engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id,
4003                                                              leaky_bucket);
4004     }
4005     if (reset) {
4006       *reset = true;
4007     }
4008     LogSendCodecChange("Capture size changed");
4009   }
4010
4011   return true;
4012 }
4013
4014 void WebRtcVideoMediaChannel::MaybeChangeBitrates(
4015   int channel_id, webrtc::VideoCodec* codec) {
4016   codec->minBitrate = GetBitrate(codec->minBitrate, kMinVideoBitrate);
4017   codec->startBitrate = GetBitrate(codec->startBitrate, kStartVideoBitrate);
4018   codec->maxBitrate = GetBitrate(codec->maxBitrate, kMaxVideoBitrate);
4019
4020   if (codec->minBitrate > codec->maxBitrate) {
4021     LOG(LS_INFO) << "Decreasing codec min bitrate to the max ("
4022                  << codec->maxBitrate << ") because the min ("
4023                  << codec->minBitrate << ") exceeds the max.";
4024     codec->minBitrate = codec->maxBitrate;
4025   }
4026   if (codec->startBitrate < codec->minBitrate) {
4027     LOG(LS_INFO) << "Increasing codec start bitrate to the min ("
4028                  << codec->minBitrate << ") because the start ("
4029                  << codec->startBitrate << ") is less than the min.";
4030     codec->startBitrate = codec->minBitrate;
4031   } else if (codec->startBitrate > codec->maxBitrate) {
4032     LOG(LS_INFO) << "Decreasing codec start bitrate to the max ("
4033                  << codec->maxBitrate << ") because the start ("
4034                  << codec->startBitrate << ") exceeds the max.";
4035     codec->startBitrate = codec->maxBitrate;
4036   }
4037
4038   // Use a previous target bitrate, if there is one.
4039   unsigned int current_target_bitrate = 0;
4040   if (engine()->vie()->codec()->GetCodecTargetBitrate(
4041       channel_id, &current_target_bitrate) == 0) {
4042     // Convert to kbps.
4043     current_target_bitrate /= 1000;
4044     if (current_target_bitrate > codec->maxBitrate) {
4045       current_target_bitrate = codec->maxBitrate;
4046     }
4047     if (current_target_bitrate > codec->startBitrate) {
4048       codec->startBitrate = current_target_bitrate;
4049     }
4050   }
4051 }
4052
4053 void WebRtcVideoMediaChannel::OnMessage(talk_base::Message* msg) {
4054   FlushBlackFrameData* black_frame_data =
4055       static_cast<FlushBlackFrameData*>(msg->pdata);
4056   FlushBlackFrame(black_frame_data->ssrc, black_frame_data->timestamp);
4057   delete black_frame_data;
4058 }
4059
4060 int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data,
4061                                         int len) {
4062   talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
4063   return MediaChannel::SendPacket(&packet) ? len : -1;
4064 }
4065
4066 int WebRtcVideoMediaChannel::SendRTCPPacket(int channel,
4067                                             const void* data,
4068                                             int len) {
4069   talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
4070   return MediaChannel::SendRtcp(&packet) ? len : -1;
4071 }
4072
4073 void WebRtcVideoMediaChannel::QueueBlackFrame(uint32 ssrc, int64 timestamp,
4074                                               int framerate) {
4075   if (timestamp) {
4076     FlushBlackFrameData* black_frame_data = new FlushBlackFrameData(
4077         ssrc,
4078         timestamp);
4079     const int delay_ms = static_cast<int>(
4080         2 * cricket::VideoFormat::FpsToInterval(framerate) *
4081         talk_base::kNumMillisecsPerSec / talk_base::kNumNanosecsPerSec);
4082     worker_thread()->PostDelayed(delay_ms, this, 0, black_frame_data);
4083   }
4084 }
4085
4086 void WebRtcVideoMediaChannel::FlushBlackFrame(uint32 ssrc, int64 timestamp) {
4087   WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
4088   if (!send_channel) {
4089     return;
4090   }
4091   talk_base::scoped_ptr<const VideoFrame> black_frame_ptr;
4092
4093   const WebRtcLocalStreamInfo* channel_stream_info =
4094       send_channel->local_stream_info();
4095   int64 last_frame_time_stamp = channel_stream_info->time_stamp();
4096   if (last_frame_time_stamp == timestamp) {
4097     size_t last_frame_width = 0;
4098     size_t last_frame_height = 0;
4099     int64 last_frame_elapsed_time = 0;
4100     channel_stream_info->GetLastFrameInfo(&last_frame_width, &last_frame_height,
4101                                           &last_frame_elapsed_time);
4102     if (!last_frame_width || !last_frame_height) {
4103       return;
4104     }
4105     WebRtcVideoFrame black_frame;
4106     // Black frame is not screencast.
4107     const bool screencasting = false;
4108     const int64 timestamp_delta = send_channel->interval();
4109     if (!black_frame.InitToBlack(send_codec_->width, send_codec_->height, 1, 1,
4110                                  last_frame_elapsed_time + timestamp_delta,
4111                                  last_frame_time_stamp + timestamp_delta) ||
4112         !SendFrame(send_channel, &black_frame, screencasting)) {
4113       LOG(LS_ERROR) << "Failed to send black frame.";
4114     }
4115   }
4116 }
4117
4118 void WebRtcVideoMediaChannel::OnCpuAdaptationUnable() {
4119   // ssrc is hardcoded to 0.  This message is based on a system wide issue,
4120   // so finding which ssrc caused it doesn't matter.
4121   SignalMediaError(0, VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE);
4122 }
4123
4124 void WebRtcVideoMediaChannel::SetNetworkTransmissionState(
4125     bool is_transmitting) {
4126   LOG(LS_INFO) << "SetNetworkTransmissionState: " << is_transmitting;
4127   for (SendChannelMap::iterator iter = send_channels_.begin();
4128        iter != send_channels_.end(); ++iter) {
4129     WebRtcVideoChannelSendInfo* send_channel = iter->second;
4130     int channel_id = send_channel->channel_id();
4131     engine_->vie()->network()->SetNetworkTransmissionState(channel_id,
4132                                                            is_transmitting);
4133   }
4134 }
4135
4136 bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
4137     int channel_id, const RtpHeaderExtension* extension) {
4138   bool enable = false;
4139   int id = 0;
4140   if (extension) {
4141     enable = true;
4142     id = extension->id;
4143   }
4144   if ((engine_->vie()->rtp()->*setter)(channel_id, enable, id) != 0) {
4145     LOG_RTCERR4(*setter, extension->uri, channel_id, enable, id);
4146     return false;
4147   }
4148   return true;
4149 }
4150
4151 bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
4152     int channel_id, const std::vector<RtpHeaderExtension>& extensions,
4153     const char header_extension_uri[]) {
4154   const RtpHeaderExtension* extension = FindHeaderExtension(extensions,
4155       header_extension_uri);
4156   return SetHeaderExtension(setter, channel_id, extension);
4157 }
4158
4159 bool WebRtcVideoMediaChannel::SetLocalRtxSsrc(int channel_id,
4160                                               const StreamParams& send_params,
4161                                               uint32 primary_ssrc,
4162                                               int stream_idx) {
4163   uint32 rtx_ssrc = 0;
4164   bool has_rtx = send_params.GetFidSsrc(primary_ssrc, &rtx_ssrc);
4165   if (has_rtx && engine()->vie()->rtp()->SetLocalSSRC(
4166       channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, stream_idx) != 0) {
4167     LOG_RTCERR4(SetLocalSSRC, channel_id, rtx_ssrc,
4168                 webrtc::kViEStreamTypeRtx, stream_idx);
4169     return false;
4170   }
4171   return true;
4172 }
4173
4174 void WebRtcVideoMediaChannel::MaybeConnectCapturer(VideoCapturer* capturer) {
4175   if (capturer != NULL && GetSendChannelNum(capturer) == 1) {
4176     capturer->SignalVideoFrame.connect(this,
4177                                        &WebRtcVideoMediaChannel::SendFrame);
4178   }
4179 }
4180
4181 void WebRtcVideoMediaChannel::MaybeDisconnectCapturer(VideoCapturer* capturer) {
4182   if (capturer != NULL && GetSendChannelNum(capturer) == 1) {
4183     capturer->SignalVideoFrame.disconnect(this);
4184   }
4185 }
4186
4187 }  // namespace cricket
4188
4189 #endif  // HAVE_WEBRTC_VIDEO