michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef VIDEOFRAMECONTAINER_H_ michael@0: #define VIDEOFRAMECONTAINER_H_ michael@0: michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/TimeStamp.h" michael@0: #include "gfxPoint.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsAutoPtr.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace dom { michael@0: class HTMLMediaElement; michael@0: } michael@0: michael@0: namespace layers { michael@0: class Image; michael@0: class ImageContainer; michael@0: } michael@0: michael@0: /** michael@0: * This object is used in the decoder backend threads and the main thread michael@0: * to manage the "current video frame" state. This state includes timing data michael@0: * and an intrinsic size (see below). michael@0: * This has to be a thread-safe object since it's accessed by resource decoders michael@0: * and other off-main-thread components. So we can't put this state in the media michael@0: * element itself ... well, maybe we could, but it could be risky and/or michael@0: * confusing. michael@0: */ michael@0: class VideoFrameContainer { michael@0: public: michael@0: typedef layers::ImageContainer ImageContainer; michael@0: typedef layers::Image Image; michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameContainer) michael@0: michael@0: VideoFrameContainer(dom::HTMLMediaElement* aElement, michael@0: already_AddRefed aContainer); michael@0: ~VideoFrameContainer(); michael@0: michael@0: // Call on any thread michael@0: void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage, michael@0: TimeStamp aTargetTime); michael@0: void ClearCurrentFrame(bool aResetSize = false); michael@0: // Reset the VideoFrameContainer michael@0: void Reset(); michael@0: // Time in seconds by which the last painted video frame was late by. michael@0: // E.g. if the last painted frame should have been painted at time t, michael@0: // but was actually painted at t+n, this returns n in seconds. Threadsafe. michael@0: double GetFrameDelay(); michael@0: // Call on main thread michael@0: enum { michael@0: INVALIDATE_DEFAULT, michael@0: INVALIDATE_FORCE michael@0: }; michael@0: void Invalidate() { InvalidateWithFlags(INVALIDATE_DEFAULT); } michael@0: void InvalidateWithFlags(uint32_t aFlags); michael@0: ImageContainer* GetImageContainer(); michael@0: void ForgetElement() { mElement = nullptr; } michael@0: michael@0: protected: michael@0: // Non-addreffed pointer to the element. The element calls ForgetElement michael@0: // to clear this reference when the element is destroyed. michael@0: dom::HTMLMediaElement* mElement; michael@0: nsRefPtr mImageContainer; michael@0: michael@0: // mMutex protects all the fields below. michael@0: Mutex mMutex; michael@0: // The intrinsic size is the ideal size which we should render the michael@0: // ImageContainer's current Image at. michael@0: // This can differ from the Image's actual size when the media resource michael@0: // specifies that the Image should be stretched to have the correct aspect michael@0: // ratio. michael@0: gfxIntSize mIntrinsicSize; michael@0: // The time at which the current video frame should have been painted. michael@0: // Access protected by mVideoUpdateLock. michael@0: TimeStamp mPaintTarget; michael@0: // The delay between the last video frame being presented and it being michael@0: // painted. This is time elapsed after mPaintTarget until the most recently michael@0: // painted frame appeared on screen. michael@0: TimeDuration mPaintDelay; michael@0: // True when the intrinsic size has been changed by SetCurrentFrame() since michael@0: // the last call to Invalidate(). michael@0: // The next call to Invalidate() will recalculate michael@0: // and update the intrinsic size on the element, request a frame reflow and michael@0: // then reset this flag. michael@0: bool mIntrinsicSizeChanged; michael@0: // True when the Image size has changed since the last time Invalidate() was michael@0: // called. When set, the next call to Invalidate() will ensure that the michael@0: // frame is fully invalidated instead of just invalidating for the image change michael@0: // in the ImageLayer. michael@0: bool mImageSizeChanged; michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif /* VIDEOFRAMECONTAINER_H_ */