--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -63,17 +63,17 @@
#include "jsapi.h"
#include "nsITimer.h"
#include "nsEventDispatcher.h"
#include "nsMediaError.h"
#include "nsICategoryManager.h"
#include "nsCharSeparatedTokenizer.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "nsIDOMHTMLVideoElement.h"
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "nsCrossSiteListenerProxy.h"
#include "nsCycleCollectionParticipant.h"
#include "nsICachingChannel.h"
@@ -923,17 +923,17 @@ void nsHTMLMediaElement::UpdatePreloadAc
}
}
nsresult nsHTMLMediaElement::LoadResource()
{
NS_ASSERTION(mDelayingLoadEvent,
"Should delay load event (if in document) during load");
- // If a previous call to mozSetup() was made, kill that media stream
+ // If a previous call to mozSetup() was made, kill that media resource
// in order to use this new src instead.
if (mAudioStream) {
mAudioStream->Shutdown();
mAudioStream = nsnull;
}
if (mChannel) {
mChannel->Cancel(NS_BINDING_ABORTED);
@@ -1349,17 +1349,17 @@ MediaElementTableCount(nsHTMLMediaElemen
}
return count;
}
#endif
void
nsHTMLMediaElement::AddMediaElementToURITable()
{
- NS_ASSERTION(mDecoder && mDecoder->GetStream(), "Call this only with decoder Load called");
+ NS_ASSERTION(mDecoder && mDecoder->GetResource(), "Call this only with decoder Load called");
NS_ASSERTION(MediaElementTableCount(this, mLoadingSrc) == 0,
"Should not have entry for element in element table before addition");
if (!gElementTable) {
gElementTable = new MediaElementURITable();
gElementTable->Init();
}
MediaElementSetForURI* entry = gElementTable->PutEntry(mLoadingSrc);
entry->mElements.AppendElement(this);
@@ -1401,17 +1401,17 @@ nsHTMLMediaElement::LookupMediaElementUR
return nsnull;
for (PRUint32 i = 0; i < entry->mElements.Length(); ++i) {
nsHTMLMediaElement* elem = entry->mElements[i];
bool equal;
// Look for elements that have the same principal and CORS mode.
// Ditto for anything else that could cause us to send different headers.
if (NS_SUCCEEDED(elem->NodePrincipal()->Equals(NodePrincipal(), &equal)) && equal &&
elem->mCORSMode == mCORSMode) {
- NS_ASSERTION(elem->mDecoder && elem->mDecoder->GetStream(), "Decoder gone");
+ NS_ASSERTION(elem->mDecoder && elem->mDecoder->GetResource(), "Decoder gone");
return elem;
}
}
return nsnull;
}
nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
@@ -2005,18 +2005,18 @@ nsHTMLMediaElement::CreateDecoder(const
return nsnull;
}
nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
{
NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
NS_ASSERTION(mDecoder == nsnull, "Shouldn't have a decoder");
- nsMediaStream* originalStream = aOriginal->GetStream();
- if (!originalStream)
+ MediaResource* originalResource = aOriginal->GetResource();
+ if (!originalResource)
return NS_ERROR_FAILURE;
nsRefPtr<nsMediaDecoder> decoder = aOriginal->Clone();
if (!decoder)
return NS_ERROR_FAILURE;
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
if (!decoder->Init(this)) {
@@ -2025,25 +2025,25 @@ nsresult nsHTMLMediaElement::InitializeD
}
double duration = aOriginal->GetDuration();
if (duration >= 0) {
decoder->SetDuration(duration);
decoder->SetSeekable(aOriginal->IsSeekable());
}
- nsMediaStream* stream = originalStream->CloneData(decoder);
- if (!stream) {
+ 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;
}
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
- nsresult rv = decoder->Load(stream, nsnull, aOriginal);
+ nsresult rv = decoder->Load(resource, nsnull, aOriginal);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to load decoder/stream for decoder %p", this, decoder.get()));
return rv;
}
return FinishDecoderSetup(decoder);
}
@@ -2065,43 +2065,43 @@ nsresult nsHTMLMediaElement::InitializeD
ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
return NS_ERROR_FAILURE;
}
LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
- nsMediaStream* stream = nsMediaStream::Create(decoder, aChannel);
- if (!stream)
+ MediaResource* resource = MediaResource::Create(decoder, aChannel);
+ if (!resource)
return NS_ERROR_OUT_OF_MEMORY;
- nsresult rv = decoder->Load(stream, aListener, nsnull);
+ nsresult rv = decoder->Load(resource, aListener, nsnull);
if (NS_FAILED(rv)) {
return rv;
}
- // Decoder successfully created, the decoder now owns the nsMediaStream
+ // Decoder successfully created, the decoder now owns the MediaResource
// which owns the channel.
mChannel = nsnull;
return FinishDecoderSetup(decoder);
}
nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
{
NS_ASSERTION(mLoadingSrc, "mLoadingSrc set up");
mDecoder = aDecoder;
AddMediaElementToURITable();
// Force a same-origin check before allowing events for this media resource.
mMediaSecurityVerified = false;
- // The new stream has not been suspended by us.
+ // The new resource has not been suspended by us.
mPausedForInactiveDocument = false;
// But we may want to suspend it now.
// This will also do an AddRemoveSelfReference.
NotifyOwnerDocumentActivityChanged();
nsresult rv = NS_OK;
mDecoder->SetVolume(mMuted ? 0.0 : mVolume);
@@ -2287,17 +2287,17 @@ void nsHTMLMediaElement::Error(PRUint16
void nsHTMLMediaElement::PlaybackEnded()
{
NS_ASSERTION(mDecoder->IsEnded(), "Decoder fired ended, but not in ended state");
// We changed the state of IsPlaybackEnded which can affect AddRemoveSelfReference
AddRemoveSelfReference();
if (mDecoder && mDecoder->IsInfinite()) {
- LOG(PR_LOG_DEBUG, ("%p, got duration by reaching the end of the stream", this));
+ LOG(PR_LOG_DEBUG, ("%p, got duration by reaching the end of the resource", this));
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
}
if (HasAttr(kNameSpaceID_None, nsGkAtoms::loop)) {
SetCurrentTime(0);
return;
}
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -43,33 +43,33 @@ include $(DEPTH)/config/autoconf.mk
MODULE = content
LIBRARY_NAME = gkconmedia_s
LIBXUL_LIBRARY = 1
EXPORTS = \
nsAudioAvailableEventManager.h \
nsMediaDecoder.h \
- nsMediaStream.h \
nsMediaCache.h \
nsBuiltinDecoder.h \
nsBuiltinDecoderStateMachine.h \
nsBuiltinDecoderReader.h \
+ MediaResource.h \
VideoFrameContainer.h \
VideoUtils.h \
$(NULL)
CPPSRCS = \
nsAudioAvailableEventManager.cpp \
nsMediaDecoder.cpp \
nsMediaCache.cpp \
- nsMediaStream.cpp \
nsBuiltinDecoder.cpp \
nsBuiltinDecoderStateMachine.cpp \
nsBuiltinDecoderReader.cpp \
+ MediaResource.cpp \
VideoFrameContainer.cpp \
VideoUtils.cpp \
$(NULL)
ifdef MOZ_SYDNEYAUDIO
EXPORTS += \
nsAudioStream.h \
$(NULL)
rename from content/media/nsMediaStream.cpp
rename to content/media/MediaResource.cpp
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/MediaResource.cpp
@@ -31,17 +31,17 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "mozilla/Mutex.h"
#include "nsDebug.h"
#include "nsMediaDecoder.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "nsIFile.h"
#include "nsIFileChannel.h"
@@ -62,101 +62,101 @@
#include "mozilla/Util.h" // for DebugOnly
#include "nsContentUtils.h"
static const PRUint32 HTTP_OK_CODE = 200;
static const PRUint32 HTTP_PARTIAL_RESPONSE_CODE = 206;
using namespace mozilla;
-nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
+ChannelMediaResource::ChannelMediaResource(nsMediaDecoder* aDecoder,
nsIChannel* aChannel, nsIURI* aURI)
- : nsMediaStream(aDecoder, aChannel, aURI),
+ : MediaResource(aDecoder, aChannel, aURI),
mOffset(0), mSuspendCount(0),
mReopenOnError(false), mIgnoreClose(false),
mCacheStream(this),
- mLock("nsMediaChannelStream.mLock"),
+ mLock("ChannelMediaResource.mLock"),
mIgnoreResume(false)
{
}
-nsMediaChannelStream::~nsMediaChannelStream()
+ChannelMediaResource::~ChannelMediaResource()
{
if (mListener) {
// Kill its reference to us since we're going away
mListener->Revoke();
}
}
-// nsMediaChannelStream::Listener just observes the channel and
-// forwards notifications to the nsMediaChannelStream. We use multiple
+// ChannelMediaResource::Listener just observes the channel and
+// forwards notifications to the ChannelMediaResource. We use multiple
// listener objects so that when we open a new stream for a seek we can
-// disconnect the old listener from the nsMediaChannelStream and hook up
+// disconnect the old listener from the ChannelMediaResource and hook up
// a new listener, so notifications from the old channel are discarded
// and don't confuse us.
-NS_IMPL_ISUPPORTS4(nsMediaChannelStream::Listener,
+NS_IMPL_ISUPPORTS4(ChannelMediaResource::Listener,
nsIRequestObserver, nsIStreamListener, nsIChannelEventSink,
nsIInterfaceRequestor)
nsresult
-nsMediaChannelStream::Listener::OnStartRequest(nsIRequest* aRequest,
+ChannelMediaResource::Listener::OnStartRequest(nsIRequest* aRequest,
nsISupports* aContext)
{
- if (!mStream)
+ if (!mResource)
return NS_OK;
- return mStream->OnStartRequest(aRequest);
+ return mResource->OnStartRequest(aRequest);
}
nsresult
-nsMediaChannelStream::Listener::OnStopRequest(nsIRequest* aRequest,
+ChannelMediaResource::Listener::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aStatus)
{
- if (!mStream)
+ if (!mResource)
return NS_OK;
- return mStream->OnStopRequest(aRequest, aStatus);
+ return mResource->OnStopRequest(aRequest, aStatus);
}
nsresult
-nsMediaChannelStream::Listener::OnDataAvailable(nsIRequest* aRequest,
+ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest,
nsISupports* aContext,
nsIInputStream* aStream,
PRUint32 aOffset,
PRUint32 aCount)
{
- if (!mStream)
+ if (!mResource)
return NS_OK;
- return mStream->OnDataAvailable(aRequest, aStream, aCount);
+ return mResource->OnDataAvailable(aRequest, aStream, aCount);
}
nsresult
-nsMediaChannelStream::Listener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
+ChannelMediaResource::Listener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags,
nsIAsyncVerifyRedirectCallback* cb)
{
nsresult rv = NS_OK;
- if (mStream)
- rv = mStream->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
+ if (mResource)
+ rv = mResource->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
if (NS_FAILED(rv))
return rv;
cb->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
nsresult
-nsMediaChannelStream::Listener::GetInterface(const nsIID & aIID, void **aResult)
+ChannelMediaResource::Listener::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
nsresult
-nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
+ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
{
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
nsresult status;
nsresult rv = aRequest->GetStatus(&status);
NS_ENSURE_SUCCESS(rv, rv);
@@ -295,17 +295,17 @@ nsMediaChannelStream::OnStartRequest(nsI
// Fires an initial progress event and sets up the stall counter so stall events
// fire if no download occurs within the required time frame.
mDecoder->Progress(false);
return NS_OK;
}
nsresult
-nsMediaChannelStream::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
+ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
{
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
NS_ASSERTION(mSuspendCount == 0,
"How can OnStopRequest fire while we're suspended?");
{
MutexAutoLock lock(mLock);
mChannelStatistics.Stop(TimeStamp::Now());
@@ -347,83 +347,83 @@ nsMediaChannelStream::OnStopRequest(nsIR
ModifyLoadFlags(loadFlags);
}
}
return NS_OK;
}
nsresult
-nsMediaChannelStream::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew,
+ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew,
PRUint32 aFlags)
{
mChannel = aNew;
SetupChannelHeaders();
return NS_OK;
}
struct CopySegmentClosure {
nsCOMPtr<nsIPrincipal> mPrincipal;
- nsMediaChannelStream* mStream;
+ ChannelMediaResource* mResource;
};
NS_METHOD
-nsMediaChannelStream::CopySegmentToCache(nsIInputStream *aInStream,
+ChannelMediaResource::CopySegmentToCache(nsIInputStream *aInStream,
void *aClosure,
const char *aFromSegment,
PRUint32 aToOffset,
PRUint32 aCount,
PRUint32 *aWriteCount)
{
CopySegmentClosure* closure = static_cast<CopySegmentClosure*>(aClosure);
- closure->mStream->mDecoder->NotifyDataArrived(aFromSegment, aCount, closure->mStream->mOffset);
+ closure->mResource->mDecoder->NotifyDataArrived(aFromSegment, aCount, closure->mResource->mOffset);
// Keep track of where we're up to
- closure->mStream->mOffset += aCount;
- closure->mStream->mCacheStream.NotifyDataReceived(aCount, aFromSegment,
- closure->mPrincipal);
+ closure->mResource->mOffset += aCount;
+ closure->mResource->mCacheStream.NotifyDataReceived(aCount, aFromSegment,
+ closure->mPrincipal);
*aWriteCount = aCount;
return NS_OK;
}
nsresult
-nsMediaChannelStream::OnDataAvailable(nsIRequest* aRequest,
+ChannelMediaResource::OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aStream,
PRUint32 aCount)
{
NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
{
MutexAutoLock lock(mLock);
mChannelStatistics.AddBytes(aCount);
}
CopySegmentClosure closure;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (secMan && mChannel) {
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
}
- closure.mStream = this;
+ closure.mResource = this;
PRUint32 count = aCount;
while (count > 0) {
PRUint32 read;
nsresult rv = aStream->ReadSegments(CopySegmentToCache, &closure, count,
&read);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(read > 0, "Read 0 bytes while data was available?");
count -= read;
}
return NS_OK;
}
-nsresult nsMediaChannelStream::Open(nsIStreamListener **aStreamListener)
+nsresult ChannelMediaResource::Open(nsIStreamListener **aStreamListener)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsresult rv = mCacheStream.Init();
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(mOffset == 0, "Who set mOffset already?");
@@ -433,17 +433,17 @@ nsresult nsMediaChannelStream::Open(nsIS
NS_ASSERTION(!aStreamListener,
"Should have already been given a channel if we're to return a stream listener");
return NS_OK;
}
return OpenChannel(aStreamListener);
}
-nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener)
+nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ENSURE_TRUE(mChannel, NS_ERROR_NULL_POINTER);
NS_ASSERTION(!mListener, "Listener should have been removed by now");
if (aStreamListener) {
*aStreamListener = nsnull;
}
@@ -486,17 +486,17 @@ nsresult nsMediaChannelStream::OpenChann
nsresult rv = mChannel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
-void nsMediaChannelStream::SetupChannelHeaders()
+void ChannelMediaResource::SetupChannelHeaders()
{
// Always use a byte range request even if we're reading from the start
// of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
nsCAutoString rangeString("bytes=");
@@ -511,54 +511,54 @@ void nsMediaChannelStream::SetupChannelH
return;
}
element->SetRequestHeaders(hc);
} else {
NS_ASSERTION(mOffset == 0, "Don't know how to seek on this channel type");
}
}
-nsresult nsMediaChannelStream::Close()
+nsresult ChannelMediaResource::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
mCacheStream.Close();
CloseChannel();
return NS_OK;
}
-already_AddRefed<nsIPrincipal> nsMediaChannelStream::GetCurrentPrincipal()
+already_AddRefed<nsIPrincipal> ChannelMediaResource::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIPrincipal> principal = mCacheStream.GetCurrentPrincipal();
return principal.forget();
}
-nsMediaStream* nsMediaChannelStream::CloneData(nsMediaDecoder* aDecoder)
+MediaResource* ChannelMediaResource::CloneData(nsMediaDecoder* aDecoder)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
- nsMediaChannelStream* stream = new nsMediaChannelStream(aDecoder, nsnull, mURI);
- if (stream) {
+ ChannelMediaResource* resource = new ChannelMediaResource(aDecoder, nsnull, mURI);
+ 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
// it will call CacheClientResume (or CacheClientSeek with aResume true)
// which will recreate the channel. This way, if all of the media data
// is already in the cache we don't create an unneccesary HTTP channel
// and perform a useless HTTP transaction.
- stream->mSuspendCount = 1;
- stream->mCacheStream.InitAsClone(&mCacheStream);
- stream->mChannelStatistics = mChannelStatistics;
- stream->mChannelStatistics.Stop(TimeStamp::Now());
+ resource->mSuspendCount = 1;
+ resource->mCacheStream.InitAsClone(&mCacheStream);
+ resource->mChannelStatistics = mChannelStatistics;
+ resource->mChannelStatistics.Stop(TimeStamp::Now());
}
- return stream;
+ return resource;
}
-void nsMediaChannelStream::CloseChannel()
+void ChannelMediaResource::CloseChannel()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
{
MutexAutoLock lock(mLock);
mChannelStatistics.Stop(TimeStamp::Now());
}
@@ -579,52 +579,52 @@ void nsMediaChannelStream::CloseChannel(
// document load to think there was an error.
// NS_ERROR_PARSED_DATA_CACHED is the best thing we have for that
// at the moment.
mChannel->Cancel(NS_ERROR_PARSED_DATA_CACHED);
mChannel = nsnull;
}
}
-nsresult nsMediaChannelStream::ReadFromCache(char* aBuffer,
+nsresult ChannelMediaResource::ReadFromCache(char* aBuffer,
PRInt64 aOffset,
PRUint32 aCount)
{
return mCacheStream.ReadFromCache(aBuffer, aOffset, aCount);
}
-nsresult nsMediaChannelStream::Read(char* aBuffer,
+nsresult ChannelMediaResource::Read(char* aBuffer,
PRUint32 aCount,
PRUint32* aBytes)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
return mCacheStream.Read(aBuffer, aCount, aBytes);
}
-nsresult nsMediaChannelStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+nsresult ChannelMediaResource::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
return mCacheStream.Seek(aWhence, aOffset);
}
-PRInt64 nsMediaChannelStream::Tell()
+PRInt64 ChannelMediaResource::Tell()
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
return mCacheStream.Tell();
}
-nsresult nsMediaChannelStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges)
+nsresult ChannelMediaResource::GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
{
return mCacheStream.GetCachedRanges(aRanges);
}
-void nsMediaChannelStream::Suspend(bool aCloseImmediately)
+void ChannelMediaResource::Suspend(bool aCloseImmediately)
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
if (!element) {
// Shutting down; do nothing.
return;
}
@@ -643,17 +643,17 @@ void nsMediaChannelStream::Suspend(bool
PossiblySuspend();
element->DownloadSuspended();
}
}
++mSuspendCount;
}
-void nsMediaChannelStream::Resume()
+void ChannelMediaResource::Resume()
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
if (!element) {
// Shutting down; do nothing.
return;
@@ -686,17 +686,17 @@ void nsMediaChannelStream::Resume()
CacheClientSeek(mOffset, false);
}
element->DownloadResumed();
}
}
}
nsresult
-nsMediaChannelStream::RecreateChannel()
+ChannelMediaResource::RecreateChannel()
{
nsLoadFlags loadFlags =
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
(mLoadInBackground ? nsIRequest::LOAD_BACKGROUND : 0);
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
if (!element) {
// The decoder is being shut down, so don't bother opening a new channel
@@ -709,34 +709,34 @@ nsMediaChannelStream::RecreateChannel()
mURI,
nsnull,
loadGroup,
nsnull,
loadFlags);
}
void
-nsMediaChannelStream::DoNotifyDataReceived()
+ChannelMediaResource::DoNotifyDataReceived()
{
mDataReceivedEvent.Revoke();
mDecoder->NotifyBytesDownloaded();
}
void
-nsMediaChannelStream::CacheClientNotifyDataReceived()
+ChannelMediaResource::CacheClientNotifyDataReceived()
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
// 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!
if (mDataReceivedEvent.IsPending())
return;
mDataReceivedEvent =
- NS_NewNonOwningRunnableMethod(this, &nsMediaChannelStream::DoNotifyDataReceived);
+ NS_NewNonOwningRunnableMethod(this, &ChannelMediaResource::DoNotifyDataReceived);
NS_DispatchToMainThread(mDataReceivedEvent.get(), NS_DISPATCH_NORMAL);
}
class DataEnded : public nsRunnable {
public:
DataEnded(nsMediaDecoder* aDecoder, nsresult aStatus) :
mDecoder(aDecoder), mStatus(aStatus) {}
NS_IMETHOD Run() {
@@ -744,28 +744,28 @@ public:
return NS_OK;
}
private:
nsRefPtr<nsMediaDecoder> mDecoder;
nsresult mStatus;
};
void
-nsMediaChannelStream::CacheClientNotifyDataEnded(nsresult aStatus)
+ChannelMediaResource::CacheClientNotifyDataEnded(nsresult aStatus)
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
// 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_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
nsresult
-nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
+ChannelMediaResource::CacheClientSeek(PRInt64 aOffset, bool aResume)
{
NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
CloseChannel();
if (aResume) {
NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
// No need to mess with the channel, since we're making a new one
@@ -776,149 +776,149 @@ nsMediaChannelStream::CacheClientSeek(PR
if (NS_FAILED(rv))
return rv;
mOffset = aOffset;
return OpenChannel(nsnull);
}
nsresult
-nsMediaChannelStream::CacheClientSuspend()
+ChannelMediaResource::CacheClientSuspend()
{
Suspend(false);
mDecoder->NotifySuspendedStatusChanged();
return NS_OK;
}
nsresult
-nsMediaChannelStream::CacheClientResume()
+ChannelMediaResource::CacheClientResume()
{
Resume();
mDecoder->NotifySuspendedStatusChanged();
return NS_OK;
}
PRInt64
-nsMediaChannelStream::GetNextCachedData(PRInt64 aOffset)
+ChannelMediaResource::GetNextCachedData(PRInt64 aOffset)
{
return mCacheStream.GetNextCachedData(aOffset);
}
PRInt64
-nsMediaChannelStream::GetCachedDataEnd(PRInt64 aOffset)
+ChannelMediaResource::GetCachedDataEnd(PRInt64 aOffset)
{
return mCacheStream.GetCachedDataEnd(aOffset);
}
bool
-nsMediaChannelStream::IsDataCachedToEndOfStream(PRInt64 aOffset)
+ChannelMediaResource::IsDataCachedToEndOfResource(PRInt64 aOffset)
{
return mCacheStream.IsDataCachedToEndOfStream(aOffset);
}
void
-nsMediaChannelStream::EnsureCacheUpToDate()
+ChannelMediaResource::EnsureCacheUpToDate()
{
mCacheStream.EnsureCacheUpdate();
}
bool
-nsMediaChannelStream::IsSuspendedByCache(nsMediaStream** aActiveStream)
+ChannelMediaResource::IsSuspendedByCache(MediaResource** aActiveResource)
{
- return mCacheStream.AreAllStreamsForResourceSuspended(aActiveStream);
+ return mCacheStream.AreAllStreamsForResourceSuspended(aActiveResource);
}
bool
-nsMediaChannelStream::IsSuspended()
+ChannelMediaResource::IsSuspended()
{
MutexAutoLock lock(mLock);
return mSuspendCount > 0;
}
void
-nsMediaChannelStream::SetReadMode(nsMediaCacheStream::ReadMode aMode)
+ChannelMediaResource::SetReadMode(nsMediaCacheStream::ReadMode aMode)
{
mCacheStream.SetReadMode(aMode);
}
void
-nsMediaChannelStream::SetPlaybackRate(PRUint32 aBytesPerSecond)
+ChannelMediaResource::SetPlaybackRate(PRUint32 aBytesPerSecond)
{
mCacheStream.SetPlaybackRate(aBytesPerSecond);
}
void
-nsMediaChannelStream::Pin()
+ChannelMediaResource::Pin()
{
mCacheStream.Pin();
}
void
-nsMediaChannelStream::Unpin()
+ChannelMediaResource::Unpin()
{
mCacheStream.Unpin();
}
double
-nsMediaChannelStream::GetDownloadRate(bool* aIsReliable)
+ChannelMediaResource::GetDownloadRate(bool* aIsReliable)
{
MutexAutoLock lock(mLock);
return mChannelStatistics.GetRate(TimeStamp::Now(), aIsReliable);
}
PRInt64
-nsMediaChannelStream::GetLength()
+ChannelMediaResource::GetLength()
{
return mCacheStream.GetLength();
}
void
-nsMediaChannelStream::PossiblySuspend()
+ChannelMediaResource::PossiblySuspend()
{
bool isPending = false;
nsresult rv = mChannel->IsPending(&isPending);
if (NS_SUCCEEDED(rv) && isPending) {
mChannel->Suspend();
mIgnoreResume = false;
} else {
mIgnoreResume = true;
}
}
void
-nsMediaChannelStream::PossiblyResume()
+ChannelMediaResource::PossiblyResume()
{
if (!mIgnoreResume) {
mChannel->Resume();
} else {
mIgnoreResume = false;
}
}
-class nsMediaFileStream : public nsMediaStream
+class FileMediaResource : public MediaResource
{
public:
- nsMediaFileStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
- nsMediaStream(aDecoder, aChannel, aURI), mSize(-1),
- mLock("nsMediaFileStream.mLock")
+ FileMediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
+ MediaResource(aDecoder, aChannel, aURI), mSize(-1),
+ mLock("FileMediaResource.mLock")
{
}
- ~nsMediaFileStream()
+ ~FileMediaResource()
{
}
// Main thread
virtual nsresult Open(nsIStreamListener** aStreamListener);
virtual nsresult Close();
virtual void Suspend(bool aCloseImmediately) {}
virtual void Resume() {}
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
- virtual nsMediaStream* CloneData(nsMediaDecoder* aDecoder);
+ virtual MediaResource* CloneData(nsMediaDecoder* aDecoder);
virtual nsresult ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount);
// These methods are called off the main thread.
// Other thread
virtual void SetReadMode(nsMediaCacheStream::ReadMode aMode) {}
virtual void SetPlaybackRate(PRUint32 aBytesPerSecond) {}
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
@@ -935,27 +935,27 @@ public:
return 100*1024*1024; // arbitray, use 100MB/s
}
virtual PRInt64 GetLength() { return mSize; }
virtual PRInt64 GetNextCachedData(PRInt64 aOffset)
{
return (aOffset < mSize) ? aOffset : -1;
}
virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset) { return NS_MAX(aOffset, mSize); }
- virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset) { return true; }
- virtual bool IsSuspendedByCache(nsMediaStream** aActiveStream)
+ virtual bool IsDataCachedToEndOfResource(PRInt64 aOffset) { return true; }
+ virtual bool IsSuspendedByCache(MediaResource** aActiveResource)
{
- if (aActiveStream) {
- *aActiveStream = nsnull;
+ if (aActiveResource) {
+ *aActiveResource = nsnull;
}
return false;
}
virtual bool IsSuspended() { return false; }
- nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);
+ nsresult GetCachedRanges(nsTArray<MediaByteRange>& 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
@@ -989,26 +989,26 @@ public:
mDecoder->NotifyDownloadEnded(NS_OK);
return NS_OK;
}
private:
nsRefPtr<nsMediaDecoder> mDecoder;
};
-nsresult nsMediaFileStream::GetCachedRanges(nsTArray<nsByteRange>& aRanges)
+nsresult FileMediaResource::GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
{
if (mSize == -1) {
return NS_ERROR_FAILURE;
}
- aRanges.AppendElement(nsByteRange(0, mSize));
+ aRanges.AppendElement(MediaByteRange(0, mSize));
return NS_OK;
}
-nsresult nsMediaFileStream::Open(nsIStreamListener** aStreamListener)
+nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (aStreamListener) {
*aStreamListener = nsnull;
}
nsresult rv = NS_OK;
@@ -1058,44 +1058,44 @@ nsresult nsMediaFileStream::Open(nsIStre
mSize = size;
}
nsCOMPtr<nsIRunnable> event = new LoadedEvent(mDecoder);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
return NS_OK;
}
-nsresult nsMediaFileStream::Close()
+nsresult FileMediaResource::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
MutexAutoLock lock(mLock);
if (mChannel) {
mChannel->Cancel(NS_ERROR_PARSED_DATA_CACHED);
mChannel = nsnull;
mInput = nsnull;
mSeekable = nsnull;
}
return NS_OK;
}
-already_AddRefed<nsIPrincipal> nsMediaFileStream::GetCurrentPrincipal()
+already_AddRefed<nsIPrincipal> FileMediaResource::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (!secMan || !mChannel)
return nsnull;
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
return principal.forget();
}
-nsMediaStream* nsMediaFileStream::CloneData(nsMediaDecoder* aDecoder)
+MediaResource* FileMediaResource::CloneData(nsMediaDecoder* aDecoder)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsHTMLMediaElement* element = aDecoder->GetMediaElement();
if (!element) {
// The decoder is being shut down, so we can't clone
return nsnull;
}
@@ -1103,20 +1103,20 @@ nsMediaStream* nsMediaFileStream::CloneD
NS_ENSURE_TRUE(loadGroup, nsnull);
nsCOMPtr<nsIChannel> channel;
nsresult rv =
NS_NewChannel(getter_AddRefs(channel), mURI, nsnull, loadGroup, nsnull, 0);
if (NS_FAILED(rv))
return nsnull;
- return new nsMediaFileStream(aDecoder, channel, mURI);
+ return new FileMediaResource(aDecoder, channel, mURI);
}
-nsresult nsMediaFileStream::ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount)
+nsresult FileMediaResource::ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount)
{
MutexAutoLock lock(mLock);
if (!mInput || !mSeekable)
return NS_ERROR_FAILURE;
PRInt64 offset = 0;
nsresult res = mSeekable->Tell(&offset);
NS_ENSURE_SUCCESS(res,res);
res = mSeekable->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
@@ -1135,95 +1135,95 @@ nsresult nsMediaFileStream::ReadFromCach
// If a read failed in the loop above, we want to return its failure code.
NS_ENSURE_SUCCESS(res,res);
// Else we succeed if the reset-seek succeeds.
return seekres;
}
-nsresult nsMediaFileStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
+nsresult FileMediaResource::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{
MutexAutoLock lock(mLock);
if (!mInput)
return NS_ERROR_FAILURE;
return mInput->Read(aBuffer, aCount, aBytes);
}
-nsresult nsMediaFileStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+nsresult FileMediaResource::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
MutexAutoLock lock(mLock);
if (!mSeekable)
return NS_ERROR_FAILURE;
return mSeekable->Seek(aWhence, aOffset);
}
-PRInt64 nsMediaFileStream::Tell()
+PRInt64 FileMediaResource::Tell()
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
MutexAutoLock lock(mLock);
if (!mSeekable)
return 0;
PRInt64 offset = 0;
mSeekable->Tell(&offset);
return offset;
}
-nsMediaStream*
-nsMediaStream::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)
+MediaResource*
+MediaResource::Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel)
{
NS_ASSERTION(NS_IsMainThread(),
- "nsMediaStream::Open called on non-main thread");
+ "MediaResource::Open called on non-main thread");
// If the channel was redirected, we want the post-redirect URI;
// but if the URI scheme was expanded, say from chrome: to jar:file:,
// we want the original URI.
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, nsnull);
nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
if (fc) {
- return new nsMediaFileStream(aDecoder, aChannel, uri);
+ return new FileMediaResource(aDecoder, aChannel, uri);
}
- return new nsMediaChannelStream(aDecoder, aChannel, uri);
+ return new ChannelMediaResource(aDecoder, aChannel, uri);
}
-void nsMediaStream::MoveLoadsToBackground() {
+void MediaResource::MoveLoadsToBackground() {
NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?");
mLoadInBackground = true;
if (!mChannel) {
// No channel, resource is probably already loaded.
return;
}
nsresult rv;
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
if (!element) {
- NS_WARNING("Null element in nsMediaStream::MoveLoadsToBackground()");
+ NS_WARNING("Null element in MediaResource::MoveLoadsToBackground()");
return;
}
bool isPending = false;
if (NS_SUCCEEDED(mChannel->IsPending(&isPending)) &&
isPending) {
nsLoadFlags loadFlags;
rv = mChannel->GetLoadFlags(&loadFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadFlags() failed!");
loadFlags |= nsIRequest::LOAD_BACKGROUND;
ModifyLoadFlags(loadFlags);
}
}
-void nsMediaStream::ModifyLoadFlags(nsLoadFlags aFlags)
+void MediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
{
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadGroup() failed!");
nsresult status;
mChannel->GetStatus(&status);
rename from content/media/nsMediaStream.h
rename to content/media/MediaResource.h
--- a/content/media/nsMediaStream.h
+++ b/content/media/MediaResource.h
@@ -30,18 +30,18 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#if !defined(nsMediaStream_h_)
-#define nsMediaStream_h_
+#if !defined(MediaResource_h_)
+#define MediaResource_h_
#include "mozilla/Mutex.h"
#include "mozilla/XPCOM.h"
#include "nsIChannel.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
#include "nsIStreamListener.h"
#include "nsIChannelEventSink.h"
@@ -52,35 +52,34 @@
// seeked forward is less than this value then a read is
// done rather than a byte range request.
static const PRInt64 SEEK_VS_READ_THRESHOLD = 32*1024;
static const PRUint32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE = 416;
class nsMediaDecoder;
+namespace mozilla {
+
/**
* This class is useful for estimating rates of data passing through
* some channel. The idea is that activity on the channel "starts"
* and "stops" over time. At certain times data passes through the
* channel (usually while the channel is active; data passing through
* an inactive channel is ignored). The GetRate() function computes
* an estimate of the "current rate" of the channel, which is some
* kind of average of the data passing through over the time the
* channel is active.
*
* All methods take "now" as a parameter so the user of this class can
* control the timeline used.
*/
-class nsChannelStatistics {
+class MediaChannelStatistics {
public:
- typedef mozilla::TimeStamp TimeStamp;
- typedef mozilla::TimeDuration TimeDuration;
-
- nsChannelStatistics() { Reset(); }
+ MediaChannelStatistics() { Reset(); }
void Reset() {
mLastStartTime = TimeStamp();
mAccumulatedTime = TimeDuration(0);
mAccumulatedBytes = 0;
mIsStarted = false;
}
void Start(TimeStamp aNow) {
if (mIsStarted)
@@ -119,80 +118,88 @@ public:
if (seconds <= 0.0)
return 0.0;
return static_cast<double>(mAccumulatedBytes)/seconds;
}
private:
PRInt64 mAccumulatedBytes;
TimeDuration mAccumulatedTime;
TimeStamp mLastStartTime;
- bool mIsStarted;
+ bool mIsStarted;
};
// Represents a section of contiguous media, with a start and end offset.
// Used to denote ranges of data which are cached.
-class nsByteRange {
+class MediaByteRange {
public:
- nsByteRange() : mStart(0), mEnd(0) {}
+ MediaByteRange() : mStart(0), mEnd(0) {}
- nsByteRange(PRInt64 aStart, PRInt64 aEnd)
+ MediaByteRange(PRInt64 aStart, PRInt64 aEnd)
: mStart(aStart), mEnd(aEnd)
{
NS_ASSERTION(mStart < mEnd, "Range should end after start!");
}
bool 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
- Decoder they are called on the Decode thread for example. You must
- ensure that no threads are calling these methods once Close is called.
-
- Instances of this class are explicitly managed. 'delete' it when done.
-*/
-class nsMediaStream
+/**
+ * Provides a thread-safe, seek/read interface to resources
+ * loaded from a URI. Uses nsMediaCache to cache data received over
+ * Necko's async channel API, thus resolving the mismatch between clients
+ * that need efficient random access to the data and protocols that do not
+ * support efficient random access, such as HTTP.
+ *
+ * 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
+ * Decoder they are called on the Decode thread for example. You must
+ * ensure that no threads are calling these methods once Close is called.
+ *
+ * Instances of this class are explicitly managed. 'delete' it when done.
+ *
+ * The generic implementation of this class is ChannelMediaResource, which can
+ * handle any URI for which Necko supports AsyncOpen.
+ * The 'file:' protocol can be implemented efficiently with direct random
+ * access, so the FileMediaResource implementation class bypasses the cache.
+ * MediaResource::Create automatically chooses the best implementation class.
+ */
+class MediaResource
{
public:
- virtual ~nsMediaStream()
+ virtual ~MediaResource()
{
- MOZ_COUNT_DTOR(nsMediaStream);
+ MOZ_COUNT_DTOR(MediaResource);
}
// The following can be called on the main thread only:
// Get the URI
nsIURI* URI() const { return mURI; }
- // Close the stream, stop any listeners, channels, etc.
+ // Close the resource, stop any listeners, channels, etc.
// Cancels any currently blocking Read request and forces that request to
// return an error.
virtual nsresult Close() = 0;
// Suspend any downloads that are in progress.
// If aCloseImmediately is set, resources should be released immediately
// since we don't expect to resume again any time soon. Otherwise we
// may resume again soon so resources should be held for a little
// while.
virtual void Suspend(bool aCloseImmediately) = 0;
// Resume any downloads that have been suspended.
virtual void Resume() = 0;
// Get the current principal for the channel
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0;
// 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 nsMediaStream* CloneData(nsMediaDecoder* aDecoder) = 0;
+ virtual MediaResource* CloneData(nsMediaDecoder* aDecoder) = 0;
// These methods are called off the main thread.
// The mode is initially MODE_PLAYBACK.
virtual void SetReadMode(nsMediaCacheStream::ReadMode aMode) = 0;
// This is the client's estimate of the playback rate assuming
// the media plays continuously. The cache can't guess this itself
// because it doesn't know when the decoder was paused, buffering, etc.
virtual void SetPlaybackRate(PRUint32 aBytesPerSecond) = 0;
@@ -259,66 +266,65 @@ public:
// Returns the offset of the first byte of cached data at or after aOffset,
// or -1 if there is no such cached data.
virtual PRInt64 GetNextCachedData(PRInt64 aOffset) = 0;
// Returns the end of the bytes starting at the given offset
// which are in cache.
virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset) = 0;
// Returns true if all the data from aOffset to the end of the stream
// is in cache. If the end of the stream is not known, we return false.
- virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset) = 0;
+ virtual bool IsDataCachedToEndOfResource(PRInt64 aOffset) = 0;
// Returns true if this stream is suspended by the cache because the
// cache is full. If true then the decoder should try to start consuming
// 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.
- // If aActiveStream is non-null, fills it with a pointer to a stream
+ // 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(nsMediaStream** aActiveStream) = 0;
+ virtual bool IsSuspendedByCache(MediaResource** aActiveResource) = 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
// any data which overlaps uncached data, or if aCount bytes otherwise can't
// be read, this function will return failure. This function be called from
// any thread, and it is the only read operation which is safe to call on
// the main thread, since it's guaranteed to be non blocking.
virtual nsresult ReadFromCache(char* aBuffer,
PRInt64 aOffset,
PRUint32 aCount) = 0;
/**
- * Create a stream, reading data from the media resource via the
- * channel. Call on main thread only.
- * The caller must follow up by calling aStream->Open.
+ * Create a resource, reading data from the channel. Call on main thread only.
+ * The caller must follow up by calling resource->Open().
*/
- static nsMediaStream* Create(nsMediaDecoder* aDecoder, nsIChannel* aChannel);
+ static MediaResource* 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
+ * Fills aRanges with MediaByteRanges 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;
+ virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) = 0;
protected:
- nsMediaStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
+ MediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI) :
mDecoder(aDecoder),
mChannel(aChannel),
mURI(aURI),
mLoadInBackground(false)
{
- MOZ_COUNT_CTOR(nsMediaStream);
+ MOZ_COUNT_CTOR(MediaResource);
}
// Set the request's load flags to aFlags. If the request is part of a
// load group, the request is removed from the group, the flags are set, and
// then the request is added back to the load group.
void ModifyLoadFlags(nsLoadFlags aFlags);
// This is not an nsCOMPointer to prevent a circular reference
@@ -335,30 +341,28 @@ protected:
nsCOMPtr<nsIURI> mURI;
// True if MoveLoadsToBackground() has been called, i.e. the load event
// has been fired, and all channel loads will be in the background.
bool mLoadInBackground;
};
/**
- * This is the nsMediaStream implementation that wraps Necko channels.
+ * This is the MediaResource implementation that wraps Necko channels.
* Much of its functionality is actually delegated to nsMediaCache via
* an underlying nsMediaCacheStream.
*
* All synchronization is performed by nsMediaCacheStream; all off-main-
* thread operations are delegated directly to that object.
*/
-class nsMediaChannelStream : public nsMediaStream
+class ChannelMediaResource : public MediaResource
{
- typedef mozilla::Mutex Mutex;
-
public:
- nsMediaChannelStream(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI);
- ~nsMediaChannelStream();
+ ChannelMediaResource(nsMediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI);
+ ~ChannelMediaResource();
// These are called on the main thread by nsMediaCache. These must
// not block or grab locks, because the media cache is holding its lock.
// Notify that data is available from the cache. This can happen even
// if this stream didn't read any data, since another stream might have
// received data for the same resource.
void CacheClientNotifyDataReceived();
// Notify that we reached the end of the stream. This can happen even
@@ -382,17 +386,17 @@ public:
// Main thread
virtual nsresult Open(nsIStreamListener** aStreamListener);
virtual nsresult Close();
virtual void Suspend(bool aCloseImmediately);
virtual void Resume();
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
// Return true if the stream has been closed.
bool IsClosed() const { return mCacheStream.IsClosed(); }
- virtual nsMediaStream* CloneData(nsMediaDecoder* aDecoder);
+ virtual MediaResource* CloneData(nsMediaDecoder* aDecoder);
virtual nsresult ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount);
virtual void EnsureCacheUpToDate();
// Other thread
virtual void SetReadMode(nsMediaCacheStream::ReadMode aMode);
virtual void SetPlaybackRate(PRUint32 aBytesPerSecond);
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
@@ -400,41 +404,41 @@ public:
// Any thread
virtual void Pin();
virtual void Unpin();
virtual double GetDownloadRate(bool* aIsReliable);
virtual PRInt64 GetLength();
virtual PRInt64 GetNextCachedData(PRInt64 aOffset);
virtual PRInt64 GetCachedDataEnd(PRInt64 aOffset);
- virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset);
- virtual bool IsSuspendedByCache(nsMediaStream** aActiveStream);
+ virtual bool IsDataCachedToEndOfResource(PRInt64 aOffset);
+ virtual bool IsSuspendedByCache(MediaResource** aActiveResource);
virtual bool IsSuspended();
class Listener : public nsIStreamListener,
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
public:
- Listener(nsMediaChannelStream* aStream) : mStream(aStream) {}
+ Listener(ChannelMediaResource* aResource) : mResource(aResource) {}
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
- void Revoke() { mStream = nsnull; }
+ void Revoke() { mResource = nsnull; }
private:
- nsMediaChannelStream* mStream;
+ ChannelMediaResource* mResource;
};
friend class Listener;
- nsresult GetCachedRanges(nsTArray<nsByteRange>& aRanges);
+ nsresult GetCachedRanges(nsTArray<MediaByteRange>& 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);
@@ -466,31 +470,33 @@ protected:
// Resume from a suspend if we actually suspended (See PossiblySuspend).
void PossiblyResume();
// Main thread access only
PRInt64 mOffset;
nsRefPtr<Listener> mListener;
// A data received event for the decoder that has been dispatched but has
// not yet been processed.
- nsRevocableEventPtr<nsRunnableMethod<nsMediaChannelStream, void, false> > mDataReceivedEvent;
+ nsRevocableEventPtr<nsRunnableMethod<ChannelMediaResource, void, false> > mDataReceivedEvent;
PRUint32 mSuspendCount;
// When this flag is set, if we get a network error we should silently
// reopen the stream.
bool mReopenOnError;
// When this flag is set, we should not report the next close of the
// channel.
bool mIgnoreClose;
// Any thread access
nsMediaCacheStream mCacheStream;
// This lock protects mChannelStatistics
Mutex mLock;
- nsChannelStatistics mChannelStatistics;
+ MediaChannelStatistics mChannelStatistics;
// 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
// isPending state at the time of the suspend request.
bool mIgnoreResume;
};
+}
+
#endif
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -153,56 +153,56 @@ void nsBuiltinDecoder::Shutdown()
// necessary to unblock the state machine thread if it's blocked, so
// the asynchronous shutdown in nsDestroyStateMachine won't deadlock.
if (mDecoderStateMachine) {
mDecoderStateMachine->Shutdown();
}
// Force any outstanding seek and byterange requests to complete
// to prevent shutdown from deadlocking.
- if (mStream) {
- mStream->Close();
+ if (mResource) {
+ mResource->Close();
}
ChangeState(PLAY_STATE_SHUTDOWN);
nsMediaDecoder::Shutdown();
nsContentUtils::UnregisterShutdownObserver(this);
}
nsBuiltinDecoder::~nsBuiltinDecoder()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
UnpinForSeek();
MOZ_COUNT_DTOR(nsBuiltinDecoder);
}
-nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
+nsresult nsBuiltinDecoder::Load(MediaResource* aResource,
nsIStreamListener** aStreamListener,
nsMediaDecoder* aCloneDonor)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (aStreamListener) {
*aStreamListener = nsnull;
}
{
// Hold the lock while we do this to set proper lock ordering
// expectations for dynamic deadlock detectors: decoder lock(s)
// should be grabbed before the cache lock
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- nsresult rv = aStream->Open(aStreamListener);
+ nsresult rv = aResource->Open(aStreamListener);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
- delete aStream;
+ delete aResource;
return rv;
}
- mStream = aStream;
+ mResource = aResource;
}
mDecoderStateMachine = CreateStateMachine();
if (!mDecoderStateMachine) {
LOG(PR_LOG_DEBUG, ("%p Failed to create state machine!", this));
return NS_ERROR_FAILURE;
}
@@ -378,25 +378,20 @@ nsresult nsBuiltinDecoder::PlaybackRateC
}
double nsBuiltinDecoder::GetCurrentTime()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
return mCurrentTime;
}
-nsMediaStream* nsBuiltinDecoder::GetStream()
-{
- return mStream;
-}
-
already_AddRefed<nsIPrincipal> nsBuiltinDecoder::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- return mStream ? mStream->GetCurrentPrincipal() : nsnull;
+ return mResource ? mResource->GetCurrentPrincipal() : nsnull;
}
void nsBuiltinDecoder::AudioAvailable(float* aFrameBuffer,
PRUint32 aFrameBufferLength,
float aTime)
{
// Auto manage the frame buffer's memory. If we return due to an error
// here, this ensures we free the memory. Otherwise, we pass off ownership
@@ -446,24 +441,24 @@ void nsBuiltinDecoder::MetadataLoaded(PR
// Resource was loaded during metadata loading, when progress
// events are being ignored. Fire the final progress event.
mElement->DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
}
// Only inform the element of FirstFrameLoaded if not doing a load() in order
// to fulfill a seek, otherwise we'll get multiple loadedfirstframe events.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- bool resourceIsLoaded = !mResourceLoaded && mStream &&
- mStream->IsDataCachedToEndOfStream(mDecoderPosition);
+ bool resourceIsLoaded = !mResourceLoaded && mResource &&
+ mResource->IsDataCachedToEndOfResource(mDecoderPosition);
if (mElement && notifyElement) {
mElement->FirstFrameLoaded(resourceIsLoaded);
}
// This can run cache callbacks.
- mStream->EnsureCacheUpToDate();
+ mResource->EnsureCacheUpToDate();
// The element can run javascript via events
// before reaching here, so only change the
// state if we're still set to the original
// loading state.
if (mPlayState == PLAY_STATE_LOADING) {
if (mRequestedSeekTime >= 0.0) {
ChangeState(PLAY_STATE_SEEKING);
@@ -581,22 +576,22 @@ NS_IMETHODIMP nsBuiltinDecoder::Observe(
nsMediaDecoder::Statistics
nsBuiltinDecoder::GetStatistics()
{
NS_ASSERTION(NS_IsMainThread() || OnStateMachineThread(),
"Should be on main or state machine thread.");
Statistics result;
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- if (mStream) {
+ if (mResource) {
result.mDownloadRate =
- mStream->GetDownloadRate(&result.mDownloadRateReliable);
+ mResource->GetDownloadRate(&result.mDownloadRateReliable);
result.mDownloadPosition =
- mStream->GetCachedDataEnd(mDecoderPosition);
- result.mTotalBytes = mStream->GetLength();
+ mResource->GetCachedDataEnd(mDecoderPosition);
+ result.mTotalBytes = mResource->GetLength();
result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable);
result.mDecoderPosition = mDecoderPosition;
result.mPlaybackPosition = mPlaybackPosition;
}
else {
result.mDownloadRate = 0;
result.mDownloadRateReliable = true;
result.mPlaybackRate = 0;
@@ -611,52 +606,52 @@ nsBuiltinDecoder::GetStatistics()
}
double nsBuiltinDecoder::ComputePlaybackRate(bool* aReliable)
{
GetReentrantMonitor().AssertCurrentThreadIn();
NS_ASSERTION(NS_IsMainThread() || OnStateMachineThread(),
"Should be on main or state machine thread.");
- PRInt64 length = mStream ? mStream->GetLength() : -1;
+ PRInt64 length = mResource ? mResource->GetLength() : -1;
if (mDuration >= 0 && length >= 0) {
*aReliable = true;
return length * static_cast<double>(USECS_PER_S) / mDuration;
}
return mPlaybackStatistics.GetRateAtLastStop(aReliable);
}
void nsBuiltinDecoder::UpdatePlaybackRate()
{
NS_ASSERTION(NS_IsMainThread() || OnStateMachineThread(),
"Should be on main or state machine thread.");
GetReentrantMonitor().AssertCurrentThreadIn();
- if (!mStream)
+ if (!mResource)
return;
bool reliable;
PRUint32 rate = PRUint32(ComputePlaybackRate(&reliable));
if (reliable) {
// Avoid passing a zero rate
rate = NS_MAX(rate, 1u);
}
else {
// Set a minimum rate of 10,000 bytes per second ... sometimes we just
// don't have good data
rate = NS_MAX(rate, 10000u);
}
- mStream->SetPlaybackRate(rate);
+ mResource->SetPlaybackRate(rate);
}
void nsBuiltinDecoder::NotifySuspendedStatusChanged()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- if (!mStream)
+ if (!mResource)
return;
- nsMediaStream* activeStream;
- bool suspended = mStream->IsSuspendedByCache(&activeStream);
+ MediaResource* activeStream;
+ bool suspended = mResource->IsSuspendedByCache(&activeStream);
if (suspended && mElement) {
// if this is an autoplay element, we need to kick off its autoplaying
// now so we consume data and hopefully free up cache space
mElement->NotifyAutoplayDataReady();
}
}
@@ -956,63 +951,63 @@ void nsBuiltinDecoder::SetEndTime(double
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mDecoderStateMachine->SetFragmentEndTime(static_cast<PRInt64>(aTime * USECS_PER_S));
}
}
void nsBuiltinDecoder::Suspend()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- if (mStream) {
- mStream->Suspend(true);
+ if (mResource) {
+ mResource->Suspend(true);
}
}
void nsBuiltinDecoder::Resume(bool aForceBuffering)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- if (mStream) {
- mStream->Resume();
+ if (mResource) {
+ mResource->Resume();
}
if (aForceBuffering) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (mDecoderStateMachine) {
mDecoderStateMachine->StartBuffering();
}
}
}
void nsBuiltinDecoder::StopProgressUpdates()
{
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread.");
GetReentrantMonitor().AssertCurrentThreadIn();
mIgnoreProgressData = true;
- if (mStream) {
- mStream->SetReadMode(nsMediaCacheStream::MODE_METADATA);
+ if (mResource) {
+ mResource->SetReadMode(nsMediaCacheStream::MODE_METADATA);
}
}
void nsBuiltinDecoder::StartProgressUpdates()
{
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread.");
GetReentrantMonitor().AssertCurrentThreadIn();
mIgnoreProgressData = false;
- if (mStream) {
- mStream->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK);
- mDecoderPosition = mPlaybackPosition = mStream->Tell();
+ if (mResource) {
+ mResource->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK);
+ mDecoderPosition = mPlaybackPosition = mResource->Tell();
}
}
void nsBuiltinDecoder::MoveLoadsToBackground()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- if (mStream) {
- mStream->MoveLoadsToBackground();
+ if (mResource) {
+ mResource->MoveLoadsToBackground();
}
}
void nsBuiltinDecoder::UpdatePlaybackOffset(PRInt64 aOffset)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mPlaybackPosition = NS_MAX(aOffset, mPlaybackPosition);
}
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -220,17 +220,17 @@ destroying the nsBuiltinDecoder object.
#include "nsIChannel.h"
#include "nsIObserver.h"
#include "nsIFrame.h"
#include "nsAutoPtr.h"
#include "nsSize.h"
#include "prlog.h"
#include "gfxContext.h"
#include "gfxRect.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "nsMediaDecoder.h"
#include "nsHTMLMediaElement.h"
#include "mozilla/ReentrantMonitor.h"
class nsAudioStream;
static inline bool IsCurrentThread(nsIThread* aThread) {
return NS_GetCurrentThread() == aThread;
@@ -347,25 +347,22 @@ public:
// Called when a "MozAudioAvailable" event listener is added to the media
// element. Called on the main thread.
virtual void NotifyAudioAvailableListener() = 0;
};
class nsBuiltinDecoder : public nsMediaDecoder
{
- // ISupports
- NS_DECL_ISUPPORTS
+public:
+ typedef mozilla::MediaChannelStatistics MediaChannelStatistics;
- // nsIObserver
+ NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
- public:
- typedef mozilla::ReentrantMonitor ReentrantMonitor;
-
// Enumeration for the valid play states (see mPlayState)
enum PlayState {
PLAY_STATE_START,
PLAY_STATE_LOADING,
PLAY_STATE_PAUSED,
PLAY_STATE_PLAYING,
PLAY_STATE_SEEKING,
PLAY_STATE_ENDED,
@@ -378,17 +375,17 @@ class nsBuiltinDecoder : public nsMediaD
virtual bool Init(nsHTMLMediaElement* aElement);
// This method must be called by the owning object before that
// object disposes of this decoder object.
virtual void Shutdown();
virtual double GetCurrentTime();
- virtual nsresult Load(nsMediaStream* aStream,
+ virtual nsresult Load(MediaResource* aResource,
nsIStreamListener** aListener,
nsMediaDecoder* aCloneDonor);
virtual nsDecoderStateMachine* CreateStateMachine() = 0;
// Start playback of a video. 'Load' must have previously been
// called.
virtual nsresult Play();
@@ -400,17 +397,17 @@ class nsBuiltinDecoder : public nsMediaD
virtual void Pause();
virtual void SetVolume(double aVolume);
virtual double GetDuration();
virtual void SetInfinite(bool aInfinite);
virtual bool IsInfinite();
- virtual nsMediaStream* GetStream();
+ virtual MediaResource* GetResource() { return mResource; }
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
virtual void NotifySuspendedStatusChanged();
virtual void NotifyBytesDownloaded();
virtual void NotifyDownloadEnded(nsresult aStatus);
// Called by the decode thread to keep track of the number of bytes read
// from the resource.
void NotifyBytesConsumed(PRInt64 aBytes);
@@ -455,17 +452,17 @@ class nsBuiltinDecoder : public nsMediaD
// thread only.
virtual void Suspend();
// Resume any media downloads that have been suspended. Called by the
// media element when it is restored from the bfcache. Call on the
// main thread only.
virtual void Resume(bool aForceBuffering);
- // Tells our nsMediaStream to put all loads in the background.
+ // Tells our MediaResource to put all loads in the background.
virtual void MoveLoadsToBackground();
void AudioAvailable(float* aFrameBuffer, PRUint32 aFrameBufferLength, float aTime);
// Called by the state machine to notify the decoder that the duration
// has changed.
void DurationChanged();
@@ -636,17 +633,17 @@ class nsBuiltinDecoder : public nsMediaD
// Current playback position in the stream. This is (approximately)
// where we're up to playing back the stream. This is not adjusted
// during decoder seek operations, but it's updated at the end when we
// start playing back again.
PRInt64 mPlaybackPosition;
// Data needed to estimate playback data rate. The timeline used for
// this estimate is "decode time" (where the "current time" is the
// time of the last decoded video frame).
- nsChannelStatistics mPlaybackStatistics;
+ MediaChannelStatistics mPlaybackStatistics;
// The current playback position of the media resource in units of
// seconds. This is updated approximately at the framerate of the
// video (if it is a video) or the callback period of the audio.
// It is read and written from the main thread only.
double mCurrentTime;
// Volume that playback should start at. 0.0 = muted. 1.0 = full
@@ -675,18 +672,18 @@ class nsBuiltinDecoder : public nsMediaD
// The state machine object for handling the decoding. It is safe to
// call methods of this object from other threads. Its internal data
// is synchronised on a monitor. The lifetime of this object is
// after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
// is safe to access it during this period.
nsCOMPtr<nsDecoderStateMachine> mDecoderStateMachine;
- // Stream of media data.
- nsAutoPtr<nsMediaStream> mStream;
+ // Media data resource.
+ nsAutoPtr<MediaResource> mResource;
// ReentrantMonitor for detecting when the video play state changes. A call
// to Wait on this monitor will block the thread until the next
// state change.
ReentrantMonitor mReentrantMonitor;
// Set to one of the valid play states. It is protected by the
// monitor mReentrantMonitor. This monitor must be acquired when reading or
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1646,17 +1646,17 @@ void nsBuiltinDecoderStateMachine::Decod
LOG(PR_LOG_DEBUG, ("%p Seek completed, mCurrentFrameTime=%lld\n",
mDecoder.get(), mCurrentFrameTime));
// Change state to DECODING or COMPLETED now. SeekingStopped will
// call nsBuiltinDecoderStateMachine::Seek to reset our state to SEEKING
// if we need to seek again.
nsCOMPtr<nsIRunnable> stopEvent;
- bool isLiveStream = mDecoder->GetStream()->GetLength() == -1;
+ bool isLiveStream = mDecoder->GetResource()->GetLength() == -1;
if (GetMediaTime() == mEndTime && !isLiveStream) {
// Seeked to end of media, move to COMPLETED state. Note we don't do
// this if we're playing a live stream, since the end of media will advance
// once we download more data!
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
mDecoder.get(), seekTime));
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStoppedAtEnd);
mState = DECODER_STATE_COMPLETED;
@@ -1716,18 +1716,18 @@ private:
nsRefPtr<nsBuiltinDecoder> mDecoder;
nsCOMPtr<nsBuiltinDecoderStateMachine> mStateMachine;
};
nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
{
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream, NS_ERROR_NULL_POINTER);
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource, NS_ERROR_NULL_POINTER);
switch (mState) {
case DECODER_STATE_SHUTDOWN: {
if (IsPlaying()) {
StopPlayback();
}
StopAudioThread();
StopDecodeThread();
@@ -1797,23 +1797,23 @@ nsresult nsBuiltinDecoderStateMachine::R
TimeStamp now = TimeStamp::Now();
NS_ASSERTION(!mBufferingStart.IsNull(), "Must know buffering start time.");
// We will remain in the buffering state if we've not decoded enough
// data to begin playback, or if we've not downloaded a reasonable
// amount of data inside our buffering time.
TimeDuration elapsed = now - mBufferingStart;
- bool isLiveStream = mDecoder->GetStream()->GetLength() == -1;
+ bool isLiveStream = mDecoder->GetResource()->GetLength() == -1;
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
elapsed < TimeDuration::FromSeconds(mBufferingWait) &&
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
: (GetUndecodedData() < mBufferingWait * USECS_PER_S / 1000)) &&
- !stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
- !stream->IsSuspended())
+ !resource->IsDataCachedToEndOfResource(mDecoder->mDecoderPosition) &&
+ !resource->IsSuspended())
{
LOG(PR_LOG_DEBUG,
("%p Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
mDecoder.get(),
GetUndecodedData() / static_cast<double>(USECS_PER_S),
mBufferingWait,
mBufferingWait - elapsed.ToSeconds(),
(mQuickBuffering ? "(quick exit)" : "")));
@@ -1995,22 +1995,22 @@ void nsBuiltinDecoderStateMachine::Advan
? (DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration)
: mPlayDuration;
remainingTime = frame->mTime - mStartTime - now;
}
}
// Check to see if we don't have enough data to play up to the next frame.
// If we don't, switch to buffering mode.
- nsMediaStream* stream = mDecoder->GetStream();
+ MediaResource* resource = mDecoder->GetResource();
if (mState == DECODER_STATE_DECODING &&
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
- !stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
- !stream->IsSuspended() &&
+ !resource->IsDataCachedToEndOfResource(mDecoder->mDecoderPosition) &&
+ !resource->IsSuspended() &&
(JustExitedQuickBuffering() || HasLowUndecodedData()))
{
if (currentFrame) {
mReader->mVideoQueue.PushFront(currentFrame.forget());
}
StartBuffering();
ScheduleStateMachine();
return;
@@ -2173,21 +2173,21 @@ void nsBuiltinDecoderStateMachine::Start
nsMediaDecoder::Statistics stats = mDecoder->GetStatistics();
LOG(PR_LOG_DEBUG, ("%p Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
mDecoder.get(),
stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)"));
}
nsresult nsBuiltinDecoderStateMachine::GetBuffered(nsTimeRanges* aBuffered) {
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
- stream->Pin();
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource, NS_ERROR_FAILURE);
+ resource->Pin();
nsresult res = mReader->GetBuffered(aBuffered, mStartTime);
- stream->Unpin();
+ resource->Unpin();
return res;
}
bool nsBuiltinDecoderStateMachine::IsPausedAndDecoderWaiting() {
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
return
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -40,17 +40,17 @@
#include "mozilla/XPCOM.h"
#include "nsMediaCache.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsNetUtil.h"
#include "prio.h"
#include "nsThreadUtils.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "nsMathUtils.h"
#include "prlog.h"
#include "nsIPrivateBrowsingService.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
#ifdef PR_LOGGING
@@ -1903,27 +1903,27 @@ nsMediaCacheStream::SetSeekable(bool aIs
bool
nsMediaCacheStream::IsSeekable()
{
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
return mIsSeekable;
}
bool
-nsMediaCacheStream::AreAllStreamsForResourceSuspended(nsMediaStream** aActiveStream)
+nsMediaCacheStream::AreAllStreamsForResourceSuspended(MediaResource** aActiveStream)
{
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
nsMediaCache::ResourceStreamIterator iter(mResourceID);
while (nsMediaCacheStream* stream = iter.Next()) {
if (!stream->mCacheSuspended && !stream->mChannelEnded && !stream->mClosed) {
if (aActiveStream) {
*aActiveStream = stream->mClient;
}
return false;
- }
+ }
}
if (aActiveStream) {
*aActiveStream = nsnull;
}
return true;
}
void
@@ -2357,30 +2357,30 @@ 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)
+nsresult nsMediaCacheStream::GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
{
// Take the monitor, so that the cached data ranges can't grow while we're
// trying to loop over them.
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
// 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));
+ aRanges.AppendElement(MediaByteRange(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;
}
--- a/content/media/nsMediaCache.h
+++ b/content/media/nsMediaCache.h
@@ -38,20 +38,21 @@
#ifndef nsMediaCache_h_
#define nsMediaCache_h_
#include "nsTArray.h"
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
-class nsMediaStream;
-class nsByteRange;
-
namespace mozilla {
+// defined in MediaResource.h
+class ChannelMediaResource;
+class MediaByteRange;
+class MediaResource;
class ReentrantMonitorAutoEnter;
}
/**
* 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
@@ -164,75 +165,76 @@ class ReentrantMonitorAutoEnter;
*
* All changes to the actual contents of the cache happen on the main
* thread, since that's where Necko's notifications happen.
*
* The media cache maintains at most one Necko channel for each stream.
* (In the future it might be advantageous to relax this, e.g. so that a
* seek to near the end of the file can happen without disturbing
* the loading of data from the beginning of the file.) The Necko channel
- * is managed through nsMediaChannelStream; nsMediaCache does not
+ * is managed through ChannelMediaResource; nsMediaCache does not
* depend on Necko directly.
*
* Every time something changes that might affect whether we want to
* read from a Necko channel, or whether we want to seek on the Necko
* channel --- such as data arriving or data being consumed by the
* decoder --- we asynchronously trigger nsMediaCache::Update on the main
* thread. That method implements most cache policy. It evaluates for
* each stream whether we want to suspend or resume the stream and what
* offset we should seek to, if any. It is also responsible for trimming
* back the cache size to its desired limit by moving overflowing blocks
* into the main part of the cache.
*
* Streams can be opened in non-seekable mode. In non-seekable mode,
- * the cache will only call nsMediaChannelStream::CacheClientSeek with
+ * the cache will only call ChannelMediaResource::CacheClientSeek with
* a 0 offset. The cache tries hard not to discard readahead data
* for non-seekable streams, since that could trigger a potentially
* disastrous re-read of the entire stream. It's up to cache clients
* to try to avoid requesting seeks on such streams.
*
* nsMediaCache has a single internal monitor for all synchronization.
* This is treated as the lowest level monitor in the media code. So,
- * we must not acquire any nsMediaDecoder locks or nsMediaStream locks
+ * we must not acquire any nsMediaDecoder locks or MediaResource locks
* while holding the nsMediaCache lock. But it's OK to hold those locks
* and then get the nsMediaCache lock.
*
* nsMediaCache associates a principal with each stream. CacheClientSeek
* can trigger new HTTP requests; due to redirects to other domains,
* each HTTP load can return data with a different principal. This
* principal must be passed to NotifyDataReceived, and nsMediaCache
* will detect when different principals are associated with data in the
* same stream, and replace them with a null principal.
*/
class nsMediaCache;
-// defined in nsMediaStream.h
-class nsMediaChannelStream;
/**
* If the cache fails to initialize then Init will fail, so nonstatic
* methods of this class can assume gMediaCache is non-null.
*
* This class can be directly embedded as a value.
*/
class nsMediaCacheStream {
+public:
+ typedef mozilla::ChannelMediaResource ChannelMediaResource;
+ typedef mozilla::MediaByteRange MediaByteRange;
+ typedef mozilla::MediaResource MediaResource;
typedef mozilla::ReentrantMonitorAutoEnter ReentrantMonitorAutoEnter;
-public:
enum {
// This needs to be a power of two
BLOCK_SIZE = 32768
};
enum ReadMode {
MODE_METADATA,
MODE_PLAYBACK
};
// aClient provides the underlying transport that cache will use to read
// data for this stream.
- nsMediaCacheStream(nsMediaChannelStream* aClient)
+ nsMediaCacheStream(ChannelMediaResource* aClient)
: mClient(aClient), mResourceID(0), mInitialized(false),
mHasHadUpdate(false),
mIsSeekable(false), mCacheSuspended(false),
mChannelEnded(false), mDidNotifyDataEnded(false),
mUsingNullPrincipal(false),
mChannelOffset(0), mStreamLength(-1),
mStreamOffset(0), mPlaybackBytesPerSecond(10000),
mPinCount(0), mCurrentMode(MODE_PLAYBACK),
@@ -254,17 +256,17 @@ public:
// These are called on the main thread.
// Tell us whether the stream is seekable or not. Non-seekable streams
// will always pass 0 for aOffset to CacheClientSeek. This should only
// be called while the stream is at channel offset 0. Seekability can
// change during the lifetime of the nsMediaCacheStream --- every time
// we do an HTTP load the seekability may be different (and sometimes
// is, in practice, due to the effects of caching proxies).
void SetSeekable(bool aIsSeekable);
- // This must be called (and return) before the nsMediaChannelStream
+ // This must be called (and return) before the ChannelMediaResource
// used to create this nsMediaCacheStream is deleted.
void Close();
// This returns true when the stream has been closed
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.
@@ -286,24 +288,24 @@ public:
// EOF also depend on the reported length if we haven't managed to
// read the whole stream yet.
void NotifyDataLength(PRInt64 aLength);
// Notifies the cache that a load has begun. We pass the offset
// because in some cases the offset might not be what the cache
// requested. In particular we might unexpectedly start providing
// data at offset 0. This need not be called if the offset is the
// offset that the cache requested in
- // nsMediaChannelStream::CacheClientSeek. This can be called at any
+ // ChannelMediaResource::CacheClientSeek. This can be called at any
// time by the client, not just after a CacheClientSeek.
void NotifyDataStarted(PRInt64 aOffset);
// Notifies the cache that data has been received. The stream already
// knows the offset because data is received in sequence and
// the starting offset is known via NotifyDataStarted or because
// the cache requested the offset in
- // nsMediaChannelStream::CacheClientSeek, or because it defaulted to 0.
+ // ChannelMediaResource::CacheClientSeek, or because it defaulted to 0.
// We pass in the principal that was used to load this data.
void NotifyDataReceived(PRInt64 aSize, const char* aData,
nsIPrincipal* aPrincipal);
// Notifies the cache that the channel has closed with the given status.
void NotifyDataEnded(nsresult aStatus);
// These methods can be called on any thread.
// Cached blocks associated with this stream will not be evicted
@@ -324,17 +326,17 @@ public:
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);
+ nsresult GetCachedRanges(nsTArray<MediaByteRange>& 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);
@@ -351,19 +353,19 @@ public:
// because it doesn't know when the decoder was paused, buffering, etc.
// Do not pass zero.
void SetPlaybackRate(PRUint32 aBytesPerSecond);
// Returns the last set value of SetSeekable.
bool IsSeekable();
// Returns true when all streams for this resource are suspended or their
// channel has ended.
- // If aActiveStream is non-null, fills it with a pointer to a stream
+ // If aActiveResource is non-null, fills it with a pointer to a stream
// for this resource that is not suspended or ended.
- bool AreAllStreamsForResourceSuspended(nsMediaStream** aActiveStream);
+ bool AreAllStreamsForResourceSuspended(MediaResource** aActiveResource);
// 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.
// This can fail when aWhence is NS_SEEK_END and no stream length
// is known.
nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
PRInt64 Tell();
@@ -448,17 +450,17 @@ private:
// aReentrantMonitor is the nsAutoReentrantMonitor wrapper holding the cache monitor.
// This is used to NotifyAll to wake up threads that might be
// blocked on reading from this stream.
void CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor);
// Update mPrincipal given that data has been received from aPrincipal
void UpdatePrincipal(nsIPrincipal* aPrincipal);
// These fields are main-thread-only.
- nsMediaChannelStream* mClient;
+ ChannelMediaResource* mClient;
nsCOMPtr<nsIPrincipal> mPrincipal;
// This is a unique ID representing the resource we're loading.
// All streams with the same mResourceID are loading the same
// underlying resource and should share data.
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
--- a/content/media/nsMediaDecoder.cpp
+++ b/content/media/nsMediaDecoder.cpp
@@ -32,17 +32,17 @@
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMediaDecoder.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "prlog.h"
#include "prmem.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsThreadUtils.h"
#include "nsIDOMHTMLMediaElement.h"
#include "nsNetUtil.h"
@@ -176,32 +176,32 @@ void nsMediaDecoder::FireTimeUpdate()
{
if (!mElement)
return;
mElement->FireTimeUpdate(true);
}
void nsMediaDecoder::PinForSeek()
{
- nsMediaStream* stream = GetStream();
- if (!stream || mPinnedForSeek) {
+ MediaResource* resource = GetResource();
+ if (!resource || mPinnedForSeek) {
return;
}
mPinnedForSeek = true;
- stream->Pin();
+ resource->Pin();
}
void nsMediaDecoder::UnpinForSeek()
{
- nsMediaStream* stream = GetStream();
- if (!stream || !mPinnedForSeek) {
+ MediaResource* resource = GetResource();
+ if (!resource || !mPinnedForSeek) {
return;
}
mPinnedForSeek = false;
- stream->Unpin();
+ resource->Unpin();
}
bool nsMediaDecoder::CanPlayThrough()
{
Statistics stats = GetStatistics();
if (!stats.mDownloadRateReliable || !stats.mPlaybackRateReliable) {
return false;
}
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -47,36 +47,40 @@
#include "gfxRect.h"
#include "nsITimer.h"
#include "ImageLayers.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsIMemoryReporter.h"
#include "VideoFrameContainer.h"
class nsHTMLMediaElement;
-class nsMediaStream;
class nsIStreamListener;
class nsTimeRanges;
+namespace mozilla {
+class MediaResource;
+}
+
// The size to use for audio data frames in MozAudioAvailable events.
// This value is per channel, and is chosen to give ~43 fps of events,
// for example, 44100 with 2 channels, 2*1024 = 2048.
static const PRUint32 FRAMEBUFFER_LENGTH_PER_CHANNEL = 1024;
// The total size of the framebuffer used for MozAudioAvailable events
// has to be within the following range.
static const PRUint32 FRAMEBUFFER_LENGTH_MIN = 512;
static const PRUint32 FRAMEBUFFER_LENGTH_MAX = 16384;
// All methods of nsMediaDecoder must be called from the main thread only
// with the exception of GetVideoFrameContainer and GetStatistics,
// which can be called from any thread.
class nsMediaDecoder : public nsIObserver
{
public:
+ typedef mozilla::MediaResource MediaResource;
typedef mozilla::ReentrantMonitor ReentrantMonitor;
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
typedef mozilla::VideoFrameContainer VideoFrameContainer;
typedef mozilla::layers::Image Image;
typedef mozilla::layers::ImageContainer ImageContainer;
nsMediaDecoder();
@@ -85,19 +89,19 @@ public:
// Create a new decoder of the same type as this one.
virtual nsMediaDecoder* Clone() = 0;
// Perform any initialization required for the decoder.
// Return true on successful initialisation, false
// on failure.
virtual bool Init(nsHTMLMediaElement* aElement);
- // Get the current nsMediaStream being used. Its URI will be returned
+ // Get the current MediaResource being used. Its URI will be returned
// by currentSrc. Returns what was passed to Load(), if Load() has been called.
- virtual nsMediaStream* GetStream() = 0;
+ virtual MediaResource* GetResource() = 0;
// Return the principal of the current URI being played or downloaded.
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0;
// Return the time position in the video stream being
// played measured in seconds.
virtual double GetCurrentTime() = 0;
@@ -132,20 +136,20 @@ public:
virtual void SetVolume(double aVolume) = 0;
// Start playback of a video. 'Load' must have previously been
// called.
virtual nsresult Play() = 0;
// Start downloading the media. Decode the downloaded data up to the
// point of the first frame of data.
- // aStream is the media stream to use. Ownership of aStream passes to
+ // aResource is the media stream to use. Ownership of aResource passes to
// the decoder, even if Load returns an error.
// This is called at most once per decoder, after Init().
- virtual nsresult Load(nsMediaStream* aStream,
+ virtual nsresult Load(MediaResource* aResource,
nsIStreamListener **aListener,
nsMediaDecoder* aCloneDonor) = 0;
// Called when the video file has completed downloading.
virtual void ResourceLoaded() = 0;
// Called if the media file encounters a network error.
virtual void NetworkError() = 0;
@@ -313,27 +317,27 @@ public:
// if the method is called as a result of the progress timer rather
// than the result of downloaded data.
virtual void Progress(bool aTimer);
// Fire timeupdate events if needed according to the time constraints
// outlined in the specification.
virtual void FireTimeUpdate();
- // Called by nsMediaStream when the "cache suspended" status changes.
- // If nsMediaStream::IsSuspendedByCache returns true, then the decoder
+ // Called by MediaResource when the "cache suspended" status changes.
+ // 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() = 0;
- // Called by nsMediaStream when some data has been received.
+ // Called by MediaResource when some data has been received.
// Call on the main thread only.
virtual void NotifyBytesDownloaded() = 0;
- // Called by nsChannelToPipeListener or nsMediaStream when the
+ // Called by nsChannelToPipeListener or MediaResource when the
// download has ended. Called on the main thread only. aStatus is
// the result from OnStopRequest.
virtual void NotifyDownloadEnded(nsresult aStatus) = 0;
// Called as data arrives on the stream and is read into the cache. Called
// on the main thread only.
virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0;
@@ -367,17 +371,17 @@ public:
// Sets the length of the framebuffer used in MozAudioAvailable events.
// The new size must be between 512 and 16384.
virtual nsresult RequestFrameBufferLength(PRUint32 aLength);
// Moves any existing channel loads into the background, so that they don't
// block the load event. This is called when we stop delaying the load
// event. Any new loads initiated (for example to seek) will also be in the
// background. Implementations of this must call MoveLoadsToBackground() on
- // their nsMediaStream.
+ // their MediaResource.
virtual void MoveLoadsToBackground()=0;
// Constructs the time ranges representing what segments of the media
// are buffered and playable.
virtual nsresult GetBuffered(nsTimeRanges* aBuffered) = 0;
// Returns true if we can play the entire media through without stopping
// to buffer, given the current download and playback rates.
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -72,19 +72,19 @@ extern PRLogModuleInfo* gBuiltinDecoderL
static const PRUint32 SEEK_FUZZ_USECS = 500000;
enum PageSyncResult {
PAGE_SYNC_ERROR = 1,
PAGE_SYNC_END_OF_RANGE= 2,
PAGE_SYNC_OK = 3
};
-// Reads a page from the media stream.
+// Reads a page from the media resource.
static PageSyncResult
-PageSync(nsMediaStream* aStream,
+PageSync(MediaResource* aResource,
ogg_sync_state* aState,
bool aCachedDataOnly,
PRInt64 aOffset,
PRInt64 aEndOffset,
ogg_page* aPage,
int& aSkippedBytes);
// Chunk size to read when reading Ogg files. Average Ogg page length
@@ -293,17 +293,17 @@ nsresult nsOggReader::ReadMetadata(nsVid
if (mSkeletonState) {
if (!HasAudio() && !HasVideo()) {
// We have a skeleton track, but no audio or video, may as well disable
// the skeleton, we can't do anything useful with this media.
mSkeletonState->Deactivate();
} else if (ReadHeaders(mSkeletonState) && mSkeletonState->HasIndex()) {
// Extract the duration info out of the index, so we don't need to seek to
- // the end of stream to get it.
+ // the end of resource to get it.
nsAutoTArray<PRUint32, 2> tracks;
if (HasVideo()) {
tracks.AppendElement(mTheoraState->mSerial);
}
if (HasAudio()) {
tracks.AppendElement(mVorbisState->mSerial);
}
PRInt64 duration = 0;
@@ -313,25 +313,25 @@ nsresult nsOggReader::ReadMetadata(nsVid
LOG(PR_LOG_DEBUG, ("Got duration from Skeleton index %lld", duration));
}
}
}
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- nsMediaStream* stream = mDecoder->GetStream();
+ MediaResource* resource = mDecoder->GetResource();
if (mDecoder->GetStateMachine()->GetDuration() == -1 &&
mDecoder->GetStateMachine()->GetState() != nsDecoderStateMachine::DECODER_STATE_SHUTDOWN &&
- stream->GetLength() >= 0 &&
+ resource->GetLength() >= 0 &&
mDecoder->GetStateMachine()->IsSeekable())
{
// We didn't get a duration from the index or a Content-Duration header.
// Seek to the end of file to find the end time.
- PRInt64 length = stream->GetLength();
+ PRInt64 length = resource->GetLength();
NS_ASSERTION(length > 0, "Must have a content length to get end time");
PRInt64 endTime = 0;
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
endTime = RangeEndTime(length);
}
if (endTime != -1) {
@@ -547,20 +547,20 @@ PRInt64 nsOggReader::ReadOggPage(ogg_pag
continue;
}
// Returns a buffer that can be written too
// with the given size. This buffer is stored
// in the ogg synchronisation structure.
char* buffer = ogg_sync_buffer(&mOggState, 4096);
NS_ASSERTION(buffer, "ogg_sync_buffer failed");
- // Read from the stream into the buffer
+ // Read from the resource into the buffer
PRUint32 bytesRead = 0;
- nsresult rv = mDecoder->GetStream()->Read(buffer, 4096, &bytesRead);
+ nsresult rv = mDecoder->GetResource()->Read(buffer, 4096, &bytesRead);
if (NS_FAILED(rv) || (bytesRead == 0 && ret == 0)) {
// End of file.
return -1;
}
mDecoder->NotifyBytesConsumed(bytesRead);
// Update the synchronisation layer with the number
// of bytes written to the buffer
@@ -614,19 +614,19 @@ GetChecksum(ogg_page* page)
(p[2] << 16) +
(p[3] << 24);
return c;
}
PRInt64 nsOggReader::RangeStartTime(PRInt64 aOffset)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream != nsnull, nsnull);
- nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource != nsnull, nsnull);
+ nsresult res = resource->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
NS_ENSURE_SUCCESS(res, nsnull);
PRInt64 startTime = 0;
nsBuiltinDecoderReader::FindStartTime(startTime);
return startTime;
}
struct nsAutoOggSyncState {
nsAutoOggSyncState() {
@@ -638,30 +638,30 @@ struct nsAutoOggSyncState {
ogg_sync_state mState;
};
PRInt64 nsOggReader::RangeEndTime(PRInt64 aEndOffset)
{
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
"Should be on state machine or decode thread.");
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream != nsnull, -1);
- PRInt64 position = stream->Tell();
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource != nsnull, -1);
+ PRInt64 position = resource->Tell();
PRInt64 endTime = RangeEndTime(0, aEndOffset, false);
- nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, position);
+ nsresult res = resource->Seek(nsISeekableStream::NS_SEEK_SET, position);
NS_ENSURE_SUCCESS(res, -1);
return endTime;
}
PRInt64 nsOggReader::RangeEndTime(PRInt64 aStartOffset,
PRInt64 aEndOffset,
bool aCachedDataOnly)
{
- nsMediaStream* stream = mDecoder->GetStream();
+ MediaResource* resource = mDecoder->GetResource();
nsAutoOggSyncState sync;
// We need to find the last page which ends before aEndOffset that
// has a granulepos that we can convert to a timestamp. We do this by
// backing off from aEndOffset until we encounter a page on which we can
// interpret the granulepos. If while backing off we encounter a page which
// we've previously encountered before, we'll either backoff again if we
// haven't found an end time yet, or return the last end time found.
@@ -696,25 +696,25 @@ PRInt64 nsOggReader::RangeEndTime(PRInt6
limit = NS_MAX(static_cast<PRInt64>(0), limit);
limit = NS_MIN(limit, static_cast<PRInt64>(step));
PRUint32 bytesToRead = static_cast<PRUint32>(limit);
PRUint32 bytesRead = 0;
char* buffer = ogg_sync_buffer(&sync.mState, bytesToRead);
NS_ASSERTION(buffer, "Must have buffer");
nsresult res;
if (aCachedDataOnly) {
- res = stream->ReadFromCache(buffer, readHead, bytesToRead);
+ res = resource->ReadFromCache(buffer, readHead, bytesToRead);
NS_ENSURE_SUCCESS(res, -1);
bytesRead = bytesToRead;
} else {
NS_ASSERTION(readHead < aEndOffset,
- "Stream pos must be before range end");
- res = stream->Seek(nsISeekableStream::NS_SEEK_SET, readHead);
+ "resource pos must be before range end");
+ res = resource->Seek(nsISeekableStream::NS_SEEK_SET, readHead);
NS_ENSURE_SUCCESS(res, -1);
- res = stream->Read(buffer, bytesToRead, &bytesRead);
+ res = resource->Read(buffer, bytesToRead, &bytesRead);
NS_ENSURE_SUCCESS(res, -1);
}
readHead += bytesRead;
// Update the synchronisation layer with the number
// of bytes written to the buffer
ret = ogg_sync_wrote(&sync.mState, bytesRead);
if (ret != 0) {
@@ -767,22 +767,22 @@ PRInt64 nsOggReader::RangeEndTime(PRInt6
}
return endTime;
}
nsresult nsOggReader::GetSeekRanges(nsTArray<SeekRange>& aRanges)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
- nsTArray<nsByteRange> cached;
- nsresult res = mDecoder->GetStream()->GetCachedRanges(cached);
+ nsTArray<MediaByteRange> cached;
+ nsresult res = mDecoder->GetResource()->GetCachedRanges(cached);
NS_ENSURE_SUCCESS(res, res);
for (PRUint32 index = 0; index < cached.Length(); index++) {
- nsByteRange& range = cached[index];
+ MediaByteRange& range = cached[index];
PRInt64 startTime = -1;
PRInt64 endTime = -1;
if (NS_FAILED(ResetDecode())) {
return NS_ERROR_FAILURE;
}
PRInt64 startOffset = range.mStart;
PRInt64 endOffset = range.mEnd;
startTime = RangeStartTime(startOffset);
@@ -807,17 +807,17 @@ nsOggReader::SeekRange
nsOggReader::SelectSeekRange(const nsTArray<SeekRange>& ranges,
PRInt64 aTarget,
PRInt64 aStartTime,
PRInt64 aEndTime,
bool aExact)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
PRInt64 so = 0;
- PRInt64 eo = mDecoder->GetStream()->GetLength();
+ PRInt64 eo = mDecoder->GetResource()->GetLength();
PRInt64 st = aStartTime;
PRInt64 et = aEndTime;
for (PRUint32 i = 0; i < ranges.Length(); i++) {
const SeekRange &r = ranges[i];
if (r.mTimeStart < aTarget) {
so = r.mOffsetStart;
st = r.mTimeStart;
}
@@ -835,27 +835,27 @@ nsOggReader::SelectSeekRange(const nsTAr
return SeekRange();
}
return SeekRange(so, eo, st, et);
}
nsOggReader::IndexedSeekResult nsOggReader::RollbackIndexedSeek(PRInt64 aOffset)
{
mSkeletonState->Deactivate();
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream != nsnull, SEEK_FATAL_ERROR);
- nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource != nsnull, SEEK_FATAL_ERROR);
+ nsresult res = resource->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
return SEEK_INDEX_FAIL;
}
nsOggReader::IndexedSeekResult nsOggReader::SeekToKeyframeUsingIndex(PRInt64 aTarget)
{
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream != nsnull, SEEK_FATAL_ERROR);
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource != nsnull, SEEK_FATAL_ERROR);
if (!HasSkeleton() || !mSkeletonState->HasIndex()) {
return SEEK_INDEX_FAIL;
}
// We have an index from the Skeleton track, try to use it to seek.
nsAutoTArray<PRUint32, 2> tracks;
if (HasVideo()) {
tracks.AppendElement(mTheoraState->mSerial);
}
@@ -866,46 +866,46 @@ nsOggReader::IndexedSeekResult nsOggRead
if (NS_FAILED(mSkeletonState->IndexedSeekTarget(aTarget,
tracks,
keyframe)))
{
// Could not locate a keypoint for the target in the index.
return SEEK_INDEX_FAIL;
}
- // Remember original stream read cursor position so we can rollback on failure.
- PRInt64 tell = stream->Tell();
+ // Remember original resource read cursor position so we can rollback on failure.
+ PRInt64 tell = resource->Tell();
// Seek to the keypoint returned by the index.
- if (keyframe.mKeyPoint.mOffset > stream->GetLength() ||
+ if (keyframe.mKeyPoint.mOffset > resource->GetLength() ||
keyframe.mKeyPoint.mOffset < 0)
{
// Index must be invalid.
return RollbackIndexedSeek(tell);
}
LOG(PR_LOG_DEBUG, ("Seeking using index to keyframe at offset %lld\n",
keyframe.mKeyPoint.mOffset));
- nsresult res = stream->Seek(nsISeekableStream::NS_SEEK_SET,
+ nsresult res = resource->Seek(nsISeekableStream::NS_SEEK_SET,
keyframe.mKeyPoint.mOffset);
NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
mPageOffset = keyframe.mKeyPoint.mOffset;
// We've moved the read set, so reset decode.
res = ResetDecode();
NS_ENSURE_SUCCESS(res, SEEK_FATAL_ERROR);
// Check that the page the index thinks is exactly here is actually exactly
// here. If not, the index is invalid.
ogg_page page;
int skippedBytes = 0;
- PageSyncResult syncres = PageSync(stream,
+ PageSyncResult syncres = PageSync(resource,
&mOggState,
false,
mPageOffset,
- stream->GetLength(),
+ resource->GetLength(),
&page,
skippedBytes);
NS_ENSURE_TRUE(syncres != PAGE_SYNC_ERROR, SEEK_FATAL_ERROR);
if (syncres != PAGE_SYNC_OK || skippedBytes != 0) {
LOG(PR_LOG_DEBUG, ("Indexed-seek failure: Ogg Skeleton Index is invalid "
"or sync error after seek"));
return RollbackIndexedSeek(tell);
}
@@ -916,17 +916,17 @@ nsOggReader::IndexedSeekResult nsOggRead
return RollbackIndexedSeek(tell);
}
nsOggCodecState* codecState = nsnull;
mCodecStates.Get(serial, &codecState);
if (codecState &&
codecState->mActive &&
ogg_stream_pagein(&codecState->mState, &page) != 0)
{
- // Couldn't insert page into the ogg stream, or somehow the stream
+ // Couldn't insert page into the ogg resource, or somehow the resource
// is no longer active.
return RollbackIndexedSeek(tell);
}
mPageOffset = keyframe.mKeyPoint.mOffset + page.header_len + page.body_len;
return SEEK_OK;
}
nsresult nsOggReader::SeekInBufferedRange(PRInt64 aTarget,
@@ -1012,23 +1012,23 @@ nsresult nsOggReader::SeekInUnbuffered(P
nsresult nsOggReader::Seek(PRInt64 aTarget,
PRInt64 aStartTime,
PRInt64 aEndTime,
PRInt64 aCurrentTime)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
LOG(PR_LOG_DEBUG, ("%p About to seek to %lld", mDecoder, aTarget));
nsresult res;
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ENSURE_TRUE(stream != nsnull, NS_ERROR_FAILURE);
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ENSURE_TRUE(resource != nsnull, NS_ERROR_FAILURE);
if (aTarget == aStartTime) {
// We've seeked to the media start. Just seek to the offset of the first
// content page.
- res = stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ res = resource->Seek(nsISeekableStream::NS_SEEK_SET, 0);
NS_ENSURE_SUCCESS(res,res);
mPageOffset = 0;
res = ResetDecode();
NS_ENSURE_SUCCESS(res,res);
NS_ASSERTION(aStartTime != -1, "mStartTime should be known");
{
@@ -1065,19 +1065,19 @@ nsresult nsOggReader::Seek(PRInt64 aTarg
}
// The decode position must now be either close to the seek target, or
// we've seeked to before the keyframe before the seek target. Decode
// forward to the seek target frame.
return DecodeToTarget(aTarget);
}
-// Reads a page from the media stream.
+// Reads a page from the media resource.
static PageSyncResult
-PageSync(nsMediaStream* aStream,
+PageSync(MediaResource* aResource,
ogg_sync_state* aState,
bool aCachedDataOnly,
PRInt64 aOffset,
PRInt64 aEndOffset,
ogg_page* aPage,
int& aSkippedBytes)
{
aSkippedBytes = 0;
@@ -1095,26 +1095,26 @@ PageSync(nsMediaStream* aStream,
PRInt64 bytesToRead = NS_MIN(static_cast<PRInt64>(PAGE_STEP),
aEndOffset - readHead);
NS_ASSERTION(bytesToRead <= PR_UINT32_MAX, "bytesToRead range check");
if (bytesToRead <= 0) {
return PAGE_SYNC_END_OF_RANGE;
}
nsresult rv = NS_OK;
if (aCachedDataOnly) {
- rv = aStream->ReadFromCache(buffer, readHead,
- static_cast<PRUint32>(bytesToRead));
+ rv = aResource->ReadFromCache(buffer, readHead,
+ static_cast<PRUint32>(bytesToRead));
NS_ENSURE_SUCCESS(rv,PAGE_SYNC_ERROR);
bytesRead = static_cast<PRUint32>(bytesToRead);
} else {
- rv = aStream->Seek(nsISeekableStream::NS_SEEK_SET, readHead);
+ rv = aResource->Seek(nsISeekableStream::NS_SEEK_SET, readHead);
NS_ENSURE_SUCCESS(rv,PAGE_SYNC_ERROR);
- rv = aStream->Read(buffer,
- static_cast<PRUint32>(bytesToRead),
- &bytesRead);
+ rv = aResource->Read(buffer,
+ static_cast<PRUint32>(bytesToRead),
+ &bytesRead);
NS_ENSURE_SUCCESS(rv,PAGE_SYNC_ERROR);
}
if (bytesRead == 0 && NS_SUCCEEDED(rv)) {
// End of file.
return PAGE_SYNC_END_OF_RANGE;
}
readHead += bytesRead;
@@ -1137,23 +1137,23 @@ PageSync(nsMediaStream* aStream,
}
nsresult nsOggReader::SeekBisection(PRInt64 aTarget,
const SeekRange& aRange,
PRUint32 aFuzz)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
nsresult res;
- nsMediaStream* stream = mDecoder->GetStream();
+ MediaResource* resource = mDecoder->GetResource();
if (aTarget == aRange.mTimeStart) {
if (NS_FAILED(ResetDecode())) {
return NS_ERROR_FAILURE;
}
- res = stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ res = resource->Seek(nsISeekableStream::NS_SEEK_SET, 0);
NS_ENSURE_SUCCESS(res,res);
mPageOffset = 0;
return NS_OK;
}
// Bisection search, find start offset of last page with end time less than
// the seek target.
ogg_int64_t startOffset = aRange.mOffsetStart;
@@ -1250,17 +1250,17 @@ nsresult nsOggReader::SeekBisection(PRIn
NS_ASSERTION(guess != previousGuess, "Guess should be different to previous");
previousGuess = guess;
hops++;
// Locate the next page after our seek guess, and then figure out the
// granule time of the audio and video bitstreams there. We can then
// make a bisection decision based on our location in the media.
- PageSyncResult res = PageSync(stream,
+ PageSyncResult res = PageSync(resource,
&mOggState,
false,
guess,
endOffset,
&page,
skippedBytes);
NS_ENSURE_TRUE(res != PAGE_SYNC_ERROR, NS_ERROR_FAILURE);
@@ -1350,29 +1350,29 @@ nsresult nsOggReader::SeekBisection(PRIn
break;
} // End of "until we determine time at guess offset" loop.
if (interval == 0) {
// Seek termination condition; we've found the page boundary of the
// last page before the target, and the first page after the target.
SEEK_LOG(PR_LOG_DEBUG, ("Terminating seek at offset=%lld", startOffset));
NS_ASSERTION(startTime < aTarget, "Start time must always be less than target");
- res = stream->Seek(nsISeekableStream::NS_SEEK_SET, startOffset);
+ res = resource->Seek(nsISeekableStream::NS_SEEK_SET, startOffset);
NS_ENSURE_SUCCESS(res,res);
mPageOffset = startOffset;
if (NS_FAILED(ResetDecode())) {
return NS_ERROR_FAILURE;
}
break;
}
SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lld", guess, granuleTime));
if (granuleTime < seekTarget && granuleTime > seekLowerBound) {
// We're within the fuzzy region in which we want to terminate the search.
- res = stream->Seek(nsISeekableStream::NS_SEEK_SET, pageOffset);
+ res = resource->Seek(nsISeekableStream::NS_SEEK_SET, pageOffset);
NS_ENSURE_SUCCESS(res,res);
mPageOffset = pageOffset;
if (NS_FAILED(ResetDecode())) {
return NS_ERROR_FAILURE;
}
SEEK_LOG(PR_LOG_DEBUG, ("Terminating seek at offset=%lld", mPageOffset));
break;
}
@@ -1405,24 +1405,24 @@ nsresult nsOggReader::GetBuffered(nsTime
// a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
// after metadata is read and GetBuffered isn't called before metadata is
// read.
if (!mInfo.mHasVideo && !mInfo.mHasAudio) {
// No need to search through the file if there are no audio or video tracks
return NS_OK;
}
- nsMediaStream* stream = mDecoder->GetStream();
- nsTArray<nsByteRange> ranges;
- nsresult res = stream->GetCachedRanges(ranges);
+ MediaResource* resource = mDecoder->GetResource();
+ nsTArray<MediaByteRange> ranges;
+ nsresult res = resource->GetCachedRanges(ranges);
NS_ENSURE_SUCCESS(res, res);
// Traverse across the buffered byte ranges, determining the time ranges
- // they contain. nsMediaStream::GetNextCachedData(offset) returns -1 when
- // offset is after the end of the media stream, or there's no more cached
+ // they contain. MediaResource::GetNextCachedData(offset) returns -1 when
+ // offset is after the end of the media resource, or there's no more cached
// data after the offset. This loop will run until we've checked every
// buffered range in the media, in increasing order of offset.
nsAutoOggSyncState sync;
for (PRUint32 index = 0; index < ranges.Length(); index++) {
// Ensure the offsets are after the header pages.
PRInt64 startOffset = ranges[index].mStart;
PRInt64 endOffset = ranges[index].mEnd;
@@ -1434,17 +1434,17 @@ nsresult nsOggReader::GetBuffered(nsTime
// Find the start time of the range. Read pages until we find one with a
// granulepos which we can convert into a timestamp to use as the time of
// the start of the buffered range.
ogg_sync_reset(&sync.mState);
while (startTime == -1) {
ogg_page page;
PRInt32 discard;
- PageSyncResult res = PageSync(stream,
+ PageSyncResult res = PageSync(resource,
&sync.mState,
true,
startOffset,
endOffset,
&page,
discard);
if (res == PAGE_SYNC_ERROR) {
return NS_ERROR_FAILURE;
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -188,17 +188,17 @@ private:
PRUint32 aFuzz);
// Returns true if the serial number is for a stream we encountered
// while reading metadata. Call on the main thread only.
bool IsKnownStream(PRUint32 aSerial);
// Fills aRanges with SeekRanges denoting the sections of the media which
// have been downloaded and are stored in the media cache. The reader
- // monitor must must be held with exactly one lock count. The nsMediaStream
+ // monitor must must be held with exactly one lock count. The MediaResource
// must be pinned while calling this.
nsresult GetSeekRanges(nsTArray<SeekRange>& aRanges);
// Returns the range in which you should perform a seek bisection if
// you wish to seek to aTarget usecs, given the known (buffered) byte ranges
// in aRanges. If aExact is true, we only return an exact copy of a
// range in which aTarget lies, or a null range if aTarget isn't contained
// in any of the (buffered) ranges. Otherwise, when aExact is false,
--- a/content/media/raw/nsRawReader.cpp
+++ b/content/media/raw/nsRawReader.cpp
@@ -66,21 +66,21 @@ nsresult nsRawReader::ResetDecode()
return nsBuiltinDecoderReader::ResetDecode();
}
nsresult nsRawReader::ReadMetadata(nsVideoInfo* aInfo)
{
NS_ASSERTION(mDecoder->OnDecodeThread(),
"Should be on decode thread.");
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
- if (!ReadFromStream(stream, reinterpret_cast<PRUint8*>(&mMetadata),
- sizeof(mMetadata)))
+ if (!ReadFromResource(resource, reinterpret_cast<PRUint8*>(&mMetadata),
+ sizeof(mMetadata)))
return NS_ERROR_FAILURE;
// Validate the header
if (!(mMetadata.headerPacketID == 0 /* Packet ID of 0 for the header*/ &&
mMetadata.codecID == RAW_ID /* "YUV" */ &&
mMetadata.majorVersion == 0 &&
mMetadata.minorVersion == 1))
return NS_ERROR_FAILURE;
@@ -123,17 +123,17 @@ nsresult nsRawReader::ReadMetadata(nsVid
mMetadata.lumaChannelBpp != 8 ||
mMetadata.colorspace != 1 /* 4:2:0 */)
return NS_ERROR_FAILURE;
mFrameSize = mMetadata.frameWidth * mMetadata.frameHeight *
(mMetadata.lumaChannelBpp + mMetadata.chromaChannelBpp) / 8.0 +
sizeof(nsRawPacketHeader);
- PRInt64 length = stream->GetLength();
+ PRInt64 length = resource->GetLength();
if (length != -1) {
mozilla::ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor());
mDecoder->GetStateMachine()->SetDuration(USECS_PER_S *
(length - sizeof(nsRawVideoHeader)) /
(mFrameSize * mFrameRate));
}
*aInfo = mInfo;
@@ -145,24 +145,24 @@ nsresult nsRawReader::ReadMetadata(nsVid
{
NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
"Should be on state machine thread or decode thread.");
return false;
}
// Helper method that either reads until it gets aLength bytes
// or returns false
-bool nsRawReader::ReadFromStream(nsMediaStream *aStream, PRUint8* aBuf,
+bool nsRawReader::ReadFromResource(MediaResource *aResource, PRUint8* aBuf,
PRUint32 aLength)
{
while (aLength > 0) {
PRUint32 bytesRead = 0;
nsresult rv;
- rv = aStream->Read(reinterpret_cast<char*>(aBuf), aLength, &bytesRead);
+ rv = aResource->Read(reinterpret_cast<char*>(aBuf), aLength, &bytesRead);
NS_ENSURE_SUCCESS(rv, false);
if (bytesRead == 0) {
return false;
}
aLength -= bytesRead;
aBuf += bytesRead;
@@ -184,31 +184,31 @@ bool nsRawReader::DecodeVideoFrame(bool
if (!mFrameSize)
return false; // Metadata read failed. We should refuse to play.
PRInt64 currentFrameTime = USECS_PER_S * mCurrentFrame / mFrameRate;
PRUint32 length = mFrameSize - sizeof(nsRawPacketHeader);
nsAutoArrayPtr<PRUint8> buffer(new PRUint8[length]);
- nsMediaStream* stream = mDecoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
+ MediaResource* resource = mDecoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
// We're always decoding one frame when called
while(true) {
nsRawPacketHeader header;
// Read in a packet header and validate
- if (!(ReadFromStream(stream, reinterpret_cast<PRUint8*>(&header),
- sizeof(header))) ||
+ if (!(ReadFromResource(resource, reinterpret_cast<PRUint8*>(&header),
+ sizeof(header))) ||
!(header.packetID == 0xFF && header.codecID == RAW_ID /* "YUV" */)) {
return false;
}
- if (!ReadFromStream(stream, buffer, length)) {
+ if (!ReadFromResource(resource, buffer, length)) {
return false;
}
parsed++;
if (currentFrameTime >= aTimeThreshold)
break;
@@ -254,31 +254,31 @@ bool nsRawReader::DecodeVideoFrame(bool
return true;
}
nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime)
{
NS_ASSERTION(mDecoder->OnDecodeThread(),
"Should be on decode thread.");
- nsMediaStream *stream = mDecoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
+ MediaResource *resource = mDecoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
PRUint32 frame = mCurrentFrame;
if (aTime >= UINT_MAX)
return NS_ERROR_FAILURE;
mCurrentFrame = aTime * mFrameRate / USECS_PER_S;
PRUint32 offset;
if (!MulOverflow32(mCurrentFrame, mFrameSize, offset))
return NS_ERROR_FAILURE;
offset += sizeof(nsRawVideoHeader);
- nsresult rv = stream->Seek(nsISeekableStream::NS_SEEK_SET, offset);
+ nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset);
NS_ENSURE_SUCCESS(rv, rv);
mVideoQueue.Erase();
while(mVideoQueue.GetSize() == 0) {
bool keyframeSkip = false;
if (!DecodeVideoFrame(keyframeSkip, 0)) {
mCurrentFrame = frame;
--- a/content/media/raw/nsRawReader.h
+++ b/content/media/raw/nsRawReader.h
@@ -66,18 +66,17 @@ public:
return true;
}
virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
private:
- bool ReadFromStream(nsMediaStream *aStream, PRUint8 *aBuf,
- PRUint32 aLength);
+ bool ReadFromResource(MediaResource *aResource, PRUint8 *aBuf, PRUint32 aLength);
nsRawVideoHeader mMetadata;
PRUint32 mCurrentFrame;
double mFrameRate;
PRUint32 mFrameSize;
nsIntRect mPicture;
};
--- a/content/media/wave/nsWaveReader.cpp
+++ b/content/media/wave/nsWaveReader.cpp
@@ -33,17 +33,17 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsError.h"
#include "nsBuiltinDecoderStateMachine.h"
#include "nsBuiltinDecoder.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "nsWaveReader.h"
#include "nsTimeRanges.h"
#include "VideoUtils.h"
#include "mozilla/StdInt.h"
using namespace mozilla;
@@ -258,53 +258,53 @@ nsresult nsWaveReader::Seek(PRInt64 aTar
}
double d = BytesToTime(GetDataLength());
NS_ASSERTION(d < INT64_MAX / USECS_PER_S, "Duration overflow");
PRInt64 duration = static_cast<PRInt64>(d * USECS_PER_S);
double seekTime = NS_MIN(aTarget, duration) / static_cast<double>(USECS_PER_S);
PRInt64 position = RoundDownToFrame(static_cast<PRInt64>(TimeToBytes(seekTime)));
NS_ASSERTION(INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
position += mWavePCMOffset;
- return mDecoder->GetStream()->Seek(nsISeekableStream::NS_SEEK_SET, position);
+ return mDecoder->GetResource()->Seek(nsISeekableStream::NS_SEEK_SET, position);
}
static double RoundToUsecs(double aSeconds) {
return floor(aSeconds * USECS_PER_S) / USECS_PER_S;
}
nsresult nsWaveReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
{
- PRInt64 startOffset = mDecoder->GetStream()->GetNextCachedData(mWavePCMOffset);
+ PRInt64 startOffset = mDecoder->GetResource()->GetNextCachedData(mWavePCMOffset);
while (startOffset >= 0) {
- PRInt64 endOffset = mDecoder->GetStream()->GetCachedDataEnd(startOffset);
+ PRInt64 endOffset = mDecoder->GetResource()->GetCachedDataEnd(startOffset);
// Bytes [startOffset..endOffset] are cached.
NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
// We need to round the buffered ranges' times to microseconds so that they
// have the same precision as the currentTime and duration attribute on
// the media element.
aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));
- startOffset = mDecoder->GetStream()->GetNextCachedData(endOffset);
+ startOffset = mDecoder->GetResource()->GetNextCachedData(endOffset);
}
return NS_OK;
}
bool
nsWaveReader::ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead)
{
PRUint32 got = 0;
if (aBytesRead) {
*aBytesRead = 0;
}
do {
PRUint32 read = 0;
- if (NS_FAILED(mDecoder->GetStream()->Read(aBuf + got, PRUint32(aSize - got), &read))) {
- NS_WARNING("Stream read failed");
+ if (NS_FAILED(mDecoder->GetResource()->Read(aBuf + got, PRUint32(aSize - got), &read))) {
+ NS_WARNING("Resource read failed");
return false;
}
if (read == 0) {
return false;
}
mDecoder->NotifyBytesConsumed(read);
got += read;
if (aBytesRead) {
@@ -315,26 +315,26 @@ nsWaveReader::ReadAll(char* aBuf, PRInt6
}
bool
nsWaveReader::LoadRIFFChunk()
{
char riffHeader[RIFF_INITIAL_SIZE];
const char* p = riffHeader;
- NS_ABORT_IF_FALSE(mDecoder->GetStream()->Tell() == 0,
- "LoadRIFFChunk called when stream in invalid state");
+ NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() == 0,
+ "LoadRIFFChunk called when resource in invalid state");
if (!ReadAll(riffHeader, sizeof(riffHeader))) {
return false;
}
PR_STATIC_ASSERT(sizeof(PRUint32) * 2 <= RIFF_INITIAL_SIZE);
if (ReadUint32BE(&p) != RIFF_CHUNK_MAGIC) {
- NS_WARNING("Stream data not in RIFF format");
+ NS_WARNING("resource data not in RIFF format");
return false;
}
// Skip over RIFF size field.
p += 4;
if (ReadUint32BE(&p) != WAVE_CHUNK_MAGIC) {
NS_WARNING("Expected WAVE chunk");
@@ -387,18 +387,18 @@ nsWaveReader::ScanForwardUntil(PRUint32
bool
nsWaveReader::LoadFormatChunk()
{
PRUint32 fmtSize, rate, channels, frameSize, sampleFormat;
char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
const char* p = waveFormat;
// RIFF chunks are always word (two byte) aligned.
- NS_ABORT_IF_FALSE(mDecoder->GetStream()->Tell() % 2 == 0,
- "LoadFormatChunk called with unaligned stream");
+ NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
+ "LoadFormatChunk called with unaligned resource");
// The "format" chunk may not directly follow the "riff" chunk, so skip
// over any intermediate chunks.
if (!ScanForwardUntil(FRMT_CHUNK_MAGIC, &fmtSize)) {
return false;
}
if (!ReadAll(waveFormat, sizeof(waveFormat))) {
@@ -452,18 +452,18 @@ nsWaveReader::LoadFormatChunk()
nsAutoArrayPtr<char> chunkExtension(new char[extra]);
if (!ReadAll(chunkExtension.get(), extra)) {
return false;
}
}
}
// RIFF chunks are always word (two byte) aligned.
- NS_ABORT_IF_FALSE(mDecoder->GetStream()->Tell() % 2 == 0,
- "LoadFormatChunk left stream unaligned");
+ NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
+ "LoadFormatChunk left resource unaligned");
// Make sure metadata is fairly sane. The rate check is fairly arbitrary,
// but the channels check is intentionally limited to mono or stereo
// because that's what the audio backend currently supports.
if (rate < 100 || rate > 96000 ||
channels < 1 || channels > MAX_CHANNELS ||
(frameSize != 1 && frameSize != 2 && frameSize != 4) ||
(sampleFormat != 8 && sampleFormat != 16)) {
@@ -482,27 +482,27 @@ nsWaveReader::LoadFormatChunk()
}
return true;
}
bool
nsWaveReader::FindDataOffset()
{
// RIFF chunks are always word (two byte) aligned.
- NS_ABORT_IF_FALSE(mDecoder->GetStream()->Tell() % 2 == 0,
- "FindDataOffset called with unaligned stream");
+ NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
+ "FindDataOffset called with unaligned resource");
// The "data" chunk may not directly follow the "format" chunk, so skip
// over any intermediate chunks.
PRUint32 length;
if (!ScanForwardUntil(DATA_CHUNK_MAGIC, &length)) {
return false;
}
- PRInt64 offset = mDecoder->GetStream()->Tell();
+ PRInt64 offset = mDecoder->GetResource()->Tell();
if (offset <= 0 || offset > PR_UINT32_MAX) {
NS_WARNING("PCM data offset out of range");
return false;
}
ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor());
mWaveLength = length;
mWavePCMOffset = PRUint32(offset);
@@ -532,21 +532,21 @@ nsWaveReader::RoundDownToFrame(PRInt64 a
PRInt64
nsWaveReader::GetDataLength()
{
PRInt64 length = mWaveLength;
// If the decoder has a valid content length, and it's shorter than the
// expected length of the PCM data, calculate the playback duration from
// the content length rather than the expected PCM data length.
- PRInt64 streamLength = mDecoder->GetStream()->GetLength();
+ PRInt64 streamLength = mDecoder->GetResource()->GetLength();
if (streamLength >= 0) {
PRInt64 dataLength = NS_MAX<PRInt64>(0, streamLength - mWavePCMOffset);
length = NS_MIN(dataLength, length);
}
return length;
}
PRInt64
nsWaveReader::GetPosition()
{
- return mDecoder->GetStream()->Tell();
+ return mDecoder->GetResource()->Tell();
}
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -34,17 +34,17 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsError.h"
#include "nsBuiltinDecoderStateMachine.h"
#include "nsBuiltinDecoder.h"
-#include "nsMediaStream.h"
+#include "MediaResource.h"
#include "nsWebMReader.h"
#include "VideoUtils.h"
#include "nsTimeRanges.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
using namespace mozilla::layers;
@@ -74,62 +74,62 @@ static const int SEEK_DECODE_MARGIN = 25
template <>
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
{
public:
static void Release(NesteggPacketHolder* aHolder) { delete aHolder; }
};
-// Functions for reading and seeking using nsMediaStream required for
+// Functions for reading and seeking using MediaResource required for
// nestegg_io. The 'user data' passed to these functions is the
-// decoder from which the media stream is obtained.
+// decoder from which the media resource is obtained.
static int webm_read(void *aBuffer, size_t aLength, void *aUserData)
{
NS_ASSERTION(aUserData, "aUserData must point to a valid nsBuiltinDecoder");
nsBuiltinDecoder* decoder = reinterpret_cast<nsBuiltinDecoder*>(aUserData);
- nsMediaStream* stream = decoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
+ MediaResource* resource = decoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
nsresult rv = NS_OK;
bool eof = false;
char *p = static_cast<char *>(aBuffer);
while (NS_SUCCEEDED(rv) && aLength > 0) {
PRUint32 bytes = 0;
- rv = stream->Read(p, aLength, &bytes);
+ rv = resource->Read(p, aLength, &bytes);
if (bytes == 0) {
eof = true;
break;
}
decoder->NotifyBytesConsumed(bytes);
aLength -= bytes;
p += bytes;
}
return NS_FAILED(rv) ? -1 : eof ? 0 : 1;
}
static int webm_seek(int64_t aOffset, int aWhence, void *aUserData)
{
NS_ASSERTION(aUserData, "aUserData must point to a valid nsBuiltinDecoder");
nsBuiltinDecoder* decoder = reinterpret_cast<nsBuiltinDecoder*>(aUserData);
- nsMediaStream* stream = decoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
- nsresult rv = stream->Seek(aWhence, aOffset);
+ MediaResource* resource = decoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
+ nsresult rv = resource->Seek(aWhence, aOffset);
return NS_SUCCEEDED(rv) ? 0 : -1;
}
static int64_t webm_tell(void *aUserData)
{
NS_ASSERTION(aUserData, "aUserData must point to a valid nsBuiltinDecoder");
nsBuiltinDecoder* decoder = reinterpret_cast<nsBuiltinDecoder*>(aUserData);
- nsMediaStream* stream = decoder->GetStream();
- NS_ASSERTION(stream, "Decoder has no media stream");
- return stream->Tell();
+ MediaResource* resource = decoder->GetResource();
+ NS_ASSERTION(resource, "Decoder has no media resource");
+ return resource->Tell();
}
nsWebMReader::nsWebMReader(nsBuiltinDecoder* aDecoder)
: nsBuiltinDecoderReader(aDecoder),
mContext(nsnull),
mPacketCount(0),
mChannels(0),
mVideoTrack(0),
@@ -560,17 +560,17 @@ nsReturnRef<NesteggPacketHolder> nsWebMR
// Keep reading packets until we find a packet
// for the track we want.
do {
nestegg_packet* packet;
int r = nestegg_read_packet(mContext, &packet);
if (r <= 0) {
return nsReturnRef<NesteggPacketHolder>();
}
- PRInt64 offset = mDecoder->GetStream()->Tell();
+ PRInt64 offset = mDecoder->GetResource()->Tell();
holder.own(new NesteggPacketHolder(packet, offset));
unsigned int track = 0;
r = nestegg_packet_track(packet, &track);
if (r == -1) {
return nsReturnRef<NesteggPacketHolder>();
}
@@ -635,17 +635,17 @@ bool nsWebMReader::DecodeVideoFrame(bool
uint64_t tstamp = 0;
r = nestegg_packet_tstamp(packet, &tstamp);
if (r == -1) {
return false;
}
// The end time of this frame is the start time of the next frame. Fetch
// the timestamp of the next packet for this track. If we've reached the
- // end of the stream, use the file's duration as the end time of this
+ // end of the resource, use the file's duration as the end time of this
// video frame.
uint64_t next_tstamp = 0;
{
nsAutoRef<NesteggPacketHolder> next_holder(NextPacket(VIDEO));
if (next_holder) {
r = nestegg_packet_tstamp(next_holder->mPacket, &next_tstamp);
if (r == -1) {
return false;
@@ -770,33 +770,33 @@ nsresult nsWebMReader::Seek(PRInt64 aTar
if (r != 0) {
return NS_ERROR_FAILURE;
}
return DecodeToTarget(aTarget);
}
nsresult nsWebMReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
{
- nsMediaStream* stream = mDecoder->GetStream();
+ MediaResource* resource = mDecoder->GetResource();
uint64_t timecodeScale;
if (!mContext || nestegg_tstamp_scale(mContext, &timecodeScale) == -1) {
return NS_OK;
}
// Special case completely cached files. This also handles local files.
- if (stream->IsDataCachedToEndOfStream(0)) {
+ if (resource->IsDataCachedToEndOfResource(0)) {
uint64_t duration = 0;
if (nestegg_duration(mContext, &duration) == 0) {
aBuffered->Add(0, duration / NS_PER_S);
}
} else {
- nsMediaStream* stream = mDecoder->GetStream();
- nsTArray<nsByteRange> ranges;
- nsresult res = stream->GetCachedRanges(ranges);
+ MediaResource* resource = mDecoder->GetResource();
+ nsTArray<MediaByteRange> ranges;
+ nsresult res = resource->GetCachedRanges(ranges);
NS_ENSURE_SUCCESS(res, res);
PRInt64 startTimeOffsetNS = aStartTime * NS_PER_USEC;
for (PRUint32 index = 0; index < ranges.Length(); index++) {
mBufferedState->CalculateBufferedForRange(aBuffered,
ranges[index].mStart,
ranges[index].mEnd,
timecodeScale,