// Copyright (c) 2012 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. // // VideoCaptureDevice is the abstract base class for realizing video capture // device support in Chromium. It provides the interface for OS dependent // implementations. // The class is created and functions are invoked on a thread owned by // VideoCaptureManager. Capturing is done on other threads, depending on the OS // specific implementation. #ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_ #define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_ #include #include #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "media/base/media_export.h" #include "media/base/video_frame.h" #include "media/video/capture/video_capture_types.h" namespace media { class MEDIA_EXPORT VideoCaptureDevice { public: // Represents a capture device name and ID. // You should not create an instance of this class directly by e.g. setting // various properties directly. Instead use // VideoCaptureDevice::GetDeviceNames to do this for you and if you need to // cache your own copy of a name, you can do so via the copy constructor. // The reason for this is that a device name might contain platform specific // settings that are relevant only to the platform specific implementation of // VideoCaptureDevice::Create. class MEDIA_EXPORT Name { public: Name(); Name(const std::string& name, const std::string& id); #if defined(OS_WIN) // Windows targets Capture Api type: it can only be set on construction. enum CaptureApiType { MEDIA_FOUNDATION, DIRECT_SHOW, DIRECT_SHOW_WDM_CROSSBAR, API_TYPE_UNKNOWN }; #endif #if defined(OS_MACOSX) // Mac targets Capture Api type: it can only be set on construction. enum CaptureApiType { AVFOUNDATION, QTKIT, DECKLINK, API_TYPE_UNKNOWN }; // For AVFoundation Api, identify devices that are built-in or USB. enum TransportType { USB_OR_BUILT_IN, OTHER_TRANSPORT }; #endif #if defined(OS_WIN) || defined(OS_MACOSX) Name(const std::string& name, const std::string& id, const CaptureApiType api_type); #endif #if defined(OS_MACOSX) Name(const std::string& name, const std::string& id, const CaptureApiType api_type, const TransportType transport_type); #endif ~Name(); // Friendly name of a device const std::string& name() const { return device_name_; } // Unique name of a device. Even if there are multiple devices with the same // friendly name connected to the computer this will be unique. const std::string& id() const { return unique_id_; } // The unique hardware model identifier of the capture device. Returns // "[vid]:[pid]" when a USB device is detected, otherwise "". // The implementation of this method is platform-dependent. const std::string GetModel() const; // Friendly name of a device, plus the model identifier in parentheses. const std::string GetNameAndModel() const; // These operators are needed due to storing the name in an STL container. // In the shared build, all methods from the STL container will be exported // so even though they're not used, they're still depended upon. bool operator==(const Name& other) const { return other.id() == unique_id_; } bool operator<(const Name& other) const { return unique_id_ < other.id(); } #if defined(OS_WIN) || defined(OS_MACOSX) CaptureApiType capture_api_type() const { return capture_api_class_.capture_api_type(); } const char* GetCaptureApiTypeString() const; #endif #if defined(OS_WIN) // Certain devices need an ID different from the |unique_id_| for // capabilities retrieval. const std::string& capabilities_id() const { return capabilities_id_; } void set_capabilities_id(const std::string& id) { capabilities_id_ = id; } #endif #if defined(OS_MACOSX) TransportType transport_type() const { return transport_type_; } bool is_blacklisted() const { return is_blacklisted_; } void set_is_blacklisted(bool is_blacklisted) { is_blacklisted_ = is_blacklisted; } #endif // if defined(OS_WIN) private: std::string device_name_; std::string unique_id_; #if defined(OS_WIN) || defined(OS_MACOSX) // This class wraps the CaptureApiType to give it a by default value if not // initialized. class CaptureApiClass { public: CaptureApiClass(): capture_api_type_(API_TYPE_UNKNOWN) {} CaptureApiClass(const CaptureApiType api_type) : capture_api_type_(api_type) {} CaptureApiType capture_api_type() const { DCHECK_NE(capture_api_type_, API_TYPE_UNKNOWN); return capture_api_type_; } private: CaptureApiType capture_api_type_; }; CaptureApiClass capture_api_class_; #endif #if defined(OS_WIN) // ID used for capabilities retrieval. By default is equal to |unique_id|. std::string capabilities_id_; #endif #if defined(OS_MACOSX) TransportType transport_type_; // Flag used to mark blacklisted devices for QTKit Api. bool is_blacklisted_; #endif // Allow generated copy constructor and assignment. }; // Manages a list of Name entries. typedef std::list Names; // Interface defining the methods that clients of VideoCapture must have. It // is actually two-in-one: clients may implement OnIncomingCapturedData() or // ReserveOutputBuffer() + OnIncomingCapturedVideoFrame(), or all of them. // All clients must implement OnError(). class MEDIA_EXPORT Client { public: // Memory buffer returned by Client::ReserveOutputBuffer(). class Buffer : public base::RefCountedThreadSafe { public: virtual int id() const = 0; virtual void* data() const = 0; virtual size_t size() const = 0; protected: friend class base::RefCountedThreadSafe; virtual ~Buffer() {} }; virtual ~Client() {} // Captured a new video frame, data for which is pointed to by |data|. // // The format of the frame is described by |frame_format|, and is assumed to // be tightly packed. This method will try to reserve an output buffer and // copy from |data| into the output buffer. If no output buffer is // available, the frame will be silently dropped. virtual void OnIncomingCapturedData(const uint8* data, int length, const VideoCaptureFormat& frame_format, int rotation, // Clockwise. const base::TimeTicks& timestamp) = 0; // Reserve an output buffer into which contents can be captured directly. // The returned Buffer will always be allocated with a memory size suitable // for holding a packed video frame with pixels of |format| format, of // |dimensions| frame dimensions. It is permissible for |dimensions| to be // zero; in which case the returned Buffer does not guarantee memory // backing, but functions as a reservation for external input for the // purposes of buffer throttling. // // The output buffer stays reserved for use until the Buffer object is // destroyed. virtual scoped_refptr ReserveOutputBuffer( media::VideoFrame::Format format, const gfx::Size& dimensions) = 0; // Captured a new video frame, held in |frame|. // // As the frame is backed by a reservation returned by // ReserveOutputBuffer(), delivery is guaranteed and will require no // additional copies in the browser process. virtual void OnIncomingCapturedVideoFrame( const scoped_refptr& buffer, const VideoCaptureFormat& buffer_format, const scoped_refptr& frame, const base::TimeTicks& timestamp) = 0; // An error has occurred that cannot be handled and VideoCaptureDevice must // be StopAndDeAllocate()-ed. |reason| is a text description of the error. virtual void OnError(const std::string& reason) = 0; // VideoCaptureDevice requests the |message| to be logged. virtual void OnLog(const std::string& message) {} // The video stream has been muted. After this callback, no more // OnIncomingCapturedData() will be called. This may happen when // CaptureImage() has called. After the still image captured, the client // will get notified by OnUnmute() and the video stream will be resumed. virtual void OnMute() {} // The video stream has resumed. virtual void OnUnmute() {} }; // Interface for clients that use VideoCaptureDevice for taking still images. class MEDIA_EXPORT ImageClient { public: virtual ~ImageClient() {} // Callback function to notify the client a captured image is available. // // The captured still image is stored at address |data| and is of |length| // bytes. The format of the frame is described by |format|, and is assumed // to be tightly packed. The still image should be rotated |rotation| // degrees clockwise for viewing. // // Note that the content in |data| will not be valid after this callback // returns. Copy the content to use it later. virtual void OnIncomingCapturedData(const uint8* data, size_t length, const ImageCaptureFormat& format, int rotation, base::TimeTicks timestamp) = 0; // Callback function to notify the client about a failure of the image // capture. The VideoCaptureDevice must be StopAndDeAllocate()-ed. // |reason| contains a text description of the error. virtual void OnError(const std::string& reason) = 0; }; virtual ~VideoCaptureDevice(); // Prepares the camera for use. After this function has been called no other // applications can use the camera. StopAndDeAllocate() must be called before // the object is deleted. virtual void AllocateAndStart(const VideoCaptureParams& params, scoped_ptr client) = 0; // Deallocates the camera, possibly asynchronously. // // This call requires the device to do the following things, eventually: put // camera hardware into a state where other applications could use it, free // the memory associated with capture, and delete the |client| pointer passed // into AllocateAndStart. // // If deallocation is done asynchronously, then the device implementation must // ensure that a subsequent AllocateAndStart() operation targeting the same ID // would be sequenced through the same task runner, so that deallocation // happens first. virtual void StopAndDeAllocate() = 0; // Gets the power line frequency from the current system time zone if this is // defined, otherwise returns 0. int GetPowerLineFrequencyForLocation() const; // Initializes the device for still image capture for the given image format. // This call is synchronous and returns true iff the initialization is // successful. // // This function must be called between AllocateAndStart() and // StopAndDeAllocate(). virtual bool InitializeImageCapture(const ImageCaptureFormat& image_format, scoped_ptr client); // Releases resources for image capture. // // The ImageClient passed from InitializeImageCapture will be freed. This // method must be called between InitializeImageCapture() and // StopAndDeAllocate(). virtual void ReleaseImageCapture() {} // Requests one image from the device. // // The image will be returned via the ImageClient::OnIncomingCapturedData() // callback. If the video stream has to be stopped to capture the still image, // the Client::OnMute() and Client::OnUnmute() will be called. // // This function must be called between InitializeImageCapture() and // ReleaseImageCapture(). virtual void CaptureImage() {} protected: static const int kPowerLine50Hz = 50; static const int kPowerLine60Hz = 60; }; } // namespace media #endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_