mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1218280. Part 1 - create MediaResourceCallback for MediaResource to send notifications. r=roc.
This commit is contained in:
parent
c7d3c4e21a
commit
a7589ce310
@ -50,7 +50,7 @@ private:
|
||||
return principal.forget();
|
||||
}
|
||||
virtual bool CanClone() override { return false; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback*) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -716,6 +716,50 @@ MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
element->FinishDecoderSetup(this, aResource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::NotifyNetworkError()
|
||||
{
|
||||
NetworkError();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::NotifyDecodeError()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableMethod(this, &MediaDecoder::DecodeError);
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::NotifyDataEnded(nsresult aStatus)
|
||||
{
|
||||
RefPtr<MediaDecoder> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
self->NotifyDownloadEnded(aStatus);
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
HTMLMediaElement* element = self->mOwner->GetMediaElement();
|
||||
if (element) {
|
||||
element->DownloadSuspended();
|
||||
}
|
||||
// NotifySuspendedStatusChanged will tell the element that download
|
||||
// has been suspended "by the cache", which is true since we never
|
||||
// download anything. The element can then transition to HAVE_ENOUGH_DATA.
|
||||
self->NotifySuspendedStatusChanged();
|
||||
}
|
||||
});
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::ResetConnectionState()
|
||||
{
|
||||
@ -927,6 +971,13 @@ MediaDecoder::NotifyPrincipalChanged()
|
||||
void
|
||||
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArgs<int64_t, int64_t>(
|
||||
this, &MediaDecoder::NotifyBytesConsumed, aBytes, aOffset);
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown || mIgnoreProgressData) {
|
||||
|
@ -209,6 +209,7 @@ destroying the MediaDecoder object.
|
||||
#include "MediaEventSource.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MediaResourceCallback.h"
|
||||
#include "MediaStatistics.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "TimeUnits.h"
|
||||
@ -272,7 +273,7 @@ struct SeekTarget {
|
||||
MediaDecoderEventVisibility mEventVisibility;
|
||||
};
|
||||
|
||||
class MediaDecoder : public AbstractMediaDecoder
|
||||
class MediaDecoder : public AbstractMediaDecoder, public MediaResourceCallback
|
||||
{
|
||||
public:
|
||||
struct SeekResolveValue {
|
||||
@ -303,7 +304,7 @@ public:
|
||||
|
||||
// Reset the decoder and notify the media element that
|
||||
// server connection is closed.
|
||||
virtual void ResetConnectionState();
|
||||
virtual void ResetConnectionState() override;
|
||||
// Create a new decoder of the same type as this one.
|
||||
// Subclasses must implement this.
|
||||
virtual MediaDecoder* Clone(MediaDecoderOwner* aOwner) = 0;
|
||||
@ -410,7 +411,7 @@ public:
|
||||
//
|
||||
// When the media stream ends, we can know the duration, thus the stream is
|
||||
// no longer considered to be infinite.
|
||||
virtual void SetInfinite(bool aInfinite);
|
||||
virtual void SetInfinite(bool aInfinite) override;
|
||||
|
||||
// Return true if the stream is infinite (see SetInfinite).
|
||||
virtual bool IsInfinite();
|
||||
@ -419,11 +420,11 @@ public:
|
||||
// If MediaResource::IsSuspendedByCache returns true, then the decoder
|
||||
// should stop buffering or otherwise waiting for download progress and
|
||||
// start consuming data, if possible, because the cache is full.
|
||||
virtual void NotifySuspendedStatusChanged();
|
||||
virtual void NotifySuspendedStatusChanged() override;
|
||||
|
||||
// Called by MediaResource when some data has been received.
|
||||
// Call on the main thread only.
|
||||
virtual void NotifyBytesDownloaded();
|
||||
virtual void NotifyBytesDownloaded() override;
|
||||
|
||||
// Called by nsChannelToPipeListener or MediaResource when the
|
||||
// download has ended. Called on the main thread only. aStatus is
|
||||
@ -437,7 +438,7 @@ public:
|
||||
|
||||
// Called by MediaResource when the principal of the resource has
|
||||
// changed. Called on main thread only.
|
||||
virtual void NotifyPrincipalChanged();
|
||||
virtual void NotifyPrincipalChanged() override;
|
||||
|
||||
// Called by the MediaResource to keep track of the number of bytes read
|
||||
// from the resource. Called on the main by an event runner dispatched
|
||||
@ -509,7 +510,7 @@ public:
|
||||
void SetLoadInBackground(bool aLoadInBackground);
|
||||
|
||||
// Returns a weak reference to the media decoder owner.
|
||||
MediaDecoderOwner* GetMediaOwner() const;
|
||||
MediaDecoderOwner* GetMediaOwner() const override;
|
||||
|
||||
bool OnStateMachineTaskQueue() const override;
|
||||
|
||||
@ -1054,6 +1055,13 @@ public:
|
||||
AbstractCanonical<bool>* CanonicalMediaSeekable() {
|
||||
return &mMediaSeekable;
|
||||
}
|
||||
|
||||
private:
|
||||
/* MediaResourceCallback functions */
|
||||
virtual nsresult FinishDecoderSetup(MediaResource* aResource) override;
|
||||
virtual void NotifyNetworkError() override;
|
||||
virtual void NotifyDecodeError() override;
|
||||
virtual void NotifyDataEnded(nsresult aStatus) override;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "MediaResource.h"
|
||||
#include "MediaResourceCallback.h"
|
||||
#include "RtspMediaResource.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
@ -65,11 +66,11 @@ NS_IMPL_ADDREF(MediaResource)
|
||||
NS_IMPL_RELEASE_WITH_DESTROY(MediaResource, Destroy())
|
||||
NS_IMPL_QUERY_INTERFACE0(MediaResource)
|
||||
|
||||
ChannelMediaResource::ChannelMediaResource(MediaDecoder* aDecoder,
|
||||
ChannelMediaResource::ChannelMediaResource(MediaResourceCallback* aCallback,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aContentType)
|
||||
: BaseMediaResource(aDecoder, aChannel, aURI, aContentType),
|
||||
: BaseMediaResource(aCallback, aChannel, aURI, aContentType),
|
||||
mOffset(0),
|
||||
mReopenOnError(false),
|
||||
mIgnoreClose(false),
|
||||
@ -161,7 +162,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
{
|
||||
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
@ -183,7 +184,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
// If the request was cancelled by nsCORSListenerProxy due to failing
|
||||
// the CORS security check, send an error through to the media element.
|
||||
if (status == NS_ERROR_DOM_BAD_URI) {
|
||||
mDecoder->NetworkError();
|
||||
mCallback->NotifyNetworkError();
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
@ -211,7 +212,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
// work here.
|
||||
mCacheStream.NotifyDataEnded(status);
|
||||
} else {
|
||||
mDecoder->NetworkError();
|
||||
mCallback->NotifyNetworkError();
|
||||
}
|
||||
|
||||
// This disconnects our listener so we don't get any more data. We
|
||||
@ -249,8 +250,8 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
// Content-Range header text should be parse-able.
|
||||
CMLOG("Error processing \'Content-Range' for "
|
||||
"HTTP_PARTIAL_RESPONSE_CODE: rv[%x] channel[%p] decoder[%p]",
|
||||
rv, hc.get(), mDecoder);
|
||||
mDecoder->NetworkError();
|
||||
rv, hc.get(), mCallback);
|
||||
mCallback->NotifyNetworkError();
|
||||
CloseChannel();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -307,7 +308,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
dataIsBounded = true;
|
||||
}
|
||||
|
||||
mDecoder->SetInfinite(!dataIsBounded);
|
||||
mCallback->SetInfinite(!dataIsBounded);
|
||||
}
|
||||
mCacheStream.SetTransportSeekable(seekable);
|
||||
|
||||
@ -377,7 +378,7 @@ ChannelMediaResource::ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
|
||||
}
|
||||
|
||||
CMLOG("Received bytes [%lld] to [%lld] of [%lld] for decoder[%p]",
|
||||
aRangeStart, aRangeEnd, aRangeTotal, mDecoder);
|
||||
aRangeStart, aRangeEnd, aRangeTotal, mCallback);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -455,14 +456,14 @@ ChannelMediaResource::CopySegmentToCache(nsIInputStream *aInStream,
|
||||
{
|
||||
CopySegmentClosure* closure = static_cast<CopySegmentClosure*>(aClosure);
|
||||
|
||||
closure->mResource->mDecoder->NotifyDataArrived(aCount, closure->mResource->mOffset,
|
||||
closure->mResource->mCallback->NotifyDataArrived(aCount, closure->mResource->mOffset,
|
||||
/* aThrottleUpdates = */ true);
|
||||
|
||||
// Keep track of where we're up to.
|
||||
RESOURCE_LOG("%p [ChannelMediaResource]: CopySegmentToCache at mOffset [%lld] add "
|
||||
"[%d] bytes for decoder[%p]",
|
||||
closure->mResource, closure->mResource->mOffset, aCount,
|
||||
closure->mResource->mDecoder);
|
||||
closure->mResource->mCallback);
|
||||
closure->mResource->mOffset += aCount;
|
||||
|
||||
closure->mResource->mCacheStream.NotifyDataReceived(aCount, aFromSegment,
|
||||
@ -569,7 +570,7 @@ nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Tell the media element that we are fetching data from a channel.
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
element->DownloadResumed(true);
|
||||
@ -604,7 +605,7 @@ nsresult ChannelMediaResource::SetupChannelHeaders()
|
||||
|
||||
// Send Accept header for video and audio types only (Bug 489071)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
@ -638,13 +639,13 @@ bool ChannelMediaResource::CanClone()
|
||||
return mCacheStream.IsAvailableForSharing();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaResource> ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
already_AddRefed<MediaResource> ChannelMediaResource::CloneData(MediaResourceCallback* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
NS_ASSERTION(mCacheStream.IsAvailableForSharing(), "Stream can't be cloned");
|
||||
|
||||
RefPtr<ChannelMediaResource> resource =
|
||||
new ChannelMediaResource(aDecoder,
|
||||
new ChannelMediaResource(aCallback,
|
||||
nullptr,
|
||||
mURI,
|
||||
GetContentType());
|
||||
@ -753,7 +754,7 @@ void ChannelMediaResource::Suspend(bool aCloseImmediately)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
if (!owner) {
|
||||
// Shutting down; do nothing.
|
||||
return;
|
||||
@ -786,7 +787,7 @@ void ChannelMediaResource::Resume()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
if (!owner) {
|
||||
// Shutting down; do nothing.
|
||||
return;
|
||||
@ -835,7 +836,7 @@ ChannelMediaResource::RecreateChannel()
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||
(mLoadInBackground ? nsIRequest::LOAD_BACKGROUND : 0);
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
if (!owner) {
|
||||
// The decoder is being shut down, so don't bother opening a new channel
|
||||
return NS_OK;
|
||||
@ -885,7 +886,7 @@ void
|
||||
ChannelMediaResource::DoNotifyDataReceived()
|
||||
{
|
||||
mDataReceivedEvent.Revoke();
|
||||
mDecoder->NotifyBytesDownloaded();
|
||||
mCallback->NotifyBytesDownloaded();
|
||||
}
|
||||
|
||||
void
|
||||
@ -933,11 +934,7 @@ void
|
||||
ChannelMediaResource::CacheClientNotifyDataEnded(nsresult aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// NOTE: this can be called with the media cache lock held, so don't
|
||||
// block or do anything which might try to acquire a lock!
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new DataEnded(mDecoder, aStatus);
|
||||
NS_DispatchToCurrentThread(event);
|
||||
mCallback->NotifyDataEnded(aStatus);
|
||||
}
|
||||
|
||||
void
|
||||
@ -945,14 +942,14 @@ ChannelMediaResource::CacheClientNotifyPrincipalChanged()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
mDecoder->NotifyPrincipalChanged();
|
||||
mCallback->NotifyPrincipalChanged();
|
||||
}
|
||||
|
||||
void
|
||||
ChannelMediaResource::CacheClientNotifySuspendedStatusChanged()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
mCallback->NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -961,7 +958,7 @@ ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
CMLOG("CacheClientSeek requested for aOffset [%lld] for decoder [%p]",
|
||||
aOffset, mDecoder);
|
||||
aOffset, mCallback);
|
||||
|
||||
CloseChannel();
|
||||
|
||||
@ -1171,11 +1168,11 @@ ChannelSuspendAgent::IsSuspended()
|
||||
class FileMediaResource : public BaseMediaResource
|
||||
{
|
||||
public:
|
||||
FileMediaResource(MediaDecoder* aDecoder,
|
||||
FileMediaResource(MediaResourceCallback* aCallback,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aContentType) :
|
||||
BaseMediaResource(aDecoder, aChannel, aURI, aContentType),
|
||||
BaseMediaResource(aCallback, aChannel, aURI, aContentType),
|
||||
mSize(-1),
|
||||
mLock("FileMediaResource.mLock"),
|
||||
mSizeInitialized(false)
|
||||
@ -1192,7 +1189,7 @@ public:
|
||||
virtual void Resume() override {}
|
||||
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
|
||||
virtual bool CanClone() override;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback* aCallback) override;
|
||||
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) override;
|
||||
|
||||
// These methods are called off the main thread.
|
||||
@ -1306,8 +1303,7 @@ void FileMediaResource::EnsureSizeInitialized()
|
||||
nsresult res = mInput->Available(&size);
|
||||
if (NS_SUCCEEDED(res) && size <= INT64_MAX) {
|
||||
mSize = (int64_t)size;
|
||||
nsCOMPtr<nsIRunnable> event = new DataEnded(mDecoder, NS_OK);
|
||||
NS_DispatchToMainThread(event);
|
||||
mCallback->NotifyDataEnded(NS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1404,11 +1400,11 @@ bool FileMediaResource::CanClone()
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaResourceCallback* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
if (!owner) {
|
||||
// The decoder is being shut down, so we can't clone
|
||||
return nullptr;
|
||||
@ -1441,7 +1437,7 @@ already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDeco
|
||||
if (NS_FAILED(rv))
|
||||
return nullptr;
|
||||
|
||||
RefPtr<MediaResource> resource(new FileMediaResource(aDecoder, channel, mURI, GetContentType()));
|
||||
RefPtr<MediaResource> resource(new FileMediaResource(aCallback, channel, mURI, GetContentType()));
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
@ -1562,7 +1558,7 @@ int64_t FileMediaResource::Tell()
|
||||
}
|
||||
|
||||
already_AddRefed<MediaResource>
|
||||
MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
|
||||
MediaResource::Create(MediaResourceCallback* aCallback, nsIChannel* aChannel)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"MediaResource::Open called on non-main thread");
|
||||
@ -1580,11 +1576,11 @@ MediaResource::Create(MediaDecoder* aDecoder, nsIChannel* aChannel)
|
||||
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
|
||||
RefPtr<MediaResource> resource;
|
||||
if (fc || IsBlobURI(uri)) {
|
||||
resource = new FileMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
resource = new FileMediaResource(aCallback, aChannel, uri, contentType);
|
||||
} else if (IsRtspURI(uri)) {
|
||||
resource = new RtspMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
resource = new RtspMediaResource(aCallback, aChannel, uri, contentType);
|
||||
} else {
|
||||
resource = new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
|
||||
resource = new ChannelMediaResource(aCallback, aChannel, uri, contentType);
|
||||
}
|
||||
return resource.forget();
|
||||
}
|
||||
@ -1599,7 +1595,7 @@ void BaseMediaResource::SetLoadInBackground(bool aLoadInBackground) {
|
||||
return;
|
||||
}
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
if (!owner) {
|
||||
NS_WARNING("Null owner in MediaResource::SetLoadInBackground()");
|
||||
return;
|
||||
@ -1689,8 +1685,7 @@ void BaseMediaResource::DispatchBytesConsumed(int64_t aNumBytes, int64_t aOffset
|
||||
if (aNumBytes <= 0) {
|
||||
return;
|
||||
}
|
||||
RefPtr<nsIRunnable> event(new DispatchBytesConsumedEvent(mDecoder, aNumBytes, aOffset));
|
||||
NS_DispatchToMainThread(event);
|
||||
mCallback->NotifyBytesConsumed(aNumBytes, aOffset);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -43,7 +43,7 @@ class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaDecoder;
|
||||
class MediaResourceCallback;
|
||||
class MediaChannelStatistics;
|
||||
|
||||
/**
|
||||
@ -270,7 +270,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 already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) = 0;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback* aCallback) = 0;
|
||||
// Set statistics to be recorded to the object passed in.
|
||||
virtual void RecordStatisticsTo(MediaChannelStatistics *aStatistics) { }
|
||||
|
||||
@ -387,7 +387,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 already_AddRefed<MediaResource> Create(MediaDecoder* aDecoder, nsIChannel* aChannel);
|
||||
static already_AddRefed<MediaResource> Create(MediaResourceCallback* aCallback, nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Open the stream. This creates a stream listener and returns it in
|
||||
@ -460,7 +460,7 @@ public:
|
||||
// - mChannel
|
||||
// - mURI (possibly owned, looks like just a ref from mChannel)
|
||||
// Not owned:
|
||||
// - mDecoder
|
||||
// - mCallback
|
||||
size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
@ -480,11 +480,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseMediaResource(MediaDecoder* aDecoder,
|
||||
BaseMediaResource(MediaResourceCallback* aCallback,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aContentType) :
|
||||
mDecoder(aDecoder),
|
||||
mCallback(aCallback),
|
||||
mChannel(aChannel),
|
||||
mURI(aURI),
|
||||
mContentType(aContentType),
|
||||
@ -516,7 +516,7 @@ protected:
|
||||
// This is not an nsCOMPointer to prevent a circular reference
|
||||
// between the decoder to the media stream object. The stream never
|
||||
// outlives the lifetime of the decoder.
|
||||
MediaDecoder* mDecoder;
|
||||
MediaResourceCallback* mCallback;
|
||||
|
||||
// Channel used to download the media data. Must be accessed
|
||||
// from the main thread only.
|
||||
@ -593,7 +593,7 @@ private:
|
||||
class ChannelMediaResource : public BaseMediaResource
|
||||
{
|
||||
public:
|
||||
ChannelMediaResource(MediaDecoder* aDecoder,
|
||||
ChannelMediaResource(MediaResourceCallback* aDecoder,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aContentType);
|
||||
@ -643,7 +643,7 @@ public:
|
||||
// Return true if the stream has been closed.
|
||||
bool IsClosed() const { return mCacheStream.IsClosed(); }
|
||||
virtual bool CanClone() override;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override;
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback* aDecoder) override;
|
||||
// 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) override {
|
||||
|
75
dom/media/MediaResourceCallback.h
Normal file
75
dom/media/MediaResourceCallback.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MediaResourceCallback_h_
|
||||
#define MediaResourceCallback_h_
|
||||
|
||||
#include "nsError.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaResource;
|
||||
|
||||
/**
|
||||
* A callback used by MediaResource (sub-classes like FileMediaResource,
|
||||
* RtspMediaResource, and ChannelMediaResource) to notify various events.
|
||||
* Currently this is implemented by MediaDecoder only.
|
||||
*
|
||||
* Since this class has no pure virtual function, it is convenient to write
|
||||
* gtests for the readers without using a mock MediaResource when you don't
|
||||
* care about the events notified by the MediaResource.
|
||||
*/
|
||||
class MediaResourceCallback {
|
||||
public:
|
||||
// Returns a weak reference to the media decoder owner.
|
||||
virtual MediaDecoderOwner* GetMediaOwner() const { return nullptr; }
|
||||
|
||||
// Notify is duration is known to this MediaResource.
|
||||
virtual void SetInfinite(bool aInfinite) {}
|
||||
|
||||
// Notify if seeking is supported by this MediaResource.
|
||||
virtual void SetMediaSeekable(bool aMediaSeekable) {}
|
||||
|
||||
// Notify that server connection is closed.
|
||||
virtual void ResetConnectionState() {}
|
||||
|
||||
// Used by RtspMediaResource which has an unusual sequence
|
||||
// to setup the decoder.
|
||||
virtual nsresult FinishDecoderSetup(MediaResource* aResource) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Notify that a network error is encountered.
|
||||
virtual void NotifyNetworkError() {}
|
||||
|
||||
// Notify that decoding has failed.
|
||||
virtual void NotifyDecodeError() {}
|
||||
|
||||
// Notify that data arrives on the stream and is read into the cache.
|
||||
virtual void NotifyDataArrived(
|
||||
uint32_t aLength, int64_t aOffset, bool aThrottleUpdates) {}
|
||||
|
||||
// Notify that MediaResource has received some data.
|
||||
virtual void NotifyBytesDownloaded() {}
|
||||
|
||||
// Notify download is ended.
|
||||
// NOTE: this can be called with the media cache lock held, so don't
|
||||
// block or do anything which might try to acquire a lock!
|
||||
virtual void NotifyDataEnded(nsresult aStatus) {}
|
||||
|
||||
// Notify that the principal of MediaResource has changed.
|
||||
virtual void NotifyPrincipalChanged() {}
|
||||
|
||||
// Notify that the "cache suspended" status of MediaResource changes.
|
||||
virtual void NotifySuspendedStatusChanged() {}
|
||||
|
||||
// Notify the number of bytes read from the resource.
|
||||
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif //MediaResourceCallback_h_
|
@ -488,9 +488,9 @@ RtspTrackBuffer::PlayoutDelayTimerCallback(nsITimer *aTimer,
|
||||
//-----------------------------------------------------------------------------
|
||||
// RtspMediaResource
|
||||
//-----------------------------------------------------------------------------
|
||||
RtspMediaResource::RtspMediaResource(MediaDecoder* aDecoder,
|
||||
RtspMediaResource::RtspMediaResource(MediaResourceCallback* aCallback,
|
||||
nsIChannel* aChannel, nsIURI* aURI, const nsACString& aContentType)
|
||||
: BaseMediaResource(aDecoder, aChannel, aURI, aContentType)
|
||||
: BaseMediaResource(aCallback, aChannel, aURI, aContentType)
|
||||
, mIsConnected(false)
|
||||
, mIsLiveStream(false)
|
||||
, mHasTimestamp(true)
|
||||
@ -537,8 +537,8 @@ void RtspMediaResource::NotifySuspend(bool aIsSuspend)
|
||||
RTSPMLOG("NotifySuspend %d",aIsSuspend);
|
||||
|
||||
mIsSuspend = aIsSuspend;
|
||||
if (mDecoder) {
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
if (mCallback) {
|
||||
mCallback->NotifySuspendedStatusChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,9 +688,7 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
|
||||
// video, we give up moving forward.
|
||||
if (!IsVideoEnabled() && IsVideo(tracks, meta)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError);
|
||||
NS_DispatchToMainThread(event);
|
||||
mCallback->NotifyDecodeError();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
uint64_t durationUs = 0;
|
||||
@ -717,7 +715,7 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
|
||||
mTrackBuffer[i]->Start();
|
||||
}
|
||||
|
||||
if (!mDecoder) {
|
||||
if (!mCallback) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -725,34 +723,30 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
|
||||
if (durationUs) {
|
||||
// Not live stream.
|
||||
mIsLiveStream = false;
|
||||
mDecoder->SetInfinite(false);
|
||||
mCallback->SetInfinite(false);
|
||||
} else {
|
||||
// Live stream.
|
||||
// Check the preference "media.realtime_decoder.enabled".
|
||||
if (!Preferences::GetBool("media.realtime_decoder.enabled", false)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError);
|
||||
NS_DispatchToMainThread(event);
|
||||
mCallback->NotifyDecodeError();
|
||||
return NS_ERROR_FAILURE;
|
||||
} else {
|
||||
mIsLiveStream = true;
|
||||
bool seekable = false;
|
||||
mDecoder->SetInfinite(true);
|
||||
mDecoder->SetMediaSeekable(seekable);
|
||||
mCallback->SetInfinite(true);
|
||||
mCallback->SetMediaSeekable(seekable);
|
||||
}
|
||||
}
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
// Fires an initial progress event.
|
||||
owner->DownloadProgressed();
|
||||
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
nsresult rv = mCallback->FinishDecoderSetup(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
element->FinishDecoderSetup(mDecoder, this);
|
||||
mIsConnected = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -766,7 +760,7 @@ RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, nsresult aReason)
|
||||
mTrackBuffer[i]->Reset();
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
if (mCallback) {
|
||||
if (aReason == NS_ERROR_NOT_INITIALIZED ||
|
||||
aReason == NS_ERROR_CONNECTION_REFUSED ||
|
||||
aReason == NS_ERROR_NOT_CONNECTED ||
|
||||
@ -774,11 +768,11 @@ RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, nsresult aReason)
|
||||
// Report error code to Decoder.
|
||||
RTSPMLOG("Error in OnDisconnected 0x%x", aReason);
|
||||
mIsConnected = false;
|
||||
mDecoder->NetworkError();
|
||||
mCallback->NotifyNetworkError();
|
||||
} else {
|
||||
// Resetting the decoder and media element when the connection
|
||||
// between RTSP client and server goes down.
|
||||
mDecoder->ResetConnectionState();
|
||||
mCallback->ResetConnectionState();
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,18 +790,18 @@ void RtspMediaResource::Suspend(bool aCloseImmediately)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
mIsSuspend = true;
|
||||
if (NS_WARN_IF(!mDecoder)) {
|
||||
if (NS_WARN_IF(!mCallback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE_VOID(owner);
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
NS_ENSURE_TRUE_VOID(element);
|
||||
|
||||
mMediaStreamController->Suspend();
|
||||
element->DownloadSuspended();
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
mCallback->NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
void RtspMediaResource::Resume()
|
||||
@ -815,11 +809,11 @@ void RtspMediaResource::Resume()
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
|
||||
|
||||
mIsSuspend = false;
|
||||
if (NS_WARN_IF(!mDecoder)) {
|
||||
if (NS_WARN_IF(!mCallback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
MediaDecoderOwner* owner = mCallback->GetMediaOwner();
|
||||
NS_ENSURE_TRUE_VOID(owner);
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
NS_ENSURE_TRUE_VOID(element);
|
||||
@ -828,7 +822,7 @@ void RtspMediaResource::Resume()
|
||||
element->DownloadResumed();
|
||||
}
|
||||
mMediaStreamController->Resume();
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
mCallback->NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
nsresult RtspMediaResource::Open(nsIStreamListener **aStreamListener)
|
||||
@ -840,11 +834,11 @@ nsresult RtspMediaResource::Close()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
mMediaStreamController->Stop();
|
||||
// Since mDecoder is not an nsCOMPtr in BaseMediaResource, we have to
|
||||
// Since mCallback is not an nsCOMPtr in BaseMediaResource, we have to
|
||||
// explicitly set it as null pointer in order to prevent misuse from this
|
||||
// object (RtspMediaResource).
|
||||
if (mDecoder) {
|
||||
mDecoder = nullptr;
|
||||
if (mCallback) {
|
||||
mCallback = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -866,7 +860,7 @@ nsresult RtspMediaResource::SeekTime(int64_t aOffset)
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
RTSPMLOG("Seek requested for aOffset [%lld] for decoder [%p]",
|
||||
aOffset, mDecoder);
|
||||
aOffset, mCallback);
|
||||
// Clear buffer and raise the frametype flag.
|
||||
for(uint32_t i = 0 ; i < mTrackBuffer.Length(); ++i) {
|
||||
mTrackBuffer[i]->ResetWithFrameType(MEDIASTREAM_FRAMETYPE_DISCONTINUITY);
|
||||
|
@ -71,7 +71,7 @@ class RtspTrackBuffer;
|
||||
class RtspMediaResource : public BaseMediaResource
|
||||
{
|
||||
public:
|
||||
RtspMediaResource(MediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI,
|
||||
RtspMediaResource(MediaResourceCallback* aCallback, nsIChannel* aChannel, nsIURI* aURI,
|
||||
const nsACString& aContentType);
|
||||
virtual ~RtspMediaResource();
|
||||
|
||||
@ -176,7 +176,7 @@ public:
|
||||
virtual bool CanClone() override {
|
||||
return false;
|
||||
}
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback*)
|
||||
override {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool CanClone() override { return false; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback*)
|
||||
override
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
virtual void Suspend(bool aCloseImmediately) override { UNIMPLEMENTED(); }
|
||||
virtual void Resume() override { UNIMPLEMENTED(); }
|
||||
virtual bool CanClone() override { UNIMPLEMENTED(); return false; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override { UNIMPLEMENTED(); return nullptr; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback*) override { UNIMPLEMENTED(); return nullptr; }
|
||||
virtual void SetReadMode(MediaCacheStream::ReadMode aMode) override { UNIMPLEMENTED(); }
|
||||
virtual void SetPlaybackRate(uint32_t aBytesPerSecond) override { UNIMPLEMENTED(); }
|
||||
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) override { UNIMPLEMENTED(); return NS_ERROR_FAILURE; }
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
virtual void Suspend(bool aCloseImmediately) override { UNIMPLEMENTED(); }
|
||||
virtual void Resume() override { UNIMPLEMENTED(); }
|
||||
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override { UNIMPLEMENTED(); return nullptr; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override { UNIMPLEMENTED(); return nullptr; }
|
||||
virtual already_AddRefed<MediaResource> CloneData(MediaResourceCallback*) override { UNIMPLEMENTED(); return nullptr; }
|
||||
virtual void SetReadMode(MediaCacheStream::ReadMode aMode) override { UNIMPLEMENTED(); }
|
||||
virtual void SetPlaybackRate(uint32_t aBytesPerSecond) override { UNIMPLEMENTED(); }
|
||||
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) override;
|
||||
|
@ -129,6 +129,7 @@ EXPORTS += [
|
||||
'MediaQueue.h',
|
||||
'MediaRecorder.h',
|
||||
'MediaResource.h',
|
||||
'MediaResourceCallback.h',
|
||||
'MediaSegment.h',
|
||||
'MediaStatistics.h',
|
||||
'MediaStreamGraph.h',
|
||||
|
Loading…
Reference in New Issue
Block a user