Index: talk/media/base/capturemanager.cc |
diff --git a/talk/media/base/capturemanager.cc b/talk/media/base/capturemanager.cc |
deleted file mode 100644 |
index 78ca99d39c80635cdade7d92ed57d82b7f51a62e..0000000000000000000000000000000000000000 |
--- a/talk/media/base/capturemanager.cc |
+++ /dev/null |
@@ -1,406 +0,0 @@ |
-/* |
- * libjingle |
- * Copyright 2012 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/media/base/capturemanager.h" |
- |
-#include <algorithm> |
- |
-#include "talk/media/base/videocapturer.h" |
-#include "webrtc/base/checks.h" |
-#include "webrtc/base/logging.h" |
- |
-namespace cricket { |
- |
-// CaptureManager helper class. |
-class VideoCapturerState { |
- public: |
- static const VideoFormatPod kDefaultCaptureFormat; |
- |
- static VideoCapturerState* Create(VideoCapturer* video_capturer); |
- ~VideoCapturerState() {} |
- |
- void AddCaptureResolution(const VideoFormat& desired_format); |
- bool RemoveCaptureResolution(const VideoFormat& format); |
- VideoFormat GetHighestFormat(VideoCapturer* video_capturer) const; |
- |
- int IncCaptureStartRef(); |
- int DecCaptureStartRef(); |
- CaptureRenderAdapter* adapter() { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- return adapter_.get(); |
- } |
- VideoCapturer* GetVideoCapturer() { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- return adapter()->video_capturer(); |
- } |
- |
- int start_count() const { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- return start_count_; |
- } |
- |
- private: |
- struct CaptureResolutionInfo { |
- VideoFormat video_format; |
- int format_ref_count; |
- }; |
- typedef std::vector<CaptureResolutionInfo> CaptureFormats; |
- |
- explicit VideoCapturerState(CaptureRenderAdapter* adapter); |
- |
- rtc::ThreadChecker thread_checker_; |
- rtc::scoped_ptr<CaptureRenderAdapter> adapter_; |
- |
- int start_count_; |
- CaptureFormats capture_formats_; |
-}; |
- |
-const VideoFormatPod VideoCapturerState::kDefaultCaptureFormat = { |
- 640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY |
-}; |
- |
-VideoCapturerState::VideoCapturerState(CaptureRenderAdapter* adapter) |
- : adapter_(adapter), start_count_(1) {} |
- |
-// static |
-VideoCapturerState* VideoCapturerState::Create(VideoCapturer* video_capturer) { |
- CaptureRenderAdapter* adapter = CaptureRenderAdapter::Create(video_capturer); |
- if (!adapter) { |
- return NULL; |
- } |
- return new VideoCapturerState(adapter); |
-} |
- |
-void VideoCapturerState::AddCaptureResolution( |
- const VideoFormat& desired_format) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- for (CaptureFormats::iterator iter = capture_formats_.begin(); |
- iter != capture_formats_.end(); ++iter) { |
- if (desired_format == iter->video_format) { |
- ++(iter->format_ref_count); |
- return; |
- } |
- } |
- CaptureResolutionInfo capture_resolution = { desired_format, 1 }; |
- capture_formats_.push_back(capture_resolution); |
-} |
- |
-bool VideoCapturerState::RemoveCaptureResolution(const VideoFormat& format) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- for (CaptureFormats::iterator iter = capture_formats_.begin(); |
- iter != capture_formats_.end(); ++iter) { |
- if (format == iter->video_format) { |
- --(iter->format_ref_count); |
- if (iter->format_ref_count == 0) { |
- capture_formats_.erase(iter); |
- } |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-VideoFormat VideoCapturerState::GetHighestFormat( |
- VideoCapturer* video_capturer) const { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoFormat highest_format(0, 0, VideoFormat::FpsToInterval(1), FOURCC_ANY); |
- if (capture_formats_.empty()) { |
- VideoFormat default_format(kDefaultCaptureFormat); |
- return default_format; |
- } |
- for (CaptureFormats::const_iterator iter = capture_formats_.begin(); |
- iter != capture_formats_.end(); ++iter) { |
- if (iter->video_format.width > highest_format.width) { |
- highest_format.width = iter->video_format.width; |
- } |
- if (iter->video_format.height > highest_format.height) { |
- highest_format.height = iter->video_format.height; |
- } |
- if (iter->video_format.interval < highest_format.interval) { |
- highest_format.interval = iter->video_format.interval; |
- } |
- } |
- return highest_format; |
-} |
- |
-int VideoCapturerState::IncCaptureStartRef() { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- return ++start_count_; |
-} |
- |
-int VideoCapturerState::DecCaptureStartRef() { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- if (start_count_ > 0) { |
- // Start count may be 0 if a capturer was added but never started. |
- --start_count_; |
- } |
- return start_count_; |
-} |
- |
-CaptureManager::CaptureManager() { |
- // Allowing construction of manager in any thread as long as subsequent calls |
- // are all from the same thread. |
- thread_checker_.DetachFromThread(); |
-} |
- |
-CaptureManager::~CaptureManager() { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- // Since we don't own any of the capturers, all capturers should have been |
- // cleaned up before we get here. In fact, in the normal shutdown sequence, |
- // all capturers *will* be shut down by now, so trying to stop them here |
- // will crash. If we're still tracking any, it's a dangling pointer. |
- // TODO(hbos): RTC_DCHECK instead of RTC_CHECK until we figure out why |
- // capture_states_ is not always empty here. |
- RTC_DCHECK(capture_states_.empty()); |
-} |
- |
-bool CaptureManager::StartVideoCapture(VideoCapturer* video_capturer, |
- const VideoFormat& desired_format) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- if (desired_format.width == 0 || desired_format.height == 0) { |
- return false; |
- } |
- if (!video_capturer) { |
- return false; |
- } |
- VideoCapturerState* capture_state = GetCaptureState(video_capturer); |
- if (capture_state) { |
- const int ref_count = capture_state->IncCaptureStartRef(); |
- if (ref_count < 1) { |
- ASSERT(false); |
- } |
- // VideoCapturer has already been started. Don't start listening to |
- // callbacks since that has already been done. |
- capture_state->AddCaptureResolution(desired_format); |
- return true; |
- } |
- if (!RegisterVideoCapturer(video_capturer)) { |
- return false; |
- } |
- capture_state = GetCaptureState(video_capturer); |
- ASSERT(capture_state != NULL); |
- capture_state->AddCaptureResolution(desired_format); |
- if (!StartWithBestCaptureFormat(capture_state, video_capturer)) { |
- UnregisterVideoCapturer(capture_state); |
- return false; |
- } |
- return true; |
-} |
- |
-bool CaptureManager::StopVideoCapture(VideoCapturer* video_capturer, |
- const VideoFormat& format) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoCapturerState* capture_state = GetCaptureState(video_capturer); |
- if (!capture_state) { |
- return false; |
- } |
- if (!capture_state->RemoveCaptureResolution(format)) { |
- return false; |
- } |
- |
- if (capture_state->DecCaptureStartRef() == 0) { |
- // Unregistering cannot fail as capture_state is not NULL. |
- UnregisterVideoCapturer(capture_state); |
- } |
- return true; |
-} |
- |
-bool CaptureManager::RestartVideoCapture( |
- VideoCapturer* video_capturer, |
- const VideoFormat& previous_format, |
- const VideoFormat& desired_format, |
- CaptureManager::RestartOptions options) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- if (!IsCapturerRegistered(video_capturer)) { |
- LOG(LS_ERROR) << "RestartVideoCapture: video_capturer is not registered."; |
- return false; |
- } |
- // Start the new format first. This keeps the capturer running. |
- if (!StartVideoCapture(video_capturer, desired_format)) { |
- LOG(LS_ERROR) << "RestartVideoCapture: unable to start video capture with " |
- "desired_format=" << desired_format.ToString(); |
- return false; |
- } |
- // Stop the old format. |
- if (!StopVideoCapture(video_capturer, previous_format)) { |
- LOG(LS_ERROR) << "RestartVideoCapture: unable to stop video capture with " |
- "previous_format=" << previous_format.ToString(); |
- // Undo the start request we just performed. |
- StopVideoCapture(video_capturer, desired_format); |
- return false; |
- } |
- |
- switch (options) { |
- case kForceRestart: { |
- VideoCapturerState* capture_state = GetCaptureState(video_capturer); |
- ASSERT(capture_state && capture_state->start_count() > 0); |
- // Try a restart using the new best resolution. |
- VideoFormat highest_asked_format = |
- capture_state->GetHighestFormat(video_capturer); |
- VideoFormat capture_format; |
- if (video_capturer->GetBestCaptureFormat(highest_asked_format, |
- &capture_format)) { |
- if (!video_capturer->Restart(capture_format)) { |
- LOG(LS_ERROR) << "RestartVideoCapture: Restart failed."; |
- } |
- } else { |
- LOG(LS_WARNING) |
- << "RestartVideoCapture: Couldn't find a best capture format for " |
- << highest_asked_format.ToString(); |
- } |
- break; |
- } |
- case kRequestRestart: |
- // TODO(ryanpetrie): Support restart requests. Should this |
- // to-be-implemented logic be used for {Start,Stop}VideoCapture as well? |
- break; |
- default: |
- LOG(LS_ERROR) << "Unknown/unimplemented RestartOption"; |
- break; |
- } |
- return true; |
-} |
- |
-void CaptureManager::AddVideoSink(VideoCapturer* video_capturer, |
- rtc::VideoSinkInterface<VideoFrame>* sink) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- // TODO(nisse): Do we really need to tolerate NULL inputs? |
- if (!video_capturer || !sink) { |
- return; |
- } |
- CaptureRenderAdapter* adapter = GetAdapter(video_capturer); |
- if (!adapter) { |
- return; |
- } |
- adapter->AddSink(sink); |
-} |
- |
-void CaptureManager::RemoveVideoSink( |
- VideoCapturer* video_capturer, |
- rtc::VideoSinkInterface<VideoFrame>* sink) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- if (!video_capturer || !sink) { |
- return; |
- } |
- CaptureRenderAdapter* adapter = GetAdapter(video_capturer); |
- if (!adapter) { |
- return; |
- } |
- adapter->RemoveSink(sink); |
-} |
- |
-bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- return GetCaptureState(video_capturer) != NULL; |
-} |
- |
-bool CaptureManager::RegisterVideoCapturer(VideoCapturer* video_capturer) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoCapturerState* capture_state = |
- VideoCapturerState::Create(video_capturer); |
- if (!capture_state) { |
- return false; |
- } |
- capture_states_[video_capturer] = capture_state; |
- SignalCapturerStateChange.repeat(video_capturer->SignalStateChange); |
- return true; |
-} |
- |
-void CaptureManager::UnregisterVideoCapturer( |
- VideoCapturerState* capture_state) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoCapturer* video_capturer = capture_state->GetVideoCapturer(); |
- capture_states_.erase(video_capturer); |
- delete capture_state; |
- |
- // When unregistering a VideoCapturer, the CaptureManager needs to unregister |
- // from all state change callbacks from the VideoCapturer. E.g. to avoid |
- // problems with multiple callbacks if registering the same VideoCapturer |
- // multiple times. The VideoCapturer will update the capturer state. However, |
- // this is done through Post-calls which means it may happen at any time. If |
- // the CaptureManager no longer is listening to the VideoCapturer it will not |
- // receive those callbacks. Here it is made sure that the the callback is |
- // indeed sent by letting the ChannelManager do the signaling. The downside is |
- // that the callback may happen before the VideoCapturer is stopped. However, |
- // for the CaptureManager it doesn't matter as it will no longer receive any |
- // frames from the VideoCapturer. |
- SignalCapturerStateChange.stop(video_capturer->SignalStateChange); |
- if (video_capturer->IsRunning()) { |
- video_capturer->Stop(); |
- SignalCapturerStateChange(video_capturer, CS_STOPPED); |
- } |
-} |
- |
-bool CaptureManager::StartWithBestCaptureFormat( |
- VideoCapturerState* capture_state, VideoCapturer* video_capturer) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoFormat highest_asked_format = |
- capture_state->GetHighestFormat(video_capturer); |
- VideoFormat capture_format; |
- if (!video_capturer->GetBestCaptureFormat(highest_asked_format, |
- &capture_format)) { |
- LOG(LS_WARNING) << "Unsupported format:" |
- << " width=" << highest_asked_format.width |
- << " height=" << highest_asked_format.height |
- << ". Supported formats are:"; |
- const std::vector<VideoFormat>* formats = |
- video_capturer->GetSupportedFormats(); |
- ASSERT(formats != NULL); |
- for (std::vector<VideoFormat>::const_iterator i = formats->begin(); |
- i != formats->end(); ++i) { |
- const VideoFormat& format = *i; |
- LOG(LS_WARNING) << " " << GetFourccName(format.fourcc) |
- << ":" << format.width << "x" << format.height << "x" |
- << format.framerate(); |
- } |
- return false; |
- } |
- return video_capturer->StartCapturing(capture_format); |
-} |
- |
-VideoCapturerState* CaptureManager::GetCaptureState( |
- VideoCapturer* video_capturer) const { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- CaptureStates::const_iterator iter = capture_states_.find(video_capturer); |
- if (iter == capture_states_.end()) { |
- return NULL; |
- } |
- return iter->second; |
-} |
- |
-CaptureRenderAdapter* CaptureManager::GetAdapter( |
- VideoCapturer* video_capturer) const { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- VideoCapturerState* capture_state = GetCaptureState(video_capturer); |
- if (!capture_state) { |
- return NULL; |
- } |
- return capture_state->adapter(); |
-} |
- |
-} // namespace cricket |