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