aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--talk/app/webrtc/datachannel_unittest.cc2
-rw-r--r--talk/app/webrtc/mediastreamhandler.cc7
-rw-r--r--talk/app/webrtc/mediastreamhandler_unittest.cc10
-rw-r--r--talk/app/webrtc/mediastreaminterface.h6
-rw-r--r--talk/app/webrtc/mediastreamsignaling.cc32
-rw-r--r--talk/app/webrtc/mediastreamsignaling.h3
-rw-r--r--talk/app/webrtc/mediastreamsignaling_unittest.cc28
-rw-r--r--talk/app/webrtc/mediastreamtrackproxy.h1
-rw-r--r--talk/app/webrtc/peerconnection.cc2
-rw-r--r--talk/app/webrtc/peerconnectionfactory.cc7
-rw-r--r--talk/app/webrtc/peerconnectioninterface_unittest.cc2
-rw-r--r--talk/app/webrtc/remotevideocapturer.cc95
-rw-r--r--talk/app/webrtc/remotevideocapturer.h65
-rw-r--r--talk/app/webrtc/remotevideocapturer_unittest.cc132
-rw-r--r--talk/app/webrtc/statscollector.cc7
-rw-r--r--talk/app/webrtc/statstypes.h1
-rw-r--r--talk/app/webrtc/test/fakemediastreamsignaling.h5
-rw-r--r--talk/app/webrtc/videosource.cc (renamed from talk/app/webrtc/localvideosource.cc)77
-rw-r--r--talk/app/webrtc/videosource.h (renamed from talk/app/webrtc/localvideosource.h)29
-rw-r--r--talk/app/webrtc/videosource_unittest.cc (renamed from talk/app/webrtc/localvideosource_unittest.cc)194
-rw-r--r--talk/app/webrtc/videosourceinterface.h1
-rw-r--r--talk/app/webrtc/videosourceproxy.h1
-rw-r--r--talk/app/webrtc/videotrack.cc8
-rw-r--r--talk/app/webrtc/videotrack.h1
-rw-r--r--talk/app/webrtc/videotrack_unittest.cc31
-rw-r--r--talk/app/webrtc/webrtcsdp.cc2
-rw-r--r--talk/app/webrtc/webrtcsession_unittest.cc9
-rw-r--r--talk/base/gunit_prod.h6
-rw-r--r--talk/base/physicalsocketserver.cc9
-rwxr-xr-xtalk/libjingle.gyp6
-rwxr-xr-xtalk/libjingle_tests.gyp3
-rw-r--r--talk/media/base/mediachannel.h4
-rw-r--r--talk/media/base/mediaengine.h4
-rw-r--r--talk/media/devices/devicemanager.cc6
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.cc9
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.h1
-rw-r--r--talk/p2p/base/sessionmanager.cc6
-rw-r--r--talk/p2p/client/httpportallocator.h8
-rw-r--r--talk/session/media/channelmanager.h3
-rw-r--r--talk/xmpp/constants.cc1
-rw-r--r--talk/xmpp/constants.h1
-rw-r--r--talk/xmpp/hangoutpubsubclient.cc5
-rw-r--r--talk/xmpp/rostermodule.h9
-rw-r--r--talk/xmpp/rostermoduleimpl.cc7
44 files changed, 647 insertions, 199 deletions
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index 211b382413..2b0a9fe5a6 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -76,7 +76,7 @@ class SctpDataChannelTest : public testing::Test {
talk_base::Thread::Current())),
media_stream_signaling_(
new webrtc::MediaStreamSignaling(talk_base::Thread::Current(),
- NULL)),
+ NULL, channel_manager_.get())),
session_(channel_manager_.get(),
talk_base::Thread::Current(),
talk_base::Thread::Current(),
diff --git a/talk/app/webrtc/mediastreamhandler.cc b/talk/app/webrtc/mediastreamhandler.cc
index d43c6d5a1d..b09af7892f 100644
--- a/talk/app/webrtc/mediastreamhandler.cc
+++ b/talk/app/webrtc/mediastreamhandler.cc
@@ -28,7 +28,7 @@
#include "talk/app/webrtc/mediastreamhandler.h"
#include "talk/app/webrtc/localaudiosource.h"
-#include "talk/app/webrtc/localvideosource.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videosourceinterface.h"
namespace webrtc {
@@ -154,6 +154,8 @@ RemoteVideoTrackHandler::RemoteVideoTrackHandler(
remote_video_track_(track),
provider_(provider) {
OnEnabledChanged();
+ provider_->SetVideoPlayout(ssrc, true,
+ remote_video_track_->GetSource()->FrameInput());
}
RemoteVideoTrackHandler::~RemoteVideoTrackHandler() {
@@ -169,9 +171,6 @@ void RemoteVideoTrackHandler::OnStateChanged() {
}
void RemoteVideoTrackHandler::OnEnabledChanged() {
- provider_->SetVideoPlayout(ssrc(),
- remote_video_track_->enabled(),
- remote_video_track_->FrameInput());
}
MediaStreamHandler::MediaStreamHandler(MediaStreamInterface* stream,
diff --git a/talk/app/webrtc/mediastreamhandler_unittest.cc b/talk/app/webrtc/mediastreamhandler_unittest.cc
index a874bde0b4..475258e9b9 100644
--- a/talk/app/webrtc/mediastreamhandler_unittest.cc
+++ b/talk/app/webrtc/mediastreamhandler_unittest.cc
@@ -30,9 +30,9 @@
#include <string>
#include "talk/app/webrtc/audiotrack.h"
-#include "talk/app/webrtc/localvideosource.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/streamcollection.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/gunit.h"
#include "talk/media/base/fakevideocapturer.h"
@@ -86,6 +86,7 @@ class FakeVideoSource : public Notifier<VideoSourceInterface> {
virtual void RemoveSink(cricket::VideoRenderer* output) {}
virtual SourceState state() const { return state_; }
virtual const cricket::VideoOptions* options() const { return &options_; }
+ virtual cricket::VideoRenderer* FrameInput() { return NULL; }
protected:
FakeVideoSource() : state_(kLive) {}
@@ -149,8 +150,8 @@ class MediaStreamHandlerTest : public testing::Test {
}
void AddRemoteVideoTrack() {
- EXPECT_CALL(video_provider_, SetVideoPlayout(kVideoSsrc, true,
- video_track_->FrameInput()));
+ EXPECT_CALL(video_provider_, SetVideoPlayout(
+ kVideoSsrc, true, video_track_->GetSource()->FrameInput()));
handlers_.AddRemoteVideoTrack(stream_, stream_->GetVideoTracks()[0],
kVideoSsrc);
}
@@ -283,11 +284,8 @@ TEST_F(MediaStreamHandlerTest, LocalVideoTrackDisable) {
TEST_F(MediaStreamHandlerTest, RemoteVideoTrackDisable) {
AddRemoteVideoTrack();
- EXPECT_CALL(video_provider_, SetVideoPlayout(kVideoSsrc, false, _));
video_track_->set_enabled(false);
- EXPECT_CALL(video_provider_, SetVideoPlayout(kVideoSsrc, true,
- video_track_->FrameInput()));
video_track_->set_enabled(true);
RemoveRemoteVideoTrack();
diff --git a/talk/app/webrtc/mediastreaminterface.h b/talk/app/webrtc/mediastreaminterface.h
index c16ac9d600..b2c4468fb9 100644
--- a/talk/app/webrtc/mediastreaminterface.h
+++ b/talk/app/webrtc/mediastreaminterface.h
@@ -134,12 +134,6 @@ class VideoTrackInterface : public MediaStreamTrackInterface {
// Deregister a renderer.
virtual void RemoveRenderer(VideoRendererInterface* renderer) = 0;
- // Gets a pointer to the frame input of this VideoTrack.
- // The pointer is valid for the lifetime of this VideoTrack.
- // VideoFrames rendered to the cricket::VideoRenderer will be rendered on all
- // registered renderers.
- virtual cricket::VideoRenderer* FrameInput() = 0;
-
virtual VideoSourceInterface* GetSource() const = 0;
protected:
diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc
index dac4543b22..371c28aaac 100644
--- a/talk/app/webrtc/mediastreamsignaling.cc
+++ b/talk/app/webrtc/mediastreamsignaling.cc
@@ -33,6 +33,8 @@
#include "talk/app/webrtc/mediastreamproxy.h"
#include "talk/app/webrtc/mediaconstraintsinterface.h"
#include "talk/app/webrtc/mediastreamtrackproxy.h"
+#include "talk/app/webrtc/remotevideocapturer.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/bytebuffer.h"
@@ -132,8 +134,10 @@ static bool EvaluateNeedForBundle(const cricket::MediaSessionOptions& options) {
// Factory class for creating remote MediaStreams and MediaStreamTracks.
class RemoteMediaStreamFactory {
public:
- explicit RemoteMediaStreamFactory(talk_base::Thread* signaling_thread)
- : signaling_thread_(signaling_thread) {
+ explicit RemoteMediaStreamFactory(talk_base::Thread* signaling_thread,
+ cricket::ChannelManager* channel_manager)
+ : signaling_thread_(signaling_thread),
+ channel_manager_(channel_manager) {
}
talk_base::scoped_refptr<MediaStreamInterface> CreateMediaStream(
@@ -144,21 +148,24 @@ class RemoteMediaStreamFactory {
AudioTrackInterface* AddAudioTrack(webrtc::MediaStreamInterface* stream,
const std::string& track_id) {
- return AddTrack<AudioTrackInterface, AudioTrack, AudioTrackProxy>(stream,
- track_id);
+ return AddTrack<AudioTrackInterface, AudioTrack, AudioTrackProxy>(
+ stream, track_id, static_cast<AudioSourceInterface*>(NULL));
}
VideoTrackInterface* AddVideoTrack(webrtc::MediaStreamInterface* stream,
const std::string& track_id) {
- return AddTrack<VideoTrackInterface, VideoTrack, VideoTrackProxy>(stream,
- track_id);
+ return AddTrack<VideoTrackInterface, VideoTrack, VideoTrackProxy>(
+ stream, track_id, VideoSource::Create(channel_manager_,
+ new RemoteVideoCapturer(),
+ NULL).get());
}
private:
- template <typename TI, typename T, typename TP>
- TI* AddTrack(MediaStreamInterface* stream, const std::string& track_id) {
+ template <typename TI, typename T, typename TP, typename S>
+ TI* AddTrack(MediaStreamInterface* stream, const std::string& track_id,
+ S* source) {
talk_base::scoped_refptr<TI> track(
- TP::Create(signaling_thread_, T::Create(track_id, NULL)));
+ TP::Create(signaling_thread_, T::Create(track_id, source)));
track->set_state(webrtc::MediaStreamTrackInterface::kLive);
if (stream->AddTrack(track)) {
return track;
@@ -167,17 +174,20 @@ class RemoteMediaStreamFactory {
}
talk_base::Thread* signaling_thread_;
+ cricket::ChannelManager* channel_manager_;
};
MediaStreamSignaling::MediaStreamSignaling(
talk_base::Thread* signaling_thread,
- MediaStreamSignalingObserver* stream_observer)
+ MediaStreamSignalingObserver* stream_observer,
+ cricket::ChannelManager* channel_manager)
: signaling_thread_(signaling_thread),
data_channel_factory_(NULL),
stream_observer_(stream_observer),
local_streams_(StreamCollection::Create()),
remote_streams_(StreamCollection::Create()),
- remote_stream_factory_(new RemoteMediaStreamFactory(signaling_thread)),
+ remote_stream_factory_(new RemoteMediaStreamFactory(signaling_thread,
+ channel_manager)),
last_allocated_sctp_id_(0) {
options_.has_video = false;
options_.has_audio = false;
diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h
index 721799da10..f64bf978ff 100644
--- a/talk/app/webrtc/mediastreamsignaling.h
+++ b/talk/app/webrtc/mediastreamsignaling.h
@@ -159,7 +159,8 @@ class MediaStreamSignalingObserver {
class MediaStreamSignaling {
public:
MediaStreamSignaling(talk_base::Thread* signaling_thread,
- MediaStreamSignalingObserver* stream_observer);
+ MediaStreamSignalingObserver* stream_observer,
+ cricket::ChannelManager* channel_manager);
virtual ~MediaStreamSignaling();
// Notify all referenced objects that MediaStreamSignaling will be teared
diff --git a/talk/app/webrtc/mediastreamsignaling_unittest.cc b/talk/app/webrtc/mediastreamsignaling_unittest.cc
index d2dc19e844..ea1336450d 100644
--- a/talk/app/webrtc/mediastreamsignaling_unittest.cc
+++ b/talk/app/webrtc/mediastreamsignaling_unittest.cc
@@ -37,8 +37,11 @@
#include "talk/base/scoped_ptr.h"
#include "talk/base/stringutils.h"
#include "talk/base/thread.h"
+#include "talk/media/base/fakemediaengine.h"
+#include "talk/media/devices/fakedevicemanager.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/sessiondescription.h"
+#include "talk/session/media/channelmanager.h"
static const char kStreams[][8] = {"stream1", "stream2"};
static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"};
@@ -285,13 +288,13 @@ class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
}
virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
- VideoTrackInterface* video_track,
- uint32 ssrc) {
+ VideoTrackInterface* video_track,
+ uint32 ssrc) {
AddTrack(&remote_video_tracks_, stream, video_track, ssrc);
}
virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
- AudioTrackInterface* audio_track) {
+ AudioTrackInterface* audio_track) {
RemoveTrack(&remote_audio_tracks_, stream, audio_track);
}
@@ -392,8 +395,10 @@ class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
class MediaStreamSignalingForTest : public webrtc::MediaStreamSignaling {
public:
- explicit MediaStreamSignalingForTest(MockSignalingObserver* observer)
- : webrtc::MediaStreamSignaling(talk_base::Thread::Current(), observer) {
+ MediaStreamSignalingForTest(MockSignalingObserver* observer,
+ cricket::ChannelManager* channel_manager)
+ : webrtc::MediaStreamSignaling(talk_base::Thread::Current(), observer,
+ channel_manager) {
};
using webrtc::MediaStreamSignaling::GetOptionsForOffer;
@@ -406,7 +411,12 @@ class MediaStreamSignalingTest: public testing::Test {
protected:
virtual void SetUp() {
observer_.reset(new MockSignalingObserver());
- signaling_.reset(new MediaStreamSignalingForTest(observer_.get()));
+ channel_manager_.reset(
+ new cricket::ChannelManager(new cricket::FakeMediaEngine(),
+ new cricket::FakeDeviceManager(),
+ talk_base::Thread::Current()));
+ signaling_.reset(new MediaStreamSignalingForTest(observer_.get(),
+ channel_manager_.get()));
}
// Create a collection of streams.
@@ -497,6 +507,9 @@ class MediaStreamSignalingTest: public testing::Test {
ASSERT_TRUE(stream->AddTrack(video_track));
}
+ // ChannelManager is used by VideoSource, so it should be released after all
+ // the video tracks. Put it as the first private variable should ensure that.
+ talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
talk_base::scoped_refptr<StreamCollection> reference_collection_;
talk_base::scoped_ptr<MockSignalingObserver> observer_;
talk_base::scoped_ptr<MediaStreamSignalingForTest> signaling_;
@@ -688,6 +701,9 @@ TEST_F(MediaStreamSignalingTest, UpdateRemoteStreams) {
observer_->VerifyRemoteAudioTrack(kStreams[0], kAudioTracks[0], 1);
EXPECT_EQ(1u, observer_->NumberOfRemoteVideoTracks());
observer_->VerifyRemoteVideoTrack(kStreams[0], kVideoTracks[0], 2);
+ ASSERT_EQ(1u, observer_->remote_streams()->count());
+ MediaStreamInterface* remote_stream = observer_->remote_streams()->at(0);
+ EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != NULL);
// Create a session description based on another SDP with another
// MediaStream.
diff --git a/talk/app/webrtc/mediastreamtrackproxy.h b/talk/app/webrtc/mediastreamtrackproxy.h
index 1efc8c616a..7c622e7333 100644
--- a/talk/app/webrtc/mediastreamtrackproxy.h
+++ b/talk/app/webrtc/mediastreamtrackproxy.h
@@ -61,7 +61,6 @@ BEGIN_PROXY_MAP(VideoTrack)
PROXY_METHOD1(void, AddRenderer, VideoRendererInterface*)
PROXY_METHOD1(void, RemoveRenderer, VideoRendererInterface*)
- PROXY_METHOD0(cricket::VideoRenderer*, FrameInput)
PROXY_CONSTMETHOD0(VideoSourceInterface*, GetSource)
PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index 77a5da65eb..9eaf915c39 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -303,7 +303,7 @@ bool PeerConnection::DoInitialize(
port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
mediastream_signaling_.reset(new MediaStreamSignaling(
- factory_->signaling_thread(), this));
+ factory_->signaling_thread(), this, factory_->channel_manager()));
session_.reset(new WebRtcSession(factory_->channel_manager(),
factory_->signaling_thread(),
diff --git a/talk/app/webrtc/peerconnectionfactory.cc b/talk/app/webrtc/peerconnectionfactory.cc
index 9c5c126b1a..7d30fab8ec 100644
--- a/talk/app/webrtc/peerconnectionfactory.cc
+++ b/talk/app/webrtc/peerconnectionfactory.cc
@@ -29,12 +29,12 @@
#include "talk/app/webrtc/audiotrack.h"
#include "talk/app/webrtc/localaudiosource.h"
-#include "talk/app/webrtc/localvideosource.h"
#include "talk/app/webrtc/mediastreamproxy.h"
#include "talk/app/webrtc/mediastreamtrackproxy.h"
#include "talk/app/webrtc/peerconnection.h"
#include "talk/app/webrtc/peerconnectionproxy.h"
#include "talk/app/webrtc/portallocatorfactory.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videosourceproxy.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/media/devices/dummydevicemanager.h"
@@ -269,9 +269,8 @@ talk_base::scoped_refptr<VideoSourceInterface>
PeerConnectionFactory::CreateVideoSource_s(
cricket::VideoCapturer* capturer,
const MediaConstraintsInterface* constraints) {
- talk_base::scoped_refptr<LocalVideoSource> source(
- LocalVideoSource::Create(channel_manager_.get(), capturer,
- constraints));
+ talk_base::scoped_refptr<VideoSource> source(
+ VideoSource::Create(channel_manager_.get(), capturer, constraints));
return VideoSourceProxy::Create(signaling_thread_, source);
}
diff --git a/talk/app/webrtc/peerconnectioninterface_unittest.cc b/talk/app/webrtc/peerconnectioninterface_unittest.cc
index e4f6e28d2e..9fbfefc616 100644
--- a/talk/app/webrtc/peerconnectioninterface_unittest.cc
+++ b/talk/app/webrtc/peerconnectioninterface_unittest.cc
@@ -29,12 +29,12 @@
#include "talk/app/webrtc/fakeportallocatorfactory.h"
#include "talk/app/webrtc/jsepsessiondescription.h"
-#include "talk/app/webrtc/localvideosource.h"
#include "talk/app/webrtc/mediastreaminterface.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
#include "talk/app/webrtc/test/testsdpstrings.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/base/gunit.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/sslstreamadapter.h"
diff --git a/talk/app/webrtc/remotevideocapturer.cc b/talk/app/webrtc/remotevideocapturer.cc
new file mode 100644
index 0000000000..072c8d81cc
--- /dev/null
+++ b/talk/app/webrtc/remotevideocapturer.cc
@@ -0,0 +1,95 @@
+/*
+ * libjingle
+ * Copyright 2013, 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/app/webrtc/remotevideocapturer.h"
+
+#include "talk/base/logging.h"
+#include "talk/media/base/videoframe.h"
+
+namespace webrtc {
+
+RemoteVideoCapturer::RemoteVideoCapturer() {}
+
+RemoteVideoCapturer::~RemoteVideoCapturer() {}
+
+cricket::CaptureState RemoteVideoCapturer::Start(
+ const cricket::VideoFormat& capture_format) {
+ if (capture_state() == cricket::CS_RUNNING) {
+ LOG(LS_WARNING)
+ << "RemoteVideoCapturer::Start called when it's already started.";
+ return capture_state();
+ }
+
+ LOG(LS_INFO) << "RemoteVideoCapturer::Start";
+ SetCaptureFormat(&capture_format);
+ return cricket::CS_RUNNING;
+}
+
+void RemoteVideoCapturer::Stop() {
+ if (capture_state() == cricket::CS_STOPPED) {
+ LOG(LS_WARNING)
+ << "RemoteVideoCapturer::Stop called when it's already stopped.";
+ return;
+ }
+
+ LOG(LS_INFO) << "RemoteVideoCapturer::Stop";
+ SetCaptureFormat(NULL);
+ SetCaptureState(cricket::CS_STOPPED);
+}
+
+bool RemoteVideoCapturer::IsRunning() {
+ return capture_state() == cricket::CS_RUNNING;
+}
+
+bool RemoteVideoCapturer::GetPreferredFourccs(std::vector<uint32>* fourccs) {
+ if (!fourccs)
+ return false;
+ fourccs->push_back(cricket::FOURCC_I420);
+ return true;
+}
+
+bool RemoteVideoCapturer::GetBestCaptureFormat(
+ const cricket::VideoFormat& desired, cricket::VideoFormat* best_format) {
+ if (!best_format) {
+ return false;
+ }
+
+ // RemoteVideoCapturer does not support capability enumeration.
+ // Use the desired format as the best format.
+ best_format->width = desired.width;
+ best_format->height = desired.height;
+ best_format->fourcc = cricket::FOURCC_I420;
+ best_format->interval = desired.interval;
+ return true;
+}
+
+bool RemoteVideoCapturer::IsScreencast() const {
+ // TODO(ronghuawu): what about remote screencast stream.
+ return false;
+}
+
+} // namespace webrtc
diff --git a/talk/app/webrtc/remotevideocapturer.h b/talk/app/webrtc/remotevideocapturer.h
new file mode 100644
index 0000000000..1ea0692006
--- /dev/null
+++ b/talk/app/webrtc/remotevideocapturer.h
@@ -0,0 +1,65 @@
+/*
+ * libjingle
+ * Copyright 2013, 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_APP_WEBRTC_REMOTEVIDEOCAPTURER_H_
+#define TALK_APP_WEBRTC_REMOTEVIDEOCAPTURER_H_
+
+#include <vector>
+
+#include "talk/app/webrtc/mediastreaminterface.h"
+#include "talk/media/base/videocapturer.h"
+#include "talk/media/base/videorenderer.h"
+
+namespace webrtc {
+
+// RemoteVideoCapturer implements a simple cricket::VideoCapturer which
+// gets decoded remote video frames from media channel.
+// It's used as the remote video source's VideoCapturer so that the remote video
+// can be used as a cricket::VideoCapturer and in that way a remote video stream
+// can implement the MediaStreamSourceInterface.
+class RemoteVideoCapturer : public cricket::VideoCapturer {
+ public:
+ RemoteVideoCapturer();
+ virtual ~RemoteVideoCapturer();
+
+ // cricket::VideoCapturer implementation.
+ virtual cricket::CaptureState Start(
+ const cricket::VideoFormat& capture_format) OVERRIDE;
+ virtual void Stop() OVERRIDE;
+ virtual bool IsRunning() OVERRIDE;
+ virtual bool GetPreferredFourccs(std::vector<uint32>* fourccs) OVERRIDE;
+ virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
+ cricket::VideoFormat* best_format) OVERRIDE;
+ virtual bool IsScreencast() const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RemoteVideoCapturer);
+};
+
+} // namespace webrtc
+
+#endif // TALK_APP_WEBRTC_REMOTEVIDEOCAPTURER_H_
diff --git a/talk/app/webrtc/remotevideocapturer_unittest.cc b/talk/app/webrtc/remotevideocapturer_unittest.cc
new file mode 100644
index 0000000000..68135507ca
--- /dev/null
+++ b/talk/app/webrtc/remotevideocapturer_unittest.cc
@@ -0,0 +1,132 @@
+/*
+ * libjingle
+ * Copyright 2013, 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 <string>
+
+#include "talk/app/webrtc/remotevideocapturer.h"
+#include "talk/base/gunit.h"
+#include "talk/media/webrtc/webrtcvideoframe.h"
+
+using cricket::CaptureState;
+using cricket::VideoCapturer;
+using cricket::VideoFormat;
+using cricket::VideoFormatPod;
+using cricket::VideoFrame;
+
+static const int kMaxWaitMs = 1000;
+static const VideoFormatPod kTestFormat =
+ {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY};
+
+class RemoteVideoCapturerTest : public testing::Test,
+ public sigslot::has_slots<> {
+ protected:
+ RemoteVideoCapturerTest()
+ : captured_frame_num_(0),
+ capture_state_(cricket::CS_STOPPED) {}
+
+ virtual void SetUp() {
+ capturer_.SignalStateChange.connect(
+ this, &RemoteVideoCapturerTest::OnStateChange);
+ capturer_.SignalVideoFrame.connect(
+ this, &RemoteVideoCapturerTest::OnVideoFrame);
+ }
+
+ ~RemoteVideoCapturerTest() {
+ capturer_.SignalStateChange.disconnect(this);
+ capturer_.SignalVideoFrame.disconnect(this);
+ }
+
+ int captured_frame_num() const {
+ return captured_frame_num_;
+ }
+
+ CaptureState capture_state() const {
+ return capture_state_;
+ }
+
+ webrtc::RemoteVideoCapturer capturer_;
+
+ private:
+ void OnStateChange(VideoCapturer* capturer,
+ CaptureState capture_state) {
+ EXPECT_EQ(&capturer_, capturer);
+ capture_state_ = capture_state;
+ }
+
+ void OnVideoFrame(VideoCapturer* capturer, const VideoFrame* frame) {
+ EXPECT_EQ(&capturer_, capturer);
+ ++captured_frame_num_;
+ }
+
+ int captured_frame_num_;
+ CaptureState capture_state_;
+};
+
+TEST_F(RemoteVideoCapturerTest, StartStop) {
+ // Start
+ EXPECT_TRUE(
+ capturer_.StartCapturing(VideoFormat(kTestFormat)));
+ EXPECT_TRUE_WAIT((cricket::CS_RUNNING == capture_state()), kMaxWaitMs);
+ EXPECT_EQ(VideoFormat(kTestFormat),
+ *capturer_.GetCaptureFormat());
+ EXPECT_TRUE(capturer_.IsRunning());
+
+ // Stop
+ capturer_.Stop();
+ EXPECT_TRUE_WAIT((cricket::CS_STOPPED == capture_state()), kMaxWaitMs);
+ EXPECT_TRUE(NULL == capturer_.GetCaptureFormat());
+}
+
+TEST_F(RemoteVideoCapturerTest, GetPreferredFourccs) {
+ EXPECT_FALSE(capturer_.GetPreferredFourccs(NULL));
+
+ std::vector<uint32> fourccs;
+ EXPECT_TRUE(capturer_.GetPreferredFourccs(&fourccs));
+ EXPECT_EQ(1u, fourccs.size());
+ EXPECT_EQ(cricket::FOURCC_I420, fourccs.at(0));
+}
+
+TEST_F(RemoteVideoCapturerTest, GetBestCaptureFormat) {
+ VideoFormat desired = VideoFormat(kTestFormat);
+ EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, NULL));
+
+ VideoFormat expected_format = VideoFormat(kTestFormat);
+ expected_format.fourcc = cricket::FOURCC_I420;
+ VideoFormat best_format;
+ EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best_format));
+ EXPECT_EQ(expected_format, best_format);
+}
+
+TEST_F(RemoteVideoCapturerTest, InputFrame) {
+ EXPECT_EQ(0, captured_frame_num());
+
+ cricket::WebRtcVideoFrame test_frame;
+ capturer_.SignalVideoFrame(&capturer_, &test_frame);
+ EXPECT_EQ(1, captured_frame_num());
+ capturer_.SignalVideoFrame(&capturer_, &test_frame);
+ EXPECT_EQ(2, captured_frame_num());
+}
diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc
index b19ef7be01..06c4b44b08 100644
--- a/talk/app/webrtc/statscollector.cc
+++ b/talk/app/webrtc/statscollector.cc
@@ -94,6 +94,7 @@ const char StatsReport::kStatsValueNameRemoteAddress[] = "googRemoteAddress";
const char StatsReport::kStatsValueNameRetransmitBitrate[] =
"googRetransmitBitrate";
const char StatsReport::kStatsValueNameRtt[] = "googRtt";
+const char StatsReport::kStatsValueNameSsrc[] = "ssrc";
const char StatsReport::kStatsValueNameTargetEncBitrate[] =
"googTargetEncBitrate";
const char StatsReport::kStatsValueNameTransmitBitrate[] =
@@ -101,7 +102,8 @@ const char StatsReport::kStatsValueNameTransmitBitrate[] =
const char StatsReport::kStatsValueNameTransportId[] = "transportId";
const char StatsReport::kStatsValueNameTransportType[] = "googTransportType";
const char StatsReport::kStatsValueNameTrackId[] = "googTrackId";
-const char StatsReport::kStatsValueNameSsrc[] = "ssrc";
+const char StatsReport::kStatsValueNameTypingNoiseState[] =
+ "googTypingNoiseState";
const char StatsReport::kStatsValueNameWritable[] = "googWritable";
const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession";
@@ -115,6 +117,7 @@ const char StatsReport::kStatsReportTypeCandidatePair[] = "googCandidatePair";
const char StatsReport::kStatsReportVideoBweId[] = "bweforvideo";
+
// Implementations of functions in statstypes.h
void StatsReport::AddValue(const std::string& name, const std::string& value) {
Value temp;
@@ -200,6 +203,8 @@ void ExtractStats(const cricket::VoiceSenderInfo& info, StatsReport* report) {
report->AddValue(StatsReport::kStatsValueNameEchoReturnLossEnhancement,
info.echo_return_loss_enhancement);
report->AddValue(StatsReport::kStatsValueNameCodecName, info.codec_name);
+ report->AddBoolean(StatsReport::kStatsValueNameTypingNoiseState,
+ info.typing_noise_detected);
}
void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h
index 62f8781612..30a8b84165 100644
--- a/talk/app/webrtc/statstypes.h
+++ b/talk/app/webrtc/statstypes.h
@@ -151,6 +151,7 @@ class StatsReport {
static const char kStatsValueNameChannelId[];
static const char kStatsValueNameTrackId[];
static const char kStatsValueNameSsrc[];
+ static const char kStatsValueNameTypingNoiseState[];
};
typedef std::vector<StatsReport> StatsReports;
diff --git a/talk/app/webrtc/test/fakemediastreamsignaling.h b/talk/app/webrtc/test/fakemediastreamsignaling.h
index 2f6289dd6e..f0c19cf6d0 100644
--- a/talk/app/webrtc/test/fakemediastreamsignaling.h
+++ b/talk/app/webrtc/test/fakemediastreamsignaling.h
@@ -44,8 +44,9 @@ static const char kAudioTrack2[] = "audio2";
class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
public webrtc::MediaStreamSignalingObserver {
public:
- FakeMediaStreamSignaling() :
- webrtc::MediaStreamSignaling(talk_base::Thread::Current(), this) {
+ explicit FakeMediaStreamSignaling(cricket::ChannelManager* channel_manager) :
+ webrtc::MediaStreamSignaling(talk_base::Thread::Current(), this,
+ channel_manager) {
}
void SendAudioVideoStream1() {
diff --git a/talk/app/webrtc/localvideosource.cc b/talk/app/webrtc/videosource.cc
index 9b344daec5..f0182f4fb1 100644
--- a/talk/app/webrtc/localvideosource.cc
+++ b/talk/app/webrtc/videosource.cc
@@ -25,7 +25,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/app/webrtc/localvideosource.h"
+#include "talk/app/webrtc/videosource.h"
#include <vector>
@@ -72,7 +72,7 @@ enum {
// Default resolution. If no constraint is specified, this is the resolution we
// will use.
-static const cricket::VideoFormatPod kDefaultResolution =
+static const cricket::VideoFormatPod kDefaultFormat =
{640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY};
// List of formats used if the camera doesn't support capability enumeration.
@@ -276,7 +276,7 @@ const cricket::VideoFormat& GetBestCaptureFormat(
const std::vector<cricket::VideoFormat>& formats) {
ASSERT(formats.size() > 0);
- int default_area = kDefaultResolution.width * kDefaultResolution.height;
+ int default_area = kDefaultFormat.width * kDefaultFormat.height;
std::vector<cricket::VideoFormat>::const_iterator it = formats.begin();
std::vector<cricket::VideoFormat>::const_iterator best_it = formats.begin();
@@ -328,38 +328,72 @@ bool ExtractVideoOptions(const MediaConstraintsInterface* all_constraints,
return all_valid;
}
+class FrameInputWrapper : public cricket::VideoRenderer {
+ public:
+ explicit FrameInputWrapper(cricket::VideoCapturer* capturer)
+ : capturer_(capturer) {
+ ASSERT(capturer_ != NULL);
+ }
+
+ virtual ~FrameInputWrapper() {}
+
+ // VideoRenderer implementation.
+ virtual bool SetSize(int width, int height, int reserved) OVERRIDE {
+ return true;
+ }
+
+ virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
+ if (!capturer_->IsRunning()) {
+ return true;
+ }
+
+ // This signal will be made on media engine render thread. The clients
+ // of this signal should have no assumptions on what thread this signal
+ // come from.
+ capturer_->SignalVideoFrame(capturer_, frame);
+ return true;
+ }
+
+ private:
+ cricket::VideoCapturer* capturer_;
+ int width_;
+ int height_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameInputWrapper);
+};
+
} // anonymous namespace
namespace webrtc {
-talk_base::scoped_refptr<LocalVideoSource> LocalVideoSource::Create(
+talk_base::scoped_refptr<VideoSource> VideoSource::Create(
cricket::ChannelManager* channel_manager,
cricket::VideoCapturer* capturer,
const webrtc::MediaConstraintsInterface* constraints) {
ASSERT(channel_manager != NULL);
ASSERT(capturer != NULL);
- talk_base::scoped_refptr<LocalVideoSource> source(
- new talk_base::RefCountedObject<LocalVideoSource>(channel_manager,
- capturer));
+ talk_base::scoped_refptr<VideoSource> source(
+ new talk_base::RefCountedObject<VideoSource>(channel_manager,
+ capturer));
source->Initialize(constraints);
return source;
}
-LocalVideoSource::LocalVideoSource(cricket::ChannelManager* channel_manager,
- cricket::VideoCapturer* capturer)
+VideoSource::VideoSource(cricket::ChannelManager* channel_manager,
+ cricket::VideoCapturer* capturer)
: channel_manager_(channel_manager),
video_capturer_(capturer),
state_(kInitializing) {
channel_manager_->SignalVideoCaptureStateChange.connect(
- this, &LocalVideoSource::OnStateChange);
+ this, &VideoSource::OnStateChange);
}
-LocalVideoSource::~LocalVideoSource() {
+VideoSource::~VideoSource() {
channel_manager_->StopVideoCapture(video_capturer_.get(), format_);
channel_manager_->SignalVideoCaptureStateChange.disconnect(this);
}
-void LocalVideoSource::Initialize(
+void VideoSource::Initialize(
const webrtc::MediaConstraintsInterface* constraints) {
std::vector<cricket::VideoFormat> formats;
@@ -371,7 +405,7 @@ void LocalVideoSource::Initialize(
// format from the constraints if any.
// Note that this only affects tab capturing, not desktop capturing,
// since desktop capturer does not respect the VideoFormat passed in.
- formats.push_back(cricket::VideoFormat(kDefaultResolution));
+ formats.push_back(cricket::VideoFormat(kDefaultFormat));
} else {
// The VideoCapturer implementation doesn't support capability enumeration.
// We need to guess what the camera support.
@@ -422,25 +456,34 @@ void LocalVideoSource::Initialize(
// Initialize hasn't succeeded until a successful state change has occurred.
}
-void LocalVideoSource::AddSink(cricket::VideoRenderer* output) {
+cricket::VideoRenderer* VideoSource::FrameInput() {
+ // Defer creation of frame_input_ until it's needed, e.g. the local video
+ // sources will never need it.
+ if (!frame_input_) {
+ frame_input_.reset(new FrameInputWrapper(video_capturer_.get()));
+ }
+ return frame_input_.get();
+}
+
+void VideoSource::AddSink(cricket::VideoRenderer* output) {
channel_manager_->AddVideoRenderer(video_capturer_.get(), output);
}
-void LocalVideoSource::RemoveSink(cricket::VideoRenderer* output) {
+void VideoSource::RemoveSink(cricket::VideoRenderer* output) {
channel_manager_->RemoveVideoRenderer(video_capturer_.get(), output);
}
// OnStateChange listens to the ChannelManager::SignalVideoCaptureStateChange.
// This signal is triggered for all video capturers. Not only the one we are
// interested in.
-void LocalVideoSource::OnStateChange(cricket::VideoCapturer* capturer,
+void VideoSource::OnStateChange(cricket::VideoCapturer* capturer,
cricket::CaptureState capture_state) {
if (capturer == video_capturer_.get()) {
SetState(GetReadyState(capture_state));
}
}
-void LocalVideoSource::SetState(SourceState new_state) {
+void VideoSource::SetState(SourceState new_state) {
if (VERIFY(state_ != new_state)) {
state_ = new_state;
FireOnChanged();
diff --git a/talk/app/webrtc/localvideosource.h b/talk/app/webrtc/videosource.h
index 0a3bac091c..f58b479c28 100644
--- a/talk/app/webrtc/localvideosource.h
+++ b/talk/app/webrtc/videosource.h
@@ -25,18 +25,19 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_APP_WEBRTC_LOCALVIDEOSOURCE_H_
-#define TALK_APP_WEBRTC_LOCALVIDEOSOURCE_H_
+#ifndef TALK_APP_WEBRTC_VIDEOSOURCE_H_
+#define TALK_APP_WEBRTC_VIDEOSOURCE_H_
#include "talk/app/webrtc/mediastreaminterface.h"
#include "talk/app/webrtc/notifier.h"
#include "talk/app/webrtc/videosourceinterface.h"
+#include "talk/app/webrtc/videotrackrenderers.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/sigslot.h"
#include "talk/media/base/videocapturer.h"
#include "talk/media/base/videocommon.h"
-// LocalVideoSource implements VideoSourceInterface. It owns a
+// VideoSource implements VideoSourceInterface. It owns a
// cricket::VideoCapturer and make sure the camera is started at a resolution
// that honors the constraints.
// The state is set depending on the result of starting the capturer.
@@ -53,20 +54,21 @@ namespace webrtc {
class MediaConstraintsInterface;
-class LocalVideoSource : public Notifier<VideoSourceInterface>,
- public sigslot::has_slots<> {
+class VideoSource : public Notifier<VideoSourceInterface>,
+ public sigslot::has_slots<> {
public:
- // Creates an instance of LocalVideoSource.
- // LocalVideoSource take ownership of |capturer|.
+ // Creates an instance of VideoSource.
+ // VideoSource take ownership of |capturer|.
// |constraints| can be NULL and in that case the camera is opened using a
// default resolution.
- static talk_base::scoped_refptr<LocalVideoSource> Create(
+ static talk_base::scoped_refptr<VideoSource> Create(
cricket::ChannelManager* channel_manager,
cricket::VideoCapturer* capturer,
const webrtc::MediaConstraintsInterface* constraints);
virtual SourceState state() const { return state_; }
virtual const cricket::VideoOptions* options() const { return &options_; }
+ virtual cricket::VideoRenderer* FrameInput();
virtual cricket::VideoCapturer* GetVideoCapturer() {
return video_capturer_.get();
@@ -77,18 +79,19 @@ class LocalVideoSource : public Notifier<VideoSourceInterface>,
virtual void RemoveSink(cricket::VideoRenderer* output);
protected:
- LocalVideoSource(cricket::ChannelManager* channel_manager,
- cricket::VideoCapturer* capturer);
- ~LocalVideoSource();
+ VideoSource(cricket::ChannelManager* channel_manager,
+ cricket::VideoCapturer* capturer);
+ virtual ~VideoSource();
+ void Initialize(const webrtc::MediaConstraintsInterface* constraints);
private:
- void Initialize(const webrtc::MediaConstraintsInterface* constraints);
void OnStateChange(cricket::VideoCapturer* capturer,
cricket::CaptureState capture_state);
void SetState(SourceState new_state);
cricket::ChannelManager* channel_manager_;
talk_base::scoped_ptr<cricket::VideoCapturer> video_capturer_;
+ talk_base::scoped_ptr<cricket::VideoRenderer> frame_input_;
cricket::VideoFormat format_;
cricket::VideoOptions options_;
@@ -97,4 +100,4 @@ class LocalVideoSource : public Notifier<VideoSourceInterface>,
} // namespace webrtc
-#endif // TALK_APP_WEBRTC_LOCALVIDEOSOURCE_H_
+#endif // TALK_APP_WEBRTC_VIDEOSOURCE_H_
diff --git a/talk/app/webrtc/localvideosource_unittest.cc b/talk/app/webrtc/videosource_unittest.cc
index 5ce963fb4a..dddbdeeb4f 100644
--- a/talk/app/webrtc/localvideosource_unittest.cc
+++ b/talk/app/webrtc/videosource_unittest.cc
@@ -25,20 +25,21 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/app/webrtc/localvideosource.h"
-
#include <string>
#include <vector>
#include "talk/app/webrtc/test/fakeconstraints.h"
+#include "talk/app/webrtc/remotevideocapturer.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/base/gunit.h"
#include "talk/media/base/fakemediaengine.h"
#include "talk/media/base/fakevideorenderer.h"
#include "talk/media/devices/fakedevicemanager.h"
+#include "talk/media/webrtc/webrtcvideoframe.h"
#include "talk/session/media/channelmanager.h"
using webrtc::FakeConstraints;
-using webrtc::LocalVideoSource;
+using webrtc::VideoSource;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaSourceInterface;
using webrtc::ObserverInterface;
@@ -123,9 +124,9 @@ class StateObserver : public ObserverInterface {
talk_base::scoped_refptr<VideoSourceInterface> source_;
};
-class LocalVideoSourceTest : public testing::Test {
+class VideoSourceTest : public testing::Test {
protected:
- LocalVideoSourceTest()
+ VideoSourceTest()
: channel_manager_(new cricket::ChannelManager(
new cricket::FakeMediaEngine(),
new cricket::FakeDeviceManager(), talk_base::Thread::Current())) {
@@ -136,39 +137,39 @@ class LocalVideoSourceTest : public testing::Test {
capturer_ = new TestVideoCapturer();
}
- void CreateLocalVideoSource() {
- CreateLocalVideoSource(NULL);
+ void CreateVideoSource() {
+ CreateVideoSource(NULL);
}
- void CreateLocalVideoSource(
+ void CreateVideoSource(
const webrtc::MediaConstraintsInterface* constraints) {
// VideoSource take ownership of |capturer_|
- local_source_ = LocalVideoSource::Create(channel_manager_.get(),
- capturer_,
- constraints);
+ source_ = VideoSource::Create(channel_manager_.get(),
+ capturer_,
+ constraints);
- ASSERT_TRUE(local_source_.get() != NULL);
- EXPECT_EQ(capturer_, local_source_->GetVideoCapturer());
+ ASSERT_TRUE(source_.get() != NULL);
+ EXPECT_EQ(capturer_, source_->GetVideoCapturer());
- state_observer_.reset(new StateObserver(local_source_));
- local_source_->RegisterObserver(state_observer_.get());
- local_source_->AddSink(&renderer_);
+ state_observer_.reset(new StateObserver(source_));
+ source_->RegisterObserver(state_observer_.get());
+ source_->AddSink(&renderer_);
}
- TestVideoCapturer* capturer_; // Raw pointer. Owned by local_source_.
+ TestVideoCapturer* capturer_; // Raw pointer. Owned by source_.
cricket::FakeVideoRenderer renderer_;
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
talk_base::scoped_ptr<StateObserver> state_observer_;
- talk_base::scoped_refptr<LocalVideoSource> local_source_;
+ talk_base::scoped_refptr<VideoSource> source_;
};
-// Test that a LocalVideoSource transition to kLive state when the capture
+// Test that a VideoSource transition to kLive state when the capture
// device have started and kEnded if it is stopped.
// It also test that an output can receive video frames.
-TEST_F(LocalVideoSourceTest, StartStop) {
+TEST_F(VideoSourceTest, StartStop) {
// Initialize without constraints.
- CreateLocalVideoSource();
+ CreateVideoSource();
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
@@ -180,10 +181,41 @@ TEST_F(LocalVideoSourceTest, StartStop) {
kMaxWaitMs);
}
-// Test that a LocalVideoSource transition to kEnded if the capture device
+// Test start stop with a remote VideoSource - the video source that has a
+// RemoteVideoCapturer and takes video frames from FrameInput.
+TEST_F(VideoSourceTest, StartStopRemote) {
+ // Will use RemoteVideoCapturer.
+ delete capturer_;
+
+ source_ = VideoSource::Create(channel_manager_.get(),
+ new webrtc::RemoteVideoCapturer(),
+ NULL);
+
+ ASSERT_TRUE(source_.get() != NULL);
+ EXPECT_TRUE(NULL != source_->GetVideoCapturer());
+
+ state_observer_.reset(new StateObserver(source_));
+ source_->RegisterObserver(state_observer_.get());
+ source_->AddSink(&renderer_);
+
+ EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
+ kMaxWaitMs);
+
+ cricket::VideoRenderer* frameinput = source_->FrameInput();
+ cricket::WebRtcVideoFrame test_frame;
+ frameinput->SetSize(1280, 720, 0);
+ frameinput->RenderFrame(&test_frame);
+ EXPECT_EQ(1, renderer_.num_rendered_frames());
+
+ source_->GetVideoCapturer()->Stop();
+ EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
+ kMaxWaitMs);
+}
+
+// Test that a VideoSource transition to kEnded if the capture device
// fails.
-TEST_F(LocalVideoSourceTest, CameraFailed) {
- CreateLocalVideoSource();
+TEST_F(VideoSourceTest, CameraFailed) {
+ CreateVideoSource();
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
@@ -194,13 +226,13 @@ TEST_F(LocalVideoSourceTest, CameraFailed) {
// Test that the capture output is CIF if we set max constraints to CIF.
// and the capture device support CIF.
-TEST_F(LocalVideoSourceTest, MandatoryConstraintCif5Fps) {
+TEST_F(VideoSourceTest, MandatoryConstraintCif5Fps) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352);
constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288);
constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 5);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -212,7 +244,7 @@ TEST_F(LocalVideoSourceTest, MandatoryConstraintCif5Fps) {
// Test that the capture output is 720P if the camera support it and the
// optional constraint is set to 720P.
-TEST_F(LocalVideoSourceTest, MandatoryMinVgaOptional720P) {
+TEST_F(VideoSourceTest, MandatoryMinVgaOptional720P) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640);
constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480);
@@ -220,7 +252,7 @@ TEST_F(LocalVideoSourceTest, MandatoryMinVgaOptional720P) {
constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio,
1280.0 / 720);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -233,7 +265,7 @@ TEST_F(LocalVideoSourceTest, MandatoryMinVgaOptional720P) {
// Test that the capture output have aspect ratio 4:3 if a mandatory constraint
// require it even if an optional constraint request a higher resolution
// that don't have this aspect ratio.
-TEST_F(LocalVideoSourceTest, MandatoryAspectRatio4To3) {
+TEST_F(VideoSourceTest, MandatoryAspectRatio4To3) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640);
constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480);
@@ -241,7 +273,7 @@ TEST_F(LocalVideoSourceTest, MandatoryAspectRatio4To3) {
640.0 / 480);
constraints.AddOptional(MediaConstraintsInterface::kMinWidth, 1280);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -254,20 +286,20 @@ TEST_F(LocalVideoSourceTest, MandatoryAspectRatio4To3) {
// Test that the source state transition to kEnded if the mandatory aspect ratio
// is set higher than supported.
-TEST_F(LocalVideoSourceTest, MandatoryAspectRatioTooHigh) {
+TEST_F(VideoSourceTest, MandatoryAspectRatioTooHigh) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio, 2);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
kMaxWaitMs);
}
// Test that the source ignores an optional aspect ratio that is higher than
// supported.
-TEST_F(LocalVideoSourceTest, OptionalAspectRatioTooHigh) {
+TEST_F(VideoSourceTest, OptionalAspectRatioTooHigh) {
FakeConstraints constraints;
constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio, 2);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -278,10 +310,10 @@ TEST_F(LocalVideoSourceTest, OptionalAspectRatioTooHigh) {
// Test that the source starts video with the default resolution if the
// camera doesn't support capability enumeration and there are no constraints.
-TEST_F(LocalVideoSourceTest, NoCameraCapability) {
+TEST_F(VideoSourceTest, NoCameraCapability) {
capturer_->TestWithoutCameraFormats();
- CreateLocalVideoSource();
+ CreateVideoSource();
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -294,7 +326,7 @@ TEST_F(LocalVideoSourceTest, NoCameraCapability) {
// Test that the source can start the video and get the requested aspect ratio
// if the camera doesn't support capability enumeration and the aspect ratio is
// set.
-TEST_F(LocalVideoSourceTest, NoCameraCapability16To9Ratio) {
+TEST_F(VideoSourceTest, NoCameraCapability16To9Ratio) {
capturer_->TestWithoutCameraFormats();
FakeConstraints constraints;
@@ -303,7 +335,7 @@ TEST_F(LocalVideoSourceTest, NoCameraCapability16To9Ratio) {
constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio,
requested_aspect_ratio);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -313,26 +345,26 @@ TEST_F(LocalVideoSourceTest, NoCameraCapability16To9Ratio) {
// Test that the source state transitions to kEnded if an unknown mandatory
// constraint is found.
-TEST_F(LocalVideoSourceTest, InvalidMandatoryConstraint) {
+TEST_F(VideoSourceTest, InvalidMandatoryConstraint) {
FakeConstraints constraints;
constraints.AddMandatory("weird key", 640);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
kMaxWaitMs);
}
// Test that the source ignores an unknown optional constraint.
-TEST_F(LocalVideoSourceTest, InvalidOptionalConstraint) {
+TEST_F(VideoSourceTest, InvalidOptionalConstraint) {
FakeConstraints constraints;
constraints.AddOptional("weird key", 640);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
}
-TEST_F(LocalVideoSourceTest, SetValidOptionValues) {
+TEST_F(VideoSourceTest, SetValidOptionValues) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kNoiseReduction, "false");
constraints.AddMandatory(
@@ -342,90 +374,90 @@ TEST_F(LocalVideoSourceTest, SetValidOptionValues) {
constraints.AddOptional(
MediaConstraintsInterface::kCpuOveruseDetection, "true");
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
bool value = true;
- EXPECT_TRUE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
EXPECT_FALSE(value);
- EXPECT_TRUE(local_source_->options()->
+ EXPECT_TRUE(source_->options()->
video_temporal_layer_screencast.Get(&value));
EXPECT_FALSE(value);
- EXPECT_TRUE(local_source_->options()->video_leaky_bucket.Get(&value));
+ EXPECT_TRUE(source_->options()->video_leaky_bucket.Get(&value));
EXPECT_TRUE(value);
- EXPECT_TRUE(local_source_->options()->
+ EXPECT_TRUE(source_->options()->
cpu_overuse_detection.GetWithDefaultIfUnset(false));
}
-TEST_F(LocalVideoSourceTest, OptionNotSet) {
+TEST_F(VideoSourceTest, OptionNotSet) {
FakeConstraints constraints;
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
bool value;
- EXPECT_FALSE(local_source_->options()->video_noise_reduction.Get(&value));
- EXPECT_FALSE(local_source_->options()->cpu_overuse_detection.Get(&value));
+ EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_FALSE(source_->options()->cpu_overuse_detection.Get(&value));
}
-TEST_F(LocalVideoSourceTest, MandatoryOptionOverridesOptional) {
+TEST_F(VideoSourceTest, MandatoryOptionOverridesOptional) {
FakeConstraints constraints;
constraints.AddMandatory(
MediaConstraintsInterface::kNoiseReduction, true);
constraints.AddOptional(
MediaConstraintsInterface::kNoiseReduction, false);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
bool value = false;
- EXPECT_TRUE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
EXPECT_TRUE(value);
- EXPECT_FALSE(local_source_->options()->video_leaky_bucket.Get(&value));
+ EXPECT_FALSE(source_->options()->video_leaky_bucket.Get(&value));
}
-TEST_F(LocalVideoSourceTest, InvalidOptionKeyOptional) {
+TEST_F(VideoSourceTest, InvalidOptionKeyOptional) {
FakeConstraints constraints;
constraints.AddOptional(
MediaConstraintsInterface::kNoiseReduction, false);
constraints.AddOptional("invalidKey", false);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
bool value = true;
- EXPECT_TRUE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
EXPECT_FALSE(value);
}
-TEST_F(LocalVideoSourceTest, InvalidOptionKeyMandatory) {
+TEST_F(VideoSourceTest, InvalidOptionKeyMandatory) {
FakeConstraints constraints;
constraints.AddMandatory(
MediaConstraintsInterface::kNoiseReduction, false);
constraints.AddMandatory("invalidKey", false);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
kMaxWaitMs);
bool value;
- EXPECT_FALSE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
}
-TEST_F(LocalVideoSourceTest, InvalidOptionValueOptional) {
+TEST_F(VideoSourceTest, InvalidOptionValueOptional) {
FakeConstraints constraints;
constraints.AddOptional(
MediaConstraintsInterface::kNoiseReduction, "true");
constraints.AddOptional(
MediaConstraintsInterface::kLeakyBucket, "not boolean");
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
bool value = false;
- EXPECT_TRUE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
EXPECT_TRUE(value);
- EXPECT_FALSE(local_source_->options()->video_leaky_bucket.Get(&value));
+ EXPECT_FALSE(source_->options()->video_leaky_bucket.Get(&value));
}
-TEST_F(LocalVideoSourceTest, InvalidOptionValueMandatory) {
+TEST_F(VideoSourceTest, InvalidOptionValueMandatory) {
FakeConstraints constraints;
// Optional constraints should be ignored if the mandatory constraints fail.
constraints.AddOptional(
@@ -434,15 +466,15 @@ TEST_F(LocalVideoSourceTest, InvalidOptionValueMandatory) {
constraints.AddMandatory(
MediaConstraintsInterface::kLeakyBucket, "True");
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
kMaxWaitMs);
bool value;
- EXPECT_FALSE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
}
-TEST_F(LocalVideoSourceTest, MixedOptionsAndConstraints) {
+TEST_F(VideoSourceTest, MixedOptionsAndConstraints) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352);
constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288);
@@ -453,7 +485,7 @@ TEST_F(LocalVideoSourceTest, MixedOptionsAndConstraints) {
constraints.AddOptional(
MediaConstraintsInterface::kNoiseReduction, true);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -463,18 +495,18 @@ TEST_F(LocalVideoSourceTest, MixedOptionsAndConstraints) {
EXPECT_EQ(5, format->framerate());
bool value = true;
- EXPECT_TRUE(local_source_->options()->video_noise_reduction.Get(&value));
+ EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
EXPECT_FALSE(value);
- EXPECT_FALSE(local_source_->options()->video_leaky_bucket.Get(&value));
+ EXPECT_FALSE(source_->options()->video_leaky_bucket.Get(&value));
}
// Tests that the source starts video with the default resolution for
// screencast if no constraint is set.
-TEST_F(LocalVideoSourceTest, ScreencastResolutionNoConstraint) {
+TEST_F(VideoSourceTest, ScreencastResolutionNoConstraint) {
capturer_->TestWithoutCameraFormats();
capturer_->SetScreencast(true);
- CreateLocalVideoSource();
+ CreateVideoSource();
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -486,7 +518,7 @@ TEST_F(LocalVideoSourceTest, ScreencastResolutionNoConstraint) {
// Tests that the source starts video with the max width and height set by
// constraints for screencast.
-TEST_F(LocalVideoSourceTest, ScreencastResolutionWithConstraint) {
+TEST_F(VideoSourceTest, ScreencastResolutionWithConstraint) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 480);
constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 270);
@@ -494,7 +526,7 @@ TEST_F(LocalVideoSourceTest, ScreencastResolutionWithConstraint) {
capturer_->TestWithoutCameraFormats();
capturer_->SetScreencast(true);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
@@ -504,21 +536,21 @@ TEST_F(LocalVideoSourceTest, ScreencastResolutionWithConstraint) {
EXPECT_EQ(30, format->framerate());
}
-TEST_F(LocalVideoSourceTest, MandatorySubOneFpsConstraints) {
+TEST_F(VideoSourceTest, MandatorySubOneFpsConstraints) {
FakeConstraints constraints;
constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 0.5);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
kMaxWaitMs);
ASSERT_TRUE(capturer_->GetCaptureFormat() == NULL);
}
-TEST_F(LocalVideoSourceTest, OptionalSubOneFpsConstraints) {
+TEST_F(VideoSourceTest, OptionalSubOneFpsConstraints) {
FakeConstraints constraints;
constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 0.5);
- CreateLocalVideoSource(&constraints);
+ CreateVideoSource(&constraints);
EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
kMaxWaitMs);
const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
diff --git a/talk/app/webrtc/videosourceinterface.h b/talk/app/webrtc/videosourceinterface.h
index ae968f728f..89c90a1ec5 100644
--- a/talk/app/webrtc/videosourceinterface.h
+++ b/talk/app/webrtc/videosourceinterface.h
@@ -47,6 +47,7 @@ class VideoSourceInterface : public MediaSourceInterface {
virtual void AddSink(cricket::VideoRenderer* output) = 0;
virtual void RemoveSink(cricket::VideoRenderer* output) = 0;
virtual const cricket::VideoOptions* options() const = 0;
+ virtual cricket::VideoRenderer* FrameInput() = 0;
protected:
virtual ~VideoSourceInterface() {}
diff --git a/talk/app/webrtc/videosourceproxy.h b/talk/app/webrtc/videosourceproxy.h
index be800777c3..991dd554c6 100644
--- a/talk/app/webrtc/videosourceproxy.h
+++ b/talk/app/webrtc/videosourceproxy.h
@@ -42,6 +42,7 @@ BEGIN_PROXY_MAP(VideoSource)
PROXY_METHOD1(void, AddSink, cricket::VideoRenderer*)
PROXY_METHOD1(void, RemoveSink, cricket::VideoRenderer*)
PROXY_CONSTMETHOD0(const cricket::VideoOptions*, options)
+ PROXY_METHOD0(cricket::VideoRenderer*, FrameInput)
PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
END_PROXY()
diff --git a/talk/app/webrtc/videotrack.cc b/talk/app/webrtc/videotrack.cc
index ec17ec7e71..7ab7815ba2 100644
--- a/talk/app/webrtc/videotrack.cc
+++ b/talk/app/webrtc/videotrack.cc
@@ -39,12 +39,12 @@ VideoTrack::VideoTrack(const std::string& label,
: MediaStreamTrack<VideoTrackInterface>(label),
video_source_(video_source) {
if (video_source_)
- video_source_->AddSink(FrameInput());
+ video_source_->AddSink(&renderers_);
}
VideoTrack::~VideoTrack() {
if (video_source_)
- video_source_->RemoveSink(FrameInput());
+ video_source_->RemoveSink(&renderers_);
}
std::string VideoTrack::kind() const {
@@ -59,10 +59,6 @@ void VideoTrack::RemoveRenderer(VideoRendererInterface* renderer) {
renderers_.RemoveRenderer(renderer);
}
-cricket::VideoRenderer* VideoTrack::FrameInput() {
- return &renderers_;
-}
-
bool VideoTrack::set_enabled(bool enable) {
renderers_.SetEnabled(enable);
return MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);
diff --git a/talk/app/webrtc/videotrack.h b/talk/app/webrtc/videotrack.h
index aefeb502cb..acd1b755c5 100644
--- a/talk/app/webrtc/videotrack.h
+++ b/talk/app/webrtc/videotrack.h
@@ -44,7 +44,6 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface> {
virtual void AddRenderer(VideoRendererInterface* renderer);
virtual void RemoveRenderer(VideoRendererInterface* renderer);
- virtual cricket::VideoRenderer* FrameInput();
virtual VideoSourceInterface* GetSource() const {
return video_source_.get();
}
diff --git a/talk/app/webrtc/videotrack_unittest.cc b/talk/app/webrtc/videotrack_unittest.cc
index 671e360f21..4a30293c7e 100644
--- a/talk/app/webrtc/videotrack_unittest.cc
+++ b/talk/app/webrtc/videotrack_unittest.cc
@@ -28,38 +28,53 @@
#include <string>
#include "talk/app/webrtc/test/fakevideotrackrenderer.h"
+#include "talk/app/webrtc/remotevideocapturer.h"
+#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/gunit.h"
#include "talk/base/scoped_ptr.h"
+#include "talk/media/base/fakemediaengine.h"
+#include "talk/media/devices/fakedevicemanager.h"
#include "talk/media/webrtc/webrtcvideoframe.h"
+#include "talk/session/media/channelmanager.h"
using webrtc::FakeVideoTrackRenderer;
+using webrtc::VideoSource;
using webrtc::VideoTrack;
using webrtc::VideoTrackInterface;
// Test adding renderers to a video track and render to them by providing
-// VideoFrames to the track frame input.
+// frames to the source.
TEST(VideoTrack, RenderVideo) {
static const char kVideoTrackId[] = "track_id";
+
+ talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
+ channel_manager_.reset(
+ new cricket::ChannelManager(new cricket::FakeMediaEngine(),
+ new cricket::FakeDeviceManager(),
+ talk_base::Thread::Current()));
+ ASSERT_TRUE(channel_manager_->Init());
talk_base::scoped_refptr<VideoTrackInterface> video_track(
- VideoTrack::Create(kVideoTrackId, NULL));
+ VideoTrack::Create(kVideoTrackId,
+ VideoSource::Create(channel_manager_.get(),
+ new webrtc::RemoteVideoCapturer(),
+ NULL)));
// FakeVideoTrackRenderer register itself to |video_track|
talk_base::scoped_ptr<FakeVideoTrackRenderer> renderer_1(
new FakeVideoTrackRenderer(video_track.get()));
- cricket::VideoRenderer* render_input = video_track->FrameInput();
+ cricket::VideoRenderer* render_input = video_track->GetSource()->FrameInput();
ASSERT_FALSE(render_input == NULL);
- render_input->SetSize(123, 123, 0);
- EXPECT_EQ(1, renderer_1->num_set_sizes());
- EXPECT_EQ(123, renderer_1->width());
- EXPECT_EQ(123, renderer_1->height());
-
cricket::WebRtcVideoFrame frame;
frame.InitToBlack(123, 123, 1, 1, 0, 0);
render_input->RenderFrame(&frame);
EXPECT_EQ(1, renderer_1->num_rendered_frames());
+ EXPECT_EQ(1, renderer_1->num_set_sizes());
+ EXPECT_EQ(123, renderer_1->width());
+ EXPECT_EQ(123, renderer_1->height());
+
// FakeVideoTrackRenderer register itself to |video_track|
talk_base::scoped_ptr<FakeVideoTrackRenderer> renderer_2(
new FakeVideoTrackRenderer(video_track.get()));
diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc
index a1fd5b998c..af068af6c2 100644
--- a/talk/app/webrtc/webrtcsdp.cc
+++ b/talk/app/webrtc/webrtcsdp.cc
@@ -2121,7 +2121,7 @@ bool ParseMediaDescription(const std::string& message,
// this for backwards-compatibility. Once we don't need that any
// more, remove this.
bool support_dc_sdp_bandwidth_temporarily = true;
- if (!support_dc_sdp_bandwidth_temporarily) {
+ if (content.get() && !support_dc_sdp_bandwidth_temporarily) {
content->set_bandwidth(cricket::kAutoBandwidth);
}
} else {
diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc
index e1445d35a0..6f14432998 100644
--- a/talk/app/webrtc/webrtcsession_unittest.cc
+++ b/talk/app/webrtc/webrtcsession_unittest.cc
@@ -275,7 +275,8 @@ class WebRtcSessionTest : public testing::Test {
ss_scope_(fss_.get()),
stun_server_(talk_base::Thread::Current(), kStunAddr),
allocator_(&network_manager_, kStunAddr,
- SocketAddress(), SocketAddress(), SocketAddress()) {
+ SocketAddress(), SocketAddress(), SocketAddress()),
+ mediastream_signaling_(channel_manager_.get()) {
tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
cricket::PORTALLOCATOR_DISABLE_RELAY |
@@ -2485,9 +2486,9 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
}
-// Test fails on windows. https://code.google.com/p/webrtc/issues/detail?id=2374
-TEST_F(WebRtcSessionTest,
- DISABLED_TestCreateOfferWithSctpEnabledWithoutStreams) {
+TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
+ MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
+
constraints_.reset(new FakeConstraints());
constraints_->AddOptional(
webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
diff --git a/talk/base/gunit_prod.h b/talk/base/gunit_prod.h
index 6be5c53f97..bf5e88acb4 100644
--- a/talk/base/gunit_prod.h
+++ b/talk/base/gunit_prod.h
@@ -28,7 +28,11 @@
#ifndef TALK_BASE_GUNIT_PROD_H_
#define TALK_BASE_GUNIT_PROD_H_
-#if defined(ANDROID) || defined (GTEST_RELATIVE_PATH)
+#if defined(ANDROID)
+// Android doesn't use gtest at all, so anything that relies on gtest should
+// check this define first.
+#define NO_GTEST
+#elif defined (GTEST_RELATIVE_PATH)
#include "gtest/gtest_prod.h"
#else
#include "testing/base/gunit_prod.h"
diff --git a/talk/base/physicalsocketserver.cc b/talk/base/physicalsocketserver.cc
index 8a1bb5c265..f14c3bd69c 100644
--- a/talk/base/physicalsocketserver.cc
+++ b/talk/base/physicalsocketserver.cc
@@ -1265,7 +1265,14 @@ void PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
DispatcherList::iterator pos = std::find(dispatchers_.begin(),
dispatchers_.end(),
pdispatcher);
- ASSERT(pos != dispatchers_.end());
+ // We silently ignore duplicate calls to Add, so we should silently ignore
+ // the (expected) symmetric calls to Remove. Note that this may still hide
+ // a real issue, so we at least log a warning about it.
+ if (pos == dispatchers_.end()) {
+ LOG(LS_WARNING) << "PhysicalSocketServer asked to remove a unknown "
+ << "dispatcher, potentially from a duplicate call to Add.";
+ return;
+ }
size_t index = pos - dispatchers_.begin();
dispatchers_.erase(pos);
for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end();
diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp
index b91de3c5e1..1d288e3094 100755
--- a/talk/libjingle.gyp
+++ b/talk/libjingle.gyp
@@ -1136,8 +1136,6 @@
'app/webrtc/jsepsessiondescription.h',
'app/webrtc/localaudiosource.cc',
'app/webrtc/localaudiosource.h',
- 'app/webrtc/localvideosource.cc',
- 'app/webrtc/localvideosource.h',
'app/webrtc/mediaconstraintsinterface.cc',
'app/webrtc/mediaconstraintsinterface.h',
'app/webrtc/mediastream.cc',
@@ -1161,10 +1159,14 @@
'app/webrtc/portallocatorfactory.cc',
'app/webrtc/portallocatorfactory.h',
'app/webrtc/proxy.h',
+ 'app/webrtc/remotevideocapturer.cc',
+ 'app/webrtc/remotevideocapturer.h',
'app/webrtc/statscollector.cc',
'app/webrtc/statscollector.h',
'app/webrtc/statstypes.h',
'app/webrtc/streamcollection.h',
+ 'app/webrtc/videosource.cc',
+ 'app/webrtc/videosource.h',
'app/webrtc/videosourceinterface.h',
'app/webrtc/videosourceproxy.h',
'app/webrtc/videotrack.cc',
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp
index e0cc239012..546767d1fb 100755
--- a/talk/libjingle_tests.gyp
+++ b/talk/libjingle_tests.gyp
@@ -379,7 +379,6 @@
'app/webrtc/dtmfsender_unittest.cc',
'app/webrtc/jsepsessiondescription_unittest.cc',
'app/webrtc/localaudiosource_unittest.cc',
- 'app/webrtc/localvideosource_unittest.cc',
# 'app/webrtc/mediastream_unittest.cc',
# 'app/webrtc/mediastreamhandler_unittest.cc',
'app/webrtc/mediastreamsignaling_unittest.cc',
@@ -387,6 +386,7 @@
'app/webrtc/peerconnectionfactory_unittest.cc',
'app/webrtc/peerconnectioninterface_unittest.cc',
# 'app/webrtc/peerconnectionproxy_unittest.cc',
+ 'app/webrtc/remotevideocapturer_unittest.cc',
'app/webrtc/test/fakeaudiocapturemodule.cc',
'app/webrtc/test/fakeaudiocapturemodule.h',
'app/webrtc/test/fakeaudiocapturemodule_unittest.cc',
@@ -397,6 +397,7 @@
'app/webrtc/test/fakevideotrackrenderer.h',
'app/webrtc/test/mockpeerconnectionobservers.h',
'app/webrtc/test/testsdpstrings.h',
+ 'app/webrtc/videosource_unittest.cc',
'app/webrtc/videotrack_unittest.cc',
'app/webrtc/webrtcsdp_unittest.cc',
'app/webrtc/webrtcsession_unittest.cc',
diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h
index 35c3bb04c2..c73d20ae8d 100644
--- a/talk/media/base/mediachannel.h
+++ b/talk/media/base/mediachannel.h
@@ -519,7 +519,8 @@ struct VoiceSenderInfo {
echo_delay_median_ms(0),
echo_delay_std_ms(0),
echo_return_loss(0),
- echo_return_loss_enhancement(0) {
+ echo_return_loss_enhancement(0),
+ typing_noise_detected(false) {
}
uint32 ssrc;
@@ -537,6 +538,7 @@ struct VoiceSenderInfo {
int echo_delay_std_ms;
int echo_return_loss;
int echo_return_loss_enhancement;
+ bool typing_noise_detected;
};
struct VoiceReceiverInfo {
diff --git a/talk/media/base/mediaengine.h b/talk/media/base/mediaengine.h
index 7a1244dfae..8ebc13b108 100644
--- a/talk/media/base/mediaengine.h
+++ b/talk/media/base/mediaengine.h
@@ -259,10 +259,10 @@ class CompositeMediaEngine : public MediaEngineInterface {
}
virtual void SetVoiceLogging(int min_sev, const char* filter) {
- return voice_.SetLogging(min_sev, filter);
+ voice_.SetLogging(min_sev, filter);
}
virtual void SetVideoLogging(int min_sev, const char* filter) {
- return video_.SetLogging(min_sev, filter);
+ video_.SetLogging(min_sev, filter);
}
virtual bool RegisterVoiceProcessor(uint32 ssrc,
diff --git a/talk/media/devices/devicemanager.cc b/talk/media/devices/devicemanager.cc
index 2ce5eb08b8..6f4aa33ffc 100644
--- a/talk/media/devices/devicemanager.cc
+++ b/talk/media/devices/devicemanager.cc
@@ -149,9 +149,9 @@ bool DeviceManager::GetAudioOutputDevice(const std::string& name, Device* out) {
bool DeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
devices->clear();
-#if defined(IOS)
- // On iOS, we treat the camera(s) as a single device. Even if there are
- // multiple cameras, that's abstracted away at a higher level.
+#if defined(ANDROID) || defined(IOS)
+ // On Android and iOS, we treat the camera(s) as a single device. Even if
+ // there are multiple cameras, that's abstracted away at a higher level.
Device dev("camera", "1"); // name and ID
devices->push_back(dev);
return true;
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index dc2a0c030b..2a6ccd761f 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -1498,6 +1498,7 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
desired_playout_(false),
nack_enabled_(false),
playout_(false),
+ typing_noise_detected_(false),
desired_send_(SEND_NOTHING),
send_(SEND_NOTHING),
default_receive_ssrc_(0) {
@@ -2818,6 +2819,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
sinfo.echo_delay_median_ms = echo_delay_median_ms;
sinfo.echo_delay_std_ms = echo_delay_std_ms;
+ sinfo.typing_noise_detected = typing_noise_detected_;
info->senders.push_back(sinfo);
}
@@ -2926,6 +2928,13 @@ bool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) {
}
void WebRtcVoiceMediaChannel::OnError(uint32 ssrc, int error) {
+#ifdef USE_WEBRTC_DEV_BRANCH
+ if (error == VE_TYPING_NOISE_WARNING) {
+ typing_noise_detected_ = true;
+ } else if (error == VE_TYPING_NOISE_OFF_WARNING) {
+ typing_noise_detected_ = false;
+ }
+#endif
SignalMediaError(ssrc, WebRtcErrorToChannelError(error));
}
diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h
index a878711f7e..6cb0b3052d 100644
--- a/talk/media/webrtc/webrtcvoiceengine.h
+++ b/talk/media/webrtc/webrtcvoiceengine.h
@@ -404,6 +404,7 @@ class WebRtcVoiceMediaChannel
bool desired_playout_;
bool nack_enabled_;
bool playout_;
+ bool typing_noise_detected_;
SendFlags desired_send_;
SendFlags send_;
diff --git a/talk/p2p/base/sessionmanager.cc b/talk/p2p/base/sessionmanager.cc
index 7aa52b3596..15b745239d 100644
--- a/talk/p2p/base/sessionmanager.cc
+++ b/talk/p2p/base/sessionmanager.cc
@@ -210,6 +210,12 @@ void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
}
Session* session = FindSession(msg.sid, msg.to);
+ if (!session) {
+ // Also try the QN_FROM in the response stanza, in case we sent the request
+ // to a bare JID but got the response from a full JID.
+ std::string ack_from = response_stanza->Attr(buzz::QN_FROM);
+ session = FindSession(msg.sid, ack_from);
+ }
if (session) {
session->OnIncomingResponse(orig_stanza, response_stanza, msg);
}
diff --git a/talk/p2p/client/httpportallocator.h b/talk/p2p/client/httpportallocator.h
index cb4c8f82bb..a0ef3b722d 100644
--- a/talk/p2p/client/httpportallocator.h
+++ b/talk/p2p/client/httpportallocator.h
@@ -32,7 +32,6 @@
#include <string>
#include <vector>
-#include "talk/base/gunit_prod.h"
#include "talk/p2p/client/basicportallocator.h"
class HttpPortAllocatorTest_TestSessionRequestUrl_Test;
@@ -129,6 +128,9 @@ class HttpPortAllocatorSessionBase : public BasicPortAllocatorSession {
virtual void SendSessionRequest(const std::string& host, int port) = 0;
virtual void ReceiveSessionResponse(const std::string& response);
+ // Made public for testing. Should be protected.
+ std::string GetSessionRequestUrl();
+
protected:
virtual void GetPortConfigurations();
void TryCreateRelaySession();
@@ -137,11 +139,7 @@ class HttpPortAllocatorSessionBase : public BasicPortAllocatorSession {
BasicPortAllocatorSession::allocator());
}
- std::string GetSessionRequestUrl();
-
private:
- FRIEND_TEST(::HttpPortAllocatorTest, TestSessionRequestUrl);
-
std::vector<std::string> relay_hosts_;
std::vector<talk_base::SocketAddress> stun_hosts_;
std::string relay_token_;
diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h
index b1967bfcd5..04af5e1963 100644
--- a/talk/session/media/channelmanager.h
+++ b/talk/session/media/channelmanager.h
@@ -163,9 +163,6 @@ class ChannelManager : public talk_base::MessageHandler,
bool monitoring() const { return monitoring_; }
// Sets the local renderer where to renderer the local camera.
bool SetLocalRenderer(VideoRenderer* renderer);
- // Sets the externally provided video capturer. The ssrc is the ssrc of the
- // (video) stream for which the video capturer should be set.
- bool SetVideoCapturer(VideoCapturer* capturer);
bool capturing() const { return capturing_; }
// Configures the logging output of the mediaengine(s).
diff --git a/talk/xmpp/constants.cc b/talk/xmpp/constants.cc
index 196a1ec2c4..c56796bc9e 100644
--- a/talk/xmpp/constants.cc
+++ b/talk/xmpp/constants.cc
@@ -363,6 +363,7 @@ const StaticQName QN_ATTR_STATUS = { STR_EMPTY, "status" };
// Presence connection status
const char STR_PSTN_CONFERENCE_STATUS_CONNECTING[] = "connecting";
+const char STR_PSTN_CONFERENCE_STATUS_JOINING[] = "joining";
const char STR_PSTN_CONFERENCE_STATUS_CONNECTED[] = "connected";
const char STR_PSTN_CONFERENCE_STATUS_HANGUP[] = "hangup";
diff --git a/talk/xmpp/constants.h b/talk/xmpp/constants.h
index cd6d2b7c2c..c53abb5b86 100644
--- a/talk/xmpp/constants.h
+++ b/talk/xmpp/constants.h
@@ -322,6 +322,7 @@ extern const StaticQName QN_ATTR_STATUS;
// Presence connection status
extern const char STR_PSTN_CONFERENCE_STATUS_CONNECTING[];
+extern const char STR_PSTN_CONFERENCE_STATUS_JOINING[];
extern const char STR_PSTN_CONFERENCE_STATUS_CONNECTED[];
extern const char STR_PSTN_CONFERENCE_STATUS_HANGUP[];
diff --git a/talk/xmpp/hangoutpubsubclient.cc b/talk/xmpp/hangoutpubsubclient.cc
index edbf4dddbe..b6669a1086 100644
--- a/talk/xmpp/hangoutpubsubclient.cc
+++ b/talk/xmpp/hangoutpubsubclient.cc
@@ -238,7 +238,10 @@ class PubSubStateClient : public sigslot::has_slots<> {
}
PubSubStateChange<C> change;
- change.publisher_nick = info.publisher_nick;
+ if (!retracted) {
+ // Retracts do not have publisher information.
+ change.publisher_nick = info.publisher_nick;
+ }
change.published_nick = info.published_nick;
change.old_state = old_state;
change.new_state = new_state;
diff --git a/talk/xmpp/rostermodule.h b/talk/xmpp/rostermodule.h
index eafd595444..7e14dc1314 100644
--- a/talk/xmpp/rostermodule.h
+++ b/talk/xmpp/rostermodule.h
@@ -81,9 +81,14 @@ enum XmppPresenceAvailable {
enum XmppPresenceConnectionStatus {
XMPP_CONNECTION_STATUS_UNKNOWN = 0,
+ // Status set by the server while the user is being rung.
XMPP_CONNECTION_STATUS_CONNECTING = 1,
- XMPP_CONNECTION_STATUS_CONNECTED = 2,
- XMPP_CONNECTION_STATUS_HANGUP = 3,
+ // Status set by the client when the user has accepted the ring but before
+ // the client has joined the call.
+ XMPP_CONNECTION_STATUS_JOINING = 2,
+ // Status set by the client as part of joining the call.
+ XMPP_CONNECTION_STATUS_CONNECTED = 3,
+ XMPP_CONNECTION_STATUS_HANGUP = 4,
};
//! Presence Information
diff --git a/talk/xmpp/rostermoduleimpl.cc b/talk/xmpp/rostermoduleimpl.cc
index 2422880328..31b3abdf0f 100644
--- a/talk/xmpp/rostermoduleimpl.cc
+++ b/talk/xmpp/rostermoduleimpl.cc
@@ -300,6 +300,8 @@ XmppPresenceImpl::connection_status() const {
return XMPP_CONNECTION_STATUS_CONNECTING;
else if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTED)
return XMPP_CONNECTION_STATUS_CONNECTED;
+ else if (status == STR_PSTN_CONFERENCE_STATUS_JOINING)
+ return XMPP_CONNECTION_STATUS_JOINING;
else if (status == STR_PSTN_CONFERENCE_STATUS_HANGUP)
return XMPP_CONNECTION_STATUS_HANGUP;
}
@@ -349,8 +351,11 @@ XmppPresenceImpl::set_raw_xml(const XmlElement * xml) {
xml->Name() != QN_PRESENCE)
return XMPP_RETURN_BADARGUMENT;
- raw_xml_.reset(new XmlElement(*xml));
+ const std::string& type = xml->Attr(QN_TYPE);
+ if (type != STR_EMPTY && type != "unavailable")
+ return XMPP_RETURN_BADARGUMENT;
+ raw_xml_.reset(new XmlElement(*xml));
return XMPP_RETURN_OK;
}