Bug 1149494 - Part 1. Add a listener directly to the unblocked input stream that reports the size of the first non-empty frame seen. r=pehrsons
This commit is contained in:
@@ -2045,7 +2045,6 @@ HTMLMediaElement::LookupMediaElementURITable(nsIURI* aURI)
|
||||
|
||||
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mSrcStreamListener(nullptr),
|
||||
mCurrentLoadID(0),
|
||||
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
|
||||
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING),
|
||||
@@ -2955,6 +2954,61 @@ private:
|
||||
bool mPendingNotifyOutput;
|
||||
};
|
||||
|
||||
/**
|
||||
* This listener observes the first video frame to arrive with a non-empty size,
|
||||
* and calls HTMLMediaElement::ReceivedMediaStreamInitialSize() with that size.
|
||||
*/
|
||||
class HTMLMediaElement::StreamSizeListener : public MediaStreamListener {
|
||||
public:
|
||||
explicit StreamSizeListener(HTMLMediaElement* aElement) :
|
||||
mElement(aElement),
|
||||
mMutex("HTMLMediaElement::StreamSizeListener")
|
||||
{}
|
||||
void Forget() { mElement = nullptr; }
|
||||
|
||||
void ReceivedSize()
|
||||
{
|
||||
if (!mElement) {
|
||||
return;
|
||||
}
|
||||
gfxIntSize size;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
size = mInitialSize;
|
||||
}
|
||||
nsRefPtr<HTMLMediaElement> deathGrip = mElement;
|
||||
mElement->UpdateInitialMediaSize(size);
|
||||
}
|
||||
virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
|
||||
StreamTime aTrackOffset,
|
||||
uint32_t aTrackEvents,
|
||||
const MediaSegment& aQueuedMedia) override
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mInitialSize != gfxIntSize(0,0) ||
|
||||
aQueuedMedia.GetType() != MediaSegment::VIDEO) {
|
||||
return;
|
||||
}
|
||||
const VideoSegment& video = static_cast<const VideoSegment&>(aQueuedMedia);
|
||||
for (VideoSegment::ConstChunkIterator c(video); !c.IsEnded(); c.Next()) {
|
||||
if (c->mFrame.GetIntrinsicSize() != gfxIntSize(0,0)) {
|
||||
mInitialSize = c->mFrame.GetIntrinsicSize();
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &StreamSizeListener::ReceivedSize);
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// These fields may only be accessed on the main thread
|
||||
HTMLMediaElement* mElement;
|
||||
|
||||
// mMutex protects the fields below; they can be accessed on any thread
|
||||
Mutex mMutex;
|
||||
gfxIntSize mInitialSize;
|
||||
};
|
||||
|
||||
class HTMLMediaElement::MediaStreamTracksAvailableCallback:
|
||||
public DOMMediaStream::OnTracksAvailableCallback
|
||||
{
|
||||
@@ -2975,7 +3029,8 @@ private:
|
||||
|
||||
void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
|
||||
{
|
||||
NS_ASSERTION(!mSrcStream && !mSrcStreamListener, "Should have been ended already");
|
||||
NS_ASSERTION(!mSrcStream && !mMediaStreamListener && !mMediaStreamSizeListener,
|
||||
"Should have been ended already");
|
||||
|
||||
mSrcStream = aStream;
|
||||
|
||||
@@ -3008,8 +3063,13 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
|
||||
|
||||
// XXX if we ever support capturing the output of a media element which is
|
||||
// playing a stream, we'll need to add a CombineWithPrincipal call here.
|
||||
mSrcStreamListener = new StreamListener(this);
|
||||
GetSrcMediaStream()->AddListener(mSrcStreamListener);
|
||||
mMediaStreamListener = new StreamListener(this);
|
||||
mMediaStreamSizeListener = new StreamSizeListener(this);
|
||||
|
||||
GetSrcMediaStream()->AddListener(mMediaStreamListener);
|
||||
// Listen for an initial image size on mSrcStream so we can get results even
|
||||
// if we block the mPlaybackStream.
|
||||
stream->AddListener(mMediaStreamSizeListener);
|
||||
if (mPaused) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
|
||||
}
|
||||
@@ -3042,7 +3102,10 @@ void HTMLMediaElement::EndSrcMediaStreamPlayback()
|
||||
{
|
||||
MediaStream* stream = GetSrcMediaStream();
|
||||
if (stream) {
|
||||
stream->RemoveListener(mSrcStreamListener);
|
||||
stream->RemoveListener(mMediaStreamListener);
|
||||
}
|
||||
if (mSrcStream->GetStream()) {
|
||||
mSrcStream->GetStream()->RemoveListener(mMediaStreamSizeListener);
|
||||
}
|
||||
mSrcStream->DisconnectTrackListListeners(AudioTracks(), VideoTracks());
|
||||
|
||||
@@ -3051,8 +3114,10 @@ void HTMLMediaElement::EndSrcMediaStreamPlayback()
|
||||
}
|
||||
|
||||
// Kill its reference to this element
|
||||
mSrcStreamListener->Forget();
|
||||
mSrcStreamListener = nullptr;
|
||||
mMediaStreamListener->Forget();
|
||||
mMediaStreamListener = nullptr;
|
||||
mMediaStreamSizeListener->Forget();
|
||||
mMediaStreamSizeListener = nullptr;
|
||||
if (stream) {
|
||||
stream->RemoveAudioOutput(this);
|
||||
}
|
||||
@@ -3801,16 +3866,23 @@ void HTMLMediaElement::NotifyDecoderPrincipalChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
|
||||
void HTMLMediaElement::UpdateMediaSize(const nsIntSize& aSize)
|
||||
{
|
||||
if (IsVideo() && mReadyState != HAVE_NOTHING && mMediaSize != size) {
|
||||
if (IsVideo() && mReadyState != HAVE_NOTHING && mMediaSize != aSize) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
|
||||
}
|
||||
|
||||
mMediaSize = size;
|
||||
mMediaSize = aSize;
|
||||
UpdateReadyStateForData(mLastNextFrameStatus);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::UpdateInitialMediaSize(const nsIntSize& aSize)
|
||||
{
|
||||
if (mMediaSize == nsIntSize(-1, -1)) {
|
||||
UpdateMediaSize(aSize);
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)
|
||||
{
|
||||
if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
|
||||
|
||||
Reference in New Issue
Block a user