diff options
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/media/devices/yuvframescapturer.cc')
-rw-r--r-- | chromium/third_party/libjingle/source/talk/media/devices/yuvframescapturer.cc | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/yuvframescapturer.cc b/chromium/third_party/libjingle/source/talk/media/devices/yuvframescapturer.cc new file mode 100644 index 00000000000..648094bf43a --- /dev/null +++ b/chromium/third_party/libjingle/source/talk/media/devices/yuvframescapturer.cc @@ -0,0 +1,173 @@ +#include "talk/media/devices/yuvframescapturer.h" + +#include "talk/base/bytebuffer.h" +#include "talk/base/criticalsection.h" +#include "talk/base/logging.h" +#include "talk/base/thread.h" + +#include "webrtc/system_wrappers/interface/clock.h" + +namespace cricket { +/////////////////////////////////////////////////////////////////////// +// Definition of private class YuvFramesThread that periodically generates +// frames. +/////////////////////////////////////////////////////////////////////// +class YuvFramesCapturer::YuvFramesThread + : public talk_base::Thread, public talk_base::MessageHandler { + public: + explicit YuvFramesThread(YuvFramesCapturer* capturer) + : capturer_(capturer), + finished_(false) { + } + + virtual ~YuvFramesThread() { + Stop(); + } + + // Override virtual method of parent Thread. Context: Worker Thread. + virtual void Run() { + // Read the first frame and start the message pump. The pump runs until + // Stop() is called externally or Quit() is called by OnMessage(). + int waiting_time_ms = 0; + if (capturer_) { + capturer_->ReadFrame(true); + PostDelayed(waiting_time_ms, this); + Thread::Run(); + } + + talk_base::CritScope cs(&crit_); + finished_ = true; + } + + // Override virtual method of parent MessageHandler. Context: Worker Thread. + virtual void OnMessage(talk_base::Message* /*pmsg*/) { + int waiting_time_ms = 0; + if (capturer_) { + capturer_->ReadFrame(false); + PostDelayed(waiting_time_ms, this); + } else { + Quit(); + } + } + + // Check if Run() is finished. + bool Finished() const { + talk_base::CritScope cs(&crit_); + return finished_; + } + + private: + YuvFramesCapturer* capturer_; + mutable talk_base::CriticalSection crit_; + bool finished_; + + DISALLOW_COPY_AND_ASSIGN(YuvFramesThread); +}; + +///////////////////////////////////////////////////////////////////// +// Implementation of class YuvFramesCapturer. +///////////////////////////////////////////////////////////////////// + +const char* YuvFramesCapturer::kYuvFrameDeviceName = "YuvFramesGenerator"; + +// TODO(shaowei): allow width_ and height_ to be configurable. +YuvFramesCapturer::YuvFramesCapturer() + : frames_generator_thread(NULL), + width_(640), + height_(480), + frame_index_(0), + barcode_interval_(1) { +} + +YuvFramesCapturer::~YuvFramesCapturer() { + Stop(); + delete[] static_cast<char*>(captured_frame_.data); +} + +void YuvFramesCapturer::Init() { + int size = width_ * height_; + int qsize = size / 4; + frame_generator_ = new YuvFrameGenerator(width_, height_, true); + frame_data_size_ = size + 2 * qsize; + captured_frame_.data = new char[frame_data_size_]; + captured_frame_.fourcc = FOURCC_IYUV; + captured_frame_.pixel_height = 1; + captured_frame_.pixel_width = 1; + captured_frame_.width = width_; + captured_frame_.height = height_; + captured_frame_.data_size = frame_data_size_; + + // Enumerate the supported formats. We have only one supported format. + VideoFormat format(width_, height_, VideoFormat::kMinimumInterval, + FOURCC_IYUV); + std::vector<VideoFormat> supported; + supported.push_back(format); + SetSupportedFormats(supported); +} + +CaptureState YuvFramesCapturer::Start(const VideoFormat& capture_format) { + if (IsRunning()) { + LOG(LS_ERROR) << "Yuv Frame Generator is already running"; + return CS_FAILED; + } + SetCaptureFormat(&capture_format); + + barcode_reference_timestamp_millis_ = + static_cast<int64>(talk_base::Time()) * 1000; + // Create a thread to generate frames. + frames_generator_thread = new YuvFramesThread(this); + bool ret = frames_generator_thread->Start(); + if (ret) { + LOG(LS_INFO) << "Yuv Frame Generator started"; + return CS_RUNNING; + } else { + LOG(LS_ERROR) << "Yuv Frame Generator failed to start"; + return CS_FAILED; + } +} + +bool YuvFramesCapturer::IsRunning() { + return frames_generator_thread && !frames_generator_thread->Finished(); +} + +void YuvFramesCapturer::Stop() { + if (frames_generator_thread) { + frames_generator_thread->Stop(); + frames_generator_thread = NULL; + LOG(LS_INFO) << "Yuv Frame Generator stopped"; + } + SetCaptureFormat(NULL); +} + +bool YuvFramesCapturer::GetPreferredFourccs(std::vector<uint32>* fourccs) { + if (!fourccs) { + return false; + } + fourccs->push_back(GetSupportedFormats()->at(0).fourcc); + return true; +} + +// Executed in the context of YuvFramesThread. +void YuvFramesCapturer::ReadFrame(bool first_frame) { + // 1. Signal the previously read frame to downstream. + if (!first_frame) { + SignalFrameCaptured(this, &captured_frame_); + } + uint8* buffer = new uint8[frame_data_size_]; + frame_generator_->GenerateNextFrame(buffer, GetBarcodeValue()); + frame_index_++; + memmove(captured_frame_.data, buffer, frame_data_size_); + delete[] buffer; +} + + +int32 YuvFramesCapturer::GetBarcodeValue() { + if (barcode_reference_timestamp_millis_ == -1 || + frame_index_ % barcode_interval_ != 0) { + return -1; + } + int64 now_millis = static_cast<int64>(talk_base::Time()) * 1000; + return static_cast<int32>(now_millis - barcode_reference_timestamp_millis_); +} + +} // namespace cricket |