Bug 1155432 - Don't flush WMF PDM task queues. r=jya

This commit is contained in:
Chris Pearce 2015-04-20 20:03:41 +12:00
Родитель cea2379e64
Коммит 0eafa8396e
2 изменённых файлов: 90 добавлений и 36 удалений

Просмотреть файл

@ -27,13 +27,14 @@ WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager,
: mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mMFTManager(aMFTManager)
, mMonitor("WMFMediaDataDecoder")
, mIsDecodeTaskDispatched(false)
, mIsFlushing(false)
{
MOZ_COUNT_CTOR(WMFMediaDataDecoder);
}
WMFMediaDataDecoder::~WMFMediaDataDecoder()
{
MOZ_COUNT_DTOR(WMFMediaDataDecoder);
}
nsresult
@ -48,11 +49,13 @@ WMFMediaDataDecoder::Init()
nsresult
WMFMediaDataDecoder::Shutdown()
{
DebugOnly<nsresult> rv = mTaskQueue->FlushAndDispatch(
mTaskQueue->Dispatch(
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
#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
return NS_OK;
@ -61,36 +64,73 @@ WMFMediaDataDecoder::Shutdown()
void
WMFMediaDataDecoder::ProcessShutdown()
{
mMFTManager->Shutdown();
mMFTManager = nullptr;
if (mMFTManager) {
mMFTManager->Shutdown();
mMFTManager = 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.
nsresult
WMFMediaDataDecoder::Input(MediaRawData* aSample)
{
mTaskQueue->Dispatch(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&WMFMediaDataDecoder::ProcessDecode,
nsRefPtr<MediaRawData>(aSample)));
MonitorAutoLock mon(mMonitor);
mInput.push(aSample);
EnsureDecodeTaskDispatched();
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
WMFMediaDataDecoder::Decode()
{
HRESULT hr = mMFTManager->Input(aSample);
if (FAILED(hr)) {
NS_WARNING("MFTManager rejected sample");
mCallback->Error();
return;
while (true) {
nsRefPtr<MediaRawData> input;
{
MonitorAutoLock mon(mMonitor);
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
@ -108,24 +148,33 @@ WMFMediaDataDecoder::ProcessOutput()
}
} else if (FAILED(hr)) {
NS_WARNING("WMFMediaDataDecoder failed to output data");
{
MonitorAutoLock mon(mMonitor);
PurgeInputQueue();
}
mCallback->Error();
}
}
void
WMFMediaDataDecoder::PurgeInputQueue()
{
mMonitor.AssertCurrentThreadOwns();
while (!mInput.empty()) {
mInput.pop();
}
}
nsresult
WMFMediaDataDecoder::Flush()
{
// Flush the input task queue. This cancels all pending Decode() calls.
// Note this blocks until the task queue finishes its current job, if
// it's executing at all. Note the MP4Reader ignores all output while
// flushing.
mTaskQueue->Flush();
// 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);
MonitorAutoLock mon(mMonitor);
PurgeInputQueue();
mIsFlushing = true;
EnsureDecodeTaskDispatched();
while (mIsDecodeTaskDispatched || mIsFlushing) {
mon.Wait();
}
return NS_OK;
}

Просмотреть файл

@ -74,9 +74,9 @@ public:
private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available.
void ProcessDecode(MediaRawData* aSample);
void Decode();
void EnsureDecodeTaskDispatched();
void PurgeInputQueue();
// Called on the task queue. Extracts output if available, and delivers
// 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().
// This is used to approximate the decoder's position in the media resource.
int64_t mLastStreamOffset;
Monitor mMonitor;
std::queue<nsRefPtr<MediaRawData>> mInput;
bool mIsDecodeTaskDispatched;
bool mIsFlushing;
};
} // namespace mozilla