diff options
author | ronghuawu@chromium.org <ronghuawu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-18 03:37:47 +0000 |
---|---|---|
committer | ronghuawu@chromium.org <ronghuawu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-18 03:37:47 +0000 |
commit | 58cc8bfb2be9033cb40c0b9dc9e40e2df568b100 (patch) | |
tree | a903739980514df9decb9e826ff6cfbe8d56bd55 /third_party | |
parent | 38d0b2d49f614e30ee9d6c9ce3c1b1c66fab3dfa (diff) | |
download | chromium_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.chromium | 4 | ||||
-rw-r--r-- | third_party/libjingle/libjingle.gyp | 35 | ||||
-rw-r--r-- | third_party/libjingle/overrides/talk/base/basictypes.h | 7 | ||||
-rw-r--r-- | third_party/libjingle/overrides/talk/session/phone/webrtcvideoengine.cc | 1619 |
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 |