зеркало из https://github.com/mozilla/pjs.git
Bug 638807 - Data race on nsBuiltinDecoder::mFrameBufferLength; r=chris.double
This commit is contained in:
Родитель
7ccd33f717
Коммит
0a51ba5040
|
@ -82,6 +82,7 @@ nsAudioAvailableEventManager::nsAudioAvailableEventManager(nsBuiltinDecoder* aDe
|
||||||
mDecoder(aDecoder),
|
mDecoder(aDecoder),
|
||||||
mSignalBuffer(new float[mDecoder->GetFrameBufferLength()]),
|
mSignalBuffer(new float[mDecoder->GetFrameBufferLength()]),
|
||||||
mSignalBufferLength(mDecoder->GetFrameBufferLength()),
|
mSignalBufferLength(mDecoder->GetFrameBufferLength()),
|
||||||
|
mNewSignalBufferLength(mSignalBufferLength),
|
||||||
mSignalBufferPosition(0),
|
mSignalBufferPosition(0),
|
||||||
mMonitor("media.audioavailableeventmanager")
|
mMonitor("media.audioavailableeventmanager")
|
||||||
{
|
{
|
||||||
|
@ -119,7 +120,9 @@ void nsAudioAvailableEventManager::QueueWrittenAudioData(SoundDataValue* aAudioD
|
||||||
PRUint32 aAudioDataLength,
|
PRUint32 aAudioDataLength,
|
||||||
PRUint64 aEndTimeSampleOffset)
|
PRUint64 aEndTimeSampleOffset)
|
||||||
{
|
{
|
||||||
PRUint32 currentBufferSize = mDecoder->GetFrameBufferLength();
|
MonitorAutoEnter mon(mMonitor);
|
||||||
|
|
||||||
|
PRUint32 currentBufferSize = mNewSignalBufferLength;
|
||||||
if (currentBufferSize == 0) {
|
if (currentBufferSize == 0) {
|
||||||
NS_WARNING("Decoder framebuffer length not set.");
|
NS_WARNING("Decoder framebuffer length not set.");
|
||||||
return;
|
return;
|
||||||
|
@ -155,8 +158,6 @@ void nsAudioAvailableEventManager::QueueWrittenAudioData(SoundDataValue* aAudioD
|
||||||
audioData += signalBufferTail;
|
audioData += signalBufferTail;
|
||||||
audioDataLength -= signalBufferTail;
|
audioDataLength -= signalBufferTail;
|
||||||
|
|
||||||
MonitorAutoEnter mon(mMonitor);
|
|
||||||
|
|
||||||
if (mPendingEvents.Length() > 0) {
|
if (mPendingEvents.Length() > 0) {
|
||||||
// Check last event timecode to make sure that all queued events
|
// Check last event timecode to make sure that all queued events
|
||||||
// are in non-descending sequence.
|
// are in non-descending sequence.
|
||||||
|
@ -236,3 +237,11 @@ void nsAudioAvailableEventManager::Drain(PRUint64 aEndTime)
|
||||||
|
|
||||||
mSignalBufferPosition = 0;
|
mSignalBufferPosition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsAudioAvailableEventManager::SetSignalBufferLength(PRUint32 aLength)
|
||||||
|
{
|
||||||
|
MonitorAutoEnter mon(mMonitor);
|
||||||
|
|
||||||
|
mNewSignalBufferLength = aLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,10 @@ public:
|
||||||
// Called from the state machine thread.
|
// Called from the state machine thread.
|
||||||
void Drain(PRUint64 aTime);
|
void Drain(PRUint64 aTime);
|
||||||
|
|
||||||
|
// Sets the size of the signal buffer.
|
||||||
|
// Called from the main and the state machine thread.
|
||||||
|
void SetSignalBufferLength(PRUint32 aLength);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The decoder associated with the event manager. The event manager shares
|
// The decoder associated with the event manager. The event manager shares
|
||||||
// the same lifetime as the decoder (the decoder holds a reference to the
|
// the same lifetime as the decoder (the decoder holds a reference to the
|
||||||
|
@ -91,6 +95,9 @@ private:
|
||||||
// The current size of the signal buffer, may change due to DOM calls.
|
// The current size of the signal buffer, may change due to DOM calls.
|
||||||
PRUint32 mSignalBufferLength;
|
PRUint32 mSignalBufferLength;
|
||||||
|
|
||||||
|
// The size of the new signal buffer, may change due to DOM calls.
|
||||||
|
PRUint32 mNewSignalBufferLength;
|
||||||
|
|
||||||
// The position of the first available item in mSignalBuffer
|
// The position of the first available item in mSignalBuffer
|
||||||
PRUint32 mSignalBufferPosition;
|
PRUint32 mSignalBufferPosition;
|
||||||
|
|
||||||
|
@ -98,7 +105,7 @@ private:
|
||||||
// between the state machine and audio threads.
|
// between the state machine and audio threads.
|
||||||
nsTArray< nsCOMPtr<nsIRunnable> > mPendingEvents;
|
nsTArray< nsCOMPtr<nsIRunnable> > mPendingEvents;
|
||||||
|
|
||||||
// Monitor for shared access to mPendingEvents queue.
|
// Monitor for shared access to mPendingEvents queue or buffer length.
|
||||||
Monitor mMonitor;
|
Monitor mMonitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,11 @@ nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
|
||||||
MonitorAutoEnter mon(mMonitor);
|
MonitorAutoEnter mon(mMonitor);
|
||||||
mDecoderStateMachine->SetSeekable(mSeekable);
|
mDecoderStateMachine->SetSeekable(mSeekable);
|
||||||
mDecoderStateMachine->SetDuration(mDuration);
|
mDecoderStateMachine->SetDuration(mDuration);
|
||||||
|
|
||||||
|
if (mFrameBufferLength > 0) {
|
||||||
|
// The valid mFrameBufferLength value was specified earlier
|
||||||
|
mDecoderStateMachine->SetFrameBufferLength(mFrameBufferLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeState(PLAY_STATE_LOADING);
|
ChangeState(PLAY_STATE_LOADING);
|
||||||
|
@ -227,6 +232,18 @@ nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
|
||||||
return StartStateMachineThread();
|
return StartStateMachineThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult nsBuiltinDecoder::RequestFrameBufferLength(PRUint32 aLength)
|
||||||
|
{
|
||||||
|
nsresult res = nsMediaDecoder::RequestFrameBufferLength(aLength);
|
||||||
|
NS_ENSURE_SUCCESS(res,res);
|
||||||
|
|
||||||
|
MonitorAutoEnter mon(mMonitor);
|
||||||
|
if (mDecoderStateMachine) {
|
||||||
|
mDecoderStateMachine->SetFrameBufferLength(aLength);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsBuiltinDecoder::StartStateMachineThread()
|
nsresult nsBuiltinDecoder::StartStateMachineThread()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mDecoderStateMachine,
|
NS_ASSERTION(mDecoderStateMachine,
|
||||||
|
@ -328,16 +345,13 @@ void nsBuiltinDecoder::AudioAvailable(float* aFrameBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||||
PRUint32 aRate,
|
PRUint32 aRate)
|
||||||
PRUint32 aFrameBufferLength)
|
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
if (mShuttingDown) {
|
if (mShuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFrameBufferLength = aFrameBufferLength;
|
|
||||||
|
|
||||||
// Only inform the element of MetadataLoaded if not doing a load() in order
|
// Only inform the element of MetadataLoaded if not doing a load() in order
|
||||||
// to fulfill a seek, otherwise we'll get multiple metadataloaded events.
|
// to fulfill a seek, otherwise we'll get multiple metadataloaded events.
|
||||||
PRBool notifyElement = PR_TRUE;
|
PRBool notifyElement = PR_TRUE;
|
||||||
|
|
|
@ -303,6 +303,10 @@ public:
|
||||||
// with the decode monitor held. Called on the state machine thread and
|
// with the decode monitor held. Called on the state machine thread and
|
||||||
// the main thread.
|
// the main thread.
|
||||||
virtual void StartBuffering() = 0;
|
virtual void StartBuffering() = 0;
|
||||||
|
|
||||||
|
// Sets the current size of the framebuffer used in MozAudioAvailable events.
|
||||||
|
// Called on the state machine thread and the main thread.
|
||||||
|
virtual void SetFrameBufferLength(PRUint32 aLength) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsBuiltinDecoder : public nsMediaDecoder
|
class nsBuiltinDecoder : public nsMediaDecoder
|
||||||
|
@ -446,6 +450,10 @@ class nsBuiltinDecoder : public nsMediaDecoder
|
||||||
return mDecoderStateMachine->NotifyDataArrived(aBuffer, aLength, aOffset);
|
return mDecoderStateMachine->NotifyDataArrived(aBuffer, aLength, aOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the length of the framebuffer used in MozAudioAvailable events.
|
||||||
|
// The new size must be between 512 and 16384.
|
||||||
|
virtual nsresult RequestFrameBufferLength(PRUint32 aLength);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Return the current state. Can be called on any thread. If called from
|
// Return the current state. Can be called on any thread. If called from
|
||||||
// a non-main thread, the decoder monitor must be held.
|
// a non-main thread, the decoder monitor must be held.
|
||||||
|
@ -491,8 +499,7 @@ class nsBuiltinDecoder : public nsMediaDecoder
|
||||||
// Called when the metadata from the media file has been read.
|
// Called when the metadata from the media file has been read.
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
void MetadataLoaded(PRUint32 aChannels,
|
void MetadataLoaded(PRUint32 aChannels,
|
||||||
PRUint32 aRate,
|
PRUint32 aRate);
|
||||||
PRUint32 aFrameBufferLength);
|
|
||||||
|
|
||||||
// Called when the first frame has been loaded.
|
// Called when the first frame has been loaded.
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
|
|
|
@ -154,23 +154,21 @@ private:
|
||||||
nsCOMPtr<nsBuiltinDecoder> mDecoder;
|
nsCOMPtr<nsBuiltinDecoder> mDecoder;
|
||||||
public:
|
public:
|
||||||
nsAudioMetadataEventRunner(nsBuiltinDecoder* aDecoder, PRUint32 aChannels,
|
nsAudioMetadataEventRunner(nsBuiltinDecoder* aDecoder, PRUint32 aChannels,
|
||||||
PRUint32 aRate, PRUint32 aFrameBufferLength) :
|
PRUint32 aRate) :
|
||||||
mDecoder(aDecoder),
|
mDecoder(aDecoder),
|
||||||
mChannels(aChannels),
|
mChannels(aChannels),
|
||||||
mRate(aRate),
|
mRate(aRate)
|
||||||
mFrameBufferLength(aFrameBufferLength)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD Run()
|
NS_IMETHOD Run()
|
||||||
{
|
{
|
||||||
mDecoder->MetadataLoaded(mChannels, mRate, mFrameBufferLength);
|
mDecoder->MetadataLoaded(mChannels, mRate);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRUint32 mChannels;
|
const PRUint32 mChannels;
|
||||||
const PRUint32 mRate;
|
const PRUint32 mRate;
|
||||||
const PRUint32 mFrameBufferLength;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
|
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
|
||||||
|
@ -1031,6 +1029,14 @@ PRInt64 nsBuiltinDecoderStateMachine::GetUndecodedData() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsBuiltinDecoderStateMachine::SetFrameBufferLength(PRUint32 aLength)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aLength >= 512 && aLength <= 16384,
|
||||||
|
"The length must be between 512 and 16384");
|
||||||
|
mDecoder->GetMonitor().AssertCurrentThreadIn();
|
||||||
|
mEventManager.SetSignalBufferLength(aLength);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsBuiltinDecoderStateMachine::Run()
|
nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
||||||
|
@ -1088,15 +1094,17 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
// setting the default framebuffer size for audioavailable events. Also,
|
// setting the default framebuffer size for audioavailable events. Also,
|
||||||
// if there is audio, let the MozAudioAvailable event manager know about
|
// if there is audio, let the MozAudioAvailable event manager know about
|
||||||
// the metadata.
|
// the metadata.
|
||||||
PRUint32 frameBufferLength = mInfo.mAudioChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL;
|
|
||||||
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
|
||||||
new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels,
|
|
||||||
mInfo.mAudioRate, frameBufferLength);
|
|
||||||
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
|
|
||||||
if (HasAudio()) {
|
if (HasAudio()) {
|
||||||
mEventManager.Init(mInfo.mAudioChannels, mInfo.mAudioRate);
|
mEventManager.Init(mInfo.mAudioChannels, mInfo.mAudioRate);
|
||||||
|
// Set the buffer length at the decoder level to be able, to be able
|
||||||
|
// to retrive the value via media element method. The RequestFrameBufferLength
|
||||||
|
// will call the nsBuiltinDecoderStateMachine::SetFrameBufferLength().
|
||||||
|
PRUint32 frameBufferLength = mInfo.mAudioChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL;
|
||||||
mDecoder->RequestFrameBufferLength(frameBufferLength);
|
mDecoder->RequestFrameBufferLength(frameBufferLength);
|
||||||
}
|
}
|
||||||
|
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
||||||
|
new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels, mInfo.mAudioRate);
|
||||||
|
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
if (mState == DECODER_STATE_DECODING_METADATA) {
|
if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||||
LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder));
|
LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder));
|
||||||
|
|
|
@ -247,6 +247,10 @@ public:
|
||||||
return mEndTime;
|
return mEndTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the current frame buffer length for the MozAudioAvailable event.
|
||||||
|
// Accessed on the main and state machine threads.
|
||||||
|
virtual void SetFrameBufferLength(PRUint32 aLength);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Returns PR_TRUE if we'v got less than aAudioMs ms of decoded and playable
|
// Returns PR_TRUE if we'v got less than aAudioMs ms of decoded and playable
|
||||||
|
|
Загрузка…
Ссылка в новой задаче