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