1 #include "talk/media/devices/yuvframescapturer.h"
3 #include "webrtc/base/bytebuffer.h"
4 #include "webrtc/base/criticalsection.h"
5 #include "webrtc/base/logging.h"
6 #include "webrtc/base/thread.h"
8 #include "webrtc/system_wrappers/interface/clock.h"
11 ///////////////////////////////////////////////////////////////////////
12 // Definition of private class YuvFramesThread that periodically generates
14 ///////////////////////////////////////////////////////////////////////
15 class YuvFramesCapturer::YuvFramesThread
16 : public rtc::Thread, public rtc::MessageHandler {
18 explicit YuvFramesThread(YuvFramesCapturer* capturer)
19 : capturer_(capturer),
23 virtual ~YuvFramesThread() {
27 // Override virtual method of parent Thread. Context: Worker Thread.
29 // Read the first frame and start the message pump. The pump runs until
30 // Stop() is called externally or Quit() is called by OnMessage().
31 int waiting_time_ms = 0;
33 capturer_->ReadFrame(true);
34 PostDelayed(waiting_time_ms, this);
38 rtc::CritScope cs(&crit_);
42 // Override virtual method of parent MessageHandler. Context: Worker Thread.
43 virtual void OnMessage(rtc::Message* /*pmsg*/) {
44 int waiting_time_ms = 0;
46 capturer_->ReadFrame(false);
47 PostDelayed(waiting_time_ms, this);
53 // Check if Run() is finished.
54 bool Finished() const {
55 rtc::CritScope cs(&crit_);
60 YuvFramesCapturer* capturer_;
61 mutable rtc::CriticalSection crit_;
64 DISALLOW_COPY_AND_ASSIGN(YuvFramesThread);
67 /////////////////////////////////////////////////////////////////////
68 // Implementation of class YuvFramesCapturer.
69 /////////////////////////////////////////////////////////////////////
71 const char* YuvFramesCapturer::kYuvFrameDeviceName = "YuvFramesGenerator";
73 // TODO(shaowei): allow width_ and height_ to be configurable.
74 YuvFramesCapturer::YuvFramesCapturer()
75 : frames_generator_thread(NULL),
79 barcode_interval_(1) {
82 YuvFramesCapturer::~YuvFramesCapturer() {
84 delete[] static_cast<char*>(captured_frame_.data);
87 void YuvFramesCapturer::Init() {
88 int size = width_ * height_;
90 frame_generator_ = new YuvFrameGenerator(width_, height_, true);
91 frame_data_size_ = size + 2 * qsize;
92 captured_frame_.data = new char[frame_data_size_];
93 captured_frame_.fourcc = FOURCC_IYUV;
94 captured_frame_.pixel_height = 1;
95 captured_frame_.pixel_width = 1;
96 captured_frame_.width = width_;
97 captured_frame_.height = height_;
98 captured_frame_.data_size = frame_data_size_;
100 // Enumerate the supported formats. We have only one supported format.
101 VideoFormat format(width_, height_, VideoFormat::kMinimumInterval,
103 std::vector<VideoFormat> supported;
104 supported.push_back(format);
105 SetSupportedFormats(supported);
108 CaptureState YuvFramesCapturer::Start(const VideoFormat& capture_format) {
110 LOG(LS_ERROR) << "Yuv Frame Generator is already running";
113 SetCaptureFormat(&capture_format);
115 barcode_reference_timestamp_millis_ =
116 static_cast<int64>(rtc::Time()) * 1000;
117 // Create a thread to generate frames.
118 frames_generator_thread = new YuvFramesThread(this);
119 bool ret = frames_generator_thread->Start();
121 LOG(LS_INFO) << "Yuv Frame Generator started";
124 LOG(LS_ERROR) << "Yuv Frame Generator failed to start";
129 bool YuvFramesCapturer::IsRunning() {
130 return frames_generator_thread && !frames_generator_thread->Finished();
133 void YuvFramesCapturer::Stop() {
134 if (frames_generator_thread) {
135 frames_generator_thread->Stop();
136 frames_generator_thread = NULL;
137 LOG(LS_INFO) << "Yuv Frame Generator stopped";
139 SetCaptureFormat(NULL);
142 bool YuvFramesCapturer::GetPreferredFourccs(std::vector<uint32>* fourccs) {
146 fourccs->push_back(GetSupportedFormats()->at(0).fourcc);
150 // Executed in the context of YuvFramesThread.
151 void YuvFramesCapturer::ReadFrame(bool first_frame) {
152 // 1. Signal the previously read frame to downstream.
154 SignalFrameCaptured(this, &captured_frame_);
156 uint8* buffer = new uint8[frame_data_size_];
157 frame_generator_->GenerateNextFrame(buffer, GetBarcodeValue());
159 memmove(captured_frame_.data, buffer, frame_data_size_);
164 int32 YuvFramesCapturer::GetBarcodeValue() {
165 if (barcode_reference_timestamp_millis_ == -1 ||
166 frame_index_ % barcode_interval_ != 0) {
169 int64 now_millis = static_cast<int64>(rtc::Time()) * 1000;
170 return static_cast<int32>(now_millis - barcode_reference_timestamp_millis_);
173 } // namespace cricket