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/base/logging.h"
     29 #include "talk/base/thread.h"
     30 #include "talk/media/base/mutedvideocapturer.h"
     31 #include "talk/media/base/videoframe.h"
     32 
     33 #if defined(HAVE_WEBRTC_VIDEO)
     34 #include "talk/media/webrtc/webrtcvideoframe.h"
     35 #endif  // HAVE_WEBRTC_VIDEO
     36 
     37 
     38 namespace cricket {
     39 
     40 const char MutedVideoCapturer::kCapturerId[] = "muted_camera";
     41 
     42 class MutedFramesGenerator : public talk_base::MessageHandler {
     43  public:
     44   explicit MutedFramesGenerator(const VideoFormat& format);
     45   virtual ~MutedFramesGenerator();
     46 
     47   // Called every |interval| ms. From |format|.interval given in the
     48   // constructor.
     49   sigslot::signal1<VideoFrame*> SignalFrame;
     50 
     51  protected:
     52   virtual void OnMessage(talk_base::Message* message);
     53 
     54  private:
     55   talk_base::Thread capture_thread_;
     56   talk_base::scoped_ptr<VideoFrame> muted_frame_;
     57   const VideoFormat format_;
     58   const int interval_;
     59   uint32 create_time_;
     60 };
     61 
     62 MutedFramesGenerator::MutedFramesGenerator(const VideoFormat& format)
     63     : format_(format),
     64       interval_(static_cast<int>(format.interval /
     65                                  talk_base::kNumNanosecsPerMillisec)),
     66       create_time_(talk_base::Time()) {
     67   capture_thread_.Start();
     68   capture_thread_.PostDelayed(interval_, this);
     69 }
     70 
     71 MutedFramesGenerator::~MutedFramesGenerator() { capture_thread_.Clear(this); }
     72 
     73 void MutedFramesGenerator::OnMessage(talk_base::Message* message) {
     74   // Queue a new frame as soon as possible to minimize drift.
     75   capture_thread_.PostDelayed(interval_, this);
     76   if (!muted_frame_) {
     77 #if defined(HAVE_WEBRTC_VIDEO)
     78 #define VIDEO_FRAME_NAME WebRtcVideoFrame
     79 #endif
     80 #if defined(VIDEO_FRAME_NAME)
     81     muted_frame_.reset(new VIDEO_FRAME_NAME());
     82 #else
     83     return;
     84 #endif
     85   }
     86   uint32 current_timestamp = talk_base::Time();
     87   // Delta between create time and current time will be correct even if there is
     88   // a wraparound since they are unsigned integers.
     89   uint32 elapsed_time = current_timestamp - create_time_;
     90   if (!muted_frame_->InitToBlack(format_.width, format_.height, 1, 1,
     91                                  elapsed_time, current_timestamp)) {
     92     LOG(LS_ERROR) << "Failed to create a black frame.";
     93   }
     94   SignalFrame(muted_frame_.get());
     95 }
     96 
     97 MutedVideoCapturer::MutedVideoCapturer() { SetId(kCapturerId); }
     98 
     99 MutedVideoCapturer::~MutedVideoCapturer() { Stop(); }
    100 
    101 bool MutedVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired,
    102                                               VideoFormat* best_format) {
    103   *best_format = desired;
    104   return true;
    105 }
    106 
    107 CaptureState MutedVideoCapturer::Start(const VideoFormat& capture_format) {
    108   if (frame_generator_.get()) {
    109     return CS_RUNNING;
    110   }
    111   frame_generator_.reset(new MutedFramesGenerator(capture_format));
    112   frame_generator_->SignalFrame
    113       .connect(this, &MutedVideoCapturer::OnMutedFrame);
    114   SetCaptureFormat(&capture_format);
    115   return CS_RUNNING;
    116 }
    117 
    118 void MutedVideoCapturer::Stop() {
    119   frame_generator_.reset();
    120   SetCaptureFormat(NULL);
    121 }
    122 
    123 bool MutedVideoCapturer::IsRunning() { return frame_generator_.get() != NULL; }
    124 
    125 bool MutedVideoCapturer::GetPreferredFourccs(std::vector<uint32>* fourccs) {
    126   fourccs->clear();
    127   fourccs->push_back(cricket::FOURCC_I420);
    128   return true;
    129 }
    130 
    131 void MutedVideoCapturer::OnMutedFrame(VideoFrame* muted_frame) {
    132   SignalVideoFrame(this, muted_frame);
    133 }
    134 
    135 }  // namespace cricket
    136