HTMLVideoElement.h (7782B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_HTMLVideoElement_h 8 #define mozilla_dom_HTMLVideoElement_h 9 10 #include "ImageTypes.h" 11 #include "Units.h" 12 #include "mozilla/ErrorResult.h" 13 #include "mozilla/StaticPrefs_media.h" 14 #include "mozilla/dom/HTMLMediaElement.h" 15 #include "mozilla/dom/VideoFrameProvider.h" 16 17 namespace mozilla { 18 19 class FrameStatistics; 20 21 namespace gfx { 22 class DataSourceSurface; 23 } 24 25 namespace dom { 26 27 class WakeLock; 28 class VideoPlaybackQuality; 29 30 class HTMLVideoElement final : public HTMLMediaElement { 31 class SecondaryVideoOutput; 32 33 public: 34 NS_DECL_ISUPPORTS_INHERITED 35 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLVideoElement, HTMLMediaElement) 36 37 typedef mozilla::dom::NodeInfo NodeInfo; 38 39 explicit HTMLVideoElement(already_AddRefed<NodeInfo>&& aNodeInfo); 40 41 NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLVideoElement, video) 42 43 using HTMLMediaElement::GetPaused; 44 45 HTMLVideoElement* AsHTMLVideoElement() override { return this; }; 46 47 void Invalidate(ImageSizeChanged aImageSizeChanged, 48 const Maybe<nsIntSize>& aNewIntrinsicSize, 49 ForceInvalidate aForceInvalidate) override; 50 51 bool IsVideo() const override { return true; } 52 53 bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 54 const nsAString& aValue, 55 nsIPrincipal* aMaybeScriptedPrincipal, 56 nsAttrValue& aResult) override; 57 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; 58 59 nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; 60 61 nsresult Clone(NodeInfo*, nsINode** aResult) const override; 62 63 nsresult CopyInnerTo(Element* aDest); 64 65 void UnbindFromTree(UnbindContext&) override; 66 67 mozilla::Maybe<mozilla::CSSIntSize> GetVideoSize() const; 68 69 void UpdateMediaSize(const nsIntSize& aSize) override; 70 71 nsresult SetAcceptHeader(nsIHttpChannel* aChannel) override; 72 73 // Element 74 bool IsInteractiveHTMLContent() const override; 75 76 // WebIDL 77 78 uint32_t Width() const { 79 return GetDimensionAttrAsUnsignedInt(nsGkAtoms::width, 0); 80 } 81 82 void SetWidth(uint32_t aValue, ErrorResult& aRv) { 83 SetUnsignedIntAttr(nsGkAtoms::width, aValue, 0, aRv); 84 } 85 86 uint32_t Height() const { 87 return GetDimensionAttrAsUnsignedInt(nsGkAtoms::height, 0); 88 } 89 90 void SetHeight(uint32_t aValue, ErrorResult& aRv) { 91 SetUnsignedIntAttr(nsGkAtoms::height, aValue, 0, aRv); 92 } 93 94 uint32_t VideoWidth(); 95 96 uint32_t VideoHeight(); 97 98 VideoRotation RotationDegrees() const { return mMediaInfo.mVideo.mRotation; } 99 100 bool HasAlpha() const { return mMediaInfo.mVideo.HasAlpha(); } 101 102 void GetPoster(nsAString& aValue) { 103 GetURIAttr(nsGkAtoms::poster, nullptr, aValue); 104 } 105 void SetPoster(const nsAString& aValue, ErrorResult& aRv) { 106 SetHTMLAttr(nsGkAtoms::poster, aValue, aRv); 107 } 108 109 uint32_t MozParsedFrames() const; 110 111 uint32_t MozDecodedFrames() const; 112 113 uint32_t MozPresentedFrames(); 114 115 uint32_t MozPaintedFrames(); 116 117 double MozFrameDelay(); 118 119 bool MozHasAudio() const; 120 121 already_AddRefed<VideoPlaybackQuality> GetVideoPlaybackQuality(); 122 123 already_AddRefed<Promise> CloneElementVisually(HTMLVideoElement& aTarget, 124 ErrorResult& rv); 125 126 void StopCloningElementVisually(); 127 128 bool IsCloningElementVisually() const { return !!mVisualCloneTarget; } 129 130 void OnSecondaryVideoContainerInstalled( 131 const RefPtr<VideoFrameContainer>& aSecondaryContainer) override; 132 133 void OnSecondaryVideoOutputFirstFrameRendered(); 134 135 void OnVisibilityChange(Visibility aNewVisibility) override; 136 137 bool DisablePictureInPicture() const { 138 return GetBoolAttr(nsGkAtoms::disablepictureinpicture); 139 } 140 141 void SetDisablePictureInPicture(bool aValue, ErrorResult& aError) { 142 SetHTMLBoolAttr(nsGkAtoms::disablepictureinpicture, aValue, aError); 143 } 144 145 protected: 146 virtual ~HTMLVideoElement(); 147 148 virtual JSObject* WrapNode(JSContext* aCx, 149 JS::Handle<JSObject*> aGivenProto) override; 150 151 /** 152 * We create video wakelock when the video is playing and release it when 153 * video pauses. Note, the actual platform wakelock will automatically be 154 * released when the page is in the background, so we don't need to check the 155 * video's visibility by ourselves. 156 */ 157 void WakeLockRelease() override; 158 void UpdateWakeLock() override; 159 160 bool ShouldCreateVideoWakeLock() const; 161 void CreateVideoWakeLockIfNeeded(); 162 void ReleaseVideoWakeLockIfExists(); 163 164 gfx::IntSize GetVideoIntrinsicDimensions(); 165 166 RefPtr<WakeLock> mScreenWakeLock; 167 168 WatchManager<HTMLVideoElement> mVideoWatchManager; 169 170 private: 171 bool SetVisualCloneTarget( 172 RefPtr<HTMLVideoElement> aVisualCloneTarget, 173 RefPtr<Promise> aVisualCloneTargetPromise = nullptr); 174 bool SetVisualCloneSource(RefPtr<HTMLVideoElement> aVisualCloneSource); 175 176 // Creates a new DataSourceSurface with data copied from aImage. 177 // This is used when creating a static clone of this element, to ensure we 178 // do not hold onto an output buffer from a decoder. 179 static already_AddRefed<gfx::DataSourceSurface> CopyImage( 180 layers::Image* aImage); 181 182 // For video elements, we can clone the frames being played to 183 // a secondary video element. If we're doing that, we hold a 184 // reference to the video element we're cloning to in 185 // mVisualCloneSource. 186 // 187 // Please don't set this to non-nullptr values directly - use 188 // SetVisualCloneTarget() instead. 189 RefPtr<HTMLVideoElement> mVisualCloneTarget; 190 // Set when mVisualCloneTarget is set, and resolved (and unset) when the 191 // secondary container has been applied to the underlying resource. 192 RefPtr<Promise> mVisualCloneTargetPromise; 193 // Set when beginning to clone visually and we are playing a MediaStream. 194 // This is the output wrapping the VideoFrameContainer of mVisualCloneTarget, 195 // so we can render its first frame, and resolve mVisualCloneTargetPromise as 196 // we do. 197 RefPtr<FirstFrameVideoOutput> mSecondaryVideoOutput; 198 // If this video is the clone target of another video element, 199 // then mVisualCloneSource points to that originating video 200 // element. 201 // 202 // Please don't set this to non-nullptr values directly - use 203 // SetVisualCloneTarget() instead. 204 RefPtr<HTMLVideoElement> mVisualCloneSource; 205 206 private: 207 void ResetState() override; 208 209 bool HasPendingCallbacks() const final { 210 return !mVideoFrameRequestManager.IsEmpty(); 211 } 212 213 VideoFrameRequestManager mVideoFrameRequestManager; 214 layers::ContainerFrameID mLastPresentedFrameID = 215 layers::kContainerFrameID_Invalid; 216 uint32_t mPresentedFrames = 0; 217 218 public: 219 uint32_t RequestVideoFrameCallback(VideoFrameRequestCallback& aCallback, 220 ErrorResult& aRv); 221 void CancelVideoFrameCallback(uint32_t aHandle); 222 // Returns false if the video element is not ready and callbacks shouldn't 223 // be fired (yet). 224 [[nodiscard]] bool WillFireVideoFrameCallbacks( 225 const TimeStamp& aNowTime, const Maybe<TimeStamp>& aNextTickTime, 226 VideoFrameCallbackMetadata& aMd); 227 VideoFrameRequestManager& FrameRequestManager() { 228 return mVideoFrameRequestManager; 229 } 230 void FinishedVideoFrameRequestCallbacks(); 231 232 private: 233 static void MapAttributesIntoRule(MappedDeclarationsBuilder&); 234 235 static bool IsVideoStatsEnabled(); 236 double TotalPlayTime() const; 237 238 virtual void MaybeBeginCloningVisually() override; 239 void EndCloningVisually(); 240 }; 241 242 } // namespace dom 243 } // namespace mozilla 244 245 #endif // mozilla_dom_HTMLVideoElement_h