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