mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 968016 - Use SharedThreadPool instead of manually managed threads for the media decoding. r=kinetik
This commit is contained in:
parent
490247e674
commit
b162ede7bd
@ -1482,7 +1482,7 @@ void MediaDecoder::UpdatePlaybackOffset(int64_t aOffset)
|
||||
|
||||
bool MediaDecoder::OnStateMachineThread() const
|
||||
{
|
||||
return IsCurrentThread(MediaDecoderStateMachine::GetStateMachineThread());
|
||||
return mDecoderStateMachine->OnStateMachineThread();
|
||||
}
|
||||
|
||||
void MediaDecoder::NotifyAudioAvailableListener()
|
||||
|
@ -28,7 +28,8 @@
|
||||
#include "nsITimer.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "MediaShutdownManager.h"
|
||||
|
||||
#include "SharedThreadPool.h"
|
||||
#include "MediaTaskQueue.h"
|
||||
#include "prenv.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "gfx2DGlue.h"
|
||||
@ -146,17 +147,12 @@ static int64_t DurationToUsecs(TimeDuration aDuration) {
|
||||
return static_cast<int64_t>(aDuration.ToSeconds() * USECS_PER_S);
|
||||
}
|
||||
|
||||
// Owns the global state machine thread and counts of
|
||||
// state machine and decoder threads. There should
|
||||
// only be one instance of this class.
|
||||
class StateMachineTracker
|
||||
{
|
||||
private:
|
||||
StateMachineTracker() :
|
||||
mMonitor("media.statemachinetracker"),
|
||||
mStateMachineCount(0),
|
||||
mDecodeThreadCount(0),
|
||||
mStateMachineThread(nullptr)
|
||||
StateMachineTracker()
|
||||
: mMonitor("media.statemachinetracker")
|
||||
, mStateMachineCount(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StateMachineTracker);
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
@ -165,7 +161,6 @@ private:
|
||||
~StateMachineTracker()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
||||
MOZ_COUNT_DTOR(StateMachineTracker);
|
||||
}
|
||||
|
||||
@ -193,37 +188,6 @@ public:
|
||||
return mStateMachineThread->GetThread();
|
||||
}
|
||||
|
||||
// Requests that a decode thread be created for aStateMachine. The thread
|
||||
// may be created immediately, or after some delay, once a thread becomes
|
||||
// available. The request can be cancelled using CancelCreateDecodeThread().
|
||||
// It's the callers responsibility to not call this more than once for any
|
||||
// given state machine.
|
||||
nsresult RequestCreateDecodeThread(MediaDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Cancels a request made by RequestCreateDecodeThread to create a decode
|
||||
// thread for aStateMachine.
|
||||
nsresult CancelCreateDecodeThread(MediaDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Maximum number of active decode threads allowed. When more
|
||||
// than this number are active the thread creation will fail.
|
||||
static const uint32_t MAX_DECODE_THREADS = 25;
|
||||
|
||||
// Returns the number of active decode threads.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
uint32_t GetDecodeThreadCount();
|
||||
|
||||
// Keep track of the fact that a decode thread was destroyed.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
void NoteDecodeThreadDestroyed();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Returns true if aStateMachine has a pending request for a
|
||||
// decode thread.
|
||||
bool IsQueued(MediaDecoderStateMachine* aStateMachine);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Holds global instance of StateMachineTracker.
|
||||
// Writable on main thread only.
|
||||
@ -238,19 +202,10 @@ private:
|
||||
// main thread only.
|
||||
uint32_t mStateMachineCount;
|
||||
|
||||
// Number of instances of decoder threads that are
|
||||
// currently instantiated. Access only with the
|
||||
// mMonitor lock held. Can be used from any thread.
|
||||
uint32_t mDecodeThreadCount;
|
||||
|
||||
// Global state machine thread. Write on the main thread
|
||||
// only, read from the decoder threads. Synchronized via
|
||||
// the mMonitor.
|
||||
nsRefPtr<StateMachineThread> mStateMachineThread;
|
||||
|
||||
// Queue of state machines waiting for decode threads. Entries at the front
|
||||
// get their threads first.
|
||||
nsDeque mPending;
|
||||
};
|
||||
|
||||
StateMachineTracker* StateMachineTracker::sInstance = nullptr;
|
||||
@ -277,22 +232,6 @@ void StateMachineTracker::EnsureGlobalStateMachine()
|
||||
mStateMachineCount++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool StateMachineTracker::IsQueued(MediaDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
int32_t size = mPending.GetSize();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
MediaDecoderStateMachine* m =
|
||||
static_cast<MediaDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
@ -301,81 +240,16 @@ void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
mStateMachineCount--;
|
||||
if (mStateMachineCount == 0) {
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
|
||||
NS_ASSERTION(mPending.GetSize() == 0, "Shouldn't all requests be handled by now?");
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
mStateMachineThread->Shutdown();
|
||||
mStateMachineThread = nullptr;
|
||||
NS_ASSERTION(mDecodeThreadCount == 0, "Decode thread count must be zero.");
|
||||
sInstance = nullptr;
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachineTracker::NoteDecodeThreadDestroyed()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
--mDecodeThreadCount;
|
||||
while (mDecodeThreadCount < MAX_DECODE_THREADS && mPending.GetSize() > 0) {
|
||||
MediaDecoderStateMachine* m =
|
||||
static_cast<MediaDecoderStateMachine*>(mPending.PopFront());
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = m->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t StateMachineTracker::GetDecodeThreadCount()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
return mDecodeThreadCount;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::CancelCreateDecodeThread(MediaDecoderStateMachine* aStateMachine) {
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
int32_t size = mPending.GetSize();
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
void* m = static_cast<MediaDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
mPending.RemoveObjectAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!IsQueued(aStateMachine), "State machine should no longer have queued request.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::RequestCreateDecodeThread(MediaDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
NS_ENSURE_STATE(aStateMachine);
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
if (mPending.GetSize() > 0 || mDecodeThreadCount + 1 >= MAX_DECODE_THREADS) {
|
||||
// If there's already state machines in the queue, or we've exceeded the
|
||||
// limit, append the state machine to the queue of state machines waiting
|
||||
// for a decode thread. This ensures state machines already waiting get
|
||||
// their threads first.
|
||||
mPending.Push(aStateMachine);
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = aStateMachine->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
NS_ASSERTION(mDecodeThreadCount <= MAX_DECODE_THREADS,
|
||||
"Should keep to thread limit!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
MediaDecoderReader* aReader,
|
||||
bool aRealTime) :
|
||||
@ -405,7 +279,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mAudioCompleted(false),
|
||||
mGotDurationFromMetaData(false),
|
||||
mStopDecodeThread(true),
|
||||
mDecodeThreadIdle(false),
|
||||
mDispatchedEventToDecode(false),
|
||||
mStopAudioThread(true),
|
||||
mQuickBuffering(false),
|
||||
mIsRunning(false),
|
||||
@ -415,7 +289,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mRealTime(aRealTime),
|
||||
mDidThrottleAudioDecoding(false),
|
||||
mDidThrottleVideoDecoding(false),
|
||||
mRequestedNewDecodeThread(false),
|
||||
mEventManager(aDecoder),
|
||||
mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED)
|
||||
{
|
||||
@ -463,12 +336,15 @@ MediaDecoderStateMachine::~MediaDecoderStateMachine()
|
||||
MOZ_COUNT_DTOR(MediaDecoderStateMachine);
|
||||
NS_ASSERTION(!mPendingWakeDecoder.get(),
|
||||
"WakeDecoder should have been revoked already");
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not have a pending request for a new decode thread");
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Should not have (or flagged) a pending request for a new decode thread");
|
||||
if (mTimer)
|
||||
|
||||
if (mDecodeTaskQueue) {
|
||||
mDecodeTaskQueue->Shutdown();
|
||||
mDecodeTaskQueue = nullptr;
|
||||
}
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
mTimer = nullptr;
|
||||
mReader = nullptr;
|
||||
|
||||
@ -508,51 +384,45 @@ int64_t MediaDecoderStateMachine::GetDecodedAudioDuration() {
|
||||
|
||||
void MediaDecoderStateMachine::DecodeThreadRun()
|
||||
{
|
||||
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
||||
mReader->OnDecodeThreadStart();
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
if (mState == DECODER_STATE_DECODING_METADATA &&
|
||||
NS_FAILED(DecodeMetadata())) {
|
||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||
"Should be in shutdown state if metadata loading fails.");
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Decode metadata failed, shutting down decode thread"));
|
||||
}
|
||||
|
||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||
mState != DECODER_STATE_COMPLETED &&
|
||||
mState != DECODER_STATE_DORMANT &&
|
||||
!mStopDecodeThread)
|
||||
{
|
||||
if (mState == DECODER_STATE_DECODING || mState == DECODER_STATE_BUFFERING) {
|
||||
DecodeLoop();
|
||||
} else if (mState == DECODER_STATE_SEEKING) {
|
||||
DecodeSeek();
|
||||
} else if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||
if (NS_FAILED(DecodeMetadata())) {
|
||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||
"Should be in shutdown state if metadata loading fails.");
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Decode metadata failed, shutting down decode thread"));
|
||||
}
|
||||
} else if (mState == DECODER_STATE_WAIT_FOR_RESOURCES) {
|
||||
mDecoder->GetReentrantMonitor().Wait();
|
||||
|
||||
if (!mReader->IsWaitingMediaResources()) {
|
||||
// change state to DECODER_STATE_WAIT_FOR_RESOURCES
|
||||
StartDecodeMetadata();
|
||||
}
|
||||
} else if (mState == DECODER_STATE_DORMANT) {
|
||||
mDecoder->GetReentrantMonitor().Wait();
|
||||
}
|
||||
}
|
||||
|
||||
mDecodeThreadIdle = true;
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Decode thread finished", mDecoder.get()));
|
||||
if (mState == DECODER_STATE_DECODING_METADATA &&
|
||||
NS_FAILED(DecodeMetadata())) {
|
||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||
"Should be in shutdown state if metadata loading fails.");
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Decode metadata failed, shutting down decode thread"));
|
||||
}
|
||||
|
||||
mReader->OnDecodeThreadFinish();
|
||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||
mState != DECODER_STATE_COMPLETED &&
|
||||
mState != DECODER_STATE_DORMANT &&
|
||||
!mStopDecodeThread)
|
||||
{
|
||||
if (mState == DECODER_STATE_DECODING || mState == DECODER_STATE_BUFFERING) {
|
||||
DecodeLoop();
|
||||
} else if (mState == DECODER_STATE_SEEKING) {
|
||||
DecodeSeek();
|
||||
} else if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||
if (NS_FAILED(DecodeMetadata())) {
|
||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||
"Should be in shutdown state if metadata loading fails.");
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("Decode metadata failed, shutting down decode thread"));
|
||||
}
|
||||
} else if (mState == DECODER_STATE_WAIT_FOR_RESOURCES) {
|
||||
mDecoder->GetReentrantMonitor().Wait();
|
||||
|
||||
if (!mReader->IsWaitingMediaResources()) {
|
||||
// change state to DECODER_STATE_WAIT_FOR_RESOURCES
|
||||
StartDecodeMetadata();
|
||||
}
|
||||
} else if (mState == DECODER_STATE_DORMANT) {
|
||||
mDecoder->GetReentrantMonitor().Wait();
|
||||
}
|
||||
}
|
||||
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Decode thread finished", mDecoder.get()));
|
||||
mDispatchedEventToDecode = false;
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio,
|
||||
@ -1312,10 +1182,21 @@ uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset,
|
||||
|
||||
nsresult MediaDecoderStateMachine::Init(MediaDecoderStateMachine* aCloneDonor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<SharedThreadPool> decodePool(
|
||||
SharedThreadPool::Get(NS_LITERAL_CSTRING("Media Decode"),
|
||||
Preferences::GetUint("media.num-decode-threads", 25)));
|
||||
NS_ENSURE_TRUE(decodePool, NS_ERROR_FAILURE);
|
||||
|
||||
mDecodeTaskQueue = new MediaTaskQueue(decodePool.forget());
|
||||
NS_ENSURE_TRUE(mDecodeTaskQueue, NS_ERROR_FAILURE);
|
||||
|
||||
MediaDecoderReader* cloneReader = nullptr;
|
||||
if (aCloneDonor) {
|
||||
cloneReader = static_cast<MediaDecoderStateMachine*>(aCloneDonor)->mReader;
|
||||
}
|
||||
|
||||
return mReader->Init(cloneReader);
|
||||
}
|
||||
|
||||
@ -1706,30 +1587,8 @@ void MediaDecoderStateMachine::StopDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
AssertCurrentThreadInMonitor();
|
||||
if (mRequestedNewDecodeThread) {
|
||||
// We've requested that the decode be created, but it hasn't been yet.
|
||||
// Cancel that request.
|
||||
NS_ASSERTION(!mDecodeThread,
|
||||
"Shouldn't have a decode thread until after request processed");
|
||||
StateMachineTracker::Instance().CancelCreateDecodeThread(this);
|
||||
mRequestedNewDecodeThread = false;
|
||||
}
|
||||
mStopDecodeThread = true;
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
if (mDecodeThread) {
|
||||
DECODER_LOG(PR_LOG_DEBUG, ("%p Shutdown decode thread", mDecoder.get()));
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
mDecodeThread->Shutdown();
|
||||
StateMachineTracker::Instance().NoteDecodeThreadDestroyed();
|
||||
}
|
||||
mDecodeThread = nullptr;
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Any pending requests for decode threads must be canceled and unflagged");
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Any pending requests for decode threads must be canceled");
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::StopAudioThread()
|
||||
@ -1768,63 +1627,15 @@ MediaDecoderStateMachine::ScheduleDecodeThread()
|
||||
if (mState >= DECODER_STATE_COMPLETED) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (mDecodeThread) {
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Shouldn't have requested new decode thread when we have a decode thread");
|
||||
// We already have a decode thread...
|
||||
if (mDecodeThreadIdle) {
|
||||
// ... and it's not been shutdown yet, wake it up.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
return NS_OK;
|
||||
} else if (!mRequestedNewDecodeThread) {
|
||||
// We don't already have a decode thread, request a new one.
|
||||
mRequestedNewDecodeThread = true;
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
StateMachineTracker::Instance().RequestCreateDecodeThread(this);
|
||||
if (!mDispatchedEventToDecode) {
|
||||
nsresult rv = mDecodeTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeThreadRun));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mDispatchedEventToDecode = true;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoderStateMachine::StartDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(StateMachineTracker::Instance().GetDecodeThreadCount() <
|
||||
StateMachineTracker::MAX_DECODE_THREADS,
|
||||
"Should not have reached decode thread limit");
|
||||
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not already have a pending request for a new decode thread.");
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
NS_ASSERTION(!mDecodeThread, "Should not have decode thread yet");
|
||||
NS_ASSERTION(mRequestedNewDecodeThread, "Should have requested this...");
|
||||
|
||||
mRequestedNewDecodeThread = false;
|
||||
|
||||
nsresult rv = NS_NewNamedThread("Media Decode",
|
||||
getter_AddRefs(mDecodeThread),
|
||||
nullptr,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::DecodeError);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoderStateMachine::StartAudioThread()
|
||||
{
|
||||
@ -2206,13 +2017,17 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
return NS_OK;
|
||||
}
|
||||
StopDecodeThread();
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
// Wait for the thread decoding to exit.
|
||||
mDecodeTaskQueue->Shutdown();
|
||||
mReader->ReleaseMediaResources();
|
||||
}
|
||||
// Now that those threads are stopped, there's no possibility of
|
||||
// mPendingWakeDecoder being needed again. Revoke it.
|
||||
mPendingWakeDecoder = nullptr;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
mReader->ReleaseMediaResources();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||
"How did we escape from the shutdown state?");
|
||||
// We must daisy-chain these events to destroy the decoder. We must
|
||||
@ -2903,9 +2718,14 @@ nsresult MediaDecoderStateMachine::ScheduleStateMachine(int64_t aUsecs) {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::OnDecodeThread() const
|
||||
{
|
||||
return mDecodeTaskQueue->IsCurrentThreadIn();
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::OnStateMachineThread() const
|
||||
{
|
||||
return IsCurrentThread(GetStateMachineThread());
|
||||
return IsCurrentThread(GetStateMachineThread());
|
||||
}
|
||||
|
||||
nsIThread* MediaDecoderStateMachine::GetStateMachineThread()
|
||||
|
@ -91,6 +91,8 @@ namespace mozilla {
|
||||
|
||||
class AudioSegment;
|
||||
class VideoSegment;
|
||||
class MediaTaskQueue;
|
||||
class SharedThreadPool;
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with MediaDecoderStateMachine::GetCurrentTime
|
||||
@ -176,9 +178,7 @@ public:
|
||||
|
||||
// Functions used by assertions to ensure we're calling things
|
||||
// on the appropriate threads.
|
||||
bool OnDecodeThread() const {
|
||||
return IsCurrentThread(mDecodeThread);
|
||||
}
|
||||
bool OnDecodeThread() const;
|
||||
bool OnStateMachineThread() const;
|
||||
bool OnAudioThread() const {
|
||||
return IsCurrentThread(mAudioThread);
|
||||
@ -314,12 +314,6 @@ public:
|
||||
// earlier, in which case the request is discarded.
|
||||
nsresult ScheduleStateMachine(int64_t aUsecs = 0);
|
||||
|
||||
// Creates and starts a new decode thread. Don't call this directly,
|
||||
// request a new decode thread by calling
|
||||
// StateMachineTracker::RequestCreateDecodeThread().
|
||||
// The decoder monitor must not be held. Called on the state machine thread.
|
||||
nsresult StartDecodeThread();
|
||||
|
||||
// Timer function to implement ScheduleStateMachine(aUsecs).
|
||||
void TimeoutExpired();
|
||||
|
||||
@ -617,8 +611,10 @@ private:
|
||||
// The "audio push thread".
|
||||
nsCOMPtr<nsIThread> mAudioThread;
|
||||
|
||||
// Thread for decoding video in background. The "decode thread".
|
||||
nsCOMPtr<nsIThread> mDecodeThread;
|
||||
// The task queue in which we run decode tasks. This is referred to as
|
||||
// the "decode thread", though in practise tasks can run on a different
|
||||
// thread every time they're called.
|
||||
RefPtr<MediaTaskQueue> mDecodeTaskQueue;
|
||||
|
||||
// Timer to call the state machine Run() method. Used by
|
||||
// ScheduleStateMachine(). Access protected by decoder monitor.
|
||||
@ -780,12 +776,10 @@ private:
|
||||
// and decode threads. Syncrhonised by decoder monitor.
|
||||
bool mStopDecodeThread;
|
||||
|
||||
// True when the decode thread run function has finished, but the thread
|
||||
// has not necessarily been shut down yet. This can happen if we switch
|
||||
// from COMPLETED state to SEEKING before the state machine has a chance
|
||||
// to run in the COMPLETED state and shutdown the decode thread.
|
||||
// Synchronised by the decoder monitor.
|
||||
bool mDecodeThreadIdle;
|
||||
// True if we've dispatched an event to the decode task queue to call
|
||||
// DecodeThreadRun(). We use this flag to prevent us from dispatching
|
||||
// unneccessary runnables, since the decode thread runs in a loop.
|
||||
bool mDispatchedEventToDecode;
|
||||
|
||||
// False while audio thread should be running. Accessed state machine
|
||||
// and audio threads. Syncrhonised by decoder monitor.
|
||||
@ -827,10 +821,6 @@ private:
|
||||
bool mDidThrottleAudioDecoding;
|
||||
bool mDidThrottleVideoDecoding;
|
||||
|
||||
// True if we've requested a new decode thread, but it has not yet been
|
||||
// created. Synchronized by the decoder monitor.
|
||||
bool mRequestedNewDecodeThread;
|
||||
|
||||
// Manager for queuing and dispatching MozAudioAvailable events. The
|
||||
// event manager is accessed from the state machine and audio threads,
|
||||
// and takes care of synchronizing access to its internal queue.
|
||||
|
@ -126,6 +126,13 @@ MediaTaskQueue::Runner::Run()
|
||||
// in this task queue.
|
||||
event->Run();
|
||||
|
||||
// Drop the reference to event. The event will hold a reference to the
|
||||
// object it's calling, and we don't want to keep it alive, it may be
|
||||
// making assumptions what holds references to it. This is especially
|
||||
// the case if the object is waiting for us to shutdown, so that it
|
||||
// can shutdown (like in the MediaDecoderStateMachine's SHUTDOWN case).
|
||||
event = nullptr;
|
||||
|
||||
{
|
||||
MonitorAutoLock mon(mQueue->mQueueMonitor);
|
||||
if (mQueue->mTasks.size() == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user