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