From bcb6bcfe6c50a1aa27fa243180887eaf9cf9a23b Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Thu, 4 Sep 2014 07:32:26 +0000 Subject: [PATCH] Remove HybridVideoEngine. This is currently unused dead code. R=pthatcher@webrtc.org BUG= Review URL: https://webrtc-codereview.appspot.com/24409004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7055 4adac7df-926f-26a2-2b94-8c16560cd09d --- talk/libjingle.gyp | 2 - talk/media/base/hybridvideoengine.cc | 356 ------------- talk/media/base/hybridvideoengine.h | 283 ---------- talk/media/base/hybridvideoengine_unittest.cc | 486 ------------------ 4 files changed, 1127 deletions(-) delete mode 100644 talk/media/base/hybridvideoengine.cc delete mode 100644 talk/media/base/hybridvideoengine.h delete mode 100644 talk/media/base/hybridvideoengine_unittest.cc diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index ba63f29d96..e0cc4eb2a2 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -487,8 +487,6 @@ 'media/base/filemediaengine.cc', 'media/base/filemediaengine.h', 'media/base/hybriddataengine.h', - 'media/base/hybridvideoengine.cc', - 'media/base/hybridvideoengine.h', 'media/base/mediachannel.h', 'media/base/mediacommon.h', 'media/base/mediaengine.cc', diff --git a/talk/media/base/hybridvideoengine.cc b/talk/media/base/hybridvideoengine.cc deleted file mode 100644 index 289c4fe944..0000000000 --- a/talk/media/base/hybridvideoengine.cc +++ /dev/null @@ -1,356 +0,0 @@ -/* - * libjingle - * Copyright 2004 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. - */ - -#include "talk/media/base/hybridvideoengine.h" - -#include "webrtc/base/logging.h" - -namespace cricket { - -HybridVideoMediaChannel::HybridVideoMediaChannel( - HybridVideoEngineInterface* engine, - VideoMediaChannel* channel1, - VideoMediaChannel* channel2) - : engine_(engine), - channel1_(channel1), - channel2_(channel2), - active_channel_(NULL), - sending_(false) { -} - -HybridVideoMediaChannel::~HybridVideoMediaChannel() { -} - -void HybridVideoMediaChannel::SetInterface(NetworkInterface* iface) { - if (channel1_) { - channel1_->SetInterface(iface); - } - if (channel2_) { - channel2_->SetInterface(iface); - } -} - -bool HybridVideoMediaChannel::SetOptions(const VideoOptions &options) { - bool ret = true; - if (channel1_) { - ret = channel1_->SetOptions(options); - } - if (channel2_ && ret) { - ret = channel2_->SetOptions(options); - } - return ret; -} - -bool HybridVideoMediaChannel::GetOptions(VideoOptions *options) const { - if (active_channel_) { - return active_channel_->GetOptions(options); - } - if (channel1_) { - return channel1_->GetOptions(options); - } - if (channel2_) { - return channel2_->GetOptions(options); - } - return false; -} - -bool HybridVideoMediaChannel::SetRecvCodecs( - const std::vector& codecs) { - // Only give each channel the codecs it knows about. - bool ret = true; - std::vector codecs1, codecs2; - SplitCodecs(codecs, &codecs1, &codecs2); - if (channel1_) { - ret = channel1_->SetRecvCodecs(codecs1); - } - if (channel2_ && ret) { - ret = channel2_->SetRecvCodecs(codecs2); - } - return ret; -} - -bool HybridVideoMediaChannel::SetRecvRtpHeaderExtensions( - const std::vector& extensions) { - bool ret = true; - if (channel1_) { - ret = channel1_->SetRecvRtpHeaderExtensions(extensions); - } - if (channel2_ && ret) { - ret = channel2_->SetRecvRtpHeaderExtensions(extensions); - } - return ret; -} - -bool HybridVideoMediaChannel::SetRenderer(uint32 ssrc, - VideoRenderer* renderer) { - bool ret = true; - if (channel1_) { - ret = channel1_->SetRenderer(ssrc, renderer); - } - if (channel2_ && ret) { - ret = channel2_->SetRenderer(ssrc, renderer); - } - return ret; -} - -bool HybridVideoMediaChannel::SetRender(bool render) { - bool ret = true; - if (channel1_) { - ret = channel1_->SetRender(render); - } - if (channel2_ && ret) { - ret = channel2_->SetRender(render); - } - return ret; -} - -bool HybridVideoMediaChannel::MuteStream(uint32 ssrc, bool muted) { - bool ret = true; - if (channel1_) { - ret = channel1_->MuteStream(ssrc, muted); - } - if (channel2_ && ret) { - ret = channel2_->MuteStream(ssrc, muted); - } - return ret; -} - -bool HybridVideoMediaChannel::SetSendCodecs( - const std::vector& codecs) { - // Use the input to this function to decide what impl we're going to use. - if (!active_channel_ && !SelectActiveChannel(codecs)) { - LOG(LS_WARNING) << "Failed to select active channel"; - return false; - } - // Only give the active channel the codecs it knows about. - std::vector codecs1, codecs2; - SplitCodecs(codecs, &codecs1, &codecs2); - const std::vector& codecs_to_set = - (active_channel_ == channel1_.get()) ? codecs1 : codecs2; - bool return_value = active_channel_->SetSendCodecs(codecs_to_set); - if (!return_value) { - return false; - } - VideoCodec send_codec; - return_value = active_channel_->GetSendCodec(&send_codec); - if (!return_value) { - return false; - } - engine_->OnNewSendResolution(send_codec.width, send_codec.height); - active_channel_->UpdateAspectRatio(send_codec.width, send_codec.height); - return true; -} - -bool HybridVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) { - if (!active_channel_) { - return false; - } - return active_channel_->GetSendCodec(send_codec); -} - -bool HybridVideoMediaChannel::SetSendStreamFormat(uint32 ssrc, - const VideoFormat& format) { - return active_channel_ && active_channel_->SetSendStreamFormat(ssrc, format); -} - -bool HybridVideoMediaChannel::SetSendRtpHeaderExtensions( - const std::vector& extensions) { - return active_channel_ && - active_channel_->SetSendRtpHeaderExtensions(extensions); -} - -bool HybridVideoMediaChannel::SetStartSendBandwidth(int bps) { - return active_channel_ && active_channel_->SetStartSendBandwidth(bps); -} - -bool HybridVideoMediaChannel::SetMaxSendBandwidth(int bps) { - return active_channel_ && active_channel_->SetMaxSendBandwidth(bps); -} - -bool HybridVideoMediaChannel::SetSend(bool send) { - if (send == sending()) { - return true; // no action required if already set. - } - - bool ret = active_channel_ && - active_channel_->SetSend(send); - - // Returns error and don't connect the signal if starting up. - // Disconnects the signal anyway if shutting down. - if (ret || !send) { - // TODO(juberti): Remove this hack that connects the WebRTC channel - // to the capturer. - if (active_channel_ == channel1_.get()) { - engine_->OnSendChange1(channel1_.get(), send); - } else { - engine_->OnSendChange2(channel2_.get(), send); - } - // If succeeded, remember the state as is. - // If failed to open, sending_ should be false. - // If failed to stop, sending_ should also be false, as we disconnect the - // capture anyway. - // The failure on SetSend(false) is a known issue in webrtc. - sending_ = send; - } - return ret; -} - -bool HybridVideoMediaChannel::SetCapturer(uint32 ssrc, - VideoCapturer* capturer) { - bool ret = true; - if (channel1_.get()) { - ret = channel1_->SetCapturer(ssrc, capturer); - } - if (channel2_.get() && ret) { - ret = channel2_->SetCapturer(ssrc, capturer); - } - return ret; -} - -bool HybridVideoMediaChannel::AddSendStream(const StreamParams& sp) { - bool ret = true; - if (channel1_) { - ret = channel1_->AddSendStream(sp); - } - if (channel2_ && ret) { - ret = channel2_->AddSendStream(sp); - } - return ret; -} - -bool HybridVideoMediaChannel::RemoveSendStream(uint32 ssrc) { - bool ret = true; - if (channel1_) { - ret = channel1_->RemoveSendStream(ssrc); - } - if (channel2_ && ret) { - ret = channel2_->RemoveSendStream(ssrc); - } - return ret; -} - -bool HybridVideoMediaChannel::AddRecvStream(const StreamParams& sp) { - return active_channel_ && - active_channel_->AddRecvStream(sp); -} - -bool HybridVideoMediaChannel::RemoveRecvStream(uint32 ssrc) { - return active_channel_ && - active_channel_->RemoveRecvStream(ssrc); -} - -bool HybridVideoMediaChannel::SendIntraFrame() { - return active_channel_ && - active_channel_->SendIntraFrame(); -} - -bool HybridVideoMediaChannel::RequestIntraFrame() { - return active_channel_ && - active_channel_->RequestIntraFrame(); -} - -bool HybridVideoMediaChannel::GetStats( - const StatsOptions& options, VideoMediaInfo* info) { - // TODO(juberti): Ensure that returning no stats until SetSendCodecs is OK. - return active_channel_ && - active_channel_->GetStats(options, info); -} - -void HybridVideoMediaChannel::OnPacketReceived( - rtc::Buffer* packet, const rtc::PacketTime& packet_time) { - // Eat packets until we have an active channel; - if (active_channel_) { - active_channel_->OnPacketReceived(packet, packet_time); - } else { - LOG(LS_INFO) << "HybridVideoChannel: Eating early RTP packet"; - } -} - -void HybridVideoMediaChannel::OnRtcpReceived( - rtc::Buffer* packet, const rtc::PacketTime& packet_time) { - // Eat packets until we have an active channel; - if (active_channel_) { - active_channel_->OnRtcpReceived(packet, packet_time); - } else { - LOG(LS_INFO) << "HybridVideoChannel: Eating early RTCP packet"; - } -} - -void HybridVideoMediaChannel::OnReadyToSend(bool ready) { - if (channel1_) { - channel1_->OnReadyToSend(ready); - } - if (channel2_) { - channel2_->OnReadyToSend(ready); - } -} - -void HybridVideoMediaChannel::UpdateAspectRatio(int ratio_w, int ratio_h) { - if (active_channel_) active_channel_->UpdateAspectRatio(ratio_w, ratio_h); -} - -bool HybridVideoMediaChannel::SelectActiveChannel( - const std::vector& codecs) { - if (!active_channel_ && !codecs.empty()) { - if (engine_->HasCodec1(codecs[0])) { - channel2_.reset(); - active_channel_ = channel1_.get(); - } else if (engine_->HasCodec2(codecs[0])) { - channel1_.reset(); - active_channel_ = channel2_.get(); - } - } - if (NULL == active_channel_) { - return false; - } - // Connect signals from the active channel. - active_channel_->SignalMediaError.connect( - this, - &HybridVideoMediaChannel::OnMediaError); - return true; -} - -void HybridVideoMediaChannel::SplitCodecs( - const std::vector& codecs, - std::vector* codecs1, std::vector* codecs2) { - codecs1->clear(); - codecs2->clear(); - for (size_t i = 0; i < codecs.size(); ++i) { - if (engine_->HasCodec1(codecs[i])) { - codecs1->push_back(codecs[i]); - } - if (engine_->HasCodec2(codecs[i])) { - codecs2->push_back(codecs[i]); - } - } -} - -void HybridVideoMediaChannel::OnMediaError(uint32 ssrc, Error error) { - SignalMediaError(ssrc, error); -} - -} // namespace cricket diff --git a/talk/media/base/hybridvideoengine.h b/talk/media/base/hybridvideoengine.h deleted file mode 100644 index 02b74dafd4..0000000000 --- a/talk/media/base/hybridvideoengine.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * libjingle - * Copyright 2004 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. - */ - -#ifndef TALK_MEDIA_BASE_HYBRIDVIDEOENGINE_H_ -#define TALK_MEDIA_BASE_HYBRIDVIDEOENGINE_H_ - -#include -#include - -#include "talk/media/base/codec.h" -#include "talk/media/base/mediachannel.h" -#include "talk/media/base/videocapturer.h" -#include "talk/media/base/videocommon.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/sigslotrepeater.h" - -namespace cricket { - -struct Device; -struct VideoFormat; -class HybridVideoEngineInterface; -class VideoCapturer; -class VideoFrame; -class VideoRenderer; - -// HybridVideoMediaChannels work with a HybridVideoEngine to combine -// two unrelated VideoMediaChannel implementations into a single class. -class HybridVideoMediaChannel : public VideoMediaChannel { - public: - HybridVideoMediaChannel(HybridVideoEngineInterface* engine, - VideoMediaChannel* channel1, - VideoMediaChannel* channel2); - virtual ~HybridVideoMediaChannel(); - - // VideoMediaChannel methods - virtual void SetInterface(NetworkInterface* iface); - virtual bool SetOptions(const VideoOptions& options); - virtual bool GetOptions(VideoOptions* options) const; - virtual bool AddSendStream(const StreamParams& sp); - virtual bool RemoveSendStream(uint32 ssrc); - virtual bool SetRenderer(uint32 ssrc, VideoRenderer* renderer); - virtual bool SetRender(bool render); - virtual bool MuteStream(uint32 ssrc, bool muted); - - virtual bool SetRecvCodecs(const std::vector& codecs); - virtual bool SetRecvRtpHeaderExtensions( - const std::vector& extensions); - - virtual bool SetSendCodecs(const std::vector& codecs); - virtual bool GetSendCodec(VideoCodec* codec); - virtual bool SetSendStreamFormat(uint32 ssrc, const VideoFormat& format); - virtual bool SetSendRtpHeaderExtensions( - const std::vector& extensions); - virtual bool SetStartSendBandwidth(int bps); - virtual bool SetMaxSendBandwidth(int bps); - virtual bool SetSend(bool send); - - virtual bool AddRecvStream(const StreamParams& sp); - virtual bool RemoveRecvStream(uint32 ssrc); - virtual bool SetCapturer(uint32 ssrc, VideoCapturer* capturer); - - virtual bool SendIntraFrame(); - virtual bool RequestIntraFrame(); - - virtual bool GetStats(const StatsOptions& options, VideoMediaInfo* info); - - virtual void OnPacketReceived(rtc::Buffer* packet, - const rtc::PacketTime& packet_time); - virtual void OnRtcpReceived(rtc::Buffer* packet, - const rtc::PacketTime& packet_time); - virtual void OnReadyToSend(bool ready); - - virtual void UpdateAspectRatio(int ratio_w, int ratio_h); - - void OnLocalFrame(VideoCapturer*, const VideoFrame*); - void OnLocalFrameFormat(VideoCapturer*, const VideoFormat*); - - bool sending() const { return sending_; } - - private: - bool SelectActiveChannel(const std::vector& codecs); - void SplitCodecs(const std::vector& codecs, - std::vector* codecs1, - std::vector* codecs2); - - void OnMediaError(uint32 ssrc, Error error); - - HybridVideoEngineInterface* engine_; - rtc::scoped_ptr channel1_; - rtc::scoped_ptr channel2_; - VideoMediaChannel* active_channel_; - bool sending_; -}; - -// Interface class for HybridVideoChannels to talk to the engine. -class HybridVideoEngineInterface { - public: - virtual ~HybridVideoEngineInterface() {} - virtual bool HasCodec1(const VideoCodec& codec) = 0; - virtual bool HasCodec2(const VideoCodec& codec) = 0; - virtual void OnSendChange1(VideoMediaChannel* channel1, bool send) = 0; - virtual void OnSendChange2(VideoMediaChannel* channel1, bool send) = 0; - virtual void OnNewSendResolution(int width, int height) = 0; -}; - -// The HybridVideoEngine class combines two unrelated VideoEngine impls -// into a single class. It creates HybridVideoMediaChannels that also contain -// a VideoMediaChannel implementation from each engine. Policy is then used -// during call setup to determine which VideoMediaChannel should be used. -// Currently, this policy is based on what codec the remote side wants to use. -template -class HybridVideoEngine : public HybridVideoEngineInterface { - public: - HybridVideoEngine() { - // Unify the codec lists. - codecs_ = video1_.codecs(); - codecs_.insert(codecs_.end(), video2_.codecs().begin(), - video2_.codecs().end()); - - rtp_header_extensions_ = video1_.rtp_header_extensions(); - rtp_header_extensions_.insert(rtp_header_extensions_.end(), - video2_.rtp_header_extensions().begin(), - video2_.rtp_header_extensions().end()); - - SignalCaptureStateChange.repeat(video2_.SignalCaptureStateChange); - } - - bool Init(rtc::Thread* worker_thread) { - if (!video1_.Init(worker_thread)) { - LOG(LS_ERROR) << "Failed to init VideoEngine1"; - return false; - } - if (!video2_.Init(worker_thread)) { - LOG(LS_ERROR) << "Failed to init VideoEngine2"; - video1_.Terminate(); - return false; - } - return true; - } - void Terminate() { - video1_.Terminate(); - video2_.Terminate(); - } - - int GetCapabilities() { - return (video1_.GetCapabilities() | video2_.GetCapabilities()); - } - HybridVideoMediaChannel* CreateChannel(VoiceMediaChannel* channel) { - rtc::scoped_ptr channel1( - video1_.CreateChannel(channel)); - if (!channel1) { - LOG(LS_ERROR) << "Failed to create VideoMediaChannel1"; - return NULL; - } - rtc::scoped_ptr channel2( - video2_.CreateChannel(channel)); - if (!channel2) { - LOG(LS_ERROR) << "Failed to create VideoMediaChannel2"; - return NULL; - } - return new HybridVideoMediaChannel(this, - channel1.release(), channel2.release()); - } - - bool SetOptions(const VideoOptions& options) { - return video1_.SetOptions(options) && video2_.SetOptions(options); - } - bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) { - VideoEncoderConfig conf = config; - if (video1_.codecs().size() > 0) { - conf.max_codec.name = video1_.codecs()[0].name; - if (!video1_.SetDefaultEncoderConfig(conf)) { - LOG(LS_ERROR) << "Failed to SetDefaultEncoderConfig for video1"; - return false; - } - } - if (video2_.codecs().size() > 0) { - conf.max_codec.name = video2_.codecs()[0].name; - if (!video2_.SetDefaultEncoderConfig(conf)) { - LOG(LS_ERROR) << "Failed to SetDefaultEncoderConfig for video2"; - return false; - } - } - return true; - } - VideoEncoderConfig GetDefaultEncoderConfig() const { - // This looks pretty strange, but, in practice, it'll do sane things if - // GetDefaultEncoderConfig is only called after SetDefaultEncoderConfig, - // since both engines should be essentially equivalent at that point. If it - // hasn't been called, though, we'll use the first meaningful encoder - // config, or the config from the second video engine if neither are - // meaningful. - VideoEncoderConfig config = video1_.GetDefaultEncoderConfig(); - if (config.max_codec.width != 0) { - return config; - } else { - return video2_.GetDefaultEncoderConfig(); - } - } - const std::vector& codecs() const { - return codecs_; - } - const std::vector& rtp_header_extensions() const { - return rtp_header_extensions_; - } - void SetLogging(int min_sev, const char* filter) { - video1_.SetLogging(min_sev, filter); - video2_.SetLogging(min_sev, filter); - } - - VideoFormat GetStartCaptureFormat() const { - return video2_.GetStartCaptureFormat(); - } - - // TODO(juberti): Remove these functions after we do the capturer refactoring. - // For now they are set to always use the second engine for capturing, which - // is convenient given our intended use case. - bool SetCaptureDevice(const Device* device) { - return video2_.SetCaptureDevice(device); - } - VideoCapturer* GetVideoCapturer() const { - return video2_.GetVideoCapturer(); - } - sigslot::repeater2 SignalCaptureStateChange; - - virtual bool HasCodec1(const VideoCodec& codec) { - return HasCodec(video1_, codec); - } - virtual bool HasCodec2(const VideoCodec& codec) { - return HasCodec(video2_, codec); - } - template - bool HasCodec(const VIDEO& engine, const VideoCodec& codec) const { - for (std::vector::const_iterator i = engine.codecs().begin(); - i != engine.codecs().end(); - ++i) { - if (i->Matches(codec)) { - return true; - } - } - return false; - } - virtual void OnSendChange1(VideoMediaChannel* channel1, bool send) { - } - virtual void OnSendChange2(VideoMediaChannel* channel2, bool send) { - } - virtual void OnNewSendResolution(int width, int height) { - } - - protected: - VIDEO1 video1_; - VIDEO2 video2_; - std::vector codecs_; - std::vector rtp_header_extensions_; -}; - -} // namespace cricket - -#endif // TALK_MEDIA_BASE_HYBRIDVIDEOENGINE_H_ diff --git a/talk/media/base/hybridvideoengine_unittest.cc b/talk/media/base/hybridvideoengine_unittest.cc deleted file mode 100644 index 7b409ead2e..0000000000 --- a/talk/media/base/hybridvideoengine_unittest.cc +++ /dev/null @@ -1,486 +0,0 @@ -/* - * libjingle - * Copyright 2004 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. - */ - -#include "talk/media/base/fakemediaengine.h" -#include "talk/media/base/fakenetworkinterface.h" -#include "talk/media/base/fakevideocapturer.h" -#include "talk/media/base/hybridvideoengine.h" -#include "talk/media/base/mediachannel.h" -#include "talk/media/base/testutils.h" -#include "webrtc/base/gunit.h" - -static const cricket::VideoCodec kGenericCodec(97, "Generic", 640, 360, 30, 0); -static const cricket::VideoCodec kVp8Codec(100, "VP8", 640, 360, 30, 0); -static const cricket::VideoCodec kCodecsVp8Only[] = { kVp8Codec }; -static const cricket::VideoCodec kCodecsGenericOnly[] = { kGenericCodec }; -static const cricket::VideoCodec kCodecsVp8First[] = { kVp8Codec, - kGenericCodec }; -static const cricket::VideoCodec kCodecsGenericFirst[] = { kGenericCodec, - kVp8Codec }; - -using cricket::StreamParams; - -class FakeVp8VideoEngine : public cricket::FakeVideoEngine { - public: - FakeVp8VideoEngine() { - SetCodecs(MAKE_VECTOR(kCodecsVp8Only)); - } -}; -class FakeGenericVideoEngine : public cricket::FakeVideoEngine { - public: - FakeGenericVideoEngine() { - SetCodecs(MAKE_VECTOR(kCodecsGenericOnly)); - } - - // For testing purposes, mimic the behavior of a media engine that throws out - // resolutions that don't match the codec list. A width or height of 0 - // trivially will never match the codec list, so this is sufficient for - // testing the case we want (0x0). - virtual bool FindCodec(const cricket::VideoCodec& codec) { - if (codec.width == 0 || codec.height == 0) { - return false; - } else { - return cricket::FakeVideoEngine::FindCodec(codec); - } - } -}; -class HybridVideoEngineForTest : public cricket::HybridVideoEngine< - FakeVp8VideoEngine, FakeGenericVideoEngine> { - public: - HybridVideoEngineForTest() - : - num_ch1_send_on_(0), - num_ch1_send_off_(0), - send_width_(0), - send_height_(0) { } - cricket::FakeVideoEngine* sub_engine1() { return &video1_; } - cricket::FakeVideoEngine* sub_engine2() { return &video2_; } - - // From base class HybridVideoEngine. - void OnSendChange1(cricket::VideoMediaChannel* channel1, bool send) { - if (send) { - ++num_ch1_send_on_; - } else { - ++num_ch1_send_off_; - } - } - // From base class HybridVideoEngine - void OnNewSendResolution(int width, int height) { - send_width_ = width; - send_height_ = height; - } - - int num_ch1_send_on() const { return num_ch1_send_on_; } - int num_ch1_send_off() const { return num_ch1_send_off_; } - - int send_width() const { return send_width_; } - int send_height() const { return send_height_; } - - private: - int num_ch1_send_on_; - int num_ch1_send_off_; - - int send_width_; - int send_height_; -}; - -class HybridVideoEngineTest : public testing::Test { - public: - HybridVideoEngineTest() : sub_channel1_(NULL), sub_channel2_(NULL) { - } - ~HybridVideoEngineTest() { - engine_.Terminate(); - } - bool SetupEngine() { - bool result = engine_.Init(rtc::Thread::Current()); - if (result) { - channel_.reset(engine_.CreateChannel(NULL)); - result = (channel_.get() != NULL); - sub_channel1_ = engine_.sub_engine1()->GetChannel(0); - sub_channel2_ = engine_.sub_engine2()->GetChannel(0); - } - return result; - } - bool SetupRenderAndAddStream(const StreamParams& sp) { - if (!SetupEngine()) - return false; - channel_->SetInterface(transport_.get()); - return channel_->SetRecvCodecs(engine_.codecs()) && - channel_->AddSendStream(sp) && - channel_->SetRender(true); - } - void DeliverPacket(const void* data, int len) { - rtc::Buffer packet(data, len); - channel_->OnPacketReceived(&packet, rtc::CreatePacketTime(0)); - } - void DeliverRtcp(const void* data, int len) { - rtc::Buffer packet(data, len); - channel_->OnRtcpReceived(&packet, rtc::CreatePacketTime(0)); - } - - protected: - void TestSetSendCodecs(cricket::FakeVideoEngine* sub_engine, - const std::vector& codecs) { - EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234))); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - cricket::FakeVideoMediaChannel* sub_channel = sub_engine->GetChannel(0); - ASSERT_EQ(1U, sub_channel->send_codecs().size()); - EXPECT_EQ(codecs[0], sub_channel->send_codecs()[0]); - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(sub_channel->sending()); - } - void TestSetSendBandwidth(cricket::FakeVideoEngine* sub_engine, - const std::vector& codecs, - int start_bitrate, - int max_bitrate) { - EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234))); - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); - EXPECT_TRUE(channel_->SetStartSendBandwidth(start_bitrate)); - EXPECT_TRUE(channel_->SetMaxSendBandwidth(max_bitrate)); - cricket::FakeVideoMediaChannel* sub_channel = sub_engine->GetChannel(0); - EXPECT_EQ(start_bitrate, sub_channel->start_bps()); - EXPECT_EQ(max_bitrate, sub_channel->max_bps()); - } - HybridVideoEngineForTest engine_; - rtc::scoped_ptr channel_; - rtc::scoped_ptr transport_; - cricket::FakeVideoMediaChannel* sub_channel1_; - cricket::FakeVideoMediaChannel* sub_channel2_; -}; - -TEST_F(HybridVideoEngineTest, StartupShutdown) { - EXPECT_TRUE(engine_.Init(rtc::Thread::Current())); - engine_.Terminate(); -} - -// Tests that SetDefaultVideoEncoderConfig passes down to both engines. -TEST_F(HybridVideoEngineTest, SetDefaultVideoEncoderConfig) { - cricket::VideoEncoderConfig config( - cricket::VideoCodec(105, "", 640, 400, 30, 0), 1, 2); - EXPECT_TRUE(engine_.SetDefaultEncoderConfig(config)); - - cricket::VideoEncoderConfig config_1 = config; - config_1.max_codec.name = kCodecsVp8Only[0].name; - EXPECT_EQ(config_1, engine_.sub_engine1()->default_encoder_config()); - - cricket::VideoEncoderConfig config_2 = config; - config_2.max_codec.name = kCodecsGenericOnly[0].name; - EXPECT_EQ(config_2, engine_.sub_engine2()->default_encoder_config()); -} - -// Tests that GetDefaultVideoEncoderConfig picks a meaningful encoder config -// based on the underlying engine config and then after a call to -// SetDefaultEncoderConfig on the hybrid engine. -TEST_F(HybridVideoEngineTest, SetDefaultVideoEncoderConfigDefaultValue) { - cricket::VideoEncoderConfig blank_config; - cricket::VideoEncoderConfig meaningful_config1( - cricket::VideoCodec(111, "abcd", 320, 240, 30, 0), 1, 2); - cricket::VideoEncoderConfig meaningful_config2( - cricket::VideoCodec(111, "abcd", 1280, 720, 30, 0), 1, 2); - cricket::VideoEncoderConfig meaningful_config3( - cricket::VideoCodec(111, "abcd", 640, 360, 30, 0), 1, 2); - engine_.sub_engine1()->SetDefaultEncoderConfig(blank_config); - engine_.sub_engine2()->SetDefaultEncoderConfig(blank_config); - EXPECT_EQ(blank_config, engine_.GetDefaultEncoderConfig()); - - engine_.sub_engine2()->SetDefaultEncoderConfig(meaningful_config2); - EXPECT_EQ(meaningful_config2, engine_.GetDefaultEncoderConfig()); - - engine_.sub_engine1()->SetDefaultEncoderConfig(meaningful_config1); - EXPECT_EQ(meaningful_config1, engine_.GetDefaultEncoderConfig()); - - EXPECT_TRUE(engine_.SetDefaultEncoderConfig(meaningful_config3)); - // The overall config should now match, though the codec name will have been - // rewritten for the first media engine. - meaningful_config3.max_codec.name = kCodecsVp8Only[0].name; - EXPECT_EQ(meaningful_config3, engine_.GetDefaultEncoderConfig()); -} - -// Tests that our engine has the right codecs in the right order. -TEST_F(HybridVideoEngineTest, CheckCodecs) { - const std::vector& c = engine_.codecs(); - ASSERT_EQ(2U, c.size()); - EXPECT_EQ(kVp8Codec, c[0]); - EXPECT_EQ(kGenericCodec, c[1]); -} - -// Tests that our engine has the right caps. -TEST_F(HybridVideoEngineTest, CheckCaps) { - EXPECT_EQ(cricket::VIDEO_SEND | cricket::VIDEO_RECV, - engine_.GetCapabilities()); -} - -// Tests that we can create and destroy a channel. -TEST_F(HybridVideoEngineTest, CreateChannel) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(sub_channel1_ != NULL); - EXPECT_TRUE(sub_channel2_ != NULL); -} - -// Tests that we properly handle failures in CreateChannel. -TEST_F(HybridVideoEngineTest, CreateChannelFail) { - engine_.sub_engine1()->set_fail_create_channel(true); - EXPECT_FALSE(SetupEngine()); - EXPECT_TRUE(channel_.get() == NULL); - EXPECT_TRUE(sub_channel1_ == NULL); - EXPECT_TRUE(sub_channel2_ == NULL); - engine_.sub_engine1()->set_fail_create_channel(false); - engine_.sub_engine2()->set_fail_create_channel(true); - EXPECT_FALSE(SetupEngine()); - EXPECT_TRUE(channel_.get() == NULL); - EXPECT_TRUE(sub_channel1_ == NULL); - EXPECT_TRUE(sub_channel2_ == NULL); -} - -// Test that we set our inbound codecs and settings properly. -TEST_F(HybridVideoEngineTest, SetLocalDescription) { - EXPECT_TRUE(SetupEngine()); - channel_->SetInterface(transport_.get()); - EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs())); - ASSERT_EQ(1U, sub_channel1_->recv_codecs().size()); - ASSERT_EQ(1U, sub_channel2_->recv_codecs().size()); - EXPECT_EQ(kVp8Codec, sub_channel1_->recv_codecs()[0]); - EXPECT_EQ(kGenericCodec, sub_channel2_->recv_codecs()[0]); - StreamParams stream; - stream.id = "TestStream"; - stream.ssrcs.push_back(1234); - stream.cname = "5678"; - EXPECT_TRUE(channel_->AddSendStream(stream)); - EXPECT_EQ(1234U, sub_channel1_->send_ssrc()); - EXPECT_EQ(1234U, sub_channel2_->send_ssrc()); - EXPECT_EQ("5678", sub_channel1_->rtcp_cname()); - EXPECT_EQ("5678", sub_channel2_->rtcp_cname()); - EXPECT_TRUE(channel_->SetRender(true)); - // We've called SetRender, so we should be playing out, but not yet sending. - EXPECT_TRUE(sub_channel1_->playout()); - EXPECT_TRUE(sub_channel2_->playout()); - EXPECT_FALSE(sub_channel1_->sending()); - EXPECT_FALSE(sub_channel2_->sending()); - // We may get SetSend(false) calls during call setup. - // Since this causes no change in state, they should no-op and return true. - EXPECT_TRUE(channel_->SetSend(false)); - EXPECT_FALSE(sub_channel1_->sending()); - EXPECT_FALSE(sub_channel2_->sending()); -} - -TEST_F(HybridVideoEngineTest, OnNewSendResolution) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First))); - EXPECT_EQ(640, engine_.send_width()); - EXPECT_EQ(360, engine_.send_height()); -} - -// Test that we converge to the active channel for engine 1. -TEST_F(HybridVideoEngineTest, SetSendCodecs1) { - // This will nuke the object that sub_channel2_ points to. - TestSetSendCodecs(engine_.sub_engine1(), MAKE_VECTOR(kCodecsVp8First)); - EXPECT_TRUE(engine_.sub_engine2()->GetChannel(0) == NULL); -} - -// Test that we converge to the active channel for engine 2. -TEST_F(HybridVideoEngineTest, SetSendCodecs2) { - // This will nuke the object that sub_channel1_ points to. - TestSetSendCodecs(engine_.sub_engine2(), MAKE_VECTOR(kCodecsGenericFirst)); - EXPECT_TRUE(engine_.sub_engine1()->GetChannel(0) == NULL); -} - -// Test that we don't accidentally eat 0x0 in SetSendCodecs -TEST_F(HybridVideoEngineTest, SetSendCodecs0x0) { - EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234))); - // Send using generic codec, but with 0x0 resolution. - std::vector codecs(MAKE_VECTOR(kCodecsGenericFirst)); - codecs.resize(1); - codecs[0].width = 0; - codecs[0].height = 0; - EXPECT_TRUE(channel_->SetSendCodecs(codecs)); -} - -// Test setting the send bandwidth for VP8. -TEST_F(HybridVideoEngineTest, SetSendBandwidth1) { - TestSetSendBandwidth(engine_.sub_engine1(), - MAKE_VECTOR(kCodecsVp8First), - 100000, - 384000); -} - -// Test setting the send bandwidth for a generic codec. -TEST_F(HybridVideoEngineTest, SetSendBandwidth2) { - TestSetSendBandwidth(engine_.sub_engine2(), - MAKE_VECTOR(kCodecsGenericFirst), - 100001, - 384002); -} - -// Test that we dump RTP packets that arrive early. -TEST_F(HybridVideoEngineTest, HandleEarlyRtp) { - static const uint8 kPacket[1024] = { 0 }; - static const uint8 kRtcp[1024] = { 1 }; - EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234))); - DeliverPacket(kPacket, sizeof(kPacket)); - DeliverRtcp(kRtcp, sizeof(kRtcp)); - EXPECT_TRUE(sub_channel1_->CheckNoRtp()); - EXPECT_TRUE(sub_channel2_->CheckNoRtp()); - EXPECT_TRUE(sub_channel1_->CheckNoRtcp()); - EXPECT_TRUE(sub_channel2_->CheckNoRtcp()); -} - -// Test that we properly pass on normal RTP packets. -TEST_F(HybridVideoEngineTest, HandleRtp) { - static const uint8 kPacket[1024] = { 0 }; - static const uint8 kRtcp[1024] = { 1 }; - EXPECT_TRUE(SetupRenderAndAddStream(StreamParams::CreateLegacy(1234))); - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First))); - EXPECT_TRUE(channel_->SetSend(true)); - DeliverPacket(kPacket, sizeof(kPacket)); - DeliverRtcp(kRtcp, sizeof(kRtcp)); - EXPECT_TRUE(sub_channel1_->CheckRtp(kPacket, sizeof(kPacket))); - EXPECT_TRUE(sub_channel1_->CheckRtcp(kRtcp, sizeof(kRtcp))); -} - -// Test that we properly connect media error signal. -TEST_F(HybridVideoEngineTest, MediaErrorSignal) { - cricket::VideoMediaErrorCatcher catcher; - - // Verify no signal from either channel before the active channel is set. - EXPECT_TRUE(SetupEngine()); - channel_->SignalMediaError.connect(&catcher, - &cricket::VideoMediaErrorCatcher::OnError); - sub_channel1_->SignalMediaError(1, cricket::VideoMediaChannel::ERROR_OTHER); - EXPECT_EQ(0U, catcher.ssrc()); - sub_channel2_->SignalMediaError(2, - cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED); - EXPECT_EQ(0U, catcher.ssrc()); - - // Set vp8 as active channel and verify that a signal comes from it. - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First))); - sub_channel1_->SignalMediaError(1, cricket::VideoMediaChannel::ERROR_OTHER); - EXPECT_EQ(cricket::VideoMediaChannel::ERROR_OTHER, catcher.error()); - EXPECT_EQ(1U, catcher.ssrc()); - - // Set generic codec as active channel and verify that a signal comes from it. - EXPECT_TRUE(SetupEngine()); - channel_->SignalMediaError.connect(&catcher, - &cricket::VideoMediaErrorCatcher::OnError); - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsGenericFirst))); - sub_channel2_->SignalMediaError(2, - cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED); - EXPECT_EQ(cricket::VideoMediaChannel::ERROR_REC_DEVICE_OPEN_FAILED, - catcher.error()); - EXPECT_EQ(2U, catcher.ssrc()); -} - -// Test that SetSend doesn't re-enter. -TEST_F(HybridVideoEngineTest, RepeatSetSend) { - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First))); - - // Verify initial status. - EXPECT_FALSE(channel_->sending()); - EXPECT_FALSE(sub_channel1_->sending()); - EXPECT_EQ(0, engine_.num_ch1_send_on()); - EXPECT_EQ(0, engine_.num_ch1_send_off()); - - // Verfiy SetSend(true) works correctly. - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->sending()); - EXPECT_TRUE(sub_channel1_->sending()); - EXPECT_EQ(1, engine_.num_ch1_send_on()); - EXPECT_EQ(0, engine_.num_ch1_send_off()); - - // SetSend(true) again and verify nothing changes. - EXPECT_TRUE(channel_->SetSend(true)); - EXPECT_TRUE(channel_->sending()); - EXPECT_TRUE(sub_channel1_->sending()); - EXPECT_EQ(1, engine_.num_ch1_send_on()); - EXPECT_EQ(0, engine_.num_ch1_send_off()); - - // Verify SetSend(false) works correctly. - EXPECT_TRUE(channel_->SetSend(false)); - EXPECT_FALSE(channel_->sending()); - EXPECT_FALSE(sub_channel1_->sending()); - EXPECT_EQ(1, engine_.num_ch1_send_on()); - EXPECT_EQ(1, engine_.num_ch1_send_off()); - - // SetSend(false) again and verfiy nothing changes. - EXPECT_TRUE(channel_->SetSend(false)); - EXPECT_FALSE(channel_->sending()); - EXPECT_FALSE(sub_channel1_->sending()); - EXPECT_EQ(1, engine_.num_ch1_send_on()); - EXPECT_EQ(1, engine_.num_ch1_send_off()); -} - -// Test that SetOptions. -TEST_F(HybridVideoEngineTest, SetOptions) { - cricket::VideoOptions vmo; - vmo.video_high_bitrate.Set(true); - vmo.system_low_adaptation_threshhold.Set(0.10f); - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->SetOptions(vmo)); - - bool high_bitrate; - float low; - EXPECT_TRUE(sub_channel1_->GetOptions(&vmo)); - EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate)); - EXPECT_TRUE(high_bitrate); - EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(0.10f, low); - EXPECT_TRUE(sub_channel2_->GetOptions(&vmo)); - EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate)); - EXPECT_TRUE(high_bitrate); - EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(0.10f, low); - - vmo.video_high_bitrate.Set(false); - vmo.system_low_adaptation_threshhold.Set(0.50f); - - EXPECT_TRUE(channel_->SetOptions(vmo)); - EXPECT_TRUE(sub_channel1_->GetOptions(&vmo)); - EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate)); - EXPECT_FALSE(high_bitrate); - EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(0.50f, low); - EXPECT_TRUE(sub_channel2_->GetOptions(&vmo)); - EXPECT_TRUE(vmo.video_high_bitrate.Get(&high_bitrate)); - EXPECT_FALSE(high_bitrate); - EXPECT_TRUE(vmo.system_low_adaptation_threshhold.Get(&low)); - EXPECT_EQ(0.50f, low); -} - -TEST_F(HybridVideoEngineTest, SetCapturer) { - EXPECT_TRUE(SetupEngine()); - // Set vp8 as active channel and verify that capturer can be set. - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsVp8First))); - cricket::FakeVideoCapturer fake_video_capturer; - EXPECT_TRUE(channel_->SetCapturer(0, &fake_video_capturer)); - EXPECT_TRUE(channel_->SetCapturer(0, NULL)); - - // Set generic codec active channel and verify that capturer can be set. - EXPECT_TRUE(SetupEngine()); - EXPECT_TRUE(channel_->SetSendCodecs(MAKE_VECTOR(kCodecsGenericFirst))); - EXPECT_TRUE(channel_->SetCapturer(0, &fake_video_capturer)); - EXPECT_TRUE(channel_->SetCapturer(0, NULL)); -}