зеркало из https://github.com/mozilla/gecko-dev.git
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
--HG-- extra : rebase_source : 79b92a9726670125cd028355e298e43a200785ab
This commit is contained in:
Родитель
f415610fd8
Коммит
1524dbeb74
|
@ -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) {
|
||||
|
|
|
@ -260,7 +260,10 @@ public:
|
|||
|
||||
// Update the visual size of the media. Called from the decoder on the
|
||||
// main thread when/if the size changes.
|
||||
void UpdateMediaSize(nsIntSize size);
|
||||
void UpdateMediaSize(const nsIntSize& aSize);
|
||||
// Like UpdateMediaSize, but only updates the size if no size has yet
|
||||
// been set.
|
||||
void UpdateInitialMediaSize(const nsIntSize& aSize);
|
||||
|
||||
// Returns the CanPlayStatus indicating if we can handle the
|
||||
// full MIME type including the optional codecs parameter.
|
||||
|
@ -642,6 +645,7 @@ protected:
|
|||
class MediaLoadListener;
|
||||
class MediaStreamTracksAvailableCallback;
|
||||
class StreamListener;
|
||||
class StreamSizeListener;
|
||||
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
virtual void SetItemValueText(const nsAString& text) override;
|
||||
|
@ -1047,8 +1051,12 @@ protected:
|
|||
};
|
||||
nsTArray<OutputMediaStream> mOutputStreams;
|
||||
|
||||
// Holds a reference to the MediaStreamListener attached to mSrcStream.
|
||||
nsRefPtr<StreamListener> mSrcStreamListener;
|
||||
// Holds a reference to the MediaStreamListener attached to mPlaybackStream
|
||||
// (or mSrcStream if mPlaybackStream is null).
|
||||
nsRefPtr<StreamListener> mMediaStreamListener;
|
||||
// Holds a reference to the size-getting MediaStreamListener attached to
|
||||
// mSrcStream.
|
||||
nsRefPtr<StreamSizeListener> mMediaStreamSizeListener;
|
||||
|
||||
// Holds a reference to the MediaSource supplying data for playback.
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
|
|
|
@ -265,6 +265,18 @@ public:
|
|||
MediaSegmentBase<C, Chunk>& mSegment;
|
||||
uint32_t mIndex;
|
||||
};
|
||||
class ConstChunkIterator {
|
||||
public:
|
||||
explicit ConstChunkIterator(const MediaSegmentBase<C, Chunk>& aSegment)
|
||||
: mSegment(aSegment), mIndex(0) {}
|
||||
bool IsEnded() { return mIndex >= mSegment.mChunks.Length(); }
|
||||
void Next() { ++mIndex; }
|
||||
const Chunk& operator*() { return mSegment.mChunks[mIndex]; }
|
||||
const Chunk* operator->() { return &mSegment.mChunks[mIndex]; }
|
||||
private:
|
||||
const MediaSegmentBase<C, Chunk>& mSegment;
|
||||
uint32_t mIndex;
|
||||
};
|
||||
|
||||
void RemoveLeading(StreamTime aDuration)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче