Bug 1416663 - Move Gecko/HTMLMediaElement specific stuff out of VideoFrameContainer. r=jwwang
MozReview-Commit-ID: 4giNMi8qsTZ
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -95,16 +95,20 @@
#include "nsIContentPolicy.h"
#include "mozilla/Telemetry.h"
#include "DecoderDoctorDiagnostics.h"
#include "DecoderTraits.h"
#include "MediaContainerType.h"
#include "MP4Decoder.h"
#include "FrameStatistics.h"
+#include "nsIFrame.h"
+#include "nsDisplayList.h"
+#include "SVGObserverUtils.h"
+
#ifdef MOZ_ANDROID_HLS_SUPPORT
#include "HLSDecoder.h"
#endif
#include "ImageContainer.h"
#include "nsRange.h"
#include <algorithm>
#include <cmath>
@@ -6398,16 +6402,49 @@ void HTMLMediaElement::AddDecoderPrincip
mDecoderPrincipalChangeObservers.AppendElement(aObserver);
}
bool HTMLMediaElement::RemoveDecoderPrincipalChangeObserver(DecoderPrincipalChangeObserver* aObserver)
{
return mDecoderPrincipalChangeObservers.RemoveElement(aObserver);
}
+void
+HTMLMediaElement::Invalidate(bool aImageSizeChanged,
+ Maybe<nsIntSize>& aNewIntrinsicSize,
+ bool aForceInvalidate)
+{
+ nsIFrame* frame = GetPrimaryFrame();
+ if (aNewIntrinsicSize) {
+ UpdateMediaSize(aNewIntrinsicSize.value());
+ if (frame) {
+ nsPresContext* presContext = frame->PresContext();
+ nsIPresShell* presShell = presContext->PresShell();
+ presShell->FrameNeedsReflow(
+ frame, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
+ }
+ }
+
+ RefPtr<ImageContainer> imageContainer = GetImageContainer();
+ bool asyncInvalidate =
+ imageContainer && imageContainer->IsAsync() && !aForceInvalidate;
+ if (frame) {
+ if (aImageSizeChanged) {
+ frame->InvalidateFrame();
+ } else {
+ frame->InvalidateLayer(DisplayItemType::TYPE_VIDEO,
+ nullptr,
+ nullptr,
+ asyncInvalidate ? nsIFrame::UPDATE_IS_ASYNC : 0);
+ }
+ }
+
+ SVGObserverUtils::InvalidateDirectRenderingObservers(this);
+}
+
void HTMLMediaElement::UpdateMediaSize(const nsIntSize& aSize)
{
if (IsVideo() && mReadyState != HAVE_NOTHING &&
mMediaInfo.mVideo.mDisplay != aSize) {
DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
}
mMediaInfo.mVideo.mDisplay = aSize;
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -238,18 +238,19 @@ public:
// From PrincipalChangeObserver<DOMMediaStream>.
void PrincipalChanged(DOMMediaStream* aStream) override;
void UpdateSrcStreamVideoPrincipal(const PrincipalHandle& aPrincipalHandle);
// Called after the MediaStream we're playing rendered a frame to aContainer
// with a different principalHandle than the previous frame.
- void PrincipalHandleChangedForVideoFrameContainer(VideoFrameContainer* aContainer,
- const PrincipalHandle& aNewPrincipalHandle);
+ void PrincipalHandleChangedForVideoFrameContainer(
+ VideoFrameContainer* aContainer,
+ const PrincipalHandle& aNewPrincipalHandle) override;
// Dispatch events
virtual void DispatchAsyncEvent(const nsAString& aName) final override;
// Triggers a recomputation of readyState.
void UpdateReadyState() override { UpdateReadyStateInternal(); }
// Dispatch events that were raised while in the bfcache
@@ -325,16 +326,20 @@ public:
// Update the visual size of the media. Called from the decoder on the
// main thread when/if the size changes.
void UpdateMediaSize(const nsIntSize& aSize);
// Like UpdateMediaSize, but only updates the size if no size has yet
// been set.
void UpdateInitialMediaSize(const nsIntSize& aSize);
+ void Invalidate(bool aImageSizeChanged,
+ Maybe<nsIntSize>& aNewIntrinsicSize,
+ bool aForceInvalidate) override;
+
// Returns the CanPlayStatus indicating if we can handle the
// full MIME type including the optional codecs parameter.
static CanPlayStatus GetCanPlay(const nsAString& aType,
DecoderDoctorDiagnostics* aDiagnostics);
/**
* Called when a child source element is added to this media element. This
* may queue a task to run the select resource algorithm if appropriate.
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -3,16 +3,20 @@
/* 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 MediaDecoderOwner_h_
#define MediaDecoderOwner_h_
#include "mozilla/UniquePtr.h"
#include "MediaInfo.h"
+#include "MediaSegment.h"
+#include "nsSize.h"
+
+class nsIDocument;
namespace mozilla {
class AbstractThread;
class GMPCrashHelper;
class VideoFrameContainer;
class MediaInfo;
class MediaResult;
@@ -169,16 +173,29 @@ public:
virtual nsIDocument* GetDocument() const { return nullptr; }
// Called by the media decoder to create a GMPCrashHelper.
virtual already_AddRefed<GMPCrashHelper> CreateGMPCrashHelper()
{
return nullptr;
}
+ // Called by the frame container to notify the layout engine that the
+ // size of the image has changed, or the video needs to be be repainted
+ // for some other reason.
+ virtual void Invalidate(bool aImageSizeChanged,
+ Maybe<nsIntSize>& aNewIntrinsicSize,
+ bool aForceInvalidate) {}
+
+ // Called after the MediaStream we're playing rendered a frame to aContainer
+ // with a different principalHandle than the previous frame.
+ virtual void PrincipalHandleChangedForVideoFrameContainer(
+ VideoFrameContainer* aContainer,
+ const PrincipalHandle& aNewPrincipalHandle) {}
+
/*
* Servo only methods go here. Please provide default implementations so they
* can build in Gecko without any modification.
*/
};
} // namespace mozilla
--- a/dom/media/VideoFrameContainer.cpp
+++ b/dom/media/VideoFrameContainer.cpp
@@ -1,22 +1,17 @@
/* -*- 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/. */
#include "VideoFrameContainer.h"
-
-#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/Telemetry.h"
-
-#include "nsIFrame.h"
-#include "nsDisplayList.h"
-#include "SVGObserverUtils.h"
+#include "MediaDecoderOwner.h"
using namespace mozilla::layers;
namespace mozilla {
static LazyLogModule gVideoFrameContainerLog("VideoFrameContainer");
#define CONTAINER_LOG(type, msg) MOZ_LOG(gVideoFrameContainerLog, type, msg)
#define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
@@ -38,28 +33,28 @@ public:
}
}
private:
const TimeStamp mStart = TimeStamp::Now();
};
}
VideoFrameContainer::VideoFrameContainer(
- dom::HTMLMediaElement* aElement,
+ MediaDecoderOwner* aOwner,
already_AddRefed<ImageContainer> aContainer)
- : mElement(aElement)
+ : mOwner(aOwner)
, mImageContainer(aContainer)
, mMutex("nsVideoFrameContainer")
, mBlackImage(nullptr)
, mFrameID(0)
, mPendingPrincipalHandle(PRINCIPAL_HANDLE_NONE)
, mFrameIDForPendingPrincipalHandle(0)
- , mMainThread(aElement->AbstractMainThread())
+ , mMainThread(aOwner->AbstractMainThread())
{
- NS_ASSERTION(aElement, "aElement must not be null");
+ NS_ASSERTION(aOwner, "aOwner must not be null");
NS_ASSERTION(mImageContainer, "aContainer must not be null");
}
VideoFrameContainer::~VideoFrameContainer()
{}
PrincipalHandle VideoFrameContainer::GetLastPrincipalHandle()
{
@@ -290,19 +285,19 @@ void VideoFrameContainer::SetCurrentFram
bool imageSizeChanged = (oldFrameSize != newFrameSize);
if (principalHandle != PRINCIPAL_HANDLE_NONE || imageSizeChanged) {
RefPtr<VideoFrameContainer> self = this;
mMainThread->Dispatch(NS_NewRunnableFunction(
"PrincipalHandleOrImageSizeChanged",
[this, self, principalHandle, imageSizeChanged]() {
mMainThreadState.mImageSizeChanged = imageSizeChanged;
- if (mElement && principalHandle != PRINCIPAL_HANDLE_NONE) {
- mElement->PrincipalHandleChangedForVideoFrameContainer(
- this, principalHandle);
+ if (mOwner && principalHandle != PRINCIPAL_HANDLE_NONE) {
+ mOwner->PrincipalHandleChangedForVideoFrameContainer(this,
+ principalHandle);
}
}));
}
}
void VideoFrameContainer::ClearCurrentFrame()
{
MutexAutoLock lock(mMutex);
@@ -341,57 +336,38 @@ VideoFrameContainer::ClearCachedResource
{
mImageContainer->ClearCachedResources();
}
ImageContainer* VideoFrameContainer::GetImageContainer() {
return mImageContainer;
}
-
double VideoFrameContainer::GetFrameDelay()
{
return mImageContainer->GetPaintDelay().ToSeconds();
}
void VideoFrameContainer::InvalidateWithFlags(uint32_t aFlags)
{
NS_ASSERTION(NS_IsMainThread(), "Must call on main thread");
- if (!mElement) {
- // Element has been destroyed
+ if (!mOwner) {
+ // Owner has been destroyed
return;
}
- nsIFrame* frame = mElement->GetPrimaryFrame();
- bool invalidateFrame = mMainThreadState.mImageSizeChanged;
+ bool imageSizeChanged = mMainThreadState.mImageSizeChanged;
mMainThreadState.mImageSizeChanged = false;
+ Maybe<nsIntSize> intrinsicSize;
if (mMainThreadState.mIntrinsicSizeChanged) {
- mElement->UpdateMediaSize(mMainThreadState.mIntrinsicSize);
+ intrinsicSize = Some(mMainThreadState.mIntrinsicSize);
mMainThreadState.mIntrinsicSizeChanged = false;
- if (frame) {
- nsPresContext* presContext = frame->PresContext();
- nsIPresShell* presShell = presContext->PresShell();
- presShell->FrameNeedsReflow(
- frame, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
- }
}
- bool asyncInvalidate = mImageContainer &&
- mImageContainer->IsAsync() &&
- !(aFlags & INVALIDATE_FORCE);
-
- if (frame) {
- if (invalidateFrame) {
- frame->InvalidateFrame();
- } else {
- frame->InvalidateLayer(DisplayItemType::TYPE_VIDEO, nullptr, nullptr,
- asyncInvalidate ? nsIFrame::UPDATE_IS_ASYNC : 0);
- }
- }
-
- SVGObserverUtils::InvalidateDirectRenderingObservers(mElement);
+ bool forceInvalidate = aFlags & INVALIDATE_FORCE;
+ mOwner->Invalidate(imageSizeChanged, intrinsicSize, forceInvalidate);
}
} // namespace mozilla
#undef NS_DispatchToMainThread
--- a/dom/media/VideoFrameContainer.h
+++ b/dom/media/VideoFrameContainer.h
@@ -13,19 +13,17 @@
#include "nsCOMPtr.h"
#include "ImageContainer.h"
#include "MediaSegment.h"
#include "MediaStreamVideoSink.h"
#include "VideoSegment.h"
namespace mozilla {
-namespace dom {
-class HTMLMediaElement;
-} // namespace dom
+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
@@ -33,17 +31,17 @@ class HTMLMediaElement;
*/
class VideoFrameContainer : public MediaStreamVideoSink {
virtual ~VideoFrameContainer();
public:
typedef layers::ImageContainer ImageContainer;
typedef layers::Image Image;
- VideoFrameContainer(dom::HTMLMediaElement* aElement,
+ VideoFrameContainer(MediaDecoderOwner* aOwner,
already_AddRefed<ImageContainer> aContainer);
// Call on any thread
virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
virtual void ClearFrames() override;
void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage,
const TimeStamp& aTargetTime);
// Returns the last principalHandle we notified mElement about.
@@ -87,27 +85,27 @@ public:
// Call on main thread
enum {
INVALIDATE_DEFAULT,
INVALIDATE_FORCE
};
void Invalidate() override { InvalidateWithFlags(INVALIDATE_DEFAULT); }
void InvalidateWithFlags(uint32_t aFlags);
ImageContainer* GetImageContainer();
- void ForgetElement() { mElement = nullptr; }
+ void ForgetElement() { mOwner = nullptr; }
uint32_t GetDroppedImageCount() { return mImageContainer->GetDroppedImageCount(); }
protected:
void SetCurrentFramesLocked(const gfx::IntSize& aIntrinsicSize,
const nsTArray<ImageContainer::NonOwningImage>& aImages);
- // Non-addreffed pointer to the element. The element calls ForgetElement
- // to clear this reference when the element is destroyed.
- dom::HTMLMediaElement* mElement;
+ // Non-addreffed pointer to the owner. The ownenr 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.
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -2,16 +2,17 @@
/* 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/. */
#include "MediaQueue.h"
#include "VideoSink.h"
#include "MediaPrefs.h"
+#include "VideoUtils.h"
#include "mozilla/IntegerPrintfMacros.h"
namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
#undef FMT