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