Bug 862182 - Hold references to MediaResource in nsRefPtrs. r=roc

This commit is contained in:
Chris Pearce 2013-05-01 11:23:46 +12:00
parent d8709a7f63
commit f7895b7d0b
8 changed files with 41 additions and 50 deletions

View File

@ -2363,7 +2363,7 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
decoder->SetMediaSeekable(aOriginal->IsMediaSeekable());
}
MediaResource* resource = originalResource->CloneData(decoder);
nsRefPtr<MediaResource> resource = originalResource->CloneData(decoder);
if (!resource) {
LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
return NS_ERROR_FAILURE;
@ -2395,7 +2395,7 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
MediaResource* resource = MediaResource::Create(decoder, aChannel);
nsRefPtr<MediaResource> resource = MediaResource::Create(decoder, aChannel);
if (!resource)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -48,7 +48,7 @@ public:
return principal.forget();
}
virtual bool CanClone() { return false; }
virtual MediaResource* CloneData(MediaDecoder* aDecoder)
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
{
return nullptr;
}
@ -102,7 +102,7 @@ public:
virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; }
virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; }
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
virtual bool IsSuspendedByCache(MediaResource** aActiveResource) { return false; }
virtual bool IsSuspendedByCache() { return false; }
virtual bool IsSuspended() { return false; }
virtual nsresult ReadFromCache(char* aBuffer,
int64_t aOffset,

View File

@ -1830,7 +1830,7 @@ MediaCacheStream::IsTransportSeekable()
}
bool
MediaCacheStream::AreAllStreamsForResourceSuspended(MediaResource** aActiveStream)
MediaCacheStream::AreAllStreamsForResourceSuspended()
{
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
MediaCache::ResourceStreamIterator iter(mResourceID);
@ -1847,15 +1847,9 @@ MediaCacheStream::AreAllStreamsForResourceSuspended(MediaResource** aActiveStrea
if (stream->mChannelOffset > dataOffset) {
continue;
}
if (aActiveStream) {
*aActiveStream = stream->mClient;
}
return false;
}
if (aActiveStream) {
*aActiveStream = nullptr;
}
return true;
}

View File

@ -331,9 +331,7 @@ public:
// Returns true when all streams for this resource are suspended or their
// channel has ended.
// If aActiveResource is non-null, fills it with a pointer to a stream
// for this resource that is not suspended or ended.
bool AreAllStreamsForResourceSuspended(MediaResource** aActiveResource);
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

View File

@ -409,7 +409,7 @@ MediaDecoder::~MediaDecoder()
}
nsresult MediaDecoder::OpenResource(MediaResource* aResource,
nsIStreamListener** aStreamListener)
nsIStreamListener** aStreamListener)
{
MOZ_ASSERT(NS_IsMainThread());
if (aStreamListener) {
@ -425,7 +425,6 @@ nsresult MediaDecoder::OpenResource(MediaResource* aResource,
nsresult rv = aResource->Open(aStreamListener);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
delete aResource;
return rv;
}
@ -948,9 +947,7 @@ void MediaDecoder::NotifySuspendedStatusChanged()
MOZ_ASSERT(NS_IsMainThread());
if (!mResource)
return;
MediaResource* activeStream;
bool suspended = mResource->IsSuspendedByCache(&activeStream);
bool suspended = mResource->IsSuspendedByCache();
if (mOwner) {
mOwner->NotifySuspendedByCache(suspended);
UpdateReadyStateForData();

View File

@ -296,6 +296,12 @@ public:
// Get the current MediaResource being used. Its URI will be returned
// by currentSrc. Returns what was passed to Load(), if Load() has been called.
// Note: The MediaResource is refcounted, but it outlives the MediaDecoder,
// so it's OK to use the reference returned by this function without
// refcounting, *unless* you need to store and use the reference after the
// MediaDecoder has been destroyed. You might need to do this if you're
// wrapping the MediaResource in some kind of byte stream interface to be
// passed to a platform decoder.
MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE
{
return mResource;

View File

@ -713,15 +713,16 @@ bool ChannelMediaResource::CanClone()
return mCacheStream.IsAvailableForSharing();
}
MediaResource* ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
already_AddRefed<MediaResource> ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ASSERTION(mCacheStream.IsAvailableForSharing(), "Stream can't be cloned");
ChannelMediaResource* resource = new ChannelMediaResource(aDecoder,
nullptr,
mURI,
GetContentType());
nsRefPtr<ChannelMediaResource> resource =
new ChannelMediaResource(aDecoder,
nullptr,
mURI,
GetContentType());
if (resource) {
// Initially the clone is treated as suspended by the cache, because
// we don't have a channel. If the cache needs to read data from the clone
@ -734,7 +735,7 @@ MediaResource* ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
resource->mChannelStatistics = new MediaChannelStatistics(mChannelStatistics);
resource->mChannelStatistics->Stop();
}
return resource;
return resource.forget();
}
void ChannelMediaResource::CloseChannel()
@ -1187,9 +1188,9 @@ ChannelMediaResource::EnsureCacheUpToDate()
}
bool
ChannelMediaResource::IsSuspendedByCache(MediaResource** aActiveResource)
ChannelMediaResource::IsSuspendedByCache()
{
return mCacheStream.AreAllStreamsForResourceSuspended(aActiveResource);
return mCacheStream.AreAllStreamsForResourceSuspended();
}
bool
@ -1283,7 +1284,7 @@ public:
virtual void Resume() {}
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
virtual bool CanClone();
virtual MediaResource* CloneData(MediaDecoder* aDecoder);
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
// These methods are called off the main thread.
@ -1326,13 +1327,7 @@ public:
return std::max(aOffset, mSize);
}
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
virtual bool IsSuspendedByCache(MediaResource** aActiveResource)
{
if (aActiveResource) {
*aActiveResource = nullptr;
}
return false;
}
virtual bool IsSuspendedByCache() { return false; }
virtual bool IsSuspended() { return false; }
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
@ -1504,7 +1499,7 @@ bool FileMediaResource::CanClone()
return true;
}
MediaResource* FileMediaResource::CloneData(MediaDecoder* aDecoder)
already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDecoder)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@ -1527,7 +1522,8 @@ MediaResource* FileMediaResource::CloneData(MediaDecoder* aDecoder)
if (NS_FAILED(rv))
return nullptr;
return new FileMediaResource(aDecoder, channel, mURI, GetContentType());
nsRefPtr<MediaResource> resource(new FileMediaResource(aDecoder, channel, mURI, GetContentType()));
return resource.forget();
}
nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
@ -1592,7 +1588,7 @@ int64_t FileMediaResource::Tell()
return offset;
}
MediaResource*
already_AddRefed<MediaResource>
MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
{
NS_ASSERTION(NS_IsMainThread(),
@ -1609,10 +1605,12 @@ MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
aChannel->GetContentType(contentType);
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
nsRefPtr<MediaResource> resource;
if (fc || IsBlobURI(uri)) {
return new FileMediaResource(aDecoder, aChannel, uri, contentType);
resource = new FileMediaResource(aDecoder, aChannel, uri, contentType);
}
return new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
resource = new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
return resource.forget();
}
void BaseMediaResource::MoveLoadsToBackground() {

View File

@ -196,8 +196,6 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaResource)
virtual ~MediaResource() {}
// The following can be called on the main thread only:
// Get the URI
virtual nsIURI* URI() const { return nullptr; }
@ -224,7 +222,7 @@ public:
// Create a new stream of the same type that refers to the same URI
// with a new channel. Any cached data associated with the original
// stream should be accessible in the new stream too.
virtual MediaResource* CloneData(MediaDecoder* aDecoder) = 0;
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) = 0;
// Set statistics to be recorded to the object passed in.
virtual void RecordStatisticsTo(MediaChannelStatistics *aStatistics) { }
@ -313,9 +311,7 @@ public:
// changes.
// For resources using the media cache, this returns true only when all
// streams for the same resource are all suspended.
// If aActiveResource is non-null, fills it with a pointer to a stream
// for this resource that is not suspended or ended.
virtual bool IsSuspendedByCache(MediaResource** aActiveResource) = 0;
virtual bool IsSuspendedByCache() = 0;
// Returns true if this stream has been suspended.
virtual bool IsSuspended() = 0;
// Reads only data which is cached in the media cache. If you try to read
@ -335,7 +331,7 @@ public:
* Create a resource, reading data from the channel. Call on main thread only.
* The caller must follow up by calling resource->Open().
*/
static MediaResource* Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
static already_AddRefed<MediaResource> Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
/**
* Open the stream. This creates a stream listener and returns it in
@ -374,6 +370,8 @@ public:
// nsIChannel when the MediaResource is created. Safe to call from
// any thread.
virtual const nsCString& GetContentType() const = 0;
protected:
virtual ~MediaResource() {};
};
class BaseMediaResource : public MediaResource {
@ -496,7 +494,7 @@ public:
// Return true if the stream has been closed.
bool IsClosed() const { return mCacheStream.IsClosed(); }
virtual bool CanClone();
virtual MediaResource* CloneData(MediaDecoder* aDecoder);
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
// Set statistics to be recorded to the object passed in. If not called,
// |ChannelMediaResource| will create it's own statistics objects in |Open|.
void RecordStatisticsTo(MediaChannelStatistics *aStatistics) MOZ_OVERRIDE {
@ -526,7 +524,7 @@ public:
virtual int64_t GetNextCachedData(int64_t aOffset);
virtual int64_t GetCachedDataEnd(int64_t aOffset);
virtual bool IsDataCachedToEndOfResource(int64_t aOffset);
virtual bool IsSuspendedByCache(MediaResource** aActiveResource);
virtual bool IsSuspendedByCache();
virtual bool IsSuspended();
virtual bool IsTransportSeekable() MOZ_OVERRIDE;
@ -547,7 +545,7 @@ public:
void Revoke() { mResource = nullptr; }
private:
ChannelMediaResource* mResource;
nsRefPtr<ChannelMediaResource> mResource;
};
friend class Listener;