Bug 1218280. Part 1 - create MediaResourceCallback for MediaResource to send notifications. r=roc.

This commit is contained in:
JW Wang 2015-10-27 10:28:26 +08:00
parent c7d3c4e21a
commit a7589ce310
12 changed files with 220 additions and 96 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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 {

View 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_

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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; }

View File

@ -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;

View File

@ -129,6 +129,7 @@ EXPORTS += [
'MediaQueue.h',
'MediaRecorder.h',
'MediaResource.h',
'MediaResourceCallback.h',
'MediaSegment.h',
'MediaStatistics.h',
'MediaStreamGraph.h',