mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Bug 1155432 - Don't flush WMF PDM task queues. r=jya
This commit is contained in:
parent
cea2379e64
commit
0eafa8396e
@ -27,13 +27,14 @@ WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager,
|
|||||||
: mTaskQueue(aTaskQueue)
|
: mTaskQueue(aTaskQueue)
|
||||||
, mCallback(aCallback)
|
, mCallback(aCallback)
|
||||||
, mMFTManager(aMFTManager)
|
, mMFTManager(aMFTManager)
|
||||||
|
, mMonitor("WMFMediaDataDecoder")
|
||||||
|
, mIsDecodeTaskDispatched(false)
|
||||||
|
, mIsFlushing(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(WMFMediaDataDecoder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WMFMediaDataDecoder::~WMFMediaDataDecoder()
|
WMFMediaDataDecoder::~WMFMediaDataDecoder()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(WMFMediaDataDecoder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@ -48,11 +49,13 @@ WMFMediaDataDecoder::Init()
|
|||||||
nsresult
|
nsresult
|
||||||
WMFMediaDataDecoder::Shutdown()
|
WMFMediaDataDecoder::Shutdown()
|
||||||
{
|
{
|
||||||
DebugOnly<nsresult> rv = mTaskQueue->FlushAndDispatch(
|
mTaskQueue->Dispatch(
|
||||||
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
|
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (NS_FAILED(rv)) {
|
{
|
||||||
NS_WARNING("WMFMediaDataDecoder::Shutdown() dispatch of task failed!");
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
// The MP4Reader should have flushed before calling Shutdown().
|
||||||
|
MOZ_ASSERT(!mIsDecodeTaskDispatched);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -61,36 +64,73 @@ WMFMediaDataDecoder::Shutdown()
|
|||||||
void
|
void
|
||||||
WMFMediaDataDecoder::ProcessShutdown()
|
WMFMediaDataDecoder::ProcessShutdown()
|
||||||
{
|
{
|
||||||
mMFTManager->Shutdown();
|
if (mMFTManager) {
|
||||||
mMFTManager = nullptr;
|
mMFTManager->Shutdown();
|
||||||
|
mMFTManager = nullptr;
|
||||||
|
}
|
||||||
mDecoder = nullptr;
|
mDecoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WMFMediaDataDecoder::EnsureDecodeTaskDispatched()
|
||||||
|
{
|
||||||
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
if (!mIsDecodeTaskDispatched) {
|
||||||
|
mTaskQueue->Dispatch(
|
||||||
|
NS_NewRunnableMethod(this,
|
||||||
|
&WMFMediaDataDecoder::Decode));
|
||||||
|
mIsDecodeTaskDispatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Inserts data into the decoder's pipeline.
|
// Inserts data into the decoder's pipeline.
|
||||||
nsresult
|
nsresult
|
||||||
WMFMediaDataDecoder::Input(MediaRawData* aSample)
|
WMFMediaDataDecoder::Input(MediaRawData* aSample)
|
||||||
{
|
{
|
||||||
mTaskQueue->Dispatch(
|
MonitorAutoLock mon(mMonitor);
|
||||||
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
|
mInput.push(aSample);
|
||||||
this,
|
EnsureDecodeTaskDispatched();
|
||||||
&WMFMediaDataDecoder::ProcessDecode,
|
|
||||||
nsRefPtr<MediaRawData>(aSample)));
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
|
WMFMediaDataDecoder::Decode()
|
||||||
{
|
{
|
||||||
HRESULT hr = mMFTManager->Input(aSample);
|
while (true) {
|
||||||
if (FAILED(hr)) {
|
nsRefPtr<MediaRawData> input;
|
||||||
NS_WARNING("MFTManager rejected sample");
|
{
|
||||||
mCallback->Error();
|
MonitorAutoLock mon(mMonitor);
|
||||||
return;
|
MOZ_ASSERT(mIsDecodeTaskDispatched);
|
||||||
|
if (mInput.empty()) {
|
||||||
|
if (mIsFlushing) {
|
||||||
|
if (mDecoder) {
|
||||||
|
mDecoder->Flush();
|
||||||
|
}
|
||||||
|
mIsFlushing = false;
|
||||||
|
}
|
||||||
|
mIsDecodeTaskDispatched = false;
|
||||||
|
mon.NotifyAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input = mInput.front();
|
||||||
|
mInput.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = mMFTManager->Input(input);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
NS_WARNING("MFTManager rejected sample");
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
PurgeInputQueue();
|
||||||
|
}
|
||||||
|
mCallback->Error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastStreamOffset = input->mOffset;
|
||||||
|
|
||||||
|
ProcessOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastStreamOffset = aSample->mOffset;
|
|
||||||
|
|
||||||
ProcessOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -108,24 +148,33 @@ WMFMediaDataDecoder::ProcessOutput()
|
|||||||
}
|
}
|
||||||
} else if (FAILED(hr)) {
|
} else if (FAILED(hr)) {
|
||||||
NS_WARNING("WMFMediaDataDecoder failed to output data");
|
NS_WARNING("WMFMediaDataDecoder failed to output data");
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
PurgeInputQueue();
|
||||||
|
}
|
||||||
mCallback->Error();
|
mCallback->Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WMFMediaDataDecoder::PurgeInputQueue()
|
||||||
|
{
|
||||||
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
while (!mInput.empty()) {
|
||||||
|
mInput.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
WMFMediaDataDecoder::Flush()
|
WMFMediaDataDecoder::Flush()
|
||||||
{
|
{
|
||||||
// Flush the input task queue. This cancels all pending Decode() calls.
|
MonitorAutoLock mon(mMonitor);
|
||||||
// Note this blocks until the task queue finishes its current job, if
|
PurgeInputQueue();
|
||||||
// it's executing at all. Note the MP4Reader ignores all output while
|
mIsFlushing = true;
|
||||||
// flushing.
|
EnsureDecodeTaskDispatched();
|
||||||
mTaskQueue->Flush();
|
while (mIsDecodeTaskDispatched || mIsFlushing) {
|
||||||
|
mon.Wait();
|
||||||
// Order the MFT to flush; drop all internal data.
|
}
|
||||||
NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
|
|
||||||
HRESULT hr = mDecoder->Flush();
|
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +74,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Called on the task queue. Inserts the sample into the decoder, and
|
void Decode();
|
||||||
// extracts output if available.
|
void EnsureDecodeTaskDispatched();
|
||||||
void ProcessDecode(MediaRawData* aSample);
|
void PurgeInputQueue();
|
||||||
|
|
||||||
// Called on the task queue. Extracts output if available, and delivers
|
// Called on the task queue. Extracts output if available, and delivers
|
||||||
// it to the reader. Called after ProcessDecode() and ProcessDrain().
|
// it to the reader. Called after ProcessDecode() and ProcessDrain().
|
||||||
@ -97,6 +97,11 @@ private:
|
|||||||
// The last offset into the media resource that was passed into Input().
|
// The last offset into the media resource that was passed into Input().
|
||||||
// This is used to approximate the decoder's position in the media resource.
|
// This is used to approximate the decoder's position in the media resource.
|
||||||
int64_t mLastStreamOffset;
|
int64_t mLastStreamOffset;
|
||||||
|
|
||||||
|
Monitor mMonitor;
|
||||||
|
std::queue<nsRefPtr<MediaRawData>> mInput;
|
||||||
|
bool mIsDecodeTaskDispatched;
|
||||||
|
bool mIsFlushing;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
Loading…
Reference in New Issue
Block a user