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: 48 FakeVideoCapturer() 49 : running_(false), 50 initial_unix_timestamp_(time(NULL) * rtc::kNumNanosecsPerSec), 51 next_timestamp_(rtc::kNumNanosecsPerMillisec), 52 is_screencast_(false) { 53 #ifdef HAVE_WEBRTC_VIDEO 54 set_frame_factory(new cricket::WebRtcVideoFrameFactory()); 55 #endif 56 // Default supported formats. Use ResetSupportedFormats to over write. 57 std::vector<cricket::VideoFormat> formats; 58 formats.push_back(cricket::VideoFormat(1280, 720, 59 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 60 formats.push_back(cricket::VideoFormat(640, 480, 61 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 62 formats.push_back(cricket::VideoFormat(320, 240, 63 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 64 formats.push_back(cricket::VideoFormat(160, 120, 65 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 66 ResetSupportedFormats(formats); 67 } 68 ~FakeVideoCapturer() { 69 SignalDestroyed(this); 70 } 71 72 void ResetSupportedFormats(const std::vector<cricket::VideoFormat>& formats) { 73 SetSupportedFormats(formats); 74 } 75 bool CaptureFrame() { 76 if (!GetCaptureFormat()) { 77 return false; 78 } 79 return CaptureCustomFrame(GetCaptureFormat()->width, 80 GetCaptureFormat()->height, 81 GetCaptureFormat()->fourcc); 82 } 83 bool CaptureCustomFrame(int width, int height, uint32 fourcc) { 84 if (!running_) { 85 return false; 86 } 87 // Currently, |fourcc| is always I420 or ARGB. 88 // TODO(fbarchard): Extend SizeOf to take fourcc. 89 uint32 size = 0u; 90 if (fourcc == cricket::FOURCC_ARGB) { 91 size = width * 4 * height; 92 } else if (fourcc == cricket::FOURCC_I420) { 93 size = static_cast<uint32>(cricket::VideoFrame::SizeOf(width, height)); 94 } else { 95 return false; // Unsupported FOURCC. 96 } 97 if (size == 0u) { 98 return false; // Width and/or Height were zero. 99 } 100 101 cricket::CapturedFrame frame; 102 frame.width = width; 103 frame.height = height; 104 frame.fourcc = fourcc; 105 frame.data_size = size; 106 frame.elapsed_time = next_timestamp_; 107 frame.time_stamp = initial_unix_timestamp_ + next_timestamp_; 108 next_timestamp_ += 33333333; // 30 fps 109 110 rtc::scoped_ptr<char[]> data(new char[size]); 111 frame.data = data.get(); 112 // Copy something non-zero into the buffer so Validate wont complain that 113 // the frame is all duplicate. 114 memset(frame.data, 1, size / 2); 115 memset(reinterpret_cast<uint8*>(frame.data) + (size / 2), 2, 116 size - (size / 2)); 117 memcpy(frame.data, reinterpret_cast<const uint8*>(&fourcc), 4); 118 // TODO(zhurunz): SignalFrameCaptured carry returned value to be able to 119 // capture results from downstream. 120 SignalFrameCaptured(this, &frame); 121 return true; 122 } 123 124 sigslot::signal1<FakeVideoCapturer*> SignalDestroyed; 125 126 virtual cricket::CaptureState Start(const cricket::VideoFormat& format) { 127 cricket::VideoFormat supported; 128 if (GetBestCaptureFormat(format, &supported)) { 129 SetCaptureFormat(&supported); 130 } 131 running_ = true; 132 SetCaptureState(cricket::CS_RUNNING); 133 return cricket::CS_RUNNING; 134 } 135 virtual void Stop() { 136 running_ = false; 137 SetCaptureFormat(NULL); 138 SetCaptureState(cricket::CS_STOPPED); 139 } 140 virtual bool IsRunning() { return running_; } 141 void SetScreencast(bool is_screencast) { 142 is_screencast_ = is_screencast; 143 } 144 virtual bool IsScreencast() const { return is_screencast_; } 145 bool GetPreferredFourccs(std::vector<uint32>* fourccs) { 146 fourccs->push_back(cricket::FOURCC_I420); 147 fourccs->push_back(cricket::FOURCC_MJPG); 148 return true; 149 } 150 151 private: 152 bool running_; 153 int64 initial_unix_timestamp_; 154 int64 next_timestamp_; 155 bool is_screencast_; 156 }; 157 158 } // namespace cricket 159 160 #endif // TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ 161