Home | History | Annotate | Download | only in base
      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