зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1155432 - Don't flush WMF PDM task queues. r=jya
This commit is contained in:
Родитель
cea2379e64
Коммит
0eafa8396e
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче