/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MediaEngineSource_h #define MediaEngineSource_h #include "MediaSegment.h" #include "MediaTrackConstraints.h" #include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/media/MediaUtils.h" #include "mozilla/RefPtr.h" #include "mozilla/ThreadSafeWeakPtr.h" #include "nsStringFwd.h" #include "PerformanceRecorder.h" namespace mozilla { namespace dom { class Blob; struct MediaTrackSettings; } // namespace dom namespace ipc { class PrincipalInfo; } // namespace ipc class MediaEnginePhotoCallback; class MediaEnginePrefs; class MediaTrack; /** * Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError() * should be called. */ class MediaEnginePhotoCallback { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEnginePhotoCallback) // aBlob is the image captured by MediaEngineSource. It is // called on main thread. virtual nsresult PhotoComplete(already_AddRefed aBlob) = 0; // It is called on main thread. aRv is the error code. virtual nsresult PhotoError(nsresult aRv) = 0; protected: virtual ~MediaEnginePhotoCallback() = default; }; /** * Lifecycle state of MediaEngineSource. */ enum MediaEngineSourceState { kAllocated, // Allocated, not yet started. kStarted, // Previously allocated or stopped, then started. kStopped, // Previously started, then stopped. kReleased // Not allocated. }; /** * The pure interface of a MediaEngineSource. * * Most sources are helped by the defaults implemented in MediaEngineSource. */ class MediaEngineSourceInterface { public: /** * Return true if this is a fake source. I.e., if it is generating media * itself rather than being an interface to underlying hardware. */ virtual bool IsFake() const = 0; /** * Override w/a promise if source has frames, in order to potentially allow * deferring success of source acquisition until first frame has arrived. */ virtual RefPtr GetFirstFramePromise() const { return nullptr; } /** * Get an id uniquely identifying the source of video frames that this * MediaEngineSource represents. This can be used in profiler markers to * separate markers from different sources into different lanes. */ virtual const TrackingId& GetTrackingId() const = 0; /** * Called by MediaEngine to allocate an instance of this source. */ virtual nsresult Allocate(const dom::MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs, uint64_t aWindowID, const char** aOutBadConstraint) = 0; /** * Called by MediaEngine when a MediaTrack has been provided for the source to * feed data to. * * This must be called before Start. */ virtual void SetTrack(const RefPtr& aTrack, const PrincipalHandle& aPrincipal) = 0; /** * Called by MediaEngine to start feeding data to the track. * * NB: Audio sources handle the enabling of pulling themselves. */ virtual nsresult Start() = 0; /** * This brings focus to the selected source, e.g. to bring a captured window * to the front. * * We return one of the following: * NS_OK - Success. * NS_ERROR_NOT_AVAILABLE - For backends where focusing does not make sense. * NS_ERROR_NOT_IMPLEMENTED - For backends where focusing makes sense, but * is not yet implemented. * NS_ERROR_FAILURE - Failures reported from underlying code. */ virtual nsresult FocusOnSelectedSource() = 0; /** * Applies new constraints to the capability selection for the underlying * device. * * Should the constraints lead to choosing a new capability while the device * is actively being captured, the device will restart using the new * capability. * * We return one of the following: * NS_OK - Successful reconfigure. * NS_ERROR_INVALID_ARG - Couldn't find a capability fitting aConstraints. * See aBadConstraint for details. * NS_ERROR_UNEXPECTED - Reconfiguring the underlying device failed * unexpectedly. This leaves the device in a stopped * state. */ virtual nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs, const char** aOutBadConstraint) = 0; /** * Called by MediaEngine to stop feeding data to the track. * * Double-stopping is allowed and will return NS_OK. This is necessary * sometimes during shutdown. * * NB: Audio sources handle the disabling of pulling themselves. */ virtual nsresult Stop() = 0; /** * Called by MediaEngine to deallocate an underlying device. */ virtual nsresult Deallocate() = 0; /** * If implementation of MediaEngineSource supports TakePhoto(), the picture * should be returned via aCallback object. Otherwise, it returns * NS_ERROR_NOT_IMPLEMENTED. */ virtual nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) = 0; /** * GetBestFitnessDistance returns the best distance the capture device can * offer as a whole, given an accumulated number of ConstraintSets. Ideal * values are considered in the first ConstraintSet only. Plain values are * treated as Ideal in the first ConstraintSet. Plain values are treated as * Exact in subsequent ConstraintSets. Infinity = UINT32_MAX e.g. device * cannot satisfy accumulated ConstraintSets. A finite result may be used to * calculate this device's ranking as a choice. */ virtual uint32_t GetBestFitnessDistance( const nsTArray& aConstraintSets) const = 0; /** * Returns the current settings of the underlying device. * * Note that this might not be the settings of the underlying hardware. * In case of a camera where we intervene and scale frames to avoid * leaking information from other documents than the current one, * GetSettings() will return the scaled resolution. I.e., the * device settings as seen by js. */ virtual void GetSettings(dom::MediaTrackSettings& aOutSettings) const = 0; }; /** * Abstract base class for MediaEngineSources. * * Implements defaults for some common MediaEngineSourceInterface methods below. * Also implements RefPtr support and an owning-thread model for thread safety * checks in subclasses. */ class MediaEngineSource : public MediaEngineSourceInterface { public: // code inside webrtc.org assumes these sizes; don't use anything smaller // without verifying it's ok static const unsigned int kMaxDeviceNameLength = 128; static const unsigned int kMaxUniqueIdLength = 256; /** * Returns true if the given source type is for video, false otherwise. * Only call with real types. */ static bool IsVideo(dom::MediaSourceEnum aSource); /** * Returns true if the given source type is for audio, false otherwise. * Only call with real types. */ static bool IsAudio(dom::MediaSourceEnum aSource); NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngineSource) NS_DECL_OWNINGEVENTTARGET void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(MediaEngineSource); } const TrackingId& GetTrackingId() const override { static auto notImplementedId = TrackingId(); return notImplementedId; } // Not fake by default. bool IsFake() const override; // Returns NS_ERROR_NOT_AVAILABLE by default. nsresult FocusOnSelectedSource() override; // TakePhoto returns NS_ERROR_NOT_IMPLEMENTED by default, // to tell the caller to fallback to other methods. nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) override; // Returns a default distance of 0 for devices that don't have capabilities. uint32_t GetBestFitnessDistance( const nsTArray& aConstraintSets) const override { return 0; } protected: virtual ~MediaEngineSource(); }; } // namespace mozilla #endif /* MediaEngineSource_h */