1 /* 2 * libjingle 3 * Copyright 2012 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/media/base/capturemanager.h" 29 30 #include <algorithm> 31 32 #include "talk/media/base/videocapturer.h" 33 #include "talk/media/base/videorenderer.h" 34 #include "webrtc/base/checks.h" 35 #include "webrtc/base/logging.h" 36 37 namespace cricket { 38 39 // CaptureManager helper class. 40 class VideoCapturerState { 41 public: 42 static const VideoFormatPod kDefaultCaptureFormat; 43 44 static VideoCapturerState* Create(VideoCapturer* video_capturer); 45 ~VideoCapturerState() {} 46 47 void AddCaptureResolution(const VideoFormat& desired_format); 48 bool RemoveCaptureResolution(const VideoFormat& format); 49 VideoFormat GetHighestFormat(VideoCapturer* video_capturer) const; 50 51 int IncCaptureStartRef(); 52 int DecCaptureStartRef(); 53 CaptureRenderAdapter* adapter() { 54 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 55 return adapter_.get(); 56 } 57 VideoCapturer* GetVideoCapturer() { 58 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 59 return adapter()->video_capturer(); 60 } 61 62 int start_count() const { 63 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 64 return start_count_; 65 } 66 67 private: 68 struct CaptureResolutionInfo { 69 VideoFormat video_format; 70 int format_ref_count; 71 }; 72 typedef std::vector<CaptureResolutionInfo> CaptureFormats; 73 74 explicit VideoCapturerState(CaptureRenderAdapter* adapter); 75 76 rtc::ThreadChecker thread_checker_; 77 rtc::scoped_ptr<CaptureRenderAdapter> adapter_; 78 79 int start_count_; 80 CaptureFormats capture_formats_; 81 }; 82 83 const VideoFormatPod VideoCapturerState::kDefaultCaptureFormat = { 84 640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY 85 }; 86 87 VideoCapturerState::VideoCapturerState(CaptureRenderAdapter* adapter) 88 : adapter_(adapter), start_count_(1) {} 89 90 // static 91 VideoCapturerState* VideoCapturerState::Create(VideoCapturer* video_capturer) { 92 CaptureRenderAdapter* adapter = CaptureRenderAdapter::Create(video_capturer); 93 if (!adapter) { 94 return NULL; 95 } 96 return new VideoCapturerState(adapter); 97 } 98 99 void VideoCapturerState::AddCaptureResolution( 100 const VideoFormat& desired_format) { 101 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 102 for (CaptureFormats::iterator iter = capture_formats_.begin(); 103 iter != capture_formats_.end(); ++iter) { 104 if (desired_format == iter->video_format) { 105 ++(iter->format_ref_count); 106 return; 107 } 108 } 109 CaptureResolutionInfo capture_resolution = { desired_format, 1 }; 110 capture_formats_.push_back(capture_resolution); 111 } 112 113 bool VideoCapturerState::RemoveCaptureResolution(const VideoFormat& format) { 114 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 115 for (CaptureFormats::iterator iter = capture_formats_.begin(); 116 iter != capture_formats_.end(); ++iter) { 117 if (format == iter->video_format) { 118 --(iter->format_ref_count); 119 if (iter->format_ref_count == 0) { 120 capture_formats_.erase(iter); 121 } 122 return true; 123 } 124 } 125 return false; 126 } 127 128 VideoFormat VideoCapturerState::GetHighestFormat( 129 VideoCapturer* video_capturer) const { 130 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 131 VideoFormat highest_format(0, 0, VideoFormat::FpsToInterval(1), FOURCC_ANY); 132 if (capture_formats_.empty()) { 133 VideoFormat default_format(kDefaultCaptureFormat); 134 return default_format; 135 } 136 for (CaptureFormats::const_iterator iter = capture_formats_.begin(); 137 iter != capture_formats_.end(); ++iter) { 138 if (iter->video_format.width > highest_format.width) { 139 highest_format.width = iter->video_format.width; 140 } 141 if (iter->video_format.height > highest_format.height) { 142 highest_format.height = iter->video_format.height; 143 } 144 if (iter->video_format.interval < highest_format.interval) { 145 highest_format.interval = iter->video_format.interval; 146 } 147 } 148 return highest_format; 149 } 150 151 int VideoCapturerState::IncCaptureStartRef() { 152 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 153 return ++start_count_; 154 } 155 156 int VideoCapturerState::DecCaptureStartRef() { 157 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 158 if (start_count_ > 0) { 159 // Start count may be 0 if a capturer was added but never started. 160 --start_count_; 161 } 162 return start_count_; 163 } 164 165 CaptureManager::CaptureManager() { 166 // Allowing construction of manager in any thread as long as subsequent calls 167 // are all from the same thread. 168 thread_checker_.DetachFromThread(); 169 } 170 171 CaptureManager::~CaptureManager() { 172 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 173 174 // Since we don't own any of the capturers, all capturers should have been 175 // cleaned up before we get here. In fact, in the normal shutdown sequence, 176 // all capturers *will* be shut down by now, so trying to stop them here 177 // will crash. If we're still tracking any, it's a dangling pointer. 178 // TODO(hbos): RTC_DCHECK instead of RTC_CHECK until we figure out why 179 // capture_states_ is not always empty here. 180 RTC_DCHECK(capture_states_.empty()); 181 } 182 183 bool CaptureManager::StartVideoCapture(VideoCapturer* video_capturer, 184 const VideoFormat& desired_format) { 185 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 186 if (desired_format.width == 0 || desired_format.height == 0) { 187 return false; 188 } 189 if (!video_capturer) { 190 return false; 191 } 192 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 193 if (capture_state) { 194 const int ref_count = capture_state->IncCaptureStartRef(); 195 if (ref_count < 1) { 196 ASSERT(false); 197 } 198 // VideoCapturer has already been started. Don't start listening to 199 // callbacks since that has already been done. 200 capture_state->AddCaptureResolution(desired_format); 201 return true; 202 } 203 if (!RegisterVideoCapturer(video_capturer)) { 204 return false; 205 } 206 capture_state = GetCaptureState(video_capturer); 207 ASSERT(capture_state != NULL); 208 capture_state->AddCaptureResolution(desired_format); 209 if (!StartWithBestCaptureFormat(capture_state, video_capturer)) { 210 UnregisterVideoCapturer(capture_state); 211 return false; 212 } 213 return true; 214 } 215 216 bool CaptureManager::StopVideoCapture(VideoCapturer* video_capturer, 217 const VideoFormat& format) { 218 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 219 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 220 if (!capture_state) { 221 return false; 222 } 223 if (!capture_state->RemoveCaptureResolution(format)) { 224 return false; 225 } 226 227 if (capture_state->DecCaptureStartRef() == 0) { 228 // Unregistering cannot fail as capture_state is not NULL. 229 UnregisterVideoCapturer(capture_state); 230 } 231 return true; 232 } 233 234 bool CaptureManager::RestartVideoCapture( 235 VideoCapturer* video_capturer, 236 const VideoFormat& previous_format, 237 const VideoFormat& desired_format, 238 CaptureManager::RestartOptions options) { 239 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 240 if (!IsCapturerRegistered(video_capturer)) { 241 LOG(LS_ERROR) << "RestartVideoCapture: video_capturer is not registered."; 242 return false; 243 } 244 // Start the new format first. This keeps the capturer running. 245 if (!StartVideoCapture(video_capturer, desired_format)) { 246 LOG(LS_ERROR) << "RestartVideoCapture: unable to start video capture with " 247 "desired_format=" << desired_format.ToString(); 248 return false; 249 } 250 // Stop the old format. 251 if (!StopVideoCapture(video_capturer, previous_format)) { 252 LOG(LS_ERROR) << "RestartVideoCapture: unable to stop video capture with " 253 "previous_format=" << previous_format.ToString(); 254 // Undo the start request we just performed. 255 StopVideoCapture(video_capturer, desired_format); 256 return false; 257 } 258 259 switch (options) { 260 case kForceRestart: { 261 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 262 ASSERT(capture_state && capture_state->start_count() > 0); 263 // Try a restart using the new best resolution. 264 VideoFormat highest_asked_format = 265 capture_state->GetHighestFormat(video_capturer); 266 VideoFormat capture_format; 267 if (video_capturer->GetBestCaptureFormat(highest_asked_format, 268 &capture_format)) { 269 if (!video_capturer->Restart(capture_format)) { 270 LOG(LS_ERROR) << "RestartVideoCapture: Restart failed."; 271 } 272 } else { 273 LOG(LS_WARNING) 274 << "RestartVideoCapture: Couldn't find a best capture format for " 275 << highest_asked_format.ToString(); 276 } 277 break; 278 } 279 case kRequestRestart: 280 // TODO(ryanpetrie): Support restart requests. Should this 281 // to-be-implemented logic be used for {Start,Stop}VideoCapture as well? 282 break; 283 default: 284 LOG(LS_ERROR) << "Unknown/unimplemented RestartOption"; 285 break; 286 } 287 return true; 288 } 289 290 bool CaptureManager::AddVideoRenderer(VideoCapturer* video_capturer, 291 VideoRenderer* video_renderer) { 292 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 293 if (!video_capturer || !video_renderer) { 294 return false; 295 } 296 CaptureRenderAdapter* adapter = GetAdapter(video_capturer); 297 if (!adapter) { 298 return false; 299 } 300 return adapter->AddRenderer(video_renderer); 301 } 302 303 bool CaptureManager::RemoveVideoRenderer(VideoCapturer* video_capturer, 304 VideoRenderer* video_renderer) { 305 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 306 if (!video_capturer || !video_renderer) { 307 return false; 308 } 309 CaptureRenderAdapter* adapter = GetAdapter(video_capturer); 310 if (!adapter) { 311 return false; 312 } 313 return adapter->RemoveRenderer(video_renderer); 314 } 315 316 bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const { 317 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 318 return GetCaptureState(video_capturer) != NULL; 319 } 320 321 bool CaptureManager::RegisterVideoCapturer(VideoCapturer* video_capturer) { 322 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 323 VideoCapturerState* capture_state = 324 VideoCapturerState::Create(video_capturer); 325 if (!capture_state) { 326 return false; 327 } 328 capture_states_[video_capturer] = capture_state; 329 SignalCapturerStateChange.repeat(video_capturer->SignalStateChange); 330 return true; 331 } 332 333 void CaptureManager::UnregisterVideoCapturer( 334 VideoCapturerState* capture_state) { 335 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 336 VideoCapturer* video_capturer = capture_state->GetVideoCapturer(); 337 capture_states_.erase(video_capturer); 338 delete capture_state; 339 340 // When unregistering a VideoCapturer, the CaptureManager needs to unregister 341 // from all state change callbacks from the VideoCapturer. E.g. to avoid 342 // problems with multiple callbacks if registering the same VideoCapturer 343 // multiple times. The VideoCapturer will update the capturer state. However, 344 // this is done through Post-calls which means it may happen at any time. If 345 // the CaptureManager no longer is listening to the VideoCapturer it will not 346 // receive those callbacks. Here it is made sure that the the callback is 347 // indeed sent by letting the ChannelManager do the signaling. The downside is 348 // that the callback may happen before the VideoCapturer is stopped. However, 349 // for the CaptureManager it doesn't matter as it will no longer receive any 350 // frames from the VideoCapturer. 351 SignalCapturerStateChange.stop(video_capturer->SignalStateChange); 352 if (video_capturer->IsRunning()) { 353 video_capturer->Stop(); 354 SignalCapturerStateChange(video_capturer, CS_STOPPED); 355 } 356 } 357 358 bool CaptureManager::StartWithBestCaptureFormat( 359 VideoCapturerState* capture_state, VideoCapturer* video_capturer) { 360 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 361 VideoFormat highest_asked_format = 362 capture_state->GetHighestFormat(video_capturer); 363 VideoFormat capture_format; 364 if (!video_capturer->GetBestCaptureFormat(highest_asked_format, 365 &capture_format)) { 366 LOG(LS_WARNING) << "Unsupported format:" 367 << " width=" << highest_asked_format.width 368 << " height=" << highest_asked_format.height 369 << ". Supported formats are:"; 370 const std::vector<VideoFormat>* formats = 371 video_capturer->GetSupportedFormats(); 372 ASSERT(formats != NULL); 373 for (std::vector<VideoFormat>::const_iterator i = formats->begin(); 374 i != formats->end(); ++i) { 375 const VideoFormat& format = *i; 376 LOG(LS_WARNING) << " " << GetFourccName(format.fourcc) 377 << ":" << format.width << "x" << format.height << "x" 378 << format.framerate(); 379 } 380 return false; 381 } 382 return video_capturer->StartCapturing(capture_format); 383 } 384 385 VideoCapturerState* CaptureManager::GetCaptureState( 386 VideoCapturer* video_capturer) const { 387 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 388 CaptureStates::const_iterator iter = capture_states_.find(video_capturer); 389 if (iter == capture_states_.end()) { 390 return NULL; 391 } 392 return iter->second; 393 } 394 395 CaptureRenderAdapter* CaptureManager::GetAdapter( 396 VideoCapturer* video_capturer) const { 397 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 398 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 399 if (!capture_state) { 400 return NULL; 401 } 402 return capture_state->adapter(); 403 } 404 405 } // namespace cricket 406