mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 687972. Try 2: Run autoplay for an element after reaching loadedmetadata if all download streams for its resource are suspended by the media cache. r=cpearce
This commit is contained in:
parent
411f20fc79
commit
57e160644f
@ -2064,10 +2064,6 @@ void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate)
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
|
||||
if (!mBegun) {
|
||||
// Something ended our downloaded. We're probably done with downloading already.
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||
}
|
||||
if (mDecoder && mDecoder->IsSeekable()) {
|
||||
ProcessMediaFragmentURI();
|
||||
mDecoder->SetEndTime(mFragmentEnd);
|
||||
|
@ -451,6 +451,9 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||
mElement->FirstFrameLoaded(resourceIsLoaded);
|
||||
}
|
||||
|
||||
// This can run cache callbacks.
|
||||
mStream->EnsureCacheUpToDate();
|
||||
|
||||
// The element can run javascript via events
|
||||
// before reaching here, so only change the
|
||||
// state if we're still set to the original
|
||||
@ -467,6 +470,10 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||
if (resourceIsLoaded) {
|
||||
ResourceLoaded();
|
||||
}
|
||||
|
||||
// Run NotifySuspendedStatusChanged now to give us a chance to notice
|
||||
// that autoplay should run.
|
||||
NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
void nsBuiltinDecoder::ResourceLoaded()
|
||||
|
@ -1369,6 +1369,8 @@ nsMediaCache::Update()
|
||||
break;
|
||||
}
|
||||
|
||||
stream->mHasHadUpdate = true;
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// Close the streams that failed due to error. This will cause all
|
||||
// client Read and Seek operations on those streams to fail. Blocked
|
||||
@ -1885,6 +1887,18 @@ nsMediaCacheStream::IsSeekable()
|
||||
return mIsSeekable;
|
||||
}
|
||||
|
||||
bool
|
||||
nsMediaCacheStream::AreAllStreamsForResourceSuspended()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
|
||||
nsMediaCache::ResourceStreamIterator iter(mResourceID);
|
||||
while (nsMediaCacheStream* stream = iter.Next()) {
|
||||
if (!stream->mCacheSuspended)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsMediaCacheStream::Close()
|
||||
{
|
||||
@ -1898,6 +1912,14 @@ nsMediaCacheStream::Close()
|
||||
gMediaCache->QueueUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
nsMediaCacheStream::EnsureCacheUpdate()
|
||||
{
|
||||
if (mHasHadUpdate)
|
||||
return;
|
||||
gMediaCache->Update();
|
||||
}
|
||||
|
||||
void
|
||||
nsMediaCacheStream::CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor)
|
||||
{
|
||||
|
@ -227,6 +227,7 @@ public:
|
||||
// data for this stream.
|
||||
nsMediaCacheStream(nsMediaChannelStream* aClient)
|
||||
: mClient(aClient), mResourceID(0), mInitialized(false),
|
||||
mHasHadUpdate(false),
|
||||
mIsSeekable(false), mCacheSuspended(false),
|
||||
mDidNotifyDataEnded(false),
|
||||
mUsingNullPrincipal(false),
|
||||
@ -263,6 +264,11 @@ public:
|
||||
bool IsClosed() const { return mClosed; }
|
||||
// Get the principal for this stream.
|
||||
nsIPrincipal* GetCurrentPrincipal() { return mPrincipal; }
|
||||
// Ensure a global media cache update has run with this stream present.
|
||||
// This ensures the cache has had a chance to suspend or unsuspend this stream.
|
||||
// Called only on main thread. This can change the state of streams, fire
|
||||
// notifications, etc.
|
||||
void EnsureCacheUpdate();
|
||||
|
||||
// These callbacks are called on the main thread by the client
|
||||
// when data has been received via the channel.
|
||||
@ -346,6 +352,9 @@ public:
|
||||
// Returns the last set value of SetSeekable.
|
||||
bool IsSeekable();
|
||||
|
||||
// Returns true when all streams for this resource are suspended.
|
||||
bool AreAllStreamsForResourceSuspended();
|
||||
|
||||
// These methods must be called on a different thread from the main
|
||||
// thread. They should always be called on the same thread for a given
|
||||
// stream.
|
||||
@ -447,6 +456,9 @@ private:
|
||||
PRInt64 mResourceID;
|
||||
// Set to true when Init or InitAsClone has been called
|
||||
bool mInitialized;
|
||||
// Set to true when nsMediaCache::Update() has finished while this stream
|
||||
// was present.
|
||||
bool mHasHadUpdate;
|
||||
|
||||
// The following fields are protected by the cache's monitor but are
|
||||
// only written on the main thread.
|
||||
|
@ -74,7 +74,6 @@ nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
|
||||
mReopenOnError(false), mIgnoreClose(false),
|
||||
mCacheStream(this),
|
||||
mLock("nsMediaChannelStream.mLock"),
|
||||
mCacheSuspendCount(0),
|
||||
mIgnoreResume(false)
|
||||
{
|
||||
}
|
||||
@ -547,8 +546,9 @@ nsMediaStream* nsMediaChannelStream::CloneData(nsMediaDecoder* aDecoder)
|
||||
// is already in the cache we don't create an unneccesary HTTP channel
|
||||
// and perform a useless HTTP transaction.
|
||||
stream->mSuspendCount = 1;
|
||||
stream->mCacheSuspendCount = 1;
|
||||
stream->mCacheStream.InitAsClone(&mCacheStream);
|
||||
stream->mChannelStatistics = mChannelStatistics;
|
||||
stream->mChannelStatistics.Stop(TimeStamp::Now());
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
@ -770,11 +770,6 @@ nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
|
||||
NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
|
||||
// No need to mess with the channel, since we're making a new one
|
||||
--mSuspendCount;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
NS_ASSERTION(mCacheSuspendCount > 0, "CacheClientSeek(aResume=true) without previous CacheClientSuspend!");
|
||||
--mCacheSuspendCount;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = RecreateChannel();
|
||||
@ -788,10 +783,6 @@ nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
|
||||
nsresult
|
||||
nsMediaChannelStream::CacheClientSuspend()
|
||||
{
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
++mCacheSuspendCount;
|
||||
}
|
||||
Suspend(false);
|
||||
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
@ -802,11 +793,6 @@ nsresult
|
||||
nsMediaChannelStream::CacheClientResume()
|
||||
{
|
||||
Resume();
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
NS_ASSERTION(mCacheSuspendCount > 0, "CacheClientResume without previous CacheClientSuspend!");
|
||||
--mCacheSuspendCount;
|
||||
}
|
||||
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
return NS_OK;
|
||||
@ -830,11 +816,16 @@ nsMediaChannelStream::IsDataCachedToEndOfStream(PRInt64 aOffset)
|
||||
return mCacheStream.IsDataCachedToEndOfStream(aOffset);
|
||||
}
|
||||
|
||||
void
|
||||
nsMediaChannelStream::EnsureCacheUpToDate()
|
||||
{
|
||||
mCacheStream.EnsureCacheUpdate();
|
||||
}
|
||||
|
||||
bool
|
||||
nsMediaChannelStream::IsSuspendedByCache()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
return mCacheSuspendCount > 0;
|
||||
return mCacheStream.AreAllStreamsForResourceSuspended();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -236,6 +236,9 @@ public:
|
||||
// block the load event. Any new loads initiated (for example to seek)
|
||||
// will also be in the background.
|
||||
void MoveLoadsToBackground();
|
||||
// Ensures that the value returned by IsSuspendedByCache below is up to date
|
||||
// (i.e. the cache has examined this stream at least once).
|
||||
virtual void EnsureCacheUpToDate() {}
|
||||
|
||||
// These can be called on any thread.
|
||||
// Cached blocks associated with this stream will not be evicted
|
||||
@ -267,6 +270,8 @@ public:
|
||||
// data, otherwise we may not be able to make progress.
|
||||
// nsMediaDecoder::NotifySuspendedStatusChanged is called when this
|
||||
// changes.
|
||||
// For resources using the media cache, this returns true only when all
|
||||
// streams for the same resource are all suspended.
|
||||
virtual bool IsSuspendedByCache() = 0;
|
||||
// Returns true if this stream has been suspended.
|
||||
virtual bool IsSuspended() = 0;
|
||||
@ -382,6 +387,7 @@ public:
|
||||
bool IsClosed() const { return mCacheStream.IsClosed(); }
|
||||
virtual nsMediaStream* CloneData(nsMediaDecoder* aDecoder);
|
||||
virtual nsresult ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount);
|
||||
virtual void EnsureCacheUpToDate();
|
||||
|
||||
// Other thread
|
||||
virtual void SetReadMode(nsMediaCacheStream::ReadMode aMode);
|
||||
@ -475,10 +481,9 @@ protected:
|
||||
// Any thread access
|
||||
nsMediaCacheStream mCacheStream;
|
||||
|
||||
// This lock protects mChannelStatistics and mCacheSuspendCount
|
||||
// This lock protects mChannelStatistics
|
||||
Mutex mLock;
|
||||
nsChannelStatistics mChannelStatistics;
|
||||
PRUint32 mCacheSuspendCount;
|
||||
|
||||
// True if we couldn't suspend the stream and we therefore don't want
|
||||
// to resume later. This is usually due to the channel not being in the
|
||||
|
Loading…
Reference in New Issue
Block a user