Bug 1040563 - Move WaitForData/NotifyGotData from MediaSource to MediaSourceDecoder, which is off-main-thread friendly. r=cajbir

Also remove mMediaSource from MediaSourceReader and rejig SetMediaSourceDuration to go via MediaSourceDecoder and handle mMediaSource being null.
This commit is contained in:
Matthew Gregan 2014-08-25 16:09:44 +12:00
parent 989833d80b
commit 5b38801b9a
7 changed files with 60 additions and 48 deletions

View File

@ -377,7 +377,6 @@ MediaSource::MediaSource(nsPIDOMWindow* aWindow)
, mDuration(UnspecifiedNaN<double>())
, mDecoder(nullptr)
, mReadyState(MediaSourceReadyState::Closed)
, mWaitForDataMonitor("MediaSource.WaitForData.Monitor")
{
MOZ_ASSERT(NS_IsMainThread());
mSourceBuffers = new SourceBufferList(this);
@ -465,22 +464,6 @@ MediaSource::NotifyEvicted(double aStart, double aEnd)
mSourceBuffers->Evict(aStart, aEnd);
}
void
MediaSource::WaitForData()
{
MSE_DEBUG("MediaSource(%p)::WaitForData()", this);
MonitorAutoLock mon(mWaitForDataMonitor);
mon.Wait();
}
void
MediaSource::NotifyGotData()
{
MSE_DEBUG("MediaSource(%p)::NotifyGotData()", this);
MonitorAutoLock mon(mWaitForDataMonitor);
mon.NotifyAll();
}
nsPIDOMWindow*
MediaSource::GetParentObject() const
{

View File

@ -13,7 +13,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/Monitor.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsCycleCollectionParticipant.h"
@ -91,12 +90,6 @@ public:
// that were evicted are provided.
void NotifyEvicted(double aStart, double aEnd);
// Block thread waiting for data to be appended to a SourceBuffer.
void WaitForData();
// Unblock threads waiting for data to be appended to a SourceBuffer.
void NotifyGotData();
private:
~MediaSource();
@ -116,10 +109,6 @@ private:
nsRefPtr<MediaSourceDecoder> mDecoder;
MediaSourceReadyState mReadyState;
// Monitor for waiting for when new data is appended to
// a Source Buffer.
Monitor mWaitForDataMonitor;
};
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)

View File

@ -47,7 +47,7 @@ MediaSourceDecoder::Clone()
MediaDecoderStateMachine*
MediaSourceDecoder::CreateStateMachine()
{
mReader = new MediaSourceReader(this, mMediaSource);
mReader = new MediaSourceReader(this);
return new MediaDecoderStateMachine(this, mReader);
}
@ -72,6 +72,10 @@ MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
nsresult
MediaSourceDecoder::GetSeekable(dom::TimeRanges* aSeekable)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mMediaSource) {
return NS_ERROR_FAILURE;
}
double duration = mMediaSource->Duration();
if (IsNaN(duration)) {
// Return empty range.
@ -86,6 +90,16 @@ MediaSourceDecoder::GetSeekable(dom::TimeRanges* aSeekable)
return NS_OK;
}
void
MediaSourceDecoder::Shutdown()
{
MediaDecoder::Shutdown();
// Kick WaitForData out of its slumber.
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mon.NotifyAll();
}
/*static*/
already_AddRefed<MediaResource>
MediaSourceDecoder::CreateResource()
@ -96,13 +110,14 @@ MediaSourceDecoder::CreateResource()
void
MediaSourceDecoder::AttachMediaSource(dom::MediaSource* aMediaSource)
{
MOZ_ASSERT(!mMediaSource && !mDecoderStateMachine);
MOZ_ASSERT(!mMediaSource && !mDecoderStateMachine && NS_IsMainThread());
mMediaSource = aMediaSource;
}
void
MediaSourceDecoder::DetachMediaSource()
{
MOZ_ASSERT(mMediaSource && NS_IsMainThread());
mMediaSource = nullptr;
}
@ -113,4 +128,31 @@ MediaSourceDecoder::CreateSubDecoder(const nsACString& aType)
return mReader->CreateSubDecoder(aType);
}
void
MediaSourceDecoder::SetMediaSourceDuration(double aDuration)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mMediaSource) {
return;
}
ErrorResult dummy;
mMediaSource->SetDuration(aDuration, dummy);
}
void
MediaSourceDecoder::WaitForData()
{
MSE_DEBUG("MediaSourceDecoder(%p)::WaitForData()", this);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mon.Wait();
}
void
MediaSourceDecoder::NotifyGotData()
{
MSE_DEBUG("MediaSourceDecoder(%p)::NotifyGotData()", this);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mon.NotifyAll();
}
} // namespace mozilla

View File

@ -38,6 +38,8 @@ public:
virtual nsresult Load(nsIStreamListener**, MediaDecoder*) MOZ_OVERRIDE;
virtual nsresult GetSeekable(dom::TimeRanges* aSeekable) MOZ_OVERRIDE;
virtual void Shutdown() MOZ_OVERRIDE;
static already_AddRefed<MediaResource> CreateResource();
void AttachMediaSource(dom::MediaSource* aMediaSource);
@ -45,6 +47,14 @@ public:
already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
void SetMediaSourceDuration(double aDuration);
// Provide a mechanism for MediaSourceReader to block waiting on data from a SourceBuffer.
void WaitForData();
// Called whenever a SourceBuffer has new data appended.
void NotifyGotData();
private:
// The owning MediaSource holds a strong reference to this decoder, and
// calls Attach/DetachMediaSource on this decoder to set and clear

View File

@ -35,12 +35,11 @@ extern PRLogModuleInfo* GetMediaSourceAPILog();
namespace mozilla {
MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder, dom::MediaSource* aSource)
MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
: MediaDecoderReader(aDecoder)
, mTimeThreshold(-1)
, mDropAudioBeforeThreshold(false)
, mDropVideoBeforeThreshold(false)
, mMediaSource(aSource)
{
}
@ -249,14 +248,6 @@ MediaSourceReader::SwitchReaders(SwitchType aType)
return didSwitch;
}
void
MediaSourceReader::SetMediaSourceDuration(double aDuration)
{
MOZ_ASSERT(NS_IsMainThread());
ErrorResult dummy;
mMediaSource->SetDuration(aDuration, dummy);
}
class ReleaseDecodersTask : public nsRunnable {
public:
ReleaseDecodersTask(nsTArray<nsRefPtr<SourceBufferDecoder>>& aDecoders)
@ -423,7 +414,7 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
// we'll remove this for an async approach based on that in bug XXXXXXX.
while (!DecodersContainTime(target) && !IsShutdown()) {
MSE_DEBUG("MediaSourceReader(%p)::Seek waiting for target=%f", this, target);
mMediaSource->WaitForData();
static_cast<MediaSourceDecoder*>(mDecoder)->WaitForData();
SwitchReaders(SWITCH_FORCED);
}
@ -491,7 +482,8 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->SetMediaDuration(maxDuration);
nsRefPtr<nsIRunnable> task (
NS_NewRunnableMethodWithArg<double>(this, &MediaSourceReader::SetMediaSourceDuration,
NS_NewRunnableMethodWithArg<double>(static_cast<MediaSourceDecoder*>(mDecoder),
&MediaSourceDecoder::SetMediaSourceDuration,
static_cast<double>(maxDuration) / USECS_PER_S));
NS_DispatchToMainThread(task);
}

View File

@ -29,7 +29,7 @@ class MediaSource;
class MediaSourceReader : public MediaDecoderReader
{
public:
MediaSourceReader(MediaSourceDecoder* aDecoder, dom::MediaSource* aSource);
MediaSourceReader(MediaSourceDecoder* aDecoder);
nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE
{
@ -98,8 +98,6 @@ private:
bool SwitchAudioReader(MediaDecoderReader* aTargetReader);
bool SwitchVideoReader(MediaDecoderReader* aTargetReader);
void SetMediaSourceDuration(double aDuration) ;
// These are read and written on the decode task queue threads.
int64_t mTimeThreshold;
bool mDropAudioBeforeThreshold;
@ -110,8 +108,6 @@ private:
nsRefPtr<MediaDecoderReader> mAudioReader;
nsRefPtr<MediaDecoderReader> mVideoReader;
dom::MediaSource* mMediaSource;
};
} // namespace mozilla

View File

@ -499,7 +499,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// if required when data is appended.
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
mMediaSource->NotifyGotData();
mMediaSource->GetDecoder()->NotifyGotData();
}
double