| Index: third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc | 
| =================================================================== | 
| --- third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc	(revision 118180) | 
| +++ third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc	(working copy) | 
| @@ -1,1619 +0,0 @@ | 
| -/* | 
| - * libjingle | 
| - * Copyright 2004--2011, Google Inc. | 
| - * | 
| - * Redistribution and use in source and binary forms, with or without | 
| - * modification, are permitted provided that the following conditions are met: | 
| - * | 
| - *  1. Redistributions of source code must retain the above copyright notice, | 
| - *     this list of conditions and the following disclaimer. | 
| - *  2. Redistributions in binary form must reproduce the above copyright notice, | 
| - *     this list of conditions and the following disclaimer in the documentation | 
| - *     and/or other materials provided with the distribution. | 
| - *  3. The name of the author may not be used to endorse or promote products | 
| - *     derived from this software without specific prior written permission. | 
| - * | 
| - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | 
| - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 
| - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 
| - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
| - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
| - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 
| - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 
| - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 
| - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 
| - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| - */ | 
| - | 
| -#ifdef HAVE_CONFIG_H | 
| -#include <config.h> | 
| -#endif | 
| - | 
| -#ifdef HAVE_WEBRTC_VIDEO | 
| - | 
| -#include "talk/session/phone/webrtcvideoengine.h" | 
| - | 
| -#include "talk/base/basictypes.h" | 
| -#include "talk/base/common.h" | 
| -#include "talk/base/buffer.h" | 
| -#include "talk/base/byteorder.h" | 
| -#include "talk/base/logging.h" | 
| -#include "talk/base/stringutils.h" | 
| -#include "talk/session/phone/videorenderer.h" | 
| -#include "talk/session/phone/webrtcpassthroughrender.h" | 
| -#include "talk/session/phone/webrtcvoiceengine.h" | 
| -#include "talk/session/phone/webrtcvideocapturer.h" | 
| -#include "talk/session/phone/webrtcvideoframe.h" | 
| -#include "talk/session/phone/webrtcvie.h" | 
| -#include "talk/session/phone/webrtcvoe.h" | 
| - | 
| -// TODO Change video protection calls when WebRTC API has changed. | 
| -#define WEBRTC_VIDEO_AVPF_NACK_ONLY | 
| - | 
| -namespace cricket { | 
| - | 
| -static const int kDefaultLogSeverity = talk_base::LS_WARNING; | 
| - | 
| -static const int kMinVideoBitrate = 100; | 
| -static const int kStartVideoBitrate = 300; | 
| -static const int kMaxVideoBitrate = 2000; | 
| - | 
| -static const int kVideoMtu = 1200; | 
| - | 
| -static const int kVideoRtpBufferSize = 65536; | 
| - | 
| -static const char kVp8PayloadName[] = "VP8"; | 
| -static const char kRedPayloadName[] = "red"; | 
| -static const char kFecPayloadName[] = "ulpfec"; | 
| - | 
| -static const int kDefaultNumberOfTemporalLayers = 3; | 
| - | 
| -static void LogMultiline(talk_base::LoggingSeverity sev, char* text) { | 
| -  const char* delim = "\r\n"; | 
| -  for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { | 
| -    LOG_V(sev) << tok; | 
| -  } | 
| -} | 
| - | 
| -class WebRtcRenderAdapter : public webrtc::ExternalRenderer { | 
| - public: | 
| -  explicit WebRtcRenderAdapter(VideoRenderer* renderer) | 
| -      : renderer_(renderer), width_(0), height_(0) { | 
| -  } | 
| -  virtual ~WebRtcRenderAdapter() { | 
| -  } | 
| - | 
| -  void SetRenderer(VideoRenderer* renderer) { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    renderer_ = renderer; | 
| -  } | 
| -  // Implementation of webrtc::ExternalRenderer. | 
| -  virtual int FrameSizeChange(unsigned int width, unsigned int height, | 
| -                              unsigned int /*number_of_streams*/) { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    if (renderer_ == NULL) { | 
| -      return 0; | 
| -    } | 
| -    width_ = width; | 
| -    height_ = height; | 
| -    return renderer_->SetSize(width_, height_, 0) ? 0 : -1; | 
| -  } | 
| -  virtual int DeliverFrame(unsigned char* buffer, int buffer_size, | 
| -                           unsigned int time_stamp) { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    frame_rate_tracker_.Update(1); | 
| -    if (renderer_ == NULL) { | 
| -      return 0; | 
| -    } | 
| -    WebRtcVideoFrame video_frame; | 
| -    video_frame.Attach(buffer, buffer_size, width_, height_, | 
| -                       1, 1, 0, time_stamp, 0); | 
| - | 
| -    int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1; | 
| -    uint8* buffer_temp; | 
| -    size_t buffer_size_temp; | 
| -    video_frame.Detach(&buffer_temp, &buffer_size_temp); | 
| -    return ret; | 
| -  } | 
| - | 
| -  unsigned int width() { | 
| -   talk_base::CritScope cs(&crit_); | 
| -   return width_; | 
| -  } | 
| -  unsigned int height() { | 
| -   talk_base::CritScope cs(&crit_); | 
| -   return height_; | 
| -  } | 
| -  int framerate() { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    return frame_rate_tracker_.units_second(); | 
| -  } | 
| - | 
| - private: | 
| -  talk_base::CriticalSection crit_; | 
| -  VideoRenderer* renderer_; | 
| -  unsigned int width_; | 
| -  unsigned int height_; | 
| -  talk_base::RateTracker frame_rate_tracker_; | 
| -}; | 
| - | 
| -class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver { | 
| - public: | 
| -  WebRtcDecoderObserver(int video_channel) | 
| -       : video_channel_(video_channel), | 
| -         framerate_(0), | 
| -         bitrate_(0), | 
| -         firs_requested_(0) { } | 
| - | 
| -  // virtual functions from VieDecoderObserver. | 
| -  virtual void IncomingCodecChanged(const int videoChannel, | 
| -                                    const webrtc::VideoCodec& videoCodec) { } | 
| -  virtual void IncomingRate(const int videoChannel, | 
| -                            const unsigned int framerate, | 
| -                            const unsigned int bitrate) { | 
| -    ASSERT(video_channel_ == videoChannel); | 
| -    framerate_ = framerate; | 
| -    bitrate_ = bitrate; | 
| -  } | 
| -  virtual void RequestNewKeyFrame(const int videoChannel) { | 
| -    ASSERT(video_channel_ == videoChannel); | 
| -    ++firs_requested_; | 
| -  } | 
| - | 
| -  int framerate() const { return framerate_; } | 
| -  int bitrate() const { return bitrate_; } | 
| -  int firs_requested() const { return firs_requested_; } | 
| - | 
| - private: | 
| -  int video_channel_; | 
| -  int framerate_; | 
| -  int bitrate_; | 
| -  int firs_requested_; | 
| -}; | 
| - | 
| -class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver { | 
| - public: | 
| -  WebRtcEncoderObserver(int video_channel) | 
| -       : video_channel_(video_channel), framerate_(0), bitrate_(0) { } | 
| - | 
| -  // virtual functions from VieEncoderObserver. | 
| -  virtual void OutgoingRate(const int videoChannel, | 
| -                            const unsigned int framerate, | 
| -                            const unsigned int bitrate) { | 
| -    ASSERT(video_channel_ == videoChannel); | 
| -    framerate_ = framerate; | 
| -    bitrate_ = bitrate; | 
| -  } | 
| - | 
| -  int framerate() const { return framerate_; } | 
| -  int bitrate() const { return bitrate_; } | 
| - | 
| - private: | 
| -  int video_channel_; | 
| -  int framerate_; | 
| -  int bitrate_; | 
| -}; | 
| - | 
| -class LocalStreamInfo { | 
| - public: | 
| -  int width() { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    return width_; | 
| -  } | 
| -  int height() { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    return height_; | 
| -  } | 
| -  int framerate() { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    return rate_tracker_.units_second(); | 
| -  } | 
| - | 
| -  void UpdateFrame(int width, int height) { | 
| -    talk_base::CritScope cs(&crit_); | 
| -    width_ = width; | 
| -    height_ = height; | 
| -    rate_tracker_.Update(1); | 
| -  } | 
| - | 
| - private: | 
| -  talk_base::CriticalSection crit_; | 
| -  unsigned int width_; | 
| -  unsigned int height_; | 
| -  talk_base::RateTracker rate_tracker_; | 
| -}; | 
| - | 
| -const WebRtcVideoEngine::VideoCodecPref | 
| -    WebRtcVideoEngine::kVideoCodecPrefs[] = { | 
| -    {kVp8PayloadName, 100, 0}, | 
| -#ifndef WEBRTC_VIDEO_AVPF_NACK_ONLY | 
| -    {kRedPayloadName, 101, 1}, | 
| -    {kFecPayloadName, 102, 2}, | 
| -#endif | 
| -}; | 
| - | 
| -// The formats are sorted by the descending order of width. We use the order to | 
| -// find the next format for CPU and bandwidth adaptation. | 
| -const VideoFormatPod WebRtcVideoEngine::kVideoFormats[] = { | 
| -  {1280, 800, 30, FOURCC_ANY}, | 
| -  {1280, 720, 30, FOURCC_ANY}, | 
| -  {960, 600, 30, FOURCC_ANY}, | 
| -  {960, 540, 30, FOURCC_ANY}, | 
| -  {640, 400, 30, FOURCC_ANY}, | 
| -  {640, 360, 30, FOURCC_ANY}, | 
| -  {640, 480, 30, FOURCC_ANY}, | 
| -  {480, 300, 30, FOURCC_ANY}, | 
| -  {480, 270, 30, FOURCC_ANY}, | 
| -  {480, 360, 30, FOURCC_ANY}, | 
| -  {320, 200, 30, FOURCC_ANY}, | 
| -  {320, 180, 30, FOURCC_ANY}, | 
| -  {320, 240, 30, FOURCC_ANY}, | 
| -  {240, 150, 30, FOURCC_ANY}, | 
| -  {240, 135, 30, FOURCC_ANY}, | 
| -  {240, 180, 30, FOURCC_ANY}, | 
| -  {160, 100, 30, FOURCC_ANY}, | 
| -  {160, 90, 30, FOURCC_ANY}, | 
| -  {160, 120, 30, FOURCC_ANY}, | 
| -}; | 
| - | 
| -const VideoFormatPod WebRtcVideoEngine::kDefaultVideoFormat = | 
| -    {640, 400, 30, FOURCC_ANY}; | 
| - | 
| -WebRtcVideoEngine::WebRtcVideoEngine() { | 
| -  Construct(new ViEWrapper(), new ViETraceWrapper(), NULL); | 
| -} | 
| - | 
| -WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, | 
| -                                     ViEWrapper* vie_wrapper) { | 
| -  Construct(vie_wrapper, new ViETraceWrapper(), voice_engine); | 
| -} | 
| - | 
| -WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, | 
| -                                     ViEWrapper* vie_wrapper, | 
| -                                     ViETraceWrapper* tracing) { | 
| -  Construct(vie_wrapper, tracing, voice_engine); | 
| -} | 
| - | 
| -void WebRtcVideoEngine::Construct(ViEWrapper* vie_wrapper, | 
| -                                  ViETraceWrapper* tracing, | 
| -                                  WebRtcVoiceEngine* voice_engine) { | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine"; | 
| -  vie_wrapper_.reset(vie_wrapper); | 
| -  vie_wrapper_base_initialized_ = false; | 
| -  tracing_.reset(tracing); | 
| -  voice_engine_ = voice_engine; | 
| -  initialized_ = false; | 
| -  log_level_ = kDefaultLogSeverity; | 
| -  render_module_.reset(new WebRtcPassthroughRender()); | 
| -  local_renderer_w_ = local_renderer_h_ = 0; | 
| -  local_renderer_ = NULL; | 
| -  owns_capturer_ = false; | 
| -  video_capturer_ = NULL; | 
| -  capture_started_ = false; | 
| - | 
| -  ApplyLogging(); | 
| -  if (tracing_->SetTraceCallback(this) != 0) { | 
| -    LOG_RTCERR1(SetTraceCallback, this); | 
| -  } | 
| - | 
| -  // Set default quality levels for our supported codecs. We override them here | 
| -  // if we know your cpu performance is low, and they can be updated explicitly | 
| -  // by calling SetDefaultCodec.  For example by a flute preference setting, or | 
| -  // by the server with a jec in response to our reported system info. | 
| -  VideoCodec max_codec(kVideoCodecPrefs[0].payload_type, | 
| -                       kVideoCodecPrefs[0].name, | 
| -                       kDefaultVideoFormat.width, | 
| -                       kDefaultVideoFormat.height, | 
| -                       kDefaultVideoFormat.framerate, | 
| -                       0); | 
| -  if (!SetDefaultCodec(max_codec)) { | 
| -    LOG(LS_ERROR) << "Failed to initialize list of supported codec types"; | 
| -  } | 
| -} | 
| - | 
| -WebRtcVideoEngine::~WebRtcVideoEngine() { | 
| -  ClearCapturer(); | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::~WebRtcVideoEngine"; | 
| -  if (initialized_) { | 
| -    Terminate(); | 
| -  } | 
| -  tracing_->SetTraceCallback(NULL); | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::Init() { | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::Init"; | 
| -  bool result = InitVideoEngine(); | 
| -  if (result) { | 
| -    LOG(LS_INFO) << "VideoEngine Init done"; | 
| -  } else { | 
| -    LOG(LS_ERROR) << "VideoEngine Init failed, releasing"; | 
| -    Terminate(); | 
| -  } | 
| -  return result; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::InitVideoEngine() { | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine"; | 
| - | 
| -  // Init WebRTC VideoEngine. | 
| -  if (!vie_wrapper_base_initialized_) { | 
| -    if (vie_wrapper_->base()->Init() != 0) { | 
| -      LOG_RTCERR0(Init); | 
| -      return false; | 
| -    } | 
| -    vie_wrapper_base_initialized_ = true; | 
| -  } | 
| - | 
| -  // Log the VoiceEngine version info. | 
| -  char buffer[1024] = ""; | 
| -  if (vie_wrapper_->base()->GetVersion(buffer) != 0) { | 
| -    LOG_RTCERR0(GetVersion); | 
| -    return false; | 
| -  } | 
| - | 
| -  LOG(LS_INFO) << "WebRtc VideoEngine Version:"; | 
| -  LogMultiline(talk_base::LS_INFO, buffer); | 
| - | 
| -  // Hook up to VoiceEngine for sync purposes, if supplied. | 
| -  if (!voice_engine_) { | 
| -    LOG(LS_WARNING) << "NULL voice engine"; | 
| -  } else if ((vie_wrapper_->base()->SetVoiceEngine( | 
| -      voice_engine_->voe()->engine())) != 0) { | 
| -    LOG_RTCERR0(SetVoiceEngine); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Register for callbacks from the engine. | 
| -  if ((vie_wrapper_->base()->RegisterObserver(*this)) != 0) { | 
| -    LOG_RTCERR0(RegisterObserver); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Register our custom render module. | 
| -  if (vie_wrapper_->render()->RegisterVideoRenderModule( | 
| -      *render_module_.get()) != 0) { | 
| -    LOG_RTCERR0(RegisterVideoRenderModule); | 
| -    return false; | 
| -  } | 
| - | 
| -  initialized_ = true; | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::Terminate() { | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::Terminate"; | 
| -  initialized_ = false; | 
| -  SetCapture(false); | 
| - | 
| -  if (vie_wrapper_->render()->DeRegisterVideoRenderModule( | 
| -      *render_module_.get()) != 0) { | 
| -    LOG_RTCERR0(DeRegisterVideoRenderModule); | 
| -  } | 
| - | 
| -  if (vie_wrapper_->base()->DeregisterObserver() != 0) { | 
| -    LOG_RTCERR0(DeregisterObserver); | 
| -  } | 
| - | 
| -  if (vie_wrapper_->base()->SetVoiceEngine(NULL) != 0) { | 
| -    LOG_RTCERR0(SetVoiceEngine); | 
| -  } | 
| -} | 
| - | 
| -int WebRtcVideoEngine::GetCapabilities() { | 
| -  return VIDEO_RECV | VIDEO_SEND; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetOptions(int options) { | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetDefaultEncoderConfig( | 
| -    const VideoEncoderConfig& config) { | 
| -  return SetDefaultCodec(config.max_codec); | 
| -} | 
| - | 
| -// SetDefaultCodec may be called while the capturer is running. For example, a | 
| -// test call is started in a page with QVGA default codec, and then a real call | 
| -// is started in another page with VGA default codec. This is the corner case | 
| -// and happens only when a session is started. We ignore this case currently. | 
| -bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) { | 
| -  if (!RebuildCodecList(codec)) { | 
| -    LOG(LS_WARNING) << "Failed to RebuildCodecList"; | 
| -    return false; | 
| -  } | 
| - | 
| -  default_codec_format_ = VideoFormat( | 
| -      video_codecs_[0].width, | 
| -      video_codecs_[0].height, | 
| -      VideoFormat::FpsToInterval(video_codecs_[0].framerate), | 
| -      FOURCC_ANY); | 
| -  return true; | 
| -} | 
| - | 
| -WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel( | 
| -    VoiceMediaChannel* voice_channel) { | 
| -  WebRtcVideoMediaChannel* channel = | 
| -      new WebRtcVideoMediaChannel(this, voice_channel); | 
| -  if (!channel->Init()) { | 
| -    delete channel; | 
| -    channel = NULL; | 
| -  } | 
| -  return channel; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetCaptureDevice(const Device* device) { | 
| -  if (!device) { | 
| -    ClearCapturer(); | 
| -    LOG(LS_INFO) << "Camera set to NULL"; | 
| -    return true; | 
| -  } | 
| -  // No-op if the device hasn't changed. | 
| -  if ((video_capturer_ != NULL) && video_capturer_->GetId() == device->id) { | 
| -    return true; | 
| -  } | 
| -  // Create a new capturer for the specified device. | 
| -  VideoCapturer* capturer = CreateVideoCapturer(*device); | 
| -  if (!capturer) { | 
| -    LOG(LS_ERROR) << "Failed to create camera '" << device->name << "', id='" | 
| -                  << device->id << "'"; | 
| -    return false; | 
| -  } | 
| -  const bool owns_capturer = true; | 
| -  if (!SetCapturer(capturer, owns_capturer)) { | 
| -    return false; | 
| -  } | 
| -  LOG(LS_INFO) << "Camera set to '" << device->name << "', id='" | 
| -               << device->id << "'"; | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetCaptureModule(webrtc::VideoCaptureModule* vcm) { | 
| -  if (!vcm) { | 
| -    if ((video_capturer_ != NULL) && video_capturer_->IsRunning()) { | 
| -      LOG(LS_WARNING) << "Failed to set camera to NULL when is running."; | 
| -      return false; | 
| -    } else { | 
| -      ClearCapturer(); | 
| -      LOG(LS_INFO) << "Camera set to NULL"; | 
| -      return true; | 
| -    } | 
| -  } | 
| -  // Create a new capturer for the specified device. | 
| -  WebRtcVideoCapturer* capturer = new WebRtcVideoCapturer; | 
| -  if (!capturer->Init(vcm)) { | 
| -    LOG(LS_ERROR) << "Failed to create camera from VCM"; | 
| -    delete capturer; | 
| -    return false; | 
| -  } | 
| -  const bool owns_capturer = true; | 
| -  if (!SetCapturer(capturer, owns_capturer)) { | 
| -    return false; | 
| -  } | 
| -  LOG(LS_INFO) << "Camera created with VCM"; | 
| -  CaptureResult ret = SetCapture(true); | 
| -  if (ret != cricket::CR_SUCCESS && ret != cricket::CR_PENDING) { | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetVideoCapturer(VideoCapturer* capturer, | 
| -                                         uint32 /*ssrc*/) { | 
| -  const bool capture = (capturer != NULL); | 
| -  const bool owns_capturer = false; | 
| -  CaptureResult res = CR_FAILURE; | 
| -  if (capture) { | 
| -    // Register the capturer before starting to capture. | 
| -    if (!SetCapturer(capturer, owns_capturer)) { | 
| -      return false; | 
| -    } | 
| -    const bool kEnableCapture = true; | 
| -    res = SetCapture(kEnableCapture); | 
| -  } else { | 
| -    // Stop capturing before unregistering the capturer. | 
| -    const bool kDisableCapture = false; | 
| -    res = SetCapture(kDisableCapture); | 
| -    if (!SetCapturer(capturer, owns_capturer)) { | 
| -      return false; | 
| -    } | 
| -  } | 
| -  return (res == CR_SUCCESS) || (res == CR_PENDING); | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetLocalRenderer(VideoRenderer* renderer) { | 
| -  local_renderer_w_ = local_renderer_h_ = 0; | 
| -  local_renderer_ = renderer; | 
| -  return true; | 
| -} | 
| - | 
| -CaptureResult WebRtcVideoEngine::SetCapture(bool capture) { | 
| -  bool old_capture = capture_started_; | 
| -  capture_started_ = capture; | 
| -  CaptureResult res = UpdateCapturingState(); | 
| -  if (res != CR_SUCCESS && res != CR_PENDING) { | 
| -    capture_started_ = old_capture; | 
| -  } | 
| -  return res; | 
| -} | 
| - | 
| -VideoCapturer* WebRtcVideoEngine::CreateVideoCapturer(const Device& device) { | 
| -  WebRtcVideoCapturer* capturer = new WebRtcVideoCapturer; | 
| -  if (!capturer->Init(device)) { | 
| -    delete capturer; | 
| -    return NULL; | 
| -  } | 
| -  return capturer; | 
| -} | 
| - | 
| -CaptureResult WebRtcVideoEngine::UpdateCapturingState() { | 
| -  CaptureResult result = CR_SUCCESS; | 
| - | 
| -  bool capture = capture_started_; | 
| -  if (!IsCapturing() && capture) {  // Start capturing. | 
| -    if (video_capturer_ == NULL) { | 
| -      return CR_NO_DEVICE; | 
| -    } | 
| - | 
| -    VideoFormat capture_format; | 
| -    if (!video_capturer_->GetBestCaptureFormat(default_codec_format_, | 
| -                                               &capture_format)) { | 
| -      LOG(LS_WARNING) << "Unsupported format:" | 
| -                      << " width=" << default_codec_format_.width | 
| -                      << " height=" << default_codec_format_.height | 
| -                      << ". Supported formats are:"; | 
| -      const std::vector<VideoFormat>* formats = | 
| -          video_capturer_->GetSupportedFormats(); | 
| -      if (formats) { | 
| -        for (std::vector<VideoFormat>::const_iterator i = formats->begin(); | 
| -             i != formats->end(); ++i) { | 
| -          const VideoFormat& format = *i; | 
| -          LOG(LS_WARNING) << "  " << GetFourccName(format.fourcc) << ":" | 
| -                          << format.width << "x" << format.height << "x" | 
| -                          << format.framerate(); | 
| -        } | 
| -      } | 
| -      return CR_FAILURE; | 
| -    } | 
| - | 
| -    // Start the video capturer. | 
| -    result = video_capturer_->Start(capture_format); | 
| -    if (CR_SUCCESS != result && CR_PENDING != result) { | 
| -      LOG(LS_ERROR) << "Failed to start the video capturer"; | 
| -      return result; | 
| -    } | 
| -  } else if (IsCapturing() && !capture) {  // Stop capturing. | 
| -    video_capturer_->Stop(); | 
| -  } | 
| - | 
| -  return result; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::IsCapturing() const { | 
| -  return (video_capturer_ != NULL) && video_capturer_->IsRunning(); | 
| -} | 
| - | 
| -void WebRtcVideoEngine::OnFrameCaptured(VideoCapturer* capturer, | 
| -                                        const CapturedFrame* frame) { | 
| -  // Force 16:10 for now. We'll be smarter with the capture refactor. | 
| -  int cropped_height = frame->width * default_codec_format_.height | 
| -      / default_codec_format_.width; | 
| -  if (cropped_height > frame->height) { | 
| -    // TODO: Once we support horizontal cropping, add cropped_width. | 
| -    cropped_height = frame->height; | 
| -  } | 
| - | 
| -  // This CapturedFrame* will already be in I420. In the future, when | 
| -  // WebRtcVideoFrame has support for independent planes, we can just attach | 
| -  // to it and update the pointers when cropping. | 
| -  WebRtcVideoFrame i420_frame; | 
| -  if (!i420_frame.Init(frame, frame->width, cropped_height)) { | 
| -    LOG(LS_ERROR) << "Couldn't convert to I420! " | 
| -                  << frame->width << " x " << cropped_height; | 
| -    return; | 
| -  } | 
| - | 
| -  // Send I420 frame to the local renderer. | 
| -  if (local_renderer_) { | 
| -    if (local_renderer_w_ != static_cast<int>(i420_frame.GetWidth()) || | 
| -        local_renderer_h_ != static_cast<int>(i420_frame.GetHeight())) { | 
| -      local_renderer_->SetSize(local_renderer_w_ = i420_frame.GetWidth(), | 
| -                               local_renderer_h_ = i420_frame.GetHeight(), 0); | 
| -    } | 
| -    local_renderer_->RenderFrame(&i420_frame); | 
| -  } | 
| - | 
| -  // Send I420 frame to the registered senders. | 
| -  talk_base::CritScope cs(&channels_crit_); | 
| -  for (VideoChannels::iterator it = channels_.begin(); | 
| -      it != channels_.end(); ++it) { | 
| -    if ((*it)->sending()) (*it)->SendFrame(0, &i420_frame); | 
| -  } | 
| -} | 
| - | 
| -const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const { | 
| -  return video_codecs_; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) { | 
| -  log_level_ = min_sev; | 
| -  ApplyLogging(); | 
| -} | 
| - | 
| -int WebRtcVideoEngine::GetLastEngineError() { | 
| -  return vie_wrapper_->error(); | 
| -} | 
| - | 
| -// Checks to see whether we comprehend and could receive a particular codec | 
| -bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) { | 
| -  for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) { | 
| -    const VideoFormat fmt(kVideoFormats[i]); | 
| -    if ((in.width == 0 && in.height == 0) || | 
| -        (fmt.width == in.width && fmt.height == in.height)) { | 
| -      for (int j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) { | 
| -        VideoCodec codec(kVideoCodecPrefs[j].payload_type, | 
| -                         kVideoCodecPrefs[j].name, 0, 0, 0, 0); | 
| -        if (codec.Matches(in)) { | 
| -          return true; | 
| -        } | 
| -      } | 
| -    } | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -// Given the requested codec, returns true if we can send that codec type and | 
| -// updates out with the best quality we could send for that codec. If current is | 
| -// not empty, we constrain out so that its aspect ratio matches current's. | 
| -bool WebRtcVideoEngine::CanSendCodec(const VideoCodec& requested, | 
| -                                     const VideoCodec& current, | 
| -                                     VideoCodec* out) { | 
| -  if (!out) { | 
| -    return false; | 
| -  } | 
| - | 
| -  std::vector<VideoCodec>::const_iterator local_max; | 
| -  for (local_max = video_codecs_.begin(); | 
| -       local_max < video_codecs_.end(); | 
| -       ++local_max) { | 
| -    // First match codecs by payload type | 
| -    if (!requested.Matches(local_max->id, local_max->name)) { | 
| -      continue; | 
| -    } | 
| - | 
| -    out->id = requested.id; | 
| -    out->name = requested.name; | 
| -    out->preference = requested.preference; | 
| -    out->framerate = talk_base::_min(requested.framerate, local_max->framerate); | 
| -    out->width = 0; | 
| -    out->height = 0; | 
| - | 
| -    if (0 == requested.width && 0 == requested.height) { | 
| -      // Special case with resolution 0. The channel should not send frames. | 
| -      return true; | 
| -    } else if (0 == requested.width || 0 == requested.height) { | 
| -      // 0xn and nx0 are invalid resolutions. | 
| -      return false; | 
| -    } | 
| - | 
| -    // Pick the best quality that is within their and our bounds and has the | 
| -    // correct aspect ratio. | 
| -    for (int j = 0; j < ARRAY_SIZE(kVideoFormats); ++j) { | 
| -      const VideoFormat format(kVideoFormats[j]); | 
| - | 
| -      // Skip any format that is larger than the local or remote maximums, or | 
| -      // smaller than the current best match | 
| -      if (format.width > requested.width || format.height > requested.height || | 
| -          format.width > local_max->width || | 
| -          (format.width < out->width && format.height < out->height)) { | 
| -        continue; | 
| -      } | 
| - | 
| -      bool better = false; | 
| - | 
| -      // Check any further constraints on this prospective format | 
| -      if (!out->width || !out->height) { | 
| -        // If we don't have any matches yet, this is the best so far. | 
| -        better = true; | 
| -      } else if (current.width && current.height) { | 
| -        // current is set so format must match its ratio exactly. | 
| -        better = | 
| -            (format.width * current.height == format.height * current.width); | 
| -      } else { | 
| -        // Prefer closer aspect ratios i.e | 
| -        // format.aspect - requested.aspect < out.aspect - requested.aspect | 
| -        better = abs(format.width * requested.height * out->height - | 
| -                     requested.width * format.height * out->height) < | 
| -                 abs(out->width * format.height * requested.height - | 
| -                     requested.width * format.height * out->height); | 
| -      } | 
| - | 
| -      if (better) { | 
| -        out->width = format.width; | 
| -        out->height = format.height; | 
| -      } | 
| -    } | 
| -    if (out->width > 0) { | 
| -      return true; | 
| -    } | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::ConvertToCricketVideoCodec( | 
| -    const webrtc::VideoCodec& in_codec, VideoCodec& out_codec) { | 
| -  out_codec.id = in_codec.plType; | 
| -  out_codec.name = in_codec.plName; | 
| -  out_codec.width = in_codec.width; | 
| -  out_codec.height = in_codec.height; | 
| -  out_codec.framerate = in_codec.maxFramerate; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::ConvertFromCricketVideoCodec( | 
| -    const VideoCodec& in_codec, webrtc::VideoCodec& out_codec) { | 
| -  bool found = false; | 
| -  int ncodecs = vie_wrapper_->codec()->NumberOfCodecs(); | 
| -  for (int i = 0; i < ncodecs; ++i) { | 
| -    if (vie_wrapper_->codec()->GetCodec(i, out_codec) == 0 && | 
| -      in_codec.name == out_codec.plName) { | 
| -      found = true; | 
| -      break; | 
| -    } | 
| -  } | 
| - | 
| -  if (!found) { | 
| -    LOG(LS_ERROR) << "invalid codec type"; | 
| -    return false; | 
| -  } | 
| - | 
| -  if (in_codec.id != 0) | 
| -    out_codec.plType = in_codec.id; | 
| - | 
| -  if (in_codec.width != 0) | 
| -    out_codec.width = in_codec.width; | 
| - | 
| -  if (in_codec.height != 0) | 
| -    out_codec.height = in_codec.height; | 
| - | 
| -  if (in_codec.framerate != 0) | 
| -    out_codec.maxFramerate = in_codec.framerate; | 
| - | 
| -  // Init the codec with the default bandwidth options. | 
| -  out_codec.minBitrate = kMinVideoBitrate; | 
| -  out_codec.startBitrate = kStartVideoBitrate; | 
| -  out_codec.maxBitrate = kMaxVideoBitrate; | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) { | 
| -  talk_base::CritScope cs(&channels_crit_); | 
| -  channels_.push_back(channel); | 
| -} | 
| - | 
| -void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) { | 
| -  talk_base::CritScope cs(&channels_crit_); | 
| -  channels_.erase(std::remove(channels_.begin(), channels_.end(), channel), | 
| -                  channels_.end()); | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) { | 
| -  if (initialized_) { | 
| -    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init."; | 
| -    return false; | 
| -  } | 
| -  voice_engine_ = voice_engine; | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::EnableTimedRender() { | 
| -  if (initialized_) { | 
| -    LOG(LS_WARNING) << "EnableTimedRender can not be called after Init."; | 
| -    return false; | 
| -  } | 
| -  render_module_.reset(webrtc::VideoRender::CreateVideoRender(0, NULL, | 
| -      false, webrtc::kRenderExternal)); | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::ApplyLogging() { | 
| -  int filter = 0; | 
| -  switch (log_level_) { | 
| -    case talk_base::LS_VERBOSE: filter |= webrtc::kTraceAll; | 
| -    case talk_base::LS_INFO: filter |= webrtc::kTraceStateInfo; | 
| -    case talk_base::LS_WARNING: filter |= webrtc::kTraceWarning; | 
| -    case talk_base::LS_ERROR: filter |= | 
| -        webrtc::kTraceError | webrtc::kTraceCritical; | 
| -  } | 
| -  tracing_->SetTraceFilter(filter); | 
| -} | 
| - | 
| -// Rebuilds the codec list to be only those that are less intensive | 
| -// than the specified codec. | 
| -bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) { | 
| -  if (!FindCodec(in_codec)) | 
| -    return false; | 
| - | 
| -  video_codecs_.clear(); | 
| - | 
| -  bool found = false; | 
| -  for (size_t i = 0; i < ARRAY_SIZE(kVideoCodecPrefs); ++i) { | 
| -    const VideoCodecPref& pref(kVideoCodecPrefs[i]); | 
| -    if (!found) | 
| -      found = (in_codec.name == pref.name); | 
| -    if (found) { | 
| -      VideoCodec codec(pref.payload_type, pref.name, | 
| -                       in_codec.width, in_codec.height, in_codec.framerate, | 
| -                       ARRAY_SIZE(kVideoCodecPrefs) - i); | 
| -      video_codecs_.push_back(codec); | 
| -    } | 
| -  } | 
| -  ASSERT(found); | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoEngine::SetCapturer(VideoCapturer* capturer, | 
| -                                    bool own_capturer) { | 
| -  if (capturer == NULL) { | 
| -    ClearCapturer(); | 
| -    return true; | 
| -  } | 
| -  // Hook up signals and install the supplied capturer. | 
| -  SignalCaptureResult.repeat(capturer->SignalStartResult); | 
| -  capturer->SignalFrameCaptured.connect(this, | 
| -      &WebRtcVideoEngine::OnFrameCaptured); | 
| -  ClearCapturer(); | 
| -  video_capturer_ = capturer; | 
| -  owns_capturer_ = own_capturer; | 
| -  // Possibly restart the capturer if it is supposed to be running. | 
| -  CaptureResult result = UpdateCapturingState(); | 
| -  if (result != CR_SUCCESS && result != CR_PENDING) { | 
| -    LOG(LS_WARNING) << "Camera failed to restart"; | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::PerformanceAlarm(const unsigned int cpu_load) { | 
| -  LOG(LS_INFO) << "WebRtcVideoEngine::PerformanceAlarm"; | 
| -} | 
| - | 
| -// Ignore spammy trace messages, mostly from the stats API when we haven't | 
| -// gotten RTCP info yet from the remote side. | 
| -bool WebRtcVideoEngine::ShouldIgnoreTrace(const std::string& trace) { | 
| -  static const char* const kTracesToIgnore[] = { | 
| -    NULL | 
| -  }; | 
| -  for (const char* const* p = kTracesToIgnore; *p; ++p) { | 
| -    if (trace.find(*p) == 0) { | 
| -      return true; | 
| -    } | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -int WebRtcVideoEngine::GetNumOfChannels() { | 
| -  talk_base::CritScope cs(&channels_crit_); | 
| -  return channels_.size(); | 
| -} | 
| - | 
| -void WebRtcVideoEngine::Print(const webrtc::TraceLevel level, | 
| -                              const char* trace, const int length) { | 
| -  talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE; | 
| -  if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) | 
| -    sev = talk_base::LS_ERROR; | 
| -  else if (level == webrtc::kTraceWarning) | 
| -    sev = talk_base::LS_WARNING; | 
| -  else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) | 
| -    sev = talk_base::LS_INFO; | 
| - | 
| -  if (sev >= log_level_) { | 
| -    // Skip past boilerplate prefix text | 
| -    if (length < 72) { | 
| -      std::string msg(trace, length); | 
| -      LOG(LS_ERROR) << "Malformed webrtc log message: "; | 
| -      LOG_V(sev) << msg; | 
| -    } else { | 
| -      std::string msg(trace + 71, length - 72); | 
| -      if (!ShouldIgnoreTrace(msg) && | 
| -          (!voice_engine_ || !voice_engine_->ShouldIgnoreTrace(msg))) { | 
| -        LOG_V(sev) << "WebRtc:" << msg; | 
| -      } | 
| -    } | 
| -  } | 
| -} | 
| - | 
| -// TODO: stubs for now | 
| -bool WebRtcVideoEngine::RegisterProcessor( | 
| -    VideoProcessor* video_processor) { | 
| -  return true; | 
| -} | 
| -bool WebRtcVideoEngine::UnregisterProcessor( | 
| -    VideoProcessor* video_processor) { | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoEngine::ClearCapturer() { | 
| -  if (owns_capturer_) { | 
| -    delete video_capturer_; | 
| -  } | 
| -  video_capturer_ = NULL; | 
| -} | 
| - | 
| -// WebRtcVideoMediaChannel | 
| - | 
| -WebRtcVideoMediaChannel::WebRtcVideoMediaChannel( | 
| -    WebRtcVideoEngine* engine, VoiceMediaChannel* channel) | 
| -    : engine_(engine), | 
| -      voice_channel_(channel), | 
| -      vie_channel_(-1), | 
| -      vie_capture_(-1), | 
| -      external_capture_(NULL), | 
| -      sending_(false), | 
| -      render_started_(false), | 
| -      muted_(false), | 
| -      send_min_bitrate_(kMinVideoBitrate), | 
| -      send_start_bitrate_(kStartVideoBitrate), | 
| -      send_max_bitrate_(kMaxVideoBitrate), | 
| -      local_stream_info_(new LocalStreamInfo()) { | 
| -  engine->RegisterChannel(this); | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::Init() { | 
| -  if (engine_->vie()->base()->CreateChannel(vie_channel_) != 0) { | 
| -    LOG_RTCERR1(CreateChannel, vie_channel_); | 
| -    return false; | 
| -  } | 
| - | 
| -  LOG(LS_INFO) << "WebRtcVideoMediaChannel::Init " | 
| -               << "vie_channel " << vie_channel_ << " created"; | 
| - | 
| -  // Connect the voice channel, if there is one. | 
| -  if (voice_channel_) { | 
| -    WebRtcVoiceMediaChannel* channel = | 
| -        static_cast<WebRtcVoiceMediaChannel*>(voice_channel_); | 
| -    if (engine_->vie()->base()->ConnectAudioChannel( | 
| -        vie_channel_, channel->voe_channel()) != 0) { | 
| -      LOG_RTCERR2(ConnectAudioChannel, vie_channel_, channel->voe_channel()); | 
| -      LOG(LS_WARNING) << "A/V not synchronized"; | 
| -      // Not a fatal error. | 
| -    } | 
| -  } | 
| - | 
| -  // Register external transport. | 
| -  if (engine_->vie()->network()->RegisterSendTransport( | 
| -      vie_channel_, *this) != 0) { | 
| -    LOG_RTCERR1(RegisterSendTransport, vie_channel_); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Set MTU. | 
| -  if (engine_->vie()->network()->SetMTU(vie_channel_, kVideoMtu) != 0) { | 
| -    LOG_RTCERR2(SetMTU, vie_channel_, kVideoMtu); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Register external capture. | 
| -  if (engine()->vie()->capture()->AllocateExternalCaptureDevice( | 
| -      vie_capture_, external_capture_) != 0) { | 
| -    LOG_RTCERR0(AllocateExternalCaptureDevice); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Connect external capture. | 
| -  if (engine()->vie()->capture()->ConnectCaptureDevice( | 
| -      vie_capture_, vie_channel_) != 0) { | 
| -    LOG_RTCERR2(ConnectCaptureDevice, vie_capture_, vie_channel_); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Install render adapter. | 
| -  remote_renderer_.reset(new WebRtcRenderAdapter(NULL)); | 
| -  if (engine_->vie()->render()->AddRenderer(vie_channel_, | 
| -      webrtc::kVideoI420, remote_renderer_.get()) != 0) { | 
| -    LOG_RTCERR3(AddRenderer, vie_channel_, webrtc::kVideoI420, | 
| -                remote_renderer_.get()); | 
| -    remote_renderer_.reset(); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Register decoder observer for incoming framerate and bitrate. | 
| -  decoder_observer_.reset(new WebRtcDecoderObserver(vie_channel_)); | 
| -  if (engine()->vie()->codec()->RegisterDecoderObserver( | 
| -      vie_channel_, *decoder_observer_) != 0) { | 
| -    LOG_RTCERR1(RegisterDecoderObserver, decoder_observer_.get()); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Register encoder observer for outgoing framerate and bitrate. | 
| -  encoder_observer_.reset(new WebRtcEncoderObserver(vie_channel_)); | 
| -  if (engine()->vie()->codec()->RegisterEncoderObserver( | 
| -      vie_channel_, *encoder_observer_) != 0) { | 
| -    LOG_RTCERR1(RegisterEncoderObserver, encoder_observer_.get()); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Turn on RTCP and loss feedback reporting. | 
| -  if (!EnableRtcp() || | 
| -      !EnablePli()) { | 
| -    return false; | 
| -  } | 
| - | 
| -#ifdef WEBRTC_VIDEO_AVPF_NACK_ONLY | 
| -  // Turn on NACK-only loss handling. | 
| -  if (!EnableNack()) | 
| -    return false; | 
| -#endif | 
| - | 
| -  // Turn on TMMBR-based BWE reporting. | 
| -  if (!EnableTmmbr()) { | 
| -    return false; | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() { | 
| -  if (vie_channel_ != -1) { | 
| -    // Stop sending. | 
| -    SetSend(false); | 
| -    if (engine()->vie()->codec()->DeregisterEncoderObserver( | 
| -        vie_channel_) != 0) { | 
| -      LOG_RTCERR1(DeregisterEncoderObserver, vie_channel_); | 
| -    } | 
| - | 
| -    // Stop the renderer. | 
| -    SetRender(false); | 
| -    if (engine()->vie()->codec()->DeregisterDecoderObserver( | 
| -        vie_channel_) != 0) { | 
| -      LOG_RTCERR1(DeregisterDecoderObserver, vie_channel_); | 
| -    } | 
| -    if (remote_renderer_.get() && | 
| -        engine()->vie()->render()->RemoveRenderer(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(RemoveRenderer, vie_channel_); | 
| -    } | 
| - | 
| -    // Destroy the external capture interface. | 
| -    if (vie_capture_ != -1) { | 
| -      if (engine()->vie()->capture()->DisconnectCaptureDevice( | 
| -          vie_channel_) != 0) { | 
| -        LOG_RTCERR1(DisconnectCaptureDevice, vie_channel_); | 
| -      } | 
| -      if (engine()->vie()->capture()->ReleaseCaptureDevice( | 
| -          vie_capture_) != 0) { | 
| -        LOG_RTCERR1(ReleaseCaptureDevice, vie_capture_); | 
| -      } | 
| -    } | 
| - | 
| -    // Deregister external transport. | 
| -    if (engine()->vie()->network()->DeregisterSendTransport( | 
| -        vie_channel_) != 0) { | 
| -      LOG_RTCERR1(DeregisterSendTransport, vie_channel_); | 
| -    } | 
| - | 
| -    // Delete the VideoEngine channel. | 
| -    if (engine()->vie()->base()->DeleteChannel(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(DeleteChannel, vie_channel_); | 
| -    } | 
| -  } | 
| - | 
| -  // Unregister the channel from the engine. | 
| -  engine()->UnregisterChannel(this); | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetRecvCodecs( | 
| -    const std::vector<VideoCodec>& codecs) { | 
| -  bool ret = true; | 
| -  for (std::vector<VideoCodec>::const_iterator iter = codecs.begin(); | 
| -      iter != codecs.end(); ++iter) { | 
| -    if (engine()->FindCodec(*iter)) { | 
| -      webrtc::VideoCodec wcodec; | 
| -      if (engine()->ConvertFromCricketVideoCodec(*iter, wcodec)) { | 
| -        if (engine()->vie()->codec()->SetReceiveCodec( | 
| -            vie_channel_, wcodec) != 0) { | 
| -          LOG_RTCERR2(SetReceiveCodec, vie_channel_, wcodec.plName); | 
| -          ret = false; | 
| -        } | 
| -      } | 
| -    } else { | 
| -      LOG(LS_INFO) << "Unknown codec " << iter->name; | 
| -      ret = false; | 
| -    } | 
| -  } | 
| - | 
| -  // make channel ready to receive packets | 
| -  if (ret) { | 
| -    if (engine()->vie()->base()->StartReceive(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(StartReceive, vie_channel_); | 
| -      ret = false; | 
| -    } | 
| -  } | 
| -  return ret; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetSendCodecs( | 
| -    const std::vector<VideoCodec>& codecs) { | 
| -  // Match with local video codec list. | 
| -  std::vector<webrtc::VideoCodec> send_codecs; | 
| -  int red_type = -1, fec_type = -1; | 
| -  VideoCodec checked_codec; | 
| -  VideoCodec current;  // defaults to 0x0 | 
| -  if (sending_) { | 
| -    engine()->ConvertToCricketVideoCodec(*send_codec_, current); | 
| -  } | 
| -  for (std::vector<VideoCodec>::const_iterator iter = codecs.begin(); | 
| -      iter != codecs.end(); ++iter) { | 
| -    if (_stricmp(iter->name.c_str(), kRedPayloadName) == 0) { | 
| -      red_type = iter->id; | 
| -    } else if (_stricmp(iter->name.c_str(), kFecPayloadName) == 0) { | 
| -      fec_type = iter->id; | 
| -    } else if (engine()->CanSendCodec(*iter, current, &checked_codec)) { | 
| -      webrtc::VideoCodec wcodec; | 
| -      if (engine()->ConvertFromCricketVideoCodec(checked_codec, wcodec)) { | 
| -        send_codecs.push_back(wcodec); | 
| -      } | 
| -    } else { | 
| -      LOG(LS_WARNING) << "Unknown codec " << iter->name; | 
| -    } | 
| -  } | 
| - | 
| -  // Fail if we don't have a match. | 
| -  if (send_codecs.empty()) { | 
| -    LOG(LS_WARNING) << "No matching codecs avilable"; | 
| -    return false; | 
| -  } | 
| - | 
| -#ifndef WEBRTC_VIDEO_AVPF_NACK_ONLY | 
| -  // Configure FEC if enabled. | 
| -  if (!SetNackFec(red_type, fec_type)) { | 
| -    return false; | 
| -  } | 
| -#endif | 
| - | 
| -  // Select the first matched codec. | 
| -  webrtc::VideoCodec& codec(send_codecs[0]); | 
| - | 
| -  // Set the default number of temporal layers for VP8. | 
| -  if (webrtc::kVideoCodecVP8 == codec.codecType) { | 
| -    codec.codecSpecific.VP8.numberOfTemporalLayers = | 
| -        kDefaultNumberOfTemporalLayers; | 
| -  } | 
| - | 
| -  if (!SetSendCodec( | 
| -      codec, send_min_bitrate_, send_start_bitrate_, send_max_bitrate_)) { | 
| -    return false; | 
| -  } | 
| - | 
| -  LOG(LS_INFO) << "Selected video codec " << send_codec_->plName << "/" | 
| -               << send_codec_->width << "x" << send_codec_->height << "x" | 
| -               << static_cast<int>(send_codec_->maxFramerate); | 
| -  if (webrtc::kVideoCodecVP8 == codec.codecType) { | 
| -    LOG(LS_INFO) << "VP8 number of layers: " | 
| -                 << static_cast<int>( | 
| -                    send_codec_->codecSpecific.VP8.numberOfTemporalLayers); | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetRender(bool render) { | 
| -  if (render == render_started_) { | 
| -    return true;  // no action required | 
| -  } | 
| - | 
| -  bool ret = true; | 
| -  if (render) { | 
| -    if (engine()->vie()->render()->StartRender(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(StartRender, vie_channel_); | 
| -      ret = false; | 
| -    } | 
| -  } else { | 
| -    if (engine()->vie()->render()->StopRender(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(StopRender, vie_channel_); | 
| -      ret = false; | 
| -    } | 
| -  } | 
| -  if (ret) { | 
| -    render_started_ = render; | 
| -  } | 
| - | 
| -  return ret; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetSend(bool send) { | 
| -  if (send == sending()) { | 
| -    return true;  // no action required | 
| -  } | 
| - | 
| -  if (send) { | 
| -    // We've been asked to start sending. | 
| -    // SetSendCodecs must have been called already. | 
| -    if (!send_codec_.get()) { | 
| -      return false; | 
| -    } | 
| - | 
| -    if (engine()->vie()->base()->StartSend(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(StartSend, vie_channel_); | 
| -      return false; | 
| -    } | 
| -  } else { | 
| -    // We've been asked to stop sending. | 
| -    if (engine()->vie()->base()->StopSend(vie_channel_) != 0) { | 
| -      LOG_RTCERR1(StopSend, vie_channel_); | 
| -      return false; | 
| -    } | 
| -  } | 
| - | 
| -  sending_ = send; | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::AddStream(uint32 ssrc, uint32 voice_ssrc) { | 
| -  return false; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::RemoveStream(uint32 ssrc) { | 
| -  return false; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetRenderer( | 
| -    uint32 ssrc, VideoRenderer* renderer) { | 
| -  if (ssrc != 0) | 
| -    return false; | 
| - | 
| -  remote_renderer_->SetRenderer(renderer); | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) { | 
| -  // Get basic statistics. | 
| -  unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv; | 
| -  unsigned int ssrc; | 
| -  if (engine_->vie()->rtp()->GetRTPStatistics(vie_channel_, | 
| -          bytes_sent, packets_sent, bytes_recv, packets_recv) != 0) { | 
| -    LOG_RTCERR1(GetRTPStatistics, vie_channel_); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Get sender statistics and build VideoSenderInfo. | 
| -  if (engine_->vie()->rtp()->GetLocalSSRC(vie_channel_, ssrc) == 0) { | 
| -    VideoSenderInfo sinfo; | 
| -    sinfo.ssrc = ssrc; | 
| -    sinfo.codec_name = send_codec_.get() ? send_codec_->plName : ""; | 
| -    sinfo.bytes_sent = bytes_sent; | 
| -    sinfo.packets_sent = packets_sent; | 
| -    sinfo.packets_cached = -1; | 
| -    sinfo.packets_lost = -1; | 
| -    sinfo.fraction_lost = -1; | 
| -    sinfo.firs_rcvd = -1; | 
| -    sinfo.nacks_rcvd = -1; | 
| -    sinfo.rtt_ms = -1; | 
| -    sinfo.frame_width = local_stream_info_->width(); | 
| -    sinfo.frame_height = local_stream_info_->height(); | 
| -    sinfo.framerate_input = local_stream_info_->framerate(); | 
| -    sinfo.framerate_sent = encoder_observer_->framerate(); | 
| -    sinfo.nominal_bitrate = encoder_observer_->bitrate(); | 
| -    sinfo.preferred_bitrate = kMaxVideoBitrate; | 
| - | 
| -    // Get received RTCP statistics for the sender, if available. | 
| -    // It's not a fatal error if we can't, since RTCP may not have arrived yet. | 
| -    uint16 r_fraction_lost; | 
| -    unsigned int r_cumulative_lost; | 
| -    unsigned int r_extended_max; | 
| -    unsigned int r_jitter; | 
| -    int r_rtt_ms; | 
| -    if (engine_->vie()->rtp()->GetReceivedRTCPStatistics(vie_channel_, | 
| -            r_fraction_lost, r_cumulative_lost, r_extended_max, | 
| -            r_jitter, r_rtt_ms) == 0) { | 
| -      // Convert Q8 to float. | 
| -      sinfo.packets_lost = r_cumulative_lost; | 
| -      sinfo.fraction_lost = static_cast<float>(r_fraction_lost) / (1 << 8); | 
| -      sinfo.rtt_ms = r_rtt_ms; | 
| -    } | 
| -    info->senders.push_back(sinfo); | 
| -  } else { | 
| -    LOG_RTCERR1(GetLocalSSRC, vie_channel_); | 
| -  } | 
| - | 
| -  // Get receiver statistics and build VideoReceiverInfo, if we have data. | 
| -  if (engine_->vie()->rtp()->GetRemoteSSRC(vie_channel_, ssrc) == 0) { | 
| -    VideoReceiverInfo rinfo; | 
| -    rinfo.ssrc = ssrc; | 
| -    rinfo.bytes_rcvd = bytes_recv; | 
| -    rinfo.packets_rcvd = packets_recv; | 
| -    rinfo.packets_lost = -1; | 
| -    rinfo.packets_concealed = -1; | 
| -    rinfo.fraction_lost = -1;  // from SentRTCP | 
| -    rinfo.firs_sent = decoder_observer_->firs_requested(); | 
| -    rinfo.nacks_sent = -1; | 
| -    rinfo.frame_width = remote_renderer_->width(); | 
| -    rinfo.frame_height = remote_renderer_->height(); | 
| -    rinfo.framerate_rcvd = decoder_observer_->framerate(); | 
| -    int fps = remote_renderer_->framerate(); | 
| -    rinfo.framerate_decoded = fps; | 
| -    rinfo.framerate_output = fps; | 
| - | 
| -    // Get sent RTCP statistics. | 
| -    uint16 s_fraction_lost; | 
| -    unsigned int s_cumulative_lost; | 
| -    unsigned int s_extended_max; | 
| -    unsigned int s_jitter; | 
| -    int s_rtt_ms; | 
| -    if (engine_->vie()->rtp()->GetSentRTCPStatistics(vie_channel_, | 
| -            s_fraction_lost, s_cumulative_lost, s_extended_max, | 
| -            s_jitter, s_rtt_ms) == 0) { | 
| -      // Convert Q8 to float. | 
| -      rinfo.packets_lost = s_cumulative_lost; | 
| -      rinfo.fraction_lost = static_cast<float>(s_fraction_lost) / (1 << 8); | 
| -    } | 
| -    info->receivers.push_back(rinfo); | 
| -  } | 
| - | 
| -  // Build BandwidthEstimationInfo. | 
| -  // TODO: Fill in more BWE stats once we have them. | 
| -  unsigned int total_bitrate_sent; | 
| -  unsigned int video_bitrate_sent; | 
| -  unsigned int fec_bitrate_sent; | 
| -  unsigned int nack_bitrate_sent; | 
| -  if (engine_->vie()->rtp()->GetBandwidthUsage(vie_channel_, | 
| -      total_bitrate_sent, video_bitrate_sent, | 
| -      fec_bitrate_sent, nack_bitrate_sent) == 0) { | 
| -    BandwidthEstimationInfo bwe; | 
| -    bwe.actual_enc_bitrate = video_bitrate_sent; | 
| -    bwe.transmit_bitrate = total_bitrate_sent; | 
| -    bwe.retransmit_bitrate = nack_bitrate_sent; | 
| -    info->bw_estimations.push_back(bwe); | 
| -  } else { | 
| -    LOG_RTCERR1(GetBandwidthUsage, vie_channel_); | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SendIntraFrame() { | 
| -  bool ret = true; | 
| -  if (engine()->vie()->codec()->SendKeyFrame(vie_channel_) != 0) { | 
| -    LOG_RTCERR1(SendKeyFrame, vie_channel_); | 
| -    ret = false; | 
| -  } | 
| - | 
| -  return ret; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::RequestIntraFrame() { | 
| -  // There is no API exposed to application to request a key frame | 
| -  // ViE does this internally when there are errors from decoder | 
| -  return false; | 
| -} | 
| - | 
| -void WebRtcVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) { | 
| -  engine()->vie()->network()->ReceivedRTPPacket(vie_channel_, | 
| -                                                         packet->data(), | 
| -                                                         packet->length()); | 
| -} | 
| - | 
| -void WebRtcVideoMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) { | 
| -  engine_->vie()->network()->ReceivedRTCPPacket(vie_channel_, | 
| -                                                         packet->data(), | 
| -                                                         packet->length()); | 
| -} | 
| - | 
| -void WebRtcVideoMediaChannel::SetSendSsrc(uint32 id) { | 
| -  if (!sending_) { | 
| -    if (engine()->vie()->rtp()->SetLocalSSRC(vie_channel_, id) != 0) { | 
| -      LOG_RTCERR1(SetLocalSSRC, vie_channel_); | 
| -    } | 
| -  } else { | 
| -    LOG(LS_ERROR) << "Channel already in send state"; | 
| -  } | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetRtcpCName(const std::string& cname) { | 
| -  if (engine()->vie()->rtp()->SetRTCPCName(vie_channel_, | 
| -                                           cname.c_str()) != 0) { | 
| -    LOG_RTCERR2(SetRTCPCName, vie_channel_, cname.c_str()); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::Mute(bool on) { | 
| -  muted_ = on; | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) { | 
| -  LOG(LS_INFO) << "RtcVideoMediaChanne::SetSendBandwidth"; | 
| - | 
| -  if (!send_codec_.get()) { | 
| -    LOG(LS_INFO) << "The send codec has not been set up yet."; | 
| -    return true; | 
| -  } | 
| - | 
| -  int min_bitrate; | 
| -  int start_bitrate; | 
| -  int max_bitrate; | 
| -  if (autobw) { | 
| -    // Use the default values for min bitrate. | 
| -    min_bitrate = kMinVideoBitrate; | 
| -    // Use the default value or the bps for the max | 
| -    max_bitrate = (bps <= 0) ? kMaxVideoBitrate : (bps / 1000); | 
| -    // Maximum start bitrate can be kStartVideoBitrate. | 
| -    start_bitrate = talk_base::_min(kStartVideoBitrate, max_bitrate); | 
| -  } else { | 
| -    // Use the default start or the bps as the target bitrate. | 
| -    int target_bitrate = (bps <= 0) ? kStartVideoBitrate : (bps / 1000); | 
| -    min_bitrate = target_bitrate; | 
| -    start_bitrate = target_bitrate; | 
| -    max_bitrate = target_bitrate; | 
| -  } | 
| - | 
| -  if (!SetSendCodec(*send_codec_, min_bitrate, start_bitrate, max_bitrate)) { | 
| -    return false; | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetOptions(int options) { | 
| -  return true; | 
| -} | 
| - | 
| -void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) { | 
| -  MediaChannel::SetInterface(iface); | 
| -  // Set the RTP recv/send buffer to a bigger size | 
| -  if (network_interface_) { | 
| -    network_interface_->SetOption(NetworkInterface::ST_RTP, | 
| -                                  talk_base::Socket::OPT_RCVBUF, | 
| -                                  kVideoRtpBufferSize); | 
| -    network_interface_->SetOption(NetworkInterface::ST_RTP, | 
| -                                  talk_base::Socket::OPT_SNDBUF, | 
| -                                  kVideoRtpBufferSize); | 
| -  } | 
| -} | 
| - | 
| -// TODO: Add unittests to test this function. | 
| -bool WebRtcVideoMediaChannel::SendFrame(uint32 ssrc, const VideoFrame* frame) { | 
| -  if (ssrc != 0 || !sending() || !external_capture_) { | 
| -    return false; | 
| -  } | 
| - | 
| -  // Update local stream statistics. | 
| -  local_stream_info_->UpdateFrame(frame->GetWidth(), frame->GetHeight()); | 
| - | 
| -  // If the captured video format is smaller than what we asked for, reset send | 
| -  // codec on video engine. | 
| -  if (send_codec_.get() != NULL && | 
| -      frame->GetWidth() < send_codec_->width && | 
| -      frame->GetHeight() < send_codec_->height) { | 
| -    LOG(LS_INFO) << "Captured video frame size changed to: " | 
| -                 << frame->GetWidth() << "x" << frame->GetHeight(); | 
| -    webrtc::VideoCodec new_codec = *send_codec_; | 
| -    new_codec.width = frame->GetWidth(); | 
| -    new_codec.height = frame->GetHeight(); | 
| -    if (!SetSendCodec( | 
| -        new_codec, send_min_bitrate_, send_start_bitrate_, send_max_bitrate_)) { | 
| -      LOG(LS_WARNING) << "Failed to switch to new frame size: " | 
| -                      << frame->GetWidth() << "x" << frame->GetHeight(); | 
| -    } | 
| -  } | 
| - | 
| -  // Blacken the frame if video is muted. | 
| -  const VideoFrame* frame_out = frame; | 
| -  talk_base::scoped_ptr<VideoFrame> black_frame; | 
| -  if (muted_) { | 
| -    black_frame.reset(frame->Copy()); | 
| -    black_frame->SetToBlack(); | 
| -    frame_out = black_frame.get(); | 
| -  } | 
| - | 
| -  webrtc::ViEVideoFrameI420 frame_i420; | 
| -  // TODO: Update the webrtc::ViEVideoFrameI420 | 
| -  // to use const unsigned char* | 
| -  frame_i420.y_plane = const_cast<unsigned char*>(frame_out->GetYPlane()); | 
| -  frame_i420.u_plane = const_cast<unsigned char*>(frame_out->GetUPlane()); | 
| -  frame_i420.v_plane = const_cast<unsigned char*>(frame_out->GetVPlane()); | 
| -  frame_i420.y_pitch = frame_out->GetYPitch(); | 
| -  frame_i420.u_pitch = frame_out->GetUPitch(); | 
| -  frame_i420.v_pitch = frame_out->GetVPitch(); | 
| -  frame_i420.width = frame_out->GetWidth(); | 
| -  frame_i420.height = frame_out->GetHeight(); | 
| - | 
| -  // Convert from nanoseconds to milliseconds. | 
| -  WebRtc_Word64 clocks = frame_out->GetTimeStamp() / | 
| -      talk_base::kNumNanosecsPerMillisec; | 
| - | 
| -  return (external_capture_->IncomingFrameI420(frame_i420, clocks) == 0); | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::EnableRtcp() { | 
| -  if (engine()->vie()->rtp()->SetRTCPStatus( | 
| -          vie_channel_, webrtc::kRtcpCompound_RFC4585) != 0) { | 
| -    LOG_RTCERR2(SetRTCPStatus, vie_channel_, webrtc::kRtcpCompound_RFC4585); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::EnablePli() { | 
| -  if (engine_->vie()->rtp()->SetKeyFrameRequestMethod( | 
| -          vie_channel_, webrtc::kViEKeyFrameRequestPliRtcp) != 0) { | 
| -    LOG_RTCERR2(SetRTCPStatus, | 
| -                vie_channel_, webrtc::kViEKeyFrameRequestPliRtcp); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::EnableTmmbr() { | 
| -  if (engine_->vie()->rtp()->SetTMMBRStatus(vie_channel_, true) != 0) { | 
| -    LOG_RTCERR1(SetTMMBRStatus, vie_channel_); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::EnableNack() { | 
| -  if (engine_->vie()->rtp()->SetNACKStatus(vie_channel_, true) != 0) { | 
| -    LOG_RTCERR1(SetNACKStatus, vie_channel_); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetNackFec(int red_payload_type, | 
| -                                         int fec_payload_type) { | 
| -  bool enable = (red_payload_type != -1 && fec_payload_type != -1); | 
| -  if (engine_->vie()->rtp()->SetHybridNACKFECStatus( | 
| -          vie_channel_, enable, red_payload_type, fec_payload_type) != 0) { | 
| -    LOG_RTCERR4(SetHybridNACKFECStatus, | 
| -                vie_channel_, enable, red_payload_type, fec_payload_type); | 
| -    return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool WebRtcVideoMediaChannel::SetSendCodec(const webrtc::VideoCodec& codec, | 
| -                                           int min_bitrate, | 
| -                                           int start_bitrate, | 
| -                                           int max_bitrate) { | 
| -  // Make a copy of the codec | 
| -  webrtc::VideoCodec target_codec = codec; | 
| -  target_codec.startBitrate = start_bitrate; | 
| -  target_codec.minBitrate = min_bitrate; | 
| -  target_codec.maxBitrate = max_bitrate; | 
| - | 
| -  if (engine()->vie()->codec()->SetSendCodec(vie_channel_, target_codec) != 0) { | 
| -    LOG_RTCERR2(SetSendCodec, vie_channel_, send_codec_->plName); | 
| -    return false; | 
| -  } | 
| - | 
| -  // Reset the send_codec_ only if SetSendCodec is success. | 
| -  send_codec_.reset(new webrtc::VideoCodec(target_codec)); | 
| -  send_min_bitrate_ = min_bitrate; | 
| -  send_start_bitrate_ = start_bitrate; | 
| -  send_max_bitrate_ = max_bitrate; | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data, | 
| -                                        int len) { | 
| -  if (!network_interface_) { | 
| -    return -1; | 
| -  } | 
| -  talk_base::Buffer packet(data, len, kMaxRtpPacketLen); | 
| -  return network_interface_->SendPacket(&packet) ? len : -1; | 
| -} | 
| - | 
| -int WebRtcVideoMediaChannel::SendRTCPPacket(int channel, | 
| -                                            const void* data, | 
| -                                            int len) { | 
| -  if (!network_interface_) { | 
| -    return -1; | 
| -  } | 
| -  talk_base::Buffer packet(data, len, kMaxRtpPacketLen); | 
| -  return network_interface_->SendRtcp(&packet) ? len : -1; | 
| -} | 
| - | 
| -}  // namespace cricket | 
| - | 
| -#endif  // HAVE_WEBRTC_VIDEO | 
|  |