1 /* 2 * libjingle 3 * Copyright 2004 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 #ifndef TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ 29 #define TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ 30 31 #include <string.h> 32 33 #include <vector> 34 35 #include "talk/media/base/videocapturer.h" 36 #include "talk/media/base/videocommon.h" 37 #include "talk/media/base/videoframe.h" 38 #include "webrtc/base/timeutils.h" 39 #ifdef HAVE_WEBRTC_VIDEO 40 #include "talk/media/webrtc/webrtcvideoframefactory.h" 41 #endif 42 43 namespace cricket { 44 45 // Fake video capturer that allows the test to manually pump in frames. 46 class FakeVideoCapturer : public cricket::VideoCapturer { 47 public: FakeVideoCapturer()48 FakeVideoCapturer() 49 : running_(false), 50 initial_unix_timestamp_(time(NULL) * rtc::kNumNanosecsPerSec), 51 next_timestamp_(rtc::kNumNanosecsPerMillisec), 52 is_screencast_(false), 53 rotation_(webrtc::kVideoRotation_0) { 54 #ifdef HAVE_WEBRTC_VIDEO 55 set_frame_factory(new cricket::WebRtcVideoFrameFactory()); 56 #endif 57 // Default supported formats. Use ResetSupportedFormats to over write. 58 std::vector<cricket::VideoFormat> formats; 59 formats.push_back(cricket::VideoFormat(1280, 720, 60 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 61 formats.push_back(cricket::VideoFormat(640, 480, 62 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 63 formats.push_back(cricket::VideoFormat(320, 240, 64 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 65 formats.push_back(cricket::VideoFormat(160, 120, 66 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 67 formats.push_back(cricket::VideoFormat(1280, 720, 68 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_I420)); 69 ResetSupportedFormats(formats); 70 } ~FakeVideoCapturer()71 ~FakeVideoCapturer() { 72 SignalDestroyed(this); 73 } 74 ResetSupportedFormats(const std::vector<cricket::VideoFormat> & formats)75 void ResetSupportedFormats(const std::vector<cricket::VideoFormat>& formats) { 76 SetSupportedFormats(formats); 77 } CaptureFrame()78 bool CaptureFrame() { 79 if (!GetCaptureFormat()) { 80 return false; 81 } 82 return CaptureCustomFrame(GetCaptureFormat()->width, 83 GetCaptureFormat()->height, 84 GetCaptureFormat()->interval, 85 GetCaptureFormat()->fourcc); 86 } CaptureCustomFrame(int width,int height,uint32_t fourcc)87 bool CaptureCustomFrame(int width, int height, uint32_t fourcc) { 88 // default to 30fps 89 return CaptureCustomFrame(width, height, 33333333, fourcc); 90 } CaptureCustomFrame(int width,int height,int64_t timestamp_interval,uint32_t fourcc)91 bool CaptureCustomFrame(int width, 92 int height, 93 int64_t timestamp_interval, 94 uint32_t fourcc) { 95 if (!running_) { 96 return false; 97 } 98 // Currently, |fourcc| is always I420 or ARGB. 99 // TODO(fbarchard): Extend SizeOf to take fourcc. 100 uint32_t size = 0u; 101 if (fourcc == cricket::FOURCC_ARGB) { 102 size = width * 4 * height; 103 } else if (fourcc == cricket::FOURCC_I420) { 104 size = static_cast<uint32_t>(cricket::VideoFrame::SizeOf(width, height)); 105 } else { 106 return false; // Unsupported FOURCC. 107 } 108 if (size == 0u) { 109 return false; // Width and/or Height were zero. 110 } 111 112 cricket::CapturedFrame frame; 113 frame.width = width; 114 frame.height = height; 115 frame.fourcc = fourcc; 116 frame.data_size = size; 117 frame.time_stamp = initial_unix_timestamp_ + next_timestamp_; 118 next_timestamp_ += timestamp_interval; 119 120 rtc::scoped_ptr<char[]> data(new char[size]); 121 frame.data = data.get(); 122 // Copy something non-zero into the buffer so Validate wont complain that 123 // the frame is all duplicate. 124 memset(frame.data, 1, size / 2); 125 memset(reinterpret_cast<uint8_t*>(frame.data) + (size / 2), 2, 126 size - (size / 2)); 127 memcpy(frame.data, reinterpret_cast<const uint8_t*>(&fourcc), 4); 128 frame.rotation = rotation_; 129 // TODO(zhurunz): SignalFrameCaptured carry returned value to be able to 130 // capture results from downstream. 131 SignalFrameCaptured(this, &frame); 132 return true; 133 } 134 SignalCapturedFrame(cricket::CapturedFrame * frame)135 void SignalCapturedFrame(cricket::CapturedFrame* frame) { 136 SignalFrameCaptured(this, frame); 137 } 138 139 sigslot::signal1<FakeVideoCapturer*> SignalDestroyed; 140 Start(const cricket::VideoFormat & format)141 virtual cricket::CaptureState Start(const cricket::VideoFormat& format) { 142 cricket::VideoFormat supported; 143 if (GetBestCaptureFormat(format, &supported)) { 144 SetCaptureFormat(&supported); 145 } 146 running_ = true; 147 SetCaptureState(cricket::CS_RUNNING); 148 return cricket::CS_RUNNING; 149 } Stop()150 virtual void Stop() { 151 running_ = false; 152 SetCaptureFormat(NULL); 153 SetCaptureState(cricket::CS_STOPPED); 154 } IsRunning()155 virtual bool IsRunning() { return running_; } SetScreencast(bool is_screencast)156 void SetScreencast(bool is_screencast) { 157 is_screencast_ = is_screencast; 158 } IsScreencast()159 virtual bool IsScreencast() const { return is_screencast_; } GetPreferredFourccs(std::vector<uint32_t> * fourccs)160 bool GetPreferredFourccs(std::vector<uint32_t>* fourccs) { 161 fourccs->push_back(cricket::FOURCC_I420); 162 fourccs->push_back(cricket::FOURCC_MJPG); 163 return true; 164 } 165 SetRotation(webrtc::VideoRotation rotation)166 void SetRotation(webrtc::VideoRotation rotation) { 167 rotation_ = rotation; 168 } 169 GetRotation()170 webrtc::VideoRotation GetRotation() { return rotation_; } 171 172 private: 173 bool running_; 174 int64_t initial_unix_timestamp_; 175 int64_t next_timestamp_; 176 bool is_screencast_; 177 webrtc::VideoRotation rotation_; 178 }; 179 180 } // namespace cricket 181 182 #endif // TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ 183