Files
palemoon27/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
T
roytam1 d1af43433c import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1187817. Part 1 - Move Set{Volume,PlaybackRate,PreservesPitch} to the audio thread. r=kinetik. (a234a7080)
- Bug 1187817. Part 2 - remove unused code. r=kinetik. (836c52a19)
- Bug 1187763. Part 1 - move while loop out of WaitingForAudioToPlay(). r=kinetik. (a80d70f87)
- Bug 1187763. Part 2 - extract some code of AudioLoop() into its own function. r=kinetik. (275b8bfb6)
- Bug 1187763. Part 3 - refactor AudioSink::AudioLoop into a series of events. r=kinetik (7eb3f506f)
- Bug 1187817. Part 3 - move SetPlaying to the audio thread. r=kinetik. (0fef85968)
- Bug 1187817. Part 4 - move some code in Shutdown to the audio thread. r=kinetik. (8c73fbe6d)
- Bug 1187817. Part 5 - assert some code in the audio thread and don't enter the monitor. r=kinetik. (64de4616f)
- move include (f842b4b1e)
- Bug 1163486 - Update test to use new MP4Demuxer. r=bholley (b853be477)
- Bug 1190496 - Namespace the SharedThreadPool.h include. r=cpearce (196d25d42)
- Bug 1190496 - Hoist SharedThreadPool into xpcom. r=froydnj (3dad8176f)
- Bug 1190492 - Hoist AbstractThread and TaskDispatcher to xpcom. r=froydnj (c3329fa29)
- bug 1166107 documentation of mWaitForInternalDrain thread access r=gerald (f762764b1)
- correct comment (b623b2959)
- revert demuxer check from promise reject to assert like in 1156708 (f540b270c)
- more chekcs back to asserts (7e82a0f99)
- space (733bd85a3)
- Bug 1188220: Allow disabling HW acceleration even when SharedDecoderManager isn't used. r=cpearce (909a86682)
- bug 1161903 ensure pending DrainComplete is not run after Flush() r=cpearce (648cabbb7)
- Bug 1158089 - Fall back to d3d9 DXVA if d3d11 initialization fails. r=cpearce (84b3a8e6d)
2021-08-20 11:12:22 +08:00

198 lines
4.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WMFMediaDataDecoder.h"
#include "VideoUtils.h"
#include "WMFUtils.h"
#include "nsTArray.h"
#include "mozilla/Logging.h"
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
namespace mozilla {
WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mMFTManager(aMFTManager)
, mMonitor("WMFMediaDataDecoder")
, mIsFlushing(false)
, mIsShutDown(false)
{
}
WMFMediaDataDecoder::~WMFMediaDataDecoder()
{
}
nsresult
WMFMediaDataDecoder::Init()
{
MOZ_ASSERT(!mDecoder);
MOZ_ASSERT(!mIsShutDown);
mDecoder = mMFTManager->Init();
NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
return NS_OK;
}
nsresult
WMFMediaDataDecoder::Shutdown()
{
MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
if (mTaskQueue) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown);
mTaskQueue->Dispatch(runnable.forget());
} else {
ProcessShutdown();
}
mIsShutDown = true;
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessShutdown()
{
if (mMFTManager) {
mMFTManager->Shutdown();
mMFTManager = nullptr;
}
mDecoder = nullptr;
}
// Inserts data into the decoder's pipeline.
nsresult
WMFMediaDataDecoder::Input(MediaRawData* aSample)
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&WMFMediaDataDecoder::ProcessDecode,
nsRefPtr<MediaRawData>(aSample));
mTaskQueue->Dispatch(runnable.forget());
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
{
{
MonitorAutoLock mon(mMonitor);
if (mIsFlushing) {
// Skip sample, to be released by runnable.
return;
}
}
HRESULT hr = mMFTManager->Input(aSample);
if (FAILED(hr)) {
NS_WARNING("MFTManager rejected sample");
mCallback->Error();
return;
}
mLastStreamOffset = aSample->mOffset;
ProcessOutput();
}
void
WMFMediaDataDecoder::ProcessOutput()
{
nsRefPtr<MediaData> output;
HRESULT hr = S_OK;
while (SUCCEEDED(hr = mMFTManager->Output(mLastStreamOffset, output)) &&
output) {
mCallback->Output(output);
}
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
} else if (FAILED(hr)) {
NS_WARNING("WMFMediaDataDecoder failed to output data");
mCallback->Error();
}
}
void
WMFMediaDataDecoder::ProcessFlush()
{
if (mDecoder) {
mDecoder->Flush();
}
MonitorAutoLock mon(mMonitor);
mIsFlushing = false;
mon.NotifyAll();
}
nsresult
WMFMediaDataDecoder::Flush()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessFlush);
MonitorAutoLock mon(mMonitor);
mIsFlushing = true;
mTaskQueue->Dispatch(runnable.forget());
while (mIsFlushing) {
mon.Wait();
}
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessDrain()
{
bool isFlushing;
{
MonitorAutoLock mon(mMonitor);
isFlushing = mIsFlushing;
}
if (!isFlushing && mDecoder) {
// Order the decoder to drain...
if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
NS_WARNING("Failed to send DRAIN command to MFT");
}
// Then extract all available output.
ProcessOutput();
}
mCallback->DrainComplete();
}
nsresult
WMFMediaDataDecoder::Drain()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessDrain);
mTaskQueue->Dispatch(runnable.forget());
return NS_OK;
}
bool
WMFMediaDataDecoder::IsHardwareAccelerated() const {
MOZ_ASSERT(!mIsShutDown);
return mMFTManager && mMFTManager->IsHardwareAccelerated();
}
} // namespace mozilla