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; mDriver = aDriver;
} }
SystemClockDriver::SystemClockDriver(MediaStreamGraphImpl* aGraphImpl) ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
: GraphDriver(aGraphImpl), : GraphDriver(aGraphImpl)
mInitialTimeStamp(TimeStamp::Now()), { }
mLastTimeStamp(TimeStamp::Now()),
mCurrentTimeStamp(TimeStamp::Now())
{}
SystemClockDriver::~SystemClockDriver() ThreadedDriver::~ThreadedDriver()
{ } { }
class MediaStreamGraphInitThreadRunnable : public nsRunnable { class MediaStreamGraphInitThreadRunnable : public nsRunnable {
public: public:
explicit MediaStreamGraphInitThreadRunnable(GraphDriver* aDriver) explicit MediaStreamGraphInitThreadRunnable(ThreadedDriver* aDriver)
: mDriver(aDriver) : mDriver(aDriver)
{ {
} }
@ -82,24 +79,24 @@ public:
return NS_OK; return NS_OK;
} }
private: private:
GraphDriver* mDriver; ThreadedDriver* mDriver;
}; };
void void
SystemClockDriver::Start() ThreadedDriver::Start()
{ {
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this); nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event); NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
} }
void void
SystemClockDriver::Dispatch(nsIRunnable* aEvent) ThreadedDriver::Dispatch(nsIRunnable* aEvent)
{ {
mThread->Dispatch(aEvent, NS_DISPATCH_NORMAL); mThread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
} }
void void
SystemClockDriver::Stop() ThreadedDriver::Stop()
{ {
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread"); NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
// mGraph's thread is not running so it's OK to do whatever here // 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 void
SystemClockDriver::RunThread() ThreadedDriver::RunThread()
{ {
AutoProfilerUnregisterThread autoUnregister; AutoProfilerUnregisterThread autoUnregister;
nsTArray<MessageBlock> messageQueue; nsTArray<MessageBlock> messageQueue;
@ -216,7 +223,7 @@ SystemClockDriver::WakeUp()
} }
OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice) OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice)
: GraphDriver(aGraphImpl), : ThreadedDriver(aGraphImpl),
mSlice(aSlice) mSlice(aSlice)
{ {
@ -225,63 +232,6 @@ OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTi
OfflineClockDriver::~OfflineClockDriver() 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 void
OfflineClockDriver::GetIntervalForIteration(GraphTime& aFrom, GraphTime& aTo) OfflineClockDriver::GetIntervalForIteration(GraphTime& aFrom, GraphTime& aTo)
{ {

View File

@ -9,7 +9,7 @@
namespace mozilla { 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. * special meaning if necessary.
*/ */
static const int32_t INITIAL_CURRENT_TIME = 1; static const int32_t INITIAL_CURRENT_TIME = 1;
@ -62,8 +62,13 @@ public:
/* Dispatch an event to the graph's thread. */ /* Dispatch an event to the graph's thread. */
virtual void Dispatch(nsIRunnable* aEvent) = 0; 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() { virtual TimeStamp GetCurrentTimeStamp() {
MOZ_ASSERT(false, "This clock does not support getting the current time stamp."); MOZ_ASSERT(false, "This clock does not support getting the current time stamp.");
return TimeStamp();
} }
bool IsWaiting() { bool IsWaiting() {
@ -87,6 +92,11 @@ public:
return mStateComputedTime; 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) { void UpdateStateComputedTime(GraphTime aStateComputedTime) {
MOZ_ASSERT(aStateComputedTime > mIterationEnd); MOZ_ASSERT(aStateComputedTime > mIterationEnd);
@ -194,19 +204,31 @@ protected:
GraphTime mLastSwitchOffset; 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 * A SystemClockDriver drives a MediaStreamGraph using a system clock, and waits
* using a monitor, between each iteration. * using a monitor, between each iteration.
*/ */
class SystemClockDriver : public GraphDriver class SystemClockDriver : public ThreadedDriver
{ {
public: public:
SystemClockDriver(MediaStreamGraphImpl* aGraphImpl); SystemClockDriver(MediaStreamGraphImpl* aGraphImpl);
virtual ~SystemClockDriver(); 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, virtual void GetIntervalForIteration(GraphTime& aFrom,
GraphTime& aTo) MOZ_OVERRIDE; GraphTime& aTo) MOZ_OVERRIDE;
virtual GraphTime GetCurrentTime() MOZ_OVERRIDE; virtual GraphTime GetCurrentTime() MOZ_OVERRIDE;
@ -219,22 +241,17 @@ private:
TimeStamp mInitialTimeStamp; TimeStamp mInitialTimeStamp;
TimeStamp mLastTimeStamp; TimeStamp mLastTimeStamp;
TimeStamp mCurrentTimeStamp; TimeStamp mCurrentTimeStamp;
nsCOMPtr<nsIThread> mThread;
}; };
/** /**
* An OfflineClockDriver runs the graph as fast as possible, without waiting * An OfflineClockDriver runs the graph as fast as possible, without waiting
* between iteration. * between iteration.
*/ */
class OfflineClockDriver : public GraphDriver class OfflineClockDriver : public ThreadedDriver
{ {
public: public:
OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice); OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
virtual ~OfflineClockDriver(); 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, virtual void GetIntervalForIteration(GraphTime& aFrom,
GraphTime& aTo) MOZ_OVERRIDE; GraphTime& aTo) MOZ_OVERRIDE;
virtual GraphTime GetCurrentTime() MOZ_OVERRIDE; virtual GraphTime GetCurrentTime() MOZ_OVERRIDE;
@ -244,7 +261,6 @@ public:
private: private:
// Time, in GraphTime, for each iteration // Time, in GraphTime, for each iteration
GraphTime mSlice; GraphTime mSlice;
nsCOMPtr<nsIThread> mThread;
}; };
} }

View File

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