1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_ 6 #define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_ 7 8 #include <string> 9 10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/threading/thread.h" 13 #include "base/threading/thread_checker.h" 14 #include "content/browser/renderer_host/media/video_capture_oracle.h" 15 #include "content/common/content_export.h" 16 #include "media/video/capture/video_capture_device.h" 17 18 namespace content { 19 20 const int kMinFrameWidth = 2; 21 const int kMinFrameHeight = 2; 22 23 // Returns the nearest even integer closer to zero. 24 template<typename IntType> 25 IntType MakeEven(IntType x) { 26 return x & static_cast<IntType>(-2); 27 } 28 29 // TODO(nick): Remove this once frame subscription is supported on Aura and 30 // Linux. 31 #if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA) 32 const bool kAcceleratedSubscriberIsSupported = true; 33 #else 34 const bool kAcceleratedSubscriberIsSupported = false; 35 #endif 36 37 class VideoCaptureMachine; 38 39 // Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps 40 // the VideoCaptureOracle, which decides which frames to capture, and a 41 // VideoCaptureDevice::Client, which allocates and receives the captured 42 // frames, in a lock to synchronize state between the two. 43 class ThreadSafeCaptureOracle 44 : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> { 45 public: 46 ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client, 47 scoped_ptr<VideoCaptureOracle> oracle, 48 const media::VideoCaptureParams& params); 49 50 // Called when a captured frame is available or an error has occurred. 51 // If |success| is true then the frame provided is valid and |timestamp| 52 // indicates when the frame was painted. 53 // If |success| is false, both the frame provided and |timestamp| are invalid. 54 typedef base::Callback<void(base::Time timestamp, bool success)> 55 CaptureFrameCallback; 56 57 bool ObserveEventAndDecideCapture(VideoCaptureOracle::Event event, 58 base::Time event_time, 59 scoped_refptr<media::VideoFrame>* storage, 60 CaptureFrameCallback* callback); 61 62 base::TimeDelta capture_period() const { 63 return oracle_->capture_period(); 64 } 65 66 // Updates capture resolution based on the supplied source size and the 67 // maximum frame size. 68 void UpdateCaptureSize(const gfx::Size& source_size); 69 70 // Stop new captures from happening (but doesn't forget the client). 71 void Stop(); 72 73 // Signal an error to the client. 74 void ReportError(); 75 76 private: 77 friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>; 78 virtual ~ThreadSafeCaptureOracle(); 79 80 // Callback invoked on completion of all captures. 81 void DidCaptureFrame( 82 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer, 83 int frame_number, 84 base::Time timestamp, 85 bool success); 86 // Protects everything below it. 87 base::Lock lock_; 88 89 // Recipient of our capture activity. 90 scoped_ptr<media::VideoCaptureDevice::Client> client_; 91 92 // Makes the decision to capture a frame. 93 const scoped_ptr<VideoCaptureOracle> oracle_; 94 95 // The video capture parameters used to construct the oracle proxy. 96 const media::VideoCaptureParams params_; 97 98 // Indicates if capture size has been updated after construction. 99 bool capture_size_updated_; 100 101 // The current capturing resolution and frame rate. 102 gfx::Size capture_size_; 103 int frame_rate_; 104 }; 105 106 // Keeps track of the video capture source frames and executes copying on the 107 // UI BrowserThread. 108 class VideoCaptureMachine { 109 public: 110 VideoCaptureMachine() : started_(false) {} 111 virtual ~VideoCaptureMachine() {} 112 113 // This should only be checked on the UI thread. 114 bool started() const { return started_; } 115 116 // Starts capturing. Returns true if succeeded. 117 // Must be run on the UI BrowserThread. 118 virtual bool Start( 119 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) = 0; 120 121 // Stops capturing. Must be run on the UI BrowserThread. 122 virtual void Stop() = 0; 123 124 protected: 125 bool started_; 126 127 private: 128 DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine); 129 }; 130 131 // The "meat" of the video capture implementation. 132 // 133 // Separating this from the "shell classes" WebContentsVideoCaptureDevice and 134 // BrowserCompositorCaptureDevice allows safe destruction without needing to 135 // block any threads (e.g., the IO BrowserThread), as well as code sharing. 136 // 137 // VideoCaptureDeviceImpl manages a simple state machine and the pipeline (see 138 // notes at top of this file). It times the start of successive 139 // captures and facilitates the processing of each through the stages of the 140 // pipeline. 141 class CONTENT_EXPORT VideoCaptureDeviceImpl 142 : public base::SupportsWeakPtr<VideoCaptureDeviceImpl> { 143 public: 144 VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine> capture_machine); 145 virtual ~VideoCaptureDeviceImpl(); 146 147 // Asynchronous requests to change VideoCaptureDeviceImpl state. 148 void AllocateAndStart(const media::VideoCaptureParams& params, 149 scoped_ptr<media::VideoCaptureDevice::Client> client); 150 void StopAndDeAllocate(); 151 152 private: 153 // Flag indicating current state. 154 enum State { 155 kIdle, 156 kCapturing, 157 kError 158 }; 159 160 void TransitionStateTo(State next_state); 161 162 // Called on the IO thread in response to StartCaptureMachine(). 163 // |success| is true if capture machine succeeded to start. 164 void CaptureStarted(bool success); 165 166 // Stops capturing and notifies client_ of an error state. 167 void Error(); 168 169 // Tracks that all activity occurs on the media stream manager's thread. 170 base::ThreadChecker thread_checker_; 171 172 // Current lifecycle state. 173 State state_; 174 175 // Tracks the CaptureMachine that's doing work on our behalf on the UI thread. 176 // This value should never be dereferenced by this class, other than to 177 // create and destroy it on the UI thread. 178 scoped_ptr<VideoCaptureMachine> capture_machine_; 179 180 // Our thread-safe capture oracle which serves as the gateway to the video 181 // capture pipeline. Besides the WCVCD itself, it is the only component of the 182 // system with direct access to |client_|. 183 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; 184 185 DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceImpl); 186 }; 187 188 189 } // namespace content 190 191 #endif // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_ 192