Bug 848954 - Part 4 - Factor behavior for drivers that manage their thread. r=roc

This commit is contained in:
Paul Adenot 2014-04-25 18:04:53 +02:00
parent af9bfbca22
commit 8f4a6f19f7
3 changed files with 52 additions and 86 deletions

View File

@ -58,19 +58,16 @@ DriverHolder::Switch(GraphDriver* aDriver)
mDriver = aDriver;
}
SystemClockDriver::SystemClockDriver(MediaStreamGraphImpl* aGraphImpl)
: GraphDriver(aGraphImpl),
mInitialTimeStamp(TimeStamp::Now()),
mLastTimeStamp(TimeStamp::Now()),
mCurrentTimeStamp(TimeStamp::Now())
{}
ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
: GraphDriver(aGraphImpl)
{ }
SystemClockDriver::~SystemClockDriver()
ThreadedDriver::~ThreadedDriver()
{ }
class MediaStreamGraphInitThreadRunnable : public nsRunnable {
public:
explicit MediaStreamGraphInitThreadRunnable(GraphDriver* aDriver)
explicit MediaStreamGraphInitThreadRunnable(ThreadedDriver* aDriver)
: mDriver(aDriver)
{
}
@ -82,24 +79,24 @@ public:
return NS_OK;
}
private:
GraphDriver* mDriver;
ThreadedDriver* mDriver;
};
void
SystemClockDriver::Start()
ThreadedDriver::Start()
{
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
}
void
SystemClockDriver::Dispatch(nsIRunnable* aEvent)
ThreadedDriver::Dispatch(nsIRunnable* aEvent)
{
mThread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
}
void
SystemClockDriver::Stop()
ThreadedDriver::Stop()
{
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
// mGraph's thread is not running so it's OK to do whatever here
@ -111,8 +108,18 @@ SystemClockDriver::Stop()
}
}
SystemClockDriver::SystemClockDriver(MediaStreamGraphImpl* aGraphImpl)
: ThreadedDriver(aGraphImpl),
mInitialTimeStamp(TimeStamp::Now()),
mLastTimeStamp(TimeStamp::Now()),
mCurrentTimeStamp(TimeStamp::Now())
{}
SystemClockDriver::~SystemClockDriver()
{ }
void
SystemClockDriver::RunThread()
ThreadedDriver::RunThread()
{
AutoProfilerUnregisterThread autoUnregister;
nsTArray<MessageBlock> messageQueue;
@ -216,7 +223,7 @@ SystemClockDriver::WakeUp()
}
OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice)
: GraphDriver(aGraphImpl),
: ThreadedDriver(aGraphImpl),
mSlice(aSlice)
{
@ -225,63 +232,6 @@ OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTi
OfflineClockDriver::~OfflineClockDriver()
{ }
void
OfflineClockDriver::Start()
{
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
}
void
OfflineClockDriver::Stop()
{
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
// mGraph's thread is not running so it's OK to do whatever here
STREAM_LOG(PR_LOG_DEBUG, ("Stopping threads for MediaStreamGraph %p", this));
if (mThread) {
mThread->Shutdown();
mThread = nullptr;
}
}
void
OfflineClockDriver::Dispatch(nsIRunnable* aEvent)
{
mThread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
}
void
OfflineClockDriver::RunThread()
{
AutoProfilerUnregisterThread autoUnregister;
nsTArray<MessageBlock> messageQueue;
{
MonitorAutoLock lock(mMonitor);
messageQueue.SwapElements(mGraphImpl->MessageQueue());
}
NS_ASSERTION(!messageQueue.IsEmpty(),
"Shouldn't have started a graph with empty message queue!");
bool stillProcessing = true;
while(stillProcessing) {
GraphTime prevCurrentTime, nextCurrentTime;
GetIntervalForIteration(prevCurrentTime, nextCurrentTime);
GraphTime nextStateComputedTime =
mGraphImpl->RoundUpToNextAudioBlock(
IterationEnd() + mGraphImpl->MillisecondsToMediaTime(AUDIO_TARGET_MS));
stillProcessing = mGraphImpl->OneIteration(prevCurrentTime,
nextCurrentTime,
StateComputedTime(),
nextStateComputedTime,
messageQueue);
}
}
void
OfflineClockDriver::GetIntervalForIteration(GraphTime& aFrom, GraphTime& aTo)
{

View File

@ -9,7 +9,7 @@
namespace mozilla {
/**
* We make the initial IterationEnd() nonzero so that zero times can have
* We make the initial graph time nonzero so that zero times can have
* special meaning if necessary.
*/
static const int32_t INITIAL_CURRENT_TIME = 1;
@ -62,8 +62,13 @@ public:
/* Dispatch an event to the graph's thread. */
virtual void Dispatch(nsIRunnable* aEvent) = 0;
/**
* If we are running a real time graph, get the current time stamp to schedule
* video frames. This has to be reimplemented by real time drivers.
*/
virtual TimeStamp GetCurrentTimeStamp() {
MOZ_ASSERT(false, "This clock does not support getting the current time stamp.");
return TimeStamp();
}
bool IsWaiting() {
@ -87,6 +92,11 @@ public:
return mStateComputedTime;
}
/**
* Whenever the graph has computed the time until it has all state
* (mStateComputedState), it calls this to indicate the new time until which
* we have computed state.
*/
void UpdateStateComputedTime(GraphTime aStateComputedTime) {
MOZ_ASSERT(aStateComputedTime > mIterationEnd);
@ -194,19 +204,31 @@ protected:
GraphTime mLastSwitchOffset;
};
/**
* This class is a driver that manages its own thread.
*/
class ThreadedDriver : public GraphDriver
{
public:
ThreadedDriver(MediaStreamGraphImpl* aGraphImpl);
virtual ~ThreadedDriver();
virtual void Start() MOZ_OVERRIDE;
virtual void Stop() MOZ_OVERRIDE;
virtual void Dispatch(nsIRunnable* aEvent) MOZ_OVERRIDE;
void RunThread();
private:
nsCOMPtr<nsIThread> mThread;
};
/**
* A SystemClockDriver drives a MediaStreamGraph using a system clock, and waits
* using a monitor, between each iteration.
*/
class SystemClockDriver : public GraphDriver
class SystemClockDriver : public ThreadedDriver
{
public:
SystemClockDriver(MediaStreamGraphImpl* aGraphImpl);
virtual ~SystemClockDriver();
virtual void Start() MOZ_OVERRIDE;
virtual void Stop() MOZ_OVERRIDE;
virtual void Dispatch(nsIRunnable* aEvent) MOZ_OVERRIDE;
virtual void RunThread() MOZ_OVERRIDE;
virtual void GetIntervalForIteration(GraphTime& aFrom,
GraphTime& aTo) MOZ_OVERRIDE;
virtual GraphTime GetCurrentTime() MOZ_OVERRIDE;
@ -219,22 +241,17 @@ private:
TimeStamp mInitialTimeStamp;
TimeStamp mLastTimeStamp;
TimeStamp mCurrentTimeStamp;
nsCOMPtr<nsIThread> mThread;
};
/**
* An OfflineClockDriver runs the graph as fast as possible, without waiting
* between iteration.
*/
class OfflineClockDriver : public GraphDriver
class OfflineClockDriver : public ThreadedDriver
{
public:
OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
virtual ~OfflineClockDriver();
virtual void Start() MOZ_OVERRIDE;
virtual void Stop() MOZ_OVERRIDE;
virtual void Dispatch(nsIRunnable* aEvent) MOZ_OVERRIDE;
virtual void RunThread() MOZ_OVERRIDE;
virtual void GetIntervalForIteration(GraphTime& aFrom,
GraphTime& aTo) MOZ_OVERRIDE;
virtual GraphTime GetCurrentTime() MOZ_OVERRIDE;
@ -244,7 +261,6 @@ public:
private:
// Time, in GraphTime, for each iteration
GraphTime mSlice;
nsCOMPtr<nsIThread> mThread;
};
}

View File

@ -2657,7 +2657,7 @@ ProcessedMediaStream::DestroyImpl()
}
MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime, TrackRate aSampleRate)
: mDriverHolder(this)
: mDriverHolder(MOZ_THIS_IN_INITIALIZER_LIST())
, mProcessingGraphUpdateIndex(0)
, mPortCount(0)
, mLifecycleState(LIFECYCLE_THREAD_NOT_STARTED)
@ -2798,7 +2798,7 @@ MediaStreamGraphImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
mNeedsMemoryReport = true;
// Wake up the MSG thread.
CurrentDriver()->EnsureImmediateWakeUpLocked();
CurrentDriver()->WakeUp();
if (mLifecycleState >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN) {
// Shutting down, nothing to report.