1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 VIDEOFRAMECONTAINER_H_
#define VIDEOFRAMECONTAINER_H_
#include "ImageContainer.h"
#include "MediaSegment.h"
#include "VideoSegment.h"
#include "gfxPoint.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsCOMPtr.h"
namespace mozilla {
class MediaDecoderOwner;
/**
* This object is used in the decoder backend threads and the main thread
* to manage the "current video frame" state. This state includes timing data
* and an intrinsic size (see below).
* This has to be a thread-safe object since it's accessed by resource decoders
* and other off-main-thread components. So we can't put this state in the media
* element itself ... well, maybe we could, but it could be risky and/or
* confusing.
*/
class VideoFrameContainer {
virtual ~VideoFrameContainer();
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameContainer)
public:
typedef layers::ImageContainer ImageContainer;
typedef layers::Image Image;
VideoFrameContainer(MediaDecoderOwner* aOwner,
already_AddRefed<ImageContainer> aContainer);
void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage,
const TimeStamp& aTargetTime,
const media::TimeUnit& aProcessingDuration,
const media::TimeUnit& aMediaTime);
// Returns the last principalHandle we notified mElement about.
PrincipalHandle GetLastPrincipalHandle();
PrincipalHandle GetLastPrincipalHandleLocked() MOZ_REQUIRES(mMutex);
// We will notify mElement that aPrincipalHandle has been applied when all
// FrameIDs prior to aFrameID have been flushed out.
// aFrameID is ignored if aPrincipalHandle already is our pending
// principalHandle.
void UpdatePrincipalHandleForFrameID(const PrincipalHandle& aPrincipalHandle,
const ImageContainer::FrameID& aFrameID);
void UpdatePrincipalHandleForFrameIDLocked(
const PrincipalHandle& aPrincipalHandle,
const ImageContainer::FrameID& aFrameID) MOZ_REQUIRES(mMutex);
void SetCurrentFrames(
const gfx::IntSize& aIntrinsicSize,
const nsTArray<ImageContainer::NonOwningImage>& aImages);
// Make the current frame the only frame in the container, i.e. discard
// all future frames.
void ClearFutureFrames(TimeStamp aNow = TimeStamp::Now());
// Time in seconds by which the last painted video frame was late by.
// E.g. if the last painted frame should have been painted at time t,
// but was actually painted at t+n, this returns n in seconds. Threadsafe.
double GetFrameDelay();
// Clear any resources in client that are not immediately necessary.
void ClearCachedResources();
// Clear images in host.
void ClearImagesInHost(layers::ClearImagesType aType);
// Returns a new frame ID for SetCurrentFrames(). The client must either
// call this on only one thread or provide barriers. Do not use together
// with SetCurrentFrame().
ImageContainer::FrameID NewFrameID() { return ++mFrameID; }
// Call on main thread
enum { INVALIDATE_DEFAULT, INVALIDATE_FORCE };
void Invalidate() { InvalidateWithFlags(INVALIDATE_DEFAULT); }
void InvalidateWithFlags(uint32_t aFlags);
ImageContainer* GetImageContainer();
void ForgetElement() { mOwner = nullptr; }
uint32_t GetDroppedImageCount() {
MutexAutoLock lock(mMutex);
return mImageContainer->GetDroppedImageCount();
}
Maybe<gfx::IntSize> CurrentIntrinsicSize() {
MutexAutoLock lock(mMutex);
return mIntrinsicSize;
}
bool SupportsOnly8BitImage() const { return mSupportsOnly8BitImage; }
protected:
void SetCurrentFramesLocked(
const gfx::IntSize& aIntrinsicSize,
const nsTArray<ImageContainer::NonOwningImage>& aImages)
MOZ_REQUIRES(mMutex);
// Non-addreffed pointer to the owner. The owner calls ForgetElement
// to clear this reference when the owner is destroyed.
MediaDecoderOwner* mOwner;
RefPtr<ImageContainer> mImageContainer;
struct {
// True when the Image size has changed since the last time Invalidate() was
// called. When set, the next call to Invalidate() will ensure that the
// frame is fully invalidated instead of just invalidating for the image
// change in the ImageLayer.
bool mImageSizeChanged = false;
// The main thread mirror of the member of the same name below, in case it
// has changed.
// Set to some size when the intrinsic size has been changed by
// SetCurrentFrame() since the last call to Invalidate().
// The next call to Invalidate() will recalculate and update the intrinsic
// size on the element, request a frame reflow and then reset this to
// Nothing.
Maybe<gfx::IntSize> mNewIntrinsicSize;
} mMainThreadState;
Mutex mMutex;
// The intrinsic size is the ideal size which we should render the
// ImageContainer's current Image at.
// This can differ from the Image's actual size when the media resource
// specifies that the Image should be stretched to have the correct aspect
// ratio.
Maybe<gfx::IntSize> mIntrinsicSize MOZ_GUARDED_BY(mMutex);
// We maintain our own mFrameID which is auto-incremented at every
// SetCurrentFrame() or NewFrameID() call.
ImageContainer::FrameID mFrameID;
// The last PrincipalHandle we notified mElement about.
PrincipalHandle mLastPrincipalHandle MOZ_GUARDED_BY(mMutex);
// The PrincipalHandle the client has notified us is changing with FrameID
// mFrameIDForPendingPrincipalHandle.
PrincipalHandle mPendingPrincipalHandle MOZ_GUARDED_BY(mMutex);
// The FrameID for which mPendingPrincipal is first valid.
ImageContainer::FrameID mFrameIDForPendingPrincipalHandle
MOZ_GUARDED_BY(mMutex);
const RefPtr<AbstractThread> mMainThread;
// True when Android GL implementation support only 8-bit texture.
const bool mSupportsOnly8BitImage;
};
} // namespace mozilla
#endif /* VIDEOFRAMECONTAINER_H_ */
|