Mozilla Home
Privacy
Cookies
Legal
Bugzilla
Browse
Advanced Search
New Bug
Reports
Documentation
Log In
Log In with GitHub
or
Remember me
Browse
Advanced Search
New Bug
Reports
Documentation
Attachment 520040 Details for
Bug 639391
[patch]
Patch 2: Make nsMediaStream responsible for determining cached media data in a threadsafe manner
639391-2-nsMediaStream-cached-ranges.patch (text/plain), 8.24 KB, created by
Chris Pearce [:cpearce (Not reading bugmail)]
(
hide
)
Description:
Patch 2: Make nsMediaStream responsible for determining cached media data in a threadsafe manner
Filename:
MIME Type:
Creator:
Chris Pearce [:cpearce (Not reading bugmail)]
Size:
8.24 KB
patch
obsolete
># HG changeset patch ># User Chris Pearce <chris@pearce.org.nz> ># Parent 21b56dbd3be867aaedaf159f947a8a4c2adaca64 >Bug 639391 - Make nsMediaStream responsible for determining cached media data in a threadsafe manner. r=? > >diff --git a/content/media/nsMediaCache.cpp b/content/media/nsMediaCache.cpp >--- a/content/media/nsMediaCache.cpp >+++ b/content/media/nsMediaCache.cpp >@@ -2288,8 +2288,31 @@ nsMediaCacheStream::InitAsClone(nsMediaC > } > // Every block is a readahead block for the clone because the clone's initial > // stream offset is zero > gMediaCache->AddBlockOwnerAsReadahead(cacheBlockIndex, this, i); > } > > return NS_OK; > } >+ >+nsresult nsMediaCacheStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges) >+{ >+ // Take the monitor, so that the cached data ranges can't grow while we're >+ // trying to loop over them. >+ nsAutoMonitor mon(gMediaCache->Monitor()); >+ >+ // We must be pinned while running this, otherwise the cached data ranges may >+ // shrink while we're trying to loop over them. >+ NS_ASSERTION(mPinCount > 0, "Must be pinned"); >+ >+ PRInt64 startOffset = GetNextCachedData(0); >+ while (startOffset >= 0) { >+ PRInt64 endOffset = GetCachedDataEnd(startOffset); >+ NS_ASSERTION(startOffset < endOffset, "Buffered range must end after its start"); >+ // Bytes [startOffset..endOffset] are cached. >+ aRanges.AppendElement(nsByteRange(startOffset, endOffset)); >+ startOffset = GetNextCachedData(endOffset); >+ NS_ASSERTION(startOffset == -1 || startOffset > endOffset, >+ "Must have advanced to start of next range, or hit end of stream"); >+ } >+ return NS_OK; >+} >diff --git a/content/media/nsMediaCache.h b/content/media/nsMediaCache.h >--- a/content/media/nsMediaCache.h >+++ b/content/media/nsMediaCache.h >@@ -39,16 +39,18 @@ > #ifndef nsMediaCache_h_ > #define nsMediaCache_h_ > > #include "nsTArray.h" > #include "nsAutoLock.h" > #include "nsIPrincipal.h" > #include "nsCOMPtr.h" > >+class nsByteRange; >+ > /** > * Media applications want fast, "on demand" random access to media data, > * for pausing, seeking, etc. But we are primarily interested > * in transporting media data using HTTP over the Internet, which has > * high latency to open a connection, requires a new connection for every > * seek, may not even support seeking on some connections (especially > * live streams), and uses a push model --- data comes from the server > * and you don't have much control over the rate. Also, transferring data >@@ -305,16 +307,21 @@ public: > // Returns the unique resource ID > PRInt64 GetResourceID() { return mResourceID; } > // Returns the end of the bytes starting at the given offset > // which are in cache. > PRInt64 GetCachedDataEnd(PRInt64 aOffset); > // Returns the offset of the first byte of cached data at or after aOffset, > // or -1 if there is no such cached data. > PRInt64 GetNextCachedData(PRInt64 aOffset); >+ // Fills aRanges with the ByteRanges representing the data which is currently >+ // cached. Locks the media cache while running, to prevent any ranges >+ // growing. The stream should be pinned while this runs and while its results >+ // are used, to ensure no data is evicted. >+ nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges); > > // Reads from buffered data only. Will fail if not all data to be read is > // in the cache. Will not mark blocks as read. Can be called from the main > // thread. It's the caller's responsibility to wrap the call in a pin/unpin, > // and also to check that the range they want is cached before calling this. > nsresult ReadFromCache(char* aBuffer, > PRInt64 aOffset, > PRInt64 aCount); >diff --git a/content/media/nsMediaStream.cpp b/content/media/nsMediaStream.cpp >--- a/content/media/nsMediaStream.cpp >+++ b/content/media/nsMediaStream.cpp >@@ -600,16 +600,21 @@ nsresult nsMediaChannelStream::Seek(PRIn > > PRInt64 nsMediaChannelStream::Tell() > { > NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); > > return mCacheStream.Tell(); > } > >+nsresult nsMediaChannelStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges) >+{ >+ return mCacheStream.GetCachedRanges(aRanges); >+} >+ > void nsMediaChannelStream::Suspend(PRBool aCloseImmediately) > { > NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread"); > > nsHTMLMediaElement* element = mDecoder->GetMediaElement(); > if (!element) { > // Shutting down; do nothing. > return; >@@ -914,16 +919,18 @@ public: > { > return (aOffset < mSize) ? aOffset : -1; > } > virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset) { return PR_MAX(aOffset, mSize); } > virtual PRBool IsDataCachedToEndOfStream(PRInt64 aOffset) { return PR_TRUE; } > virtual PRBool IsSuspendedByCache() { return PR_FALSE; } > virtual PRBool IsSuspended() { return PR_FALSE; } > >+ nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges); >+ > private: > // The file size, or -1 if not known. Immutable after Open(). > PRInt64 mSize; > > // This lock handles synchronisation between calls to Close() and > // the Read, Seek, etc calls. Close must not be called while a > // Read or Seek is in progress since it resets various internal > // values to null. >@@ -956,16 +963,25 @@ public: > mDecoder->NotifyDownloadEnded(NS_OK); > return NS_OK; > } > > private: > nsRefPtr<nsMediaDecoder> mDecoder; > }; > >+nsresult nsMediaFileStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges) >+{ >+ if (mSize == -1) { >+ return NS_ERROR_FAILURE; >+ } >+ aRanges.AppendElement(nsByteRange(0, mSize)); >+ return NS_OK; >+} >+ > nsresult nsMediaFileStream::Open(nsIStreamListener** aStreamListener) > { > NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); > > if (aStreamListener) { > *aStreamListener = nsnull; > } > >diff --git a/content/media/nsMediaStream.h b/content/media/nsMediaStream.h >--- a/content/media/nsMediaStream.h >+++ b/content/media/nsMediaStream.h >@@ -122,16 +122,35 @@ public: > } > private: > PRInt64 mAccumulatedBytes; > TimeDuration mAccumulatedTime; > TimeStamp mLastStartTime; > PRPackedBool mIsStarted; > }; > >+// Represents a section of contiguous media, with a start and end offset. >+// Used to denote ranges of data which are cached. >+class nsByteRange { >+public: >+ nsByteRange() : mStart(0), mEnd(0) {} >+ >+ nsByteRange(PRInt64 aStart, PRInt64 aEnd) >+ : mStart(aStart), mEnd(aEnd) >+ { >+ NS_ASSERTION(mStart < mEnd, "Range should end after start!"); >+ } >+ >+ PRBool IsNull() const { >+ return mStart == 0 && mEnd == 0; >+ } >+ >+ PRInt64 mStart, mEnd; >+}; >+ > /* > Provides the ability to open, read and seek into a media stream > (audio, video). Handles the underlying machinery to do range > requests, etc as needed by the actual stream type. Instances of > this class must be created on the main thread. > > Most methods must be called on the main thread only. Read, Seek and > Tell must only be called on non-main threads. In the case of the Ogg >@@ -270,16 +289,23 @@ public: > static nsMediaStream* Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel); > > /** > * Open the stream. This creates a stream listener and returns it in > * aStreamListener; this listener needs to be notified of incoming data. > */ > virtual nsresult Open(nsIStreamListener** aStreamListener) = 0; > >+ /** >+ * Fills aRanges with ByteRanges representing the data which is cached >+ * in the media cache. Stream should be pinned during call and while >+ * aRanges is being used. >+ */ >+ virtual nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges) = 0; >+ > protected: > nsMediaStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) : > mDecoder(aDecoder), > mChannel(aChannel), > mURI(aURI), > mLoadInBackground(PR_FALSE) > { > MOZ_COUNT_CTOR(nsMediaStream); >@@ -390,16 +416,18 @@ public: > > void Revoke() { mStream = nsnull; } > > private: > nsMediaChannelStream* mStream; > }; > friend class Listener; > >+ nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges); >+ > protected: > // These are called on the main thread by Listener. > nsresult OnStartRequest(nsIRequest* aRequest); > nsresult OnStopRequest(nsIRequest* aRequest, nsresult aStatus); > nsresult OnDataAvailable(nsIRequest* aRequest, > nsIInputStream* aStream, > PRUint32 aCount); > nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, PRUint32 aFlags);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Flags:
roc
: review+
Actions:
View
|
Diff
|
Review
Attachments on
bug 639391
:
520039
| 520040 |
520041
|
520042
|
520044
|
520045