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