diff options
Diffstat (limited to 'chromium/content/browser/media/capture/content_video_capture_device_core.h')
-rw-r--r-- | chromium/content/browser/media/capture/content_video_capture_device_core.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/chromium/content/browser/media/capture/content_video_capture_device_core.h b/chromium/content/browser/media/capture/content_video_capture_device_core.h new file mode 100644 index 00000000000..3a7e6974ae7 --- /dev/null +++ b/chromium/content/browser/media/capture/content_video_capture_device_core.h @@ -0,0 +1,204 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_DEVICE_CORE_H_ +#define CONTENT_BROWSER_MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_DEVICE_CORE_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread.h" +#include "base/threading/thread_checker.h" +#include "content/browser/media/capture/video_capture_oracle.h" +#include "content/common/content_export.h" +#include "media/base/video_frame.h" +#include "media/video/capture/video_capture_device.h" + +namespace media { +class VideoCaptureParams; +class VideoFrame; +} // namespace media + +namespace content { + +const int kMinFrameWidth = 2; +const int kMinFrameHeight = 2; + +// Returns the nearest even integer closer to zero. +template<typename IntType> +IntType MakeEven(IntType x) { + return x & static_cast<IntType>(-2); +} + +// TODO(nick): Remove this once frame subscription is supported on Aura and +// Linux. +#if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA) +const bool kAcceleratedSubscriberIsSupported = true; +#else +const bool kAcceleratedSubscriberIsSupported = false; +#endif + +class VideoCaptureMachine; + +// Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps +// the VideoCaptureOracle, which decides which frames to capture, and a +// VideoCaptureDevice::Client, which allocates and receives the captured +// frames, in a lock to synchronize state between the two. +class ThreadSafeCaptureOracle + : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> { + public: + ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client, + scoped_ptr<VideoCaptureOracle> oracle, + const media::VideoCaptureParams& params); + + // Called when a captured frame is available or an error has occurred. + // If |success| is true then |frame| is valid and |timestamp| indicates when + // the frame was painted. + // If |success| is false, all other parameters are invalid. + typedef base::Callback<void(const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks timestamp, + bool success)> CaptureFrameCallback; + + bool ObserveEventAndDecideCapture(VideoCaptureOracle::Event event, + base::TimeTicks event_time, + scoped_refptr<media::VideoFrame>* storage, + CaptureFrameCallback* callback); + + base::TimeDelta capture_period() const { + return oracle_->capture_period(); + } + + // Returns the current capture resolution. + gfx::Size GetCaptureSize() const; + + // Updates capture resolution based on the supplied source size and the + // maximum frame size. + void UpdateCaptureSize(const gfx::Size& source_size); + + // Stop new captures from happening (but doesn't forget the client). + void Stop(); + + // Signal an error to the client. + void ReportError(const std::string& reason); + + private: + friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>; + virtual ~ThreadSafeCaptureOracle(); + + // Callback invoked on completion of all captures. + void DidCaptureFrame( + int frame_number, + const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks timestamp, + bool success); + + // Protects everything below it. + mutable base::Lock lock_; + + // Recipient of our capture activity. + scoped_ptr<media::VideoCaptureDevice::Client> client_; + + // Makes the decision to capture a frame. + const scoped_ptr<VideoCaptureOracle> oracle_; + + // The video capture parameters used to construct the oracle proxy. + media::VideoCaptureParams params_; + + // Indicates if capture size has been updated after construction. + bool capture_size_updated_; + + // The current capturing format, as a media::VideoFrame::Format. + media::VideoFrame::Format video_frame_format_; +}; + +// Keeps track of the video capture source frames and executes copying on the +// UI BrowserThread. +class VideoCaptureMachine { + public: + VideoCaptureMachine() : started_(false) {} + virtual ~VideoCaptureMachine() {} + + // This should only be checked on the UI thread. + bool started() const { return started_; } + + // Starts capturing. Returns true if succeeded. + // Must be run on the UI BrowserThread. + virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, + const media::VideoCaptureParams& params) = 0; + + // Stops capturing. Must be run on the UI BrowserThread. + // |callback| is invoked after the capturing has stopped. + virtual void Stop(const base::Closure& callback) = 0; + + protected: + bool started_; + + private: + DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine); +}; + +// The "meat" of a content video capturer. +// +// Separating this from the "shell classes" WebContentsVideoCaptureDevice and +// DesktopCaptureDeviceAura allows safe destruction without needing to block any +// threads (e.g., the IO BrowserThread), as well as code sharing. +// +// ContentVideoCaptureDeviceCore manages a simple state machine and the pipeline +// (see notes at top of this file). It times the start of successive captures +// and facilitates the processing of each through the stages of the +// pipeline. +class CONTENT_EXPORT ContentVideoCaptureDeviceCore + : public base::SupportsWeakPtr<ContentVideoCaptureDeviceCore> { + public: + ContentVideoCaptureDeviceCore( + scoped_ptr<VideoCaptureMachine> capture_machine); + virtual ~ContentVideoCaptureDeviceCore(); + + // Asynchronous requests to change ContentVideoCaptureDeviceCore state. + void AllocateAndStart(const media::VideoCaptureParams& params, + scoped_ptr<media::VideoCaptureDevice::Client> client); + void StopAndDeAllocate(); + + private: + // Flag indicating current state. + enum State { + kIdle, + kCapturing, + kError + }; + + void TransitionStateTo(State next_state); + + // Called on the IO thread in response to StartCaptureMachine(). + // |success| is true if capture machine succeeded to start. + void CaptureStarted(bool success); + + // Stops capturing and notifies client_ of an error state. + void Error(const std::string& reason); + + // Tracks that all activity occurs on the media stream manager's thread. + base::ThreadChecker thread_checker_; + + // Current lifecycle state. + State state_; + + // Tracks the CaptureMachine that's doing work on our behalf on the UI thread. + // This value should never be dereferenced by this class, other than to + // create and destroy it on the UI thread. + scoped_ptr<VideoCaptureMachine> capture_machine_; + + // Our thread-safe capture oracle which serves as the gateway to the video + // capture pipeline. Besides the VideoCaptureDevice itself, it is the only + // component of the/ system with direct access to |client_|. + scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; + + DISALLOW_COPY_AND_ASSIGN(ContentVideoCaptureDeviceCore); +}; + + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_DEVICE_CORE_H_ |