| /* |
| * libjingle |
| * Copyright 2004 Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ |
| #define TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ |
| |
| #include <string.h> |
| |
| #include <vector> |
| |
| #include "talk/base/timeutils.h" |
| #include "talk/media/base/videocapturer.h" |
| #include "talk/media/base/videocommon.h" |
| #include "talk/media/base/videoframe.h" |
| |
| namespace cricket { |
| |
| // Fake video capturer that allows the test to manually pump in frames. |
| class FakeVideoCapturer : public cricket::VideoCapturer { |
| public: |
| FakeVideoCapturer() |
| : running_(false), |
| initial_unix_timestamp_(time(NULL) * talk_base::kNumNanosecsPerSec), |
| next_timestamp_(talk_base::kNumNanosecsPerMillisec), |
| is_screencast_(false) { |
| // Default supported formats. Use ResetSupportedFormats to over write. |
| std::vector<cricket::VideoFormat> formats; |
| formats.push_back(cricket::VideoFormat(1280, 720, |
| cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); |
| formats.push_back(cricket::VideoFormat(640, 480, |
| cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); |
| formats.push_back(cricket::VideoFormat(320, 240, |
| cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); |
| formats.push_back(cricket::VideoFormat(160, 120, |
| cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); |
| ResetSupportedFormats(formats); |
| } |
| ~FakeVideoCapturer() { |
| SignalDestroyed(this); |
| } |
| |
| void ResetSupportedFormats(const std::vector<cricket::VideoFormat>& formats) { |
| SetSupportedFormats(formats); |
| } |
| bool CaptureFrame() { |
| if (!GetCaptureFormat()) { |
| return false; |
| } |
| return CaptureCustomFrame(GetCaptureFormat()->width, |
| GetCaptureFormat()->height, |
| GetCaptureFormat()->fourcc); |
| } |
| bool CaptureCustomFrame(int width, int height, uint32 fourcc) { |
| if (!running_) { |
| return false; |
| } |
| // Currently, |fourcc| is always I420 or ARGB. |
| // TODO(fbarchard): Extend SizeOf to take fourcc. |
| uint32 size = 0u; |
| if (fourcc == cricket::FOURCC_ARGB) { |
| size = width * 4 * height; |
| } else if (fourcc == cricket::FOURCC_I420) { |
| size = static_cast<uint32>(cricket::VideoFrame::SizeOf(width, height)); |
| } else { |
| return false; // Unsupported FOURCC. |
| } |
| if (size == 0u) { |
| return false; // Width and/or Height were zero. |
| } |
| |
| cricket::CapturedFrame frame; |
| frame.width = width; |
| frame.height = height; |
| frame.fourcc = fourcc; |
| frame.data_size = size; |
| frame.elapsed_time = next_timestamp_; |
| frame.time_stamp = initial_unix_timestamp_ + next_timestamp_; |
| next_timestamp_ += 33333333; // 30 fps |
| |
| talk_base::scoped_ptr<char[]> data(new char[size]); |
| frame.data = data.get(); |
| // Copy something non-zero into the buffer so Validate wont complain that |
| // the frame is all duplicate. |
| memset(frame.data, 1, size / 2); |
| memset(reinterpret_cast<uint8*>(frame.data) + (size / 2), 2, |
| size - (size / 2)); |
| memcpy(frame.data, reinterpret_cast<const uint8*>(&fourcc), 4); |
| // TODO(zhurunz): SignalFrameCaptured carry returned value to be able to |
| // capture results from downstream. |
| SignalFrameCaptured(this, &frame); |
| return true; |
| } |
| |
| sigslot::signal1<FakeVideoCapturer*> SignalDestroyed; |
| |
| virtual cricket::CaptureState Start(const cricket::VideoFormat& format) { |
| cricket::VideoFormat supported; |
| if (GetBestCaptureFormat(format, &supported)) { |
| SetCaptureFormat(&supported); |
| } |
| running_ = true; |
| SetCaptureState(cricket::CS_RUNNING); |
| return cricket::CS_RUNNING; |
| } |
| virtual void Stop() { |
| running_ = false; |
| SetCaptureFormat(NULL); |
| SetCaptureState(cricket::CS_STOPPED); |
| } |
| virtual bool IsRunning() { return running_; } |
| void SetScreencast(bool is_screencast) { |
| is_screencast_ = is_screencast; |
| } |
| virtual bool IsScreencast() const { return is_screencast_; } |
| bool GetPreferredFourccs(std::vector<uint32>* fourccs) { |
| fourccs->push_back(cricket::FOURCC_I420); |
| fourccs->push_back(cricket::FOURCC_MJPG); |
| return true; |
| } |
| |
| private: |
| bool running_; |
| int64 initial_unix_timestamp_; |
| int64 next_timestamp_; |
| bool is_screencast_; |
| }; |
| |
| } // namespace cricket |
| |
| #endif // TALK_MEDIA_BASE_FAKEVIDEOCAPTURER_H_ |