| OLD | NEW |
| (Empty) |
| 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 #include "webrtc/media/devices/yuvframescapturer.h" | |
| 29 | |
| 30 #include "webrtc/base/bytebuffer.h" | |
| 31 #include "webrtc/base/criticalsection.h" | |
| 32 #include "webrtc/base/logging.h" | |
| 33 #include "webrtc/base/thread.h" | |
| 34 | |
| 35 #include "webrtc/system_wrappers/include/clock.h" | |
| 36 | |
| 37 namespace cricket { | |
| 38 /////////////////////////////////////////////////////////////////////// | |
| 39 // Definition of private class YuvFramesThread that periodically generates | |
| 40 // frames. | |
| 41 /////////////////////////////////////////////////////////////////////// | |
| 42 class YuvFramesCapturer::YuvFramesThread | |
| 43 : public rtc::Thread, public rtc::MessageHandler { | |
| 44 public: | |
| 45 explicit YuvFramesThread(YuvFramesCapturer* capturer) | |
| 46 : capturer_(capturer), | |
| 47 finished_(false) { | |
| 48 } | |
| 49 | |
| 50 virtual ~YuvFramesThread() { | |
| 51 Stop(); | |
| 52 } | |
| 53 | |
| 54 // Override virtual method of parent Thread. Context: Worker Thread. | |
| 55 virtual void Run() { | |
| 56 // Read the first frame and start the message pump. The pump runs until | |
| 57 // Stop() is called externally or Quit() is called by OnMessage(). | |
| 58 int waiting_time_ms = 0; | |
| 59 if (capturer_) { | |
| 60 capturer_->ReadFrame(true); | |
| 61 PostDelayed(waiting_time_ms, this); | |
| 62 Thread::Run(); | |
| 63 } | |
| 64 | |
| 65 rtc::CritScope cs(&crit_); | |
| 66 finished_ = true; | |
| 67 } | |
| 68 | |
| 69 // Override virtual method of parent MessageHandler. Context: Worker Thread. | |
| 70 virtual void OnMessage(rtc::Message* /*pmsg*/) { | |
| 71 int waiting_time_ms = 0; | |
| 72 if (capturer_) { | |
| 73 capturer_->ReadFrame(false); | |
| 74 PostDelayed(waiting_time_ms, this); | |
| 75 } else { | |
| 76 Quit(); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 // Check if Run() is finished. | |
| 81 bool Finished() const { | |
| 82 rtc::CritScope cs(&crit_); | |
| 83 return finished_; | |
| 84 } | |
| 85 | |
| 86 private: | |
| 87 YuvFramesCapturer* capturer_; | |
| 88 rtc::CriticalSection crit_; | |
| 89 bool finished_; | |
| 90 | |
| 91 RTC_DISALLOW_COPY_AND_ASSIGN(YuvFramesThread); | |
| 92 }; | |
| 93 | |
| 94 ///////////////////////////////////////////////////////////////////// | |
| 95 // Implementation of class YuvFramesCapturer. | |
| 96 ///////////////////////////////////////////////////////////////////// | |
| 97 | |
| 98 const char* YuvFramesCapturer::kYuvFrameDeviceName = "YuvFramesGenerator"; | |
| 99 | |
| 100 // TODO(shaowei): allow width_ and height_ to be configurable. | |
| 101 YuvFramesCapturer::YuvFramesCapturer() | |
| 102 : frames_generator_thread(NULL), | |
| 103 width_(640), | |
| 104 height_(480), | |
| 105 frame_index_(0), | |
| 106 barcode_interval_(1) { | |
| 107 } | |
| 108 | |
| 109 YuvFramesCapturer::~YuvFramesCapturer() { | |
| 110 Stop(); | |
| 111 delete[] static_cast<char*>(captured_frame_.data); | |
| 112 } | |
| 113 | |
| 114 void YuvFramesCapturer::Init() { | |
| 115 int size = width_ * height_; | |
| 116 int qsize = size / 4; | |
| 117 frame_generator_ = new YuvFrameGenerator(width_, height_, true); | |
| 118 frame_data_size_ = size + 2 * qsize; | |
| 119 captured_frame_.data = new char[frame_data_size_]; | |
| 120 captured_frame_.fourcc = FOURCC_IYUV; | |
| 121 captured_frame_.pixel_height = 1; | |
| 122 captured_frame_.pixel_width = 1; | |
| 123 captured_frame_.width = width_; | |
| 124 captured_frame_.height = height_; | |
| 125 captured_frame_.data_size = frame_data_size_; | |
| 126 | |
| 127 // Enumerate the supported formats. We have only one supported format. | |
| 128 VideoFormat format(width_, height_, VideoFormat::kMinimumInterval, | |
| 129 FOURCC_IYUV); | |
| 130 std::vector<VideoFormat> supported; | |
| 131 supported.push_back(format); | |
| 132 SetSupportedFormats(supported); | |
| 133 } | |
| 134 | |
| 135 CaptureState YuvFramesCapturer::Start(const VideoFormat& capture_format) { | |
| 136 if (IsRunning()) { | |
| 137 LOG(LS_ERROR) << "Yuv Frame Generator is already running"; | |
| 138 return CS_FAILED; | |
| 139 } | |
| 140 SetCaptureFormat(&capture_format); | |
| 141 | |
| 142 barcode_reference_timestamp_millis_ = | |
| 143 static_cast<int64_t>(rtc::Time()) * 1000; | |
| 144 // Create a thread to generate frames. | |
| 145 frames_generator_thread = new YuvFramesThread(this); | |
| 146 bool ret = frames_generator_thread->Start(); | |
| 147 if (ret) { | |
| 148 LOG(LS_INFO) << "Yuv Frame Generator started"; | |
| 149 return CS_RUNNING; | |
| 150 } else { | |
| 151 LOG(LS_ERROR) << "Yuv Frame Generator failed to start"; | |
| 152 return CS_FAILED; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 bool YuvFramesCapturer::IsRunning() { | |
| 157 return frames_generator_thread && !frames_generator_thread->Finished(); | |
| 158 } | |
| 159 | |
| 160 void YuvFramesCapturer::Stop() { | |
| 161 if (frames_generator_thread) { | |
| 162 frames_generator_thread->Stop(); | |
| 163 frames_generator_thread = NULL; | |
| 164 LOG(LS_INFO) << "Yuv Frame Generator stopped"; | |
| 165 } | |
| 166 SetCaptureFormat(NULL); | |
| 167 } | |
| 168 | |
| 169 bool YuvFramesCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) { | |
| 170 if (!fourccs) { | |
| 171 return false; | |
| 172 } | |
| 173 fourccs->push_back(GetSupportedFormats()->at(0).fourcc); | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 // Executed in the context of YuvFramesThread. | |
| 178 void YuvFramesCapturer::ReadFrame(bool first_frame) { | |
| 179 // 1. Signal the previously read frame to downstream. | |
| 180 if (!first_frame) { | |
| 181 SignalFrameCaptured(this, &captured_frame_); | |
| 182 } | |
| 183 uint8_t* buffer = new uint8_t[frame_data_size_]; | |
| 184 frame_generator_->GenerateNextFrame(buffer, GetBarcodeValue()); | |
| 185 frame_index_++; | |
| 186 memmove(captured_frame_.data, buffer, frame_data_size_); | |
| 187 delete[] buffer; | |
| 188 } | |
| 189 | |
| 190 int32_t YuvFramesCapturer::GetBarcodeValue() { | |
| 191 if (barcode_reference_timestamp_millis_ == -1 || | |
| 192 frame_index_ % barcode_interval_ != 0) { | |
| 193 return -1; | |
| 194 } | |
| 195 int64_t now_millis = static_cast<int64_t>(rtc::Time()) * 1000; | |
| 196 return static_cast<int32_t>(now_millis - barcode_reference_timestamp_millis_); | |
| 197 } | |
| 198 | |
| 199 } // namespace cricket | |
| OLD | NEW |