summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorronghuawu@chromium.org <ronghuawu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-18 03:37:47 +0000
committerronghuawu@chromium.org <ronghuawu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-18 03:37:47 +0000
commit58cc8bfb2be9033cb40c0b9dc9e40e2df568b100 (patch)
treea903739980514df9decb9e826ff6cfbe8d56bd55 /third_party
parent38d0b2d49f614e30ee9d6c9ce3c1b1c66fab3dfa (diff)
downloadchromium_src-58cc8bfb2be9033cb40c0b9dc9e40e2df568b100.zip
chromium_src-58cc8bfb2be9033cb40c0b9dc9e40e2df568b100.tar.gz
chromium_src-58cc8bfb2be9033cb40c0b9dc9e40e2df568b100.tar.bz2
Roll libjingle to r108:
* Add app/webrtc. * Add examples/peerconnection. * Bug fixes. Roll webrtc to 1311. BUG=110255 TEST=build and unit tests Review URL: http://codereview.chromium.org/9174012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118031 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r--third_party/libjingle/README.chromium4
-rw-r--r--third_party/libjingle/libjingle.gyp35
-rw-r--r--third_party/libjingle/overrides/talk/base/basictypes.h7
-rw-r--r--third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc1619
4 files changed, 25 insertions, 1640 deletions
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index dd77c10..5b768df 100644
--- a/third_party/libjingle/README.chromium
+++ b/third_party/libjingle/README.chromium
@@ -1,8 +1,8 @@
Name: Libjingle library. Used for p2p voice and video communication.
Short Name: libjingle
URL: http://code.google.com/p/libjingle/
-Version: 2.7.0
-Revision: 100
+Version: 0.6.10
+Revision: 108
License: BSD
License File: source/COPYING
Security Critical: yes
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 3f8aa60..916ca84 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -282,8 +282,10 @@
'source/talk/base/taskrunner.h',
'source/talk/base/thread.cc',
'source/talk/base/thread.h',
- 'source/talk/base/time.cc',
- 'source/talk/base/time.h',
+ 'source/talk/base/timeutils.cc',
+ 'source/talk/base/timeutils.h',
+ 'source/talk/base/timing.cc',
+ 'source/talk/base/timing.h',
'source/talk/base/urlencode.cc',
'source/talk/base/urlencode.h',
'source/talk/base/worker.cc',
@@ -309,8 +311,6 @@
'source/talk/xmpp/jid.h',
'source/talk/xmpp/plainsaslhandler.h',
'source/talk/xmpp/prexmppauth.h',
- 'source/talk/xmpp/ratelimitmanager.cc',
- 'source/talk/xmpp/ratelimitmanager.h',
'source/talk/xmpp/saslcookiemechanism.h',
'source/talk/xmpp/saslhandler.h',
'source/talk/xmpp/saslmechanism.cc',
@@ -458,17 +458,17 @@
'target_name': 'libjingle_peerconnection',
'type': 'static_library',
'sources': [
- 'source/talk/app/webrtc/peerconnection.h',
- 'source/talk/app/webrtc/peerconnectionfactory.cc',
- 'source/talk/app/webrtc/peerconnectionfactory.h',
- 'source/talk/app/webrtc/peerconnectionimpl.cc',
- 'source/talk/app/webrtc/peerconnectionimpl.h',
- 'source/talk/app/webrtc/peerconnectionproxy.cc',
- 'source/talk/app/webrtc/peerconnectionproxy.h',
- 'source/talk/app/webrtc/webrtcsession.cc',
- 'source/talk/app/webrtc/webrtcsession.h',
- 'source/talk/app/webrtc/webrtcjson.cc',
- 'source/talk/app/webrtc/webrtcjson.h',
+ 'source/talk/app/webrtcv1/peerconnection.h',
+ 'source/talk/app/webrtcv1/peerconnectionfactory.cc',
+ 'source/talk/app/webrtcv1/peerconnectionfactory.h',
+ 'source/talk/app/webrtcv1/peerconnectionimpl.cc',
+ 'source/talk/app/webrtcv1/peerconnectionimpl.h',
+ 'source/talk/app/webrtcv1/peerconnectionproxy.cc',
+ 'source/talk/app/webrtcv1/peerconnectionproxy.h',
+ 'source/talk/app/webrtcv1/webrtcsession.cc',
+ 'source/talk/app/webrtcv1/webrtcsession.h',
+ 'source/talk/app/webrtcv1/webrtcjson.cc',
+ 'source/talk/app/webrtcv1/webrtcjson.h',
'source/talk/session/phone/audiomonitor.cc',
'source/talk/session/phone/audiomonitor.h',
'source/talk/session/phone/call.cc',
@@ -512,6 +512,7 @@
'source/talk/session/phone/srtpfilter.h',
'source/talk/session/phone/ssrcmuxfilter.cc',
'source/talk/session/phone/ssrcmuxfilter.h',
+ 'source/talk/session/phone/streamparams.cc',
'source/talk/session/phone/videocapturer.cc',
'source/talk/session/phone/videocapturer.h',
'source/talk/session/phone/videocommon.cc',
@@ -523,9 +524,7 @@
'source/talk/session/phone/webrtcpassthroughrender.cc',
'source/talk/session/phone/webrtcvideocapturer.cc',
'source/talk/session/phone/webrtcvideocapturer.h',
- # TODO(ronghuawu): Fix this in libjingle and remove the override.
- # See http://crbug.com/110255
- 'overrides/talk/session/phone/webrtcvideoengine.cc',
+ 'source/talk/session/phone/webrtcvideoengine.cc',
'source/talk/session/phone/webrtcvideoengine.h',
'source/talk/session/phone/webrtcvideoframe.cc',
'source/talk/session/phone/webrtcvideoframe.h',
diff --git a/third_party/libjingle/overrides/talk/base/basictypes.h b/third_party/libjingle/overrides/talk/base/basictypes.h
index 4ea193e..eeecc4b 100644
--- a/third_party/libjingle/overrides/talk/base/basictypes.h
+++ b/third_party/libjingle/overrides/talk/base/basictypes.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -60,4 +60,9 @@ const int kForever = -1;
(reinterpret_cast<uint8*>(((reinterpret_cast<uintptr_t>(p) + \
((t)-1)) & ~((t)-1))))
+// LIBJINGLE_DEFINE_STATIC_LOCAL() is a libjingle's copy
+// of CR_DEFINE_STATIC_LOCAL().
+#define LIBJINGLE_DEFINE_STATIC_LOCAL(type, name, arguments) \
+ CR_DEFINE_STATIC_LOCAL(type, name, arguments)
+
#endif // OVERRIDES_TALK_BASE_BASICTYPES_H__
diff --git a/third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc b/third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc
deleted file mode 100644
index 829fac3..0000000
--- a/third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc
+++ /dev/null
@@ -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