diff --git a/third_party_mods/libjingle/libjingle.gyp b/third_party_mods/libjingle/libjingle.gyp index 003d400fd..3ad05d983 100644 --- a/third_party_mods/libjingle/libjingle.gyp +++ b/third_party_mods/libjingle/libjingle.gyp @@ -770,8 +770,8 @@ }], ], #conditions 'sources': [ - '<(libjingle_mods)/source/talk/app/webrtc_dev/mediastreamhandler_unittest.cc', - '<(libjingle_mods)/source/talk/app/webrtc_dev/mediastreamimpl_unittest.cc', + '<(libjingle_mods)/source/talk/app/webrtc_dev/mediastream_unittest.cc', + '<(libjingle_mods)/source/talk/app/webrtc_dev/mediastreamhandler_unittest.cc', '<(libjingle_mods)/source/talk/app/webrtc_dev/peerconnection_unittest.cc', '<(libjingle_mods)/source/talk/app/webrtc_dev/peerconnection_unittests.cc', '<(libjingle_mods)/source/talk/app/webrtc_dev/peerconnectionimpl_unittest.cc', diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastream_unittest.cc b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastream_unittest.cc new file mode 100644 index 000000000..2c39e9ad4 --- /dev/null +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastream_unittest.cc @@ -0,0 +1,439 @@ +/* + * libjingle + * Copyright 2011, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "talk/app/webrtc_dev/mediastreamproxy.h" +#include "talk/app/webrtc_dev/mediastreamtrackproxy.h" +#include "talk/app/webrtc_dev/ref_count.h" +#include "talk/base/scoped_ptr.h" +#include "talk/base/thread.h" + +static const char kStreamLabel1[] = "local_stream_1"; +static const char kVideoTrackLabel[] = "dummy_video_cam_1"; +static const char kAudioTrackLabel[] = "dummy_microphone_1"; + +using talk_base::scoped_refptr; +using ::testing::Exactly; + +namespace { + +class ReadyStateMessageData : public talk_base::MessageData { + public: + ReadyStateMessageData( + webrtc::MediaStreamInterface* stream, + webrtc::MediaStreamInterface::ReadyState new_state) + : stream_(stream), + ready_state_(new_state) { + } + + scoped_refptr stream_; + webrtc::MediaStreamInterface::ReadyState ready_state_; +}; + +class SsrcMessageData : public talk_base::MessageData { + public: + SsrcMessageData( + webrtc::MediaStreamTrackInterface* track, + uint32 ssrc) + : track_(track), + ssrc_(ssrc) { + } + + scoped_refptr track_; + uint32 ssrc_; +}; + +class TrackStateMessageData : public talk_base::MessageData { + public: + TrackStateMessageData( + webrtc::MediaStreamTrackInterface* track, + webrtc::MediaStreamTrackInterface::TrackState state) + : track_(track), + state_(state) { + } + + scoped_refptr track_; + webrtc::MediaStreamTrackInterface::TrackState state_; +}; + +} // namespace anonymous + +namespace webrtc { + +// Helper class to test Observer. +class MockObserver : public ObserverInterface { + public: + explicit MockObserver(talk_base::Thread* signaling_thread) + : signaling_thread_(signaling_thread) { + } + + MOCK_METHOD0(DoOnChanged, void()); + virtual void OnChanged() { + ASSERT_TRUE(talk_base::Thread::Current() == signaling_thread_); + DoOnChanged(); + } + private: + talk_base::Thread* signaling_thread_; +}; + +class MockMediaStream: public LocalMediaStreamInterface { + public: + MockMediaStream(const std::string& label, talk_base::Thread* signaling_thread) + : stream_impl_(MediaStream::Create(label)), + signaling_thread_(signaling_thread) { + } + virtual void RegisterObserver(webrtc::ObserverInterface* observer) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + stream_impl_->RegisterObserver(observer); + } + virtual void UnregisterObserver(webrtc::ObserverInterface* observer) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + stream_impl_->UnregisterObserver(observer); + } + virtual std::string label() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->label(); + } + virtual AudioTracks* audio_tracks() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->audio_tracks(); + } + virtual VideoTracks* video_tracks() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->video_tracks(); + } + virtual ReadyState ready_state() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->ready_state(); + } + virtual void set_ready_state(ReadyState state) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->set_ready_state(state); + } + virtual bool AddTrack(AudioTrackInterface* audio_track) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->AddTrack(audio_track); + } + virtual bool AddTrack(VideoTrackInterface* video_track) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return stream_impl_->AddTrack(video_track); + } + + private: + scoped_refptr stream_impl_; + talk_base::Thread* signaling_thread_; +}; + +template +class MockMediaStreamTrack: public T { + public: + MockMediaStreamTrack(T* implementation, + talk_base::Thread* signaling_thread) + : track_impl_(implementation), + signaling_thread_(signaling_thread) { + } + virtual void RegisterObserver(webrtc::ObserverInterface* observer) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + track_impl_->RegisterObserver(observer); + } + virtual void UnregisterObserver(webrtc::ObserverInterface* observer) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + track_impl_->UnregisterObserver(observer); + } + virtual const char* kind() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->kind(); + } + virtual std::string label() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->label(); + } + virtual uint32 ssrc() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->ssrc(); + } + virtual bool enabled() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->enabled(); + } + virtual MediaStreamTrackInterface::TrackState state() const { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->state(); + } + virtual bool set_enabled(bool enabled) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->set_enabled(enabled); + } + virtual bool set_ssrc(uint32 ssrc) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->set_ssrc(ssrc); + } + virtual bool set_state(webrtc::MediaStreamTrackInterface::TrackState state) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->set_state(state); + } + + protected: + scoped_refptr track_impl_; + talk_base::Thread* signaling_thread_; +}; + +class MockLocalVideoTrack + : public MockMediaStreamTrack { + public: + MockLocalVideoTrack(LocalVideoTrackInterface* implementation, + talk_base::Thread* signaling_thread) + : MockMediaStreamTrack(implementation, + signaling_thread) { + } + virtual void SetRenderer(webrtc::VideoRendererWrapperInterface* renderer) { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + track_impl_->SetRenderer(renderer); + } + virtual VideoRendererWrapperInterface* GetRenderer() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->GetRenderer(); + } + virtual VideoCaptureModule* GetVideoCapture() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->GetVideoCapture(); + } +}; + +class MockLocalAudioTrack + : public MockMediaStreamTrack { + public: + MockLocalAudioTrack(LocalAudioTrackInterface* implementation, + talk_base::Thread* signaling_thread) + : MockMediaStreamTrack(implementation, + signaling_thread) { + } + + virtual AudioDeviceModule* GetAudioDevice() { + EXPECT_EQ(talk_base::Thread::Current(), signaling_thread_); + return track_impl_->GetAudioDevice(); + } +}; + +class MediaStreamTest: public testing::Test, + public talk_base::MessageHandler { + protected: + virtual void SetUp() { + signaling_thread_ .reset(new talk_base::Thread()); + ASSERT_TRUE(signaling_thread_->Start()); + + std::string label(kStreamLabel1); + // Create a stream proxy object that uses our mocked + // version of a LocalMediaStream. + scoped_refptr mock_stream( + new talk_base::RefCount(label, + signaling_thread_.get())); + stream_ = MediaStreamProxy::Create(label, signaling_thread_.get(), + mock_stream); + ASSERT_TRUE(stream_.get()); + EXPECT_EQ(label, stream_->label()); + EXPECT_EQ(MediaStreamInterface::kInitializing, stream_->ready_state()); + + // Create a video track proxy object that uses our mocked + // version of a LocalVideoTrack + scoped_refptr video_track_impl( + VideoTrack::CreateLocal(kVideoTrackLabel, NULL)); + scoped_refptr mock_videotrack( + new talk_base::RefCount(video_track_impl, + signaling_thread_.get())); + video_track_ = VideoTrackProxy::CreateLocal(mock_videotrack, + signaling_thread_.get()); + + ASSERT_TRUE(video_track_.get()); + EXPECT_EQ(MediaStreamTrackInterface::kInitializing, video_track_->state()); + EXPECT_EQ(0u, video_track_->ssrc()); + + // Create an audio track proxy object that uses our mocked + // version of a LocalAudioTrack + scoped_refptr audio_track_impl( + AudioTrack::CreateLocal(kAudioTrackLabel, NULL)); + scoped_refptr mock_audiotrack( + new talk_base::RefCount(audio_track_impl, + signaling_thread_.get())); + audio_track_ = AudioTrackProxy::CreateLocal(mock_audiotrack, + signaling_thread_.get()); + + ASSERT_TRUE(audio_track_.get()); + EXPECT_EQ(MediaStreamTrackInterface::kInitializing, audio_track_->state()); + EXPECT_EQ(0u, audio_track_->ssrc()); + } + + enum { + MSG_SET_READYSTATE, + MSG_SET_SSRC, + MSG_SET_TRACKSTATE, + }; + + // Set the ready state on the signaling thread. + // State can only be changed on the signaling thread. + void SetReadyState(MediaStreamInterface* stream, + MediaStreamInterface::ReadyState new_state) { + ReadyStateMessageData state(stream, new_state); + signaling_thread_->Send(this, MSG_SET_READYSTATE, &state); + } + + // Set the track state on the signaling thread. + // State can only be changed on the signaling thread. + void SetTrackState(MediaStreamTrackInterface* track, + MediaStreamTrackInterface::TrackState new_state) { + TrackStateMessageData state(track, new_state); + signaling_thread_->Send(this, MSG_SET_TRACKSTATE, &state); + } + + // Set the ssrc on a track on the signaling thread. + // Ssrc can only be changed on the signaling thread. + void SetSsrc(MediaStreamTrackInterface* track, + uint32 new_ssrc) { + SsrcMessageData ssrc(track, new_ssrc); + signaling_thread_->Send(this, MSG_SET_SSRC, &ssrc); + } + + talk_base::scoped_ptr signaling_thread_; + scoped_refptr stream_; + scoped_refptr video_track_; + scoped_refptr audio_track_; + + private: + // Implements talk_base::MessageHandler. + virtual void OnMessage(talk_base::Message* msg) { + switch (msg->message_id) { + case MSG_SET_READYSTATE: { + ReadyStateMessageData* state = + static_cast(msg->pdata); + state->stream_->set_ready_state(state->ready_state_); + break; + } + case MSG_SET_SSRC: { + SsrcMessageData* ssrc = + static_cast(msg->pdata); + ssrc->track_->set_ssrc(ssrc->ssrc_); + break; + } + case MSG_SET_TRACKSTATE: { + TrackStateMessageData* state = + static_cast(msg->pdata); + state->track_->set_state(state->state_); + break; + } + default: + break; + } + } +}; + +TEST_F(MediaStreamTest, CreateLocalStream) { + EXPECT_TRUE(stream_->AddTrack(video_track_)); + EXPECT_TRUE(stream_->AddTrack(audio_track_)); + + ASSERT_EQ(1u, stream_->video_tracks()->count()); + ASSERT_EQ(1u, stream_->audio_tracks()->count()); + + // Verify the video track. + scoped_refptr track( + stream_->video_tracks()->at(0)); + EXPECT_EQ(0, track->label().compare(kVideoTrackLabel)); + EXPECT_TRUE(track->enabled()); + + // Verify the audio track. + track = stream_->audio_tracks()->at(0); + EXPECT_EQ(0, track->label().compare(kAudioTrackLabel)); + EXPECT_TRUE(track->enabled()); +} + +TEST_F(MediaStreamTest, ChangeStreamState) { + MockObserver observer(signaling_thread_.get()); + stream_->RegisterObserver(&observer); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + SetReadyState(stream_, MediaStreamInterface::kLive); + + EXPECT_EQ(MediaStreamInterface::kLive, stream_->ready_state()); + // It should not be possible to add + // streams when the state has changed to live. + EXPECT_FALSE(stream_->AddTrack(audio_track_)); + EXPECT_EQ(0u, stream_->audio_tracks()->count()); +} + +TEST_F(MediaStreamTest, ChangeVideoTrack) { + MockObserver observer(signaling_thread_.get()); + video_track_->RegisterObserver(&observer); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + + video_track_->set_enabled(false); + EXPECT_FALSE(video_track_->state()); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + SetSsrc(video_track_, 255); + EXPECT_EQ(255u, video_track_->ssrc()); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + SetTrackState(video_track_, MediaStreamTrackInterface::kLive); + EXPECT_EQ(MediaStreamTrackInterface::kLive, video_track_->state()); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + scoped_refptr renderer( + CreateVideoRenderer(NULL)); + video_track_->SetRenderer(renderer.get()); + EXPECT_TRUE(renderer.get() == video_track_->GetRenderer()); +} + +TEST_F(MediaStreamTest, ChangeAudioTrack) { + MockObserver observer(signaling_thread_.get()); + audio_track_->RegisterObserver(&observer); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + + audio_track_->set_enabled(false); + EXPECT_FALSE(audio_track_->enabled()); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + SetSsrc(audio_track_, 255); + EXPECT_EQ(255u, audio_track_->ssrc()); + + EXPECT_CALL(observer, DoOnChanged()) + .Times(Exactly(1)); + SetTrackState(audio_track_, MediaStreamTrackInterface::kLive); + EXPECT_EQ(MediaStreamTrackInterface::kLive, audio_track_->state()); +} + +} // namespace webrtc diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.cc b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.cc index 7f02fd155..f49cd26c5 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.cc +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.cc @@ -32,13 +32,13 @@ namespace { enum { - MSG_REGISTER_OBSERVER = 1, + MSG_SET_TRACKLIST_IMPLEMENTATION = 1, + MSG_REGISTER_OBSERVER, MSG_UNREGISTER_OBSERVER, MSG_LABEL, MSG_ADD_AUDIO_TRACK, MSG_ADD_VIDEO_TRACK, MSG_READY_STATE, - MSG_SET_READY_STATE, MSG_COUNT, MSG_AT }; @@ -78,6 +78,12 @@ class MediaStreamTrackAtMessageData : public talk_base::MessageData { talk_base::scoped_refptr track_; }; +class MediaStreamTrackListsMessageData : public talk_base::MessageData { + public: + talk_base::scoped_refptr audio_tracks_; + talk_base::scoped_refptr video_tracks_; +}; + } // namespace anonymous namespace webrtc { @@ -87,22 +93,43 @@ talk_base::scoped_refptr MediaStreamProxy::Create( talk_base::Thread* signaling_thread) { ASSERT(signaling_thread); talk_base::RefCount* stream = - new talk_base::RefCount(label, signaling_thread); + new talk_base::RefCount( + label, signaling_thread, + reinterpret_cast(NULL)); + return stream; +} + +talk_base::scoped_refptr MediaStreamProxy::Create( + const std::string& label, + talk_base::Thread* signaling_thread, + LocalMediaStreamInterface* media_stream_impl) { + ASSERT(signaling_thread); + ASSERT(media_stream_impl); + talk_base::RefCount* stream = + new talk_base::RefCount(label, signaling_thread, + media_stream_impl); return stream; } MediaStreamProxy::MediaStreamProxy(const std::string& label, - talk_base::Thread* signaling_thread) + talk_base::Thread* signaling_thread, + LocalMediaStreamInterface* media_stream_impl) : signaling_thread_(signaling_thread), - media_stream_impl_(MediaStream::Create(label)), + media_stream_impl_(media_stream_impl), audio_tracks_(new talk_base::RefCount< - MediaStreamTrackListProxy >( - media_stream_impl_->audio_tracks(), - signaling_thread_)), + MediaStreamTrackListProxy >( + signaling_thread_)), video_tracks_(new talk_base::RefCount< - MediaStreamTrackListProxy >( - media_stream_impl_->video_tracks(), - signaling_thread_)) { + MediaStreamTrackListProxy >( + signaling_thread_)) { + if (media_stream_impl_ == NULL) { + media_stream_impl_ = MediaStream::Create(label); + } + + MediaStreamTrackListsMessageData tracklists; + Send(MSG_SET_TRACKLIST_IMPLEMENTATION, &tracklists); + audio_tracks_->SetImplementation(tracklists.audio_tracks_); + video_tracks_->SetImplementation(tracklists.video_tracks_); } std::string MediaStreamProxy::label() const { @@ -127,8 +154,8 @@ MediaStreamInterface::ReadyState MediaStreamProxy::ready_state() { void MediaStreamProxy::set_ready_state( MediaStreamInterface::ReadyState new_state) { if (!signaling_thread_->IsCurrent()) { - ReadyStateMessageData msg(MediaStreamInterface::kInitializing); - Send(MSG_SET_READY_STATE, &msg); + // State should only be allowed to be changed from the signaling thread. + ASSERT(!"Not Allowed!"); return; } media_stream_impl_->set_ready_state(new_state); @@ -179,6 +206,13 @@ void MediaStreamProxy::Send(uint32 id, talk_base::MessageData* data) const { void MediaStreamProxy::OnMessage(talk_base::Message* msg) { talk_base::MessageData* data = msg->pdata; switch (msg->message_id) { + case MSG_SET_TRACKLIST_IMPLEMENTATION: { + MediaStreamTrackListsMessageData* lists = + static_cast(data); + lists->audio_tracks_ = media_stream_impl_->audio_tracks(); + lists->video_tracks_ = media_stream_impl_->video_tracks(); + break; + } case MSG_REGISTER_OBSERVER: { ObserverMessageData* observer = static_cast(data); media_stream_impl_->RegisterObserver(observer->data()); @@ -211,11 +245,6 @@ void MediaStreamProxy::OnMessage(talk_base::Message* msg) { state->data() = media_stream_impl_->ready_state(); break; } - case MSG_SET_READY_STATE: { - ReadyStateMessageData* state = static_cast(data); - media_stream_impl_->set_ready_state(state->data()); - break; - } default: ASSERT(!"Not Implemented!"); break; @@ -224,10 +253,14 @@ void MediaStreamProxy::OnMessage(talk_base::Message* msg) { template MediaStreamProxy::MediaStreamTrackListProxy::MediaStreamTrackListProxy( - MediaStreamTrackListInterface* track_list, talk_base::Thread* signaling_thread) - : track_list_(track_list), - signaling_thread_(signaling_thread) { + : signaling_thread_(signaling_thread) { +} + +template +void MediaStreamProxy::MediaStreamTrackListProxy::SetImplementation( + MediaStreamTrackListInterface* track_list) { + track_list_ = track_list; } template diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.h b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.h index 8ef1dfba1..c06b31011 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.h +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamproxy.h @@ -35,6 +35,7 @@ #include "talk/base/thread.h" namespace webrtc { +using talk_base::scoped_refptr; // MediaStreamProxy is a proxy for the MediaStream interface. The purpose is // to make sure MediaStreamImpl is only accessed from the signaling thread. @@ -42,34 +43,19 @@ namespace webrtc { class MediaStreamProxy : public LocalMediaStreamInterface, public talk_base::MessageHandler { public: - template - class MediaStreamTrackListProxy : public MediaStreamTrackListInterface, - public talk_base::MessageHandler { - public: - MediaStreamTrackListProxy(MediaStreamTrackListInterface* track_list, - talk_base::Thread* signaling_thread); - virtual size_t count(); - virtual T* at(size_t index); - - private: - void Send(uint32 id, talk_base::MessageData* data) const; - void OnMessage(talk_base::Message* msg); - - talk_base::scoped_refptr > track_list_; - mutable talk_base::Thread* signaling_thread_; - }; - - static talk_base::scoped_refptr Create( + static scoped_refptr Create( const std::string& label, talk_base::Thread* signaling_thread); + static scoped_refptr Create( + const std::string& label, + talk_base::Thread* signaling_thread, + LocalMediaStreamInterface* media_stream_impl); + // Implement LocalStream. virtual bool AddTrack(AudioTrackInterface* track); virtual bool AddTrack(VideoTrackInterface* track); - // This will be used when Tracks are created internally. - bool AddTrack(MediaStreamTrackInterface* track); - // Implement MediaStream. virtual std::string label() const; virtual AudioTracks* audio_tracks() { @@ -86,17 +72,38 @@ class MediaStreamProxy : public LocalMediaStreamInterface, virtual void UnregisterObserver(ObserverInterface* observer); protected: - explicit MediaStreamProxy(const std::string& label, - talk_base::Thread* signaling_thread); + MediaStreamProxy(const std::string& label, + talk_base::Thread* signaling_thread, + LocalMediaStreamInterface* media_stream_impl); + + template + class MediaStreamTrackListProxy : public MediaStreamTrackListInterface, + public talk_base::MessageHandler { + public: + MediaStreamTrackListProxy(talk_base::Thread* signaling_thread); + + void SetImplementation(MediaStreamTrackListInterface* track_list); + virtual size_t count(); + virtual T* at(size_t index); + + private: + void Send(uint32 id, talk_base::MessageData* data) const; + void OnMessage(talk_base::Message* msg); + + talk_base::scoped_refptr > track_list_; + mutable talk_base::Thread* signaling_thread_; + }; + typedef MediaStreamTrackListProxy AudioTrackListProxy; + typedef MediaStreamTrackListProxy VideoTrackListProxy; void Send(uint32 id, talk_base::MessageData* data) const; - // Implement MessageHandler + // Implement MessageHandler. virtual void OnMessage(talk_base::Message* msg); mutable talk_base::Thread* signaling_thread_; - talk_base::scoped_refptr media_stream_impl_; - talk_base::scoped_refptr audio_tracks_; - talk_base::scoped_refptr video_tracks_; + scoped_refptr media_stream_impl_; + scoped_refptr audio_tracks_; + scoped_refptr video_tracks_; }; } // namespace webrtc diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.cc b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.cc index 200bd227d..30764d878 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.cc +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.cc @@ -238,24 +238,29 @@ bool MediaStreamTrackProxy::HandleMessage(talk_base::Message* msg) { } } -AudioTrackProxy::AudioTrackProxy( - const std::string& label, - uint32 ssrc, - talk_base::Thread* signaling_thread) +AudioTrackProxy::AudioTrackProxy(const std::string& label, + uint32 ssrc, + talk_base::Thread* signaling_thread) : MediaStreamTrackProxy(signaling_thread), audio_track_(AudioTrack::CreateRemote(label, ssrc)) { Init(audio_track_); } -AudioTrackProxy::AudioTrackProxy( - const std::string& label, - AudioDeviceModule* audio_device, - talk_base::Thread* signaling_thread) +AudioTrackProxy::AudioTrackProxy(const std::string& label, + AudioDeviceModule* audio_device, + talk_base::Thread* signaling_thread) : MediaStreamTrackProxy(signaling_thread), audio_track_(AudioTrack::CreateLocal(label, audio_device)) { Init(audio_track_); } +AudioTrackProxy::AudioTrackProxy(LocalAudioTrackInterface* implementation, + talk_base::Thread* signaling_thread) + : MediaStreamTrackProxy(signaling_thread), + audio_track_(implementation) { + Init(audio_track_); +} + talk_base::scoped_refptr AudioTrackProxy::CreateRemote( const std::string& label, uint32 ssrc, @@ -279,6 +284,16 @@ talk_base::scoped_refptr AudioTrackProxy::CreateLocal( return track; } +talk_base::scoped_refptr AudioTrackProxy::CreateLocal( + LocalAudioTrackInterface* implementation, + talk_base::Thread* signaling_thread) { + ASSERT(signaling_thread); + talk_base::RefCount* track = + new talk_base::RefCount(implementation, + signaling_thread); + return track; +} + AudioDeviceModule* AudioTrackProxy::GetAudioDevice() { if (!signaling_thread_->IsCurrent()) { AudioDeviceMessageData msg; @@ -300,24 +315,29 @@ void AudioTrackProxy::OnMessage(talk_base::Message* msg) { } } -VideoTrackProxy::VideoTrackProxy( - const std::string& label, - uint32 ssrc, - talk_base::Thread* signaling_thread) +VideoTrackProxy::VideoTrackProxy(const std::string& label, + uint32 ssrc, + talk_base::Thread* signaling_thread) : MediaStreamTrackProxy(signaling_thread), video_track_(VideoTrack::CreateRemote(label, ssrc)) { Init(video_track_); } -VideoTrackProxy::VideoTrackProxy( - const std::string& label, - VideoCaptureModule* video_device, - talk_base::Thread* signaling_thread) +VideoTrackProxy::VideoTrackProxy(const std::string& label, + VideoCaptureModule* video_device, + talk_base::Thread* signaling_thread) : MediaStreamTrackProxy(signaling_thread), video_track_(VideoTrack::CreateLocal(label, video_device)) { Init(video_track_); } +VideoTrackProxy::VideoTrackProxy(LocalVideoTrackInterface* implementation, + talk_base::Thread* signaling_thread) + : MediaStreamTrackProxy(signaling_thread), + video_track_(implementation) { + Init(video_track_); +} + talk_base::scoped_refptr VideoTrackProxy::CreateRemote( const std::string& label, uint32 ssrc, @@ -340,6 +360,16 @@ talk_base::scoped_refptr VideoTrackProxy::CreateLocal( return track; } +talk_base::scoped_refptr VideoTrackProxy::CreateLocal( + LocalVideoTrackInterface* implementation, + talk_base::Thread* signaling_thread) { + ASSERT(signaling_thread); + talk_base::RefCount* track = + new talk_base::RefCount(implementation, + signaling_thread); + return track; +} + VideoCaptureModule* VideoTrackProxy::GetVideoCapture() { if (!signaling_thread_->IsCurrent()) { VideoDeviceMessageData msg; diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.h b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.h index d9f2c0cce..b2dc78fab 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.h +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/mediastreamtrackproxy.h @@ -85,6 +85,9 @@ class AudioTrackProxy : public MediaStreamTrackProxy { const std::string& label, AudioDeviceModule* audio_device, talk_base::Thread* signaling_thread); + static talk_base::scoped_refptr CreateLocal( + LocalAudioTrackInterface* implementation, + talk_base::Thread* signaling_thread); virtual AudioDeviceModule* GetAudioDevice(); @@ -95,10 +98,12 @@ class AudioTrackProxy : public MediaStreamTrackProxy { AudioTrackProxy(const std::string& label, AudioDeviceModule* audio_device, talk_base::Thread* signaling_thread); + AudioTrackProxy(LocalAudioTrackInterface* implementation, + talk_base::Thread* signaling_thread); // Implement MessageHandler virtual void OnMessage(talk_base::Message* msg); - talk_base::scoped_refptr audio_track_; + talk_base::scoped_refptr audio_track_; }; // VideoTrackProxy is a proxy for the VideoTrackInterface and @@ -115,6 +120,9 @@ class VideoTrackProxy : public MediaStreamTrackProxy { const std::string& label, VideoCaptureModule* video_device, talk_base::Thread* signaling_thread); + static talk_base::scoped_refptr CreateLocal( + LocalVideoTrackInterface* implementation, + talk_base::Thread* signaling_thread); virtual VideoCaptureModule* GetVideoCapture(); virtual void SetRenderer(VideoRendererWrapperInterface* renderer); @@ -127,10 +135,13 @@ class VideoTrackProxy : public MediaStreamTrackProxy { VideoTrackProxy(const std::string& label, VideoCaptureModule* video_device, talk_base::Thread* signaling_thread); + VideoTrackProxy(LocalVideoTrackInterface* implementation, + talk_base::Thread* signaling_thread); + // Implement MessageHandler virtual void OnMessage(talk_base::Message* msg); - talk_base::scoped_refptr video_track_; + talk_base::scoped_refptr video_track_; }; } // namespace webrtc