1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/memory/scoped_ptr.h" 6 #include "content/common/media/media_stream_options.h" 7 #include "content/renderer/media/media_stream_extra_data.h" 8 #include "content/renderer/media/media_stream_source_extra_data.h" 9 #include "content/renderer/media/mock_media_stream_dependency_factory.h" 10 #include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" 13 #include "third_party/WebKit/public/platform/WebMediaStream.h" 14 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" 15 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 16 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandler.h" 17 #include "third_party/WebKit/public/platform/WebVector.h" 18 #include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h" 19 20 namespace content { 21 22 class MediaSourceCreatedObserver { 23 public: 24 MediaSourceCreatedObserver() 25 : result_(false), 26 description_(NULL) { 27 } 28 29 void OnCreateNativeSourcesComplete( 30 WebKit::WebMediaStream* description, 31 bool request_succeeded) { 32 result_ = request_succeeded; 33 description_ = description; 34 } 35 36 WebKit::WebMediaStream* description() const { 37 return description_; 38 } 39 bool result() const { return result_; } 40 41 private: 42 bool result_; 43 WebKit::WebMediaStream* description_; 44 }; 45 46 class MediaStreamDependencyFactoryTest : public ::testing::Test { 47 public: 48 virtual void SetUp() { 49 dependency_factory_.reset(new MockMediaStreamDependencyFactory()); 50 } 51 52 virtual void TearDown() OVERRIDE { 53 // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been 54 // implemented to fully avoid a circular dependency. 55 for (size_t i = 0; i < audio_sources_.size(); ++i) 56 audio_sources_[i].setExtraData(NULL); 57 58 for (size_t i = 0; i < video_sources_.size(); ++i) 59 video_sources_[i].setExtraData(NULL); 60 } 61 62 WebKit::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) { 63 WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources( 64 audio ? static_cast<size_t>(1) : 0); 65 WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources( 66 video ? static_cast<size_t>(1) : 0); 67 68 if (audio) { 69 StreamDeviceInfo info; 70 info.device.type = content::MEDIA_DEVICE_AUDIO_CAPTURE; 71 info.device.name = "audio"; 72 info.device.sample_rate = 0; 73 info.device.channel_layout = 0; 74 info.session_id = 99; 75 audio_sources[0].initialize("audio", 76 WebKit::WebMediaStreamSource::TypeAudio, 77 "audio"); 78 audio_sources[0].setExtraData( 79 new MediaStreamSourceExtraData(info, audio_sources[0])); 80 audio_sources_.assign(audio_sources); 81 } 82 if (video) { 83 StreamDeviceInfo info; 84 info.device.type = content::MEDIA_DEVICE_VIDEO_CAPTURE; 85 info.device.name = "video"; 86 info.session_id = 98; 87 video_sources[0].initialize("video", 88 WebKit::WebMediaStreamSource::TypeVideo, 89 "video"); 90 video_sources[0].setExtraData( 91 new MediaStreamSourceExtraData(info, video_sources[0])); 92 video_sources_.assign(video_sources); 93 } 94 WebKit::WebMediaStream stream_desc; 95 WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_track_vector( 96 audio_sources.size()); 97 for (size_t i = 0; i < audio_track_vector.size(); ++i) { 98 audio_track_vector[i].initialize(audio_sources[i].id(), 99 audio_sources[i]); 100 } 101 102 WebKit::WebVector<WebKit::WebMediaStreamTrack> video_track_vector( 103 video_sources.size()); 104 for (size_t i = 0; i < video_track_vector.size(); ++i) { 105 video_track_vector[i].initialize(video_sources[i].id(), 106 video_sources[i]); 107 } 108 109 stream_desc.initialize("media stream", audio_track_vector, 110 video_track_vector); 111 return stream_desc; 112 } 113 114 void CreateNativeSources(WebKit::WebMediaStream* descriptor) { 115 static const int kRenderViewId = 1; 116 117 MediaSourceCreatedObserver observer; 118 WebKit::WebMediaConstraints audio_constraints; 119 dependency_factory_->CreateNativeMediaSources( 120 kRenderViewId, 121 WebKit::WebMediaConstraints(), 122 WebKit::WebMediaConstraints(), 123 descriptor, 124 base::Bind( 125 &MediaSourceCreatedObserver::OnCreateNativeSourcesComplete, 126 base::Unretained(&observer))); 127 128 EXPECT_FALSE(observer.result()); 129 // Change the state of the created source to live. This should trigger 130 // MediaSourceCreatedObserver::OnCreateNativeSourcesComplete 131 if (dependency_factory_->last_video_source()) { 132 dependency_factory_->last_audio_source()->SetLive(); 133 dependency_factory_->last_video_source()->SetLive(); 134 } 135 EXPECT_TRUE(observer.result()); 136 EXPECT_TRUE(observer.description() == descriptor); 137 } 138 139 void VerifyMediaStream(const WebKit::WebMediaStream& stream_desc, 140 size_t num_audio_tracks, 141 size_t num_video_tracks) { 142 content::MediaStreamExtraData* extra_data = 143 static_cast<content::MediaStreamExtraData*>(stream_desc.extraData()); 144 ASSERT_TRUE(extra_data && extra_data->stream().get()); 145 EXPECT_TRUE(extra_data->is_local()); 146 EXPECT_EQ(num_audio_tracks, extra_data->stream()->GetAudioTracks().size()); 147 EXPECT_EQ(num_video_tracks, extra_data->stream()->GetVideoTracks().size()); 148 } 149 150 protected: 151 scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_; 152 WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources_; 153 WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources_; 154 }; 155 156 TEST_F(MediaStreamDependencyFactoryTest, CreateRTCPeerConnectionHandler) { 157 MockWebRTCPeerConnectionHandlerClient client_jsep; 158 scoped_ptr<WebKit::WebRTCPeerConnectionHandler> pc_handler( 159 dependency_factory_->CreateRTCPeerConnectionHandler(&client_jsep)); 160 EXPECT_TRUE(pc_handler.get() != NULL); 161 } 162 163 TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStream) { 164 WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); 165 CreateNativeSources(&stream_desc); 166 167 dependency_factory_->CreateNativeLocalMediaStream(&stream_desc); 168 VerifyMediaStream(stream_desc, 1, 1); 169 } 170 171 // Test that we don't crash if a MediaStream is created in WebKit with unknown 172 // sources. This can for example happen if a MediaStream is created with 173 // remote tracks. 174 TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStreamWithoutSource) { 175 // Create a WebKit MediaStream description. 176 WebKit::WebMediaStreamSource audio_source; 177 audio_source.initialize("audio source", 178 WebKit::WebMediaStreamSource::TypeAudio, 179 "something"); 180 WebKit::WebMediaStreamSource video_source; 181 video_source.initialize("video source", 182 WebKit::WebMediaStreamSource::TypeVideo, 183 "something"); 184 185 WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks( 186 static_cast<size_t>(1)); 187 audio_tracks[0].initialize(audio_source.id(), audio_source); 188 WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks( 189 static_cast<size_t>(1)); 190 video_tracks[0].initialize(video_source.id(), video_source); 191 192 WebKit::WebMediaStream stream_desc; 193 stream_desc.initialize("new stream", audio_tracks, video_tracks); 194 195 EXPECT_TRUE(dependency_factory_->EnsurePeerConnectionFactory()); 196 dependency_factory_->CreateNativeLocalMediaStream(&stream_desc); 197 VerifyMediaStream(stream_desc, 0, 0); 198 } 199 200 TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) { 201 WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); 202 CreateNativeSources(&stream_desc); 203 204 dependency_factory_->CreateNativeLocalMediaStream(&stream_desc); 205 VerifyMediaStream(stream_desc, 1, 1); 206 207 WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; 208 stream_desc.audioTracks(audio_tracks); 209 EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack( 210 stream_desc, audio_tracks[0])); 211 VerifyMediaStream(stream_desc, 0, 1); 212 213 EXPECT_TRUE(dependency_factory_->AddNativeMediaStreamTrack( 214 stream_desc, audio_tracks[0])); 215 VerifyMediaStream(stream_desc, 1, 1); 216 217 WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; 218 stream_desc.videoTracks(video_tracks); 219 EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack( 220 stream_desc, video_tracks[0])); 221 VerifyMediaStream(stream_desc, 1, 0); 222 223 EXPECT_TRUE(dependency_factory_->AddNativeMediaStreamTrack( 224 stream_desc, video_tracks[0])); 225 VerifyMediaStream(stream_desc, 1, 1); 226 } 227 228 } // namespace content 229