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/base/logging.h" 33 #include "talk/media/base/videocapturer.h" 34 #include "talk/media/base/videoprocessor.h" 35 #include "talk/media/base/videorenderer.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() { return adapter_.get(); } 54 VideoCapturer* GetVideoCapturer() { return adapter()->video_capturer(); } 55 56 int start_count() const { return start_count_; } 57 58 private: 59 struct CaptureResolutionInfo { 60 VideoFormat video_format; 61 int format_ref_count; 62 }; 63 typedef std::vector<CaptureResolutionInfo> CaptureFormats; 64 65 explicit VideoCapturerState(CaptureRenderAdapter* adapter); 66 67 talk_base::scoped_ptr<CaptureRenderAdapter> adapter_; 68 69 int start_count_; 70 CaptureFormats capture_formats_; 71 }; 72 73 const VideoFormatPod VideoCapturerState::kDefaultCaptureFormat = { 74 640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY 75 }; 76 77 VideoCapturerState::VideoCapturerState(CaptureRenderAdapter* adapter) 78 : adapter_(adapter), start_count_(1) {} 79 80 VideoCapturerState* VideoCapturerState::Create(VideoCapturer* video_capturer) { 81 CaptureRenderAdapter* adapter = CaptureRenderAdapter::Create(video_capturer); 82 if (!adapter) { 83 return NULL; 84 } 85 return new VideoCapturerState(adapter); 86 } 87 88 void VideoCapturerState::AddCaptureResolution( 89 const VideoFormat& desired_format) { 90 for (CaptureFormats::iterator iter = capture_formats_.begin(); 91 iter != capture_formats_.end(); ++iter) { 92 if (desired_format == iter->video_format) { 93 ++(iter->format_ref_count); 94 return; 95 } 96 } 97 CaptureResolutionInfo capture_resolution = { desired_format, 1 }; 98 capture_formats_.push_back(capture_resolution); 99 } 100 101 bool VideoCapturerState::RemoveCaptureResolution(const VideoFormat& format) { 102 for (CaptureFormats::iterator iter = capture_formats_.begin(); 103 iter != capture_formats_.end(); ++iter) { 104 if (format == iter->video_format) { 105 --(iter->format_ref_count); 106 if (iter->format_ref_count == 0) { 107 capture_formats_.erase(iter); 108 } 109 return true; 110 } 111 } 112 return false; 113 } 114 115 VideoFormat VideoCapturerState::GetHighestFormat( 116 VideoCapturer* video_capturer) const { 117 VideoFormat highest_format(0, 0, VideoFormat::FpsToInterval(1), FOURCC_ANY); 118 if (capture_formats_.empty()) { 119 VideoFormat default_format(kDefaultCaptureFormat); 120 return default_format; 121 } 122 for (CaptureFormats::const_iterator iter = capture_formats_.begin(); 123 iter != capture_formats_.end(); ++iter) { 124 if (iter->video_format.width > highest_format.width) { 125 highest_format.width = iter->video_format.width; 126 } 127 if (iter->video_format.height > highest_format.height) { 128 highest_format.height = iter->video_format.height; 129 } 130 if (iter->video_format.interval < highest_format.interval) { 131 highest_format.interval = iter->video_format.interval; 132 } 133 } 134 return highest_format; 135 } 136 137 int VideoCapturerState::IncCaptureStartRef() { return ++start_count_; } 138 139 int VideoCapturerState::DecCaptureStartRef() { 140 if (start_count_ > 0) { 141 // Start count may be 0 if a capturer was added but never started. 142 --start_count_; 143 } 144 return start_count_; 145 } 146 147 CaptureManager::~CaptureManager() { 148 // Since we don't own any of the capturers, all capturers should have been 149 // cleaned up before we get here. In fact, in the normal shutdown sequence, 150 // all capturers *will* be shut down by now, so trying to stop them here 151 // will crash. If we're still tracking any, it's a dangling pointer. 152 if (!capture_states_.empty()) { 153 ASSERT(false && 154 "CaptureManager destructing while still tracking capturers!"); 155 // Delete remaining VideoCapturerStates, but don't touch the capturers. 156 do { 157 CaptureStates::iterator it = capture_states_.begin(); 158 delete it->second; 159 capture_states_.erase(it); 160 } while (!capture_states_.empty()); 161 } 162 } 163 164 bool CaptureManager::StartVideoCapture(VideoCapturer* video_capturer, 165 const VideoFormat& desired_format) { 166 if (desired_format.width == 0 || desired_format.height == 0) { 167 return false; 168 } 169 if (!video_capturer) { 170 return false; 171 } 172 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 173 if (capture_state) { 174 const int ref_count = capture_state->IncCaptureStartRef(); 175 if (ref_count < 1) { 176 ASSERT(false); 177 } 178 // VideoCapturer has already been started. Don't start listening to 179 // callbacks since that has already been done. 180 capture_state->AddCaptureResolution(desired_format); 181 return true; 182 } 183 if (!RegisterVideoCapturer(video_capturer)) { 184 return false; 185 } 186 capture_state = GetCaptureState(video_capturer); 187 ASSERT(capture_state != NULL); 188 capture_state->AddCaptureResolution(desired_format); 189 if (!StartWithBestCaptureFormat(capture_state, video_capturer)) { 190 UnregisterVideoCapturer(capture_state); 191 return false; 192 } 193 return true; 194 } 195 196 bool CaptureManager::StopVideoCapture(VideoCapturer* video_capturer, 197 const VideoFormat& format) { 198 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 199 if (!capture_state) { 200 return false; 201 } 202 if (!capture_state->RemoveCaptureResolution(format)) { 203 return false; 204 } 205 206 if (capture_state->DecCaptureStartRef() == 0) { 207 // Unregistering cannot fail as capture_state is not NULL. 208 UnregisterVideoCapturer(capture_state); 209 } 210 return true; 211 } 212 213 bool CaptureManager::RestartVideoCapture( 214 VideoCapturer* video_capturer, 215 const VideoFormat& previous_format, 216 const VideoFormat& desired_format, 217 CaptureManager::RestartOptions options) { 218 if (!IsCapturerRegistered(video_capturer)) { 219 LOG(LS_ERROR) << "RestartVideoCapture: video_capturer is not registered."; 220 return false; 221 } 222 // Start the new format first. This keeps the capturer running. 223 if (!StartVideoCapture(video_capturer, desired_format)) { 224 LOG(LS_ERROR) << "RestartVideoCapture: unable to start video capture with " 225 "desired_format=" << desired_format.ToString(); 226 return false; 227 } 228 // Stop the old format. 229 if (!StopVideoCapture(video_capturer, previous_format)) { 230 LOG(LS_ERROR) << "RestartVideoCapture: unable to stop video capture with " 231 "previous_format=" << previous_format.ToString(); 232 // Undo the start request we just performed. 233 StopVideoCapture(video_capturer, desired_format); 234 return false; 235 } 236 237 switch (options) { 238 case kForceRestart: { 239 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 240 ASSERT(capture_state && capture_state->start_count() > 0); 241 // Try a restart using the new best resolution. 242 VideoFormat highest_asked_format = 243 capture_state->GetHighestFormat(video_capturer); 244 VideoFormat capture_format; 245 if (video_capturer->GetBestCaptureFormat(highest_asked_format, 246 &capture_format)) { 247 if (!video_capturer->Restart(capture_format)) { 248 LOG(LS_ERROR) << "RestartVideoCapture: Restart failed."; 249 } 250 } else { 251 LOG(LS_WARNING) 252 << "RestartVideoCapture: Couldn't find a best capture format for " 253 << highest_asked_format.ToString(); 254 } 255 break; 256 } 257 case kRequestRestart: 258 // TODO(ryanpetrie): Support restart requests. Should this 259 // to-be-implemented logic be used for {Start,Stop}VideoCapture as well? 260 break; 261 default: 262 LOG(LS_ERROR) << "Unknown/unimplemented RestartOption"; 263 break; 264 } 265 return true; 266 } 267 268 bool CaptureManager::AddVideoRenderer(VideoCapturer* video_capturer, 269 VideoRenderer* video_renderer) { 270 if (!video_capturer || !video_renderer) { 271 return false; 272 } 273 CaptureRenderAdapter* adapter = GetAdapter(video_capturer); 274 if (!adapter) { 275 return false; 276 } 277 return adapter->AddRenderer(video_renderer); 278 } 279 280 bool CaptureManager::RemoveVideoRenderer(VideoCapturer* video_capturer, 281 VideoRenderer* video_renderer) { 282 if (!video_capturer || !video_renderer) { 283 return false; 284 } 285 CaptureRenderAdapter* adapter = GetAdapter(video_capturer); 286 if (!adapter) { 287 return false; 288 } 289 return adapter->RemoveRenderer(video_renderer); 290 } 291 292 bool CaptureManager::AddVideoProcessor(VideoCapturer* video_capturer, 293 VideoProcessor* video_processor) { 294 if (!video_capturer || !video_processor) { 295 return false; 296 } 297 if (!IsCapturerRegistered(video_capturer)) { 298 return false; 299 } 300 video_capturer->AddVideoProcessor(video_processor); 301 return true; 302 } 303 304 bool CaptureManager::RemoveVideoProcessor(VideoCapturer* video_capturer, 305 VideoProcessor* video_processor) { 306 if (!video_capturer || !video_processor) { 307 return false; 308 } 309 if (!IsCapturerRegistered(video_capturer)) { 310 return false; 311 } 312 return video_capturer->RemoveVideoProcessor(video_processor); 313 } 314 315 bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const { 316 return GetCaptureState(video_capturer) != NULL; 317 } 318 319 bool CaptureManager::RegisterVideoCapturer(VideoCapturer* video_capturer) { 320 VideoCapturerState* capture_state = 321 VideoCapturerState::Create(video_capturer); 322 if (!capture_state) { 323 return false; 324 } 325 capture_states_[video_capturer] = capture_state; 326 SignalCapturerStateChange.repeat(video_capturer->SignalStateChange); 327 return true; 328 } 329 330 void CaptureManager::UnregisterVideoCapturer( 331 VideoCapturerState* capture_state) { 332 VideoCapturer* video_capturer = capture_state->GetVideoCapturer(); 333 capture_states_.erase(video_capturer); 334 delete capture_state; 335 336 // When unregistering a VideoCapturer, the CaptureManager needs to unregister 337 // from all state change callbacks from the VideoCapturer. E.g. to avoid 338 // problems with multiple callbacks if registering the same VideoCapturer 339 // multiple times. The VideoCapturer will update the capturer state. However, 340 // this is done through Post-calls which means it may happen at any time. If 341 // the CaptureManager no longer is listening to the VideoCapturer it will not 342 // receive those callbacks. Here it is made sure that the the callback is 343 // indeed sent by letting the ChannelManager do the signaling. The downside is 344 // that the callback may happen before the VideoCapturer is stopped. However, 345 // for the CaptureManager it doesn't matter as it will no longer receive any 346 // frames from the VideoCapturer. 347 SignalCapturerStateChange.stop(video_capturer->SignalStateChange); 348 video_capturer->Stop(); 349 SignalCapturerStateChange(video_capturer, CS_STOPPED); 350 } 351 352 bool CaptureManager::StartWithBestCaptureFormat( 353 VideoCapturerState* capture_state, VideoCapturer* video_capturer) { 354 VideoFormat highest_asked_format = 355 capture_state->GetHighestFormat(video_capturer); 356 VideoFormat capture_format; 357 if (!video_capturer->GetBestCaptureFormat(highest_asked_format, 358 &capture_format)) { 359 LOG(LS_WARNING) << "Unsupported format:" 360 << " width=" << highest_asked_format.width 361 << " height=" << highest_asked_format.height 362 << ". Supported formats are:"; 363 const std::vector<VideoFormat>* formats = 364 video_capturer->GetSupportedFormats(); 365 ASSERT(formats != NULL); 366 for (std::vector<VideoFormat>::const_iterator i = formats->begin(); 367 i != formats->end(); ++i) { 368 const VideoFormat& format = *i; 369 LOG(LS_WARNING) << " " << GetFourccName(format.fourcc) 370 << ":" << format.width << "x" << format.height << "x" 371 << format.framerate(); 372 } 373 return false; 374 } 375 return video_capturer->StartCapturing(capture_format); 376 } 377 378 VideoCapturerState* CaptureManager::GetCaptureState( 379 VideoCapturer* video_capturer) const { 380 CaptureStates::const_iterator iter = capture_states_.find(video_capturer); 381 if (iter == capture_states_.end()) { 382 return NULL; 383 } 384 return iter->second; 385 } 386 387 CaptureRenderAdapter* CaptureManager::GetAdapter( 388 VideoCapturer* video_capturer) const { 389 VideoCapturerState* capture_state = GetCaptureState(video_capturer); 390 if (!capture_state) { 391 return NULL; 392 } 393 return capture_state->adapter(); 394 } 395 396 } // namespace cricket 397