Files
palemoon27/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp
T
trav90 8a3f415c23 Fix Windows build bustage
Followup to #954
2018-07-25 06:57:43 +08:00

208 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 "prlog.h"
#ifdef PR_LOGGING
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#define LOG(...)
#endif
namespace mozilla {
WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager,
FlushableMediaTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mMFTManager(aMFTManager)
, mMonitor("WMFMediaDataDecoder")
, mIsDecodeTaskDispatched(false)
, mIsFlushing(false)
{
}
WMFMediaDataDecoder::~WMFMediaDataDecoder()
{
}
nsresult
WMFMediaDataDecoder::Init()
{
mDecoder = mMFTManager->Init();
NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
return NS_OK;
}
nsresult
WMFMediaDataDecoder::Shutdown()
{
mTaskQueue->Dispatch(
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
#ifdef DEBUG
{
MonitorAutoLock mon(mMonitor);
// The MP4Reader should have flushed before calling Shutdown().
MOZ_ASSERT(!mIsDecodeTaskDispatched);
}
#endif
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessShutdown()
{
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)
{
MonitorAutoLock mon(mMonitor);
mInput.push(aSample);
EnsureDecodeTaskDispatched();
return NS_OK;
}
void
WMFMediaDataDecoder::Decode()
{
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();
continue; // complete flush if flushing
}
mLastStreamOffset = input->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");
{
MonitorAutoLock mon(mMonitor);
PurgeInputQueue();
}
mCallback->Error();
}
}
void
WMFMediaDataDecoder::PurgeInputQueue()
{
mMonitor.AssertCurrentThreadOwns();
while (!mInput.empty()) {
mInput.pop();
}
}
nsresult
WMFMediaDataDecoder::Flush()
{
MonitorAutoLock mon(mMonitor);
PurgeInputQueue();
mIsFlushing = true;
EnsureDecodeTaskDispatched();
while (mIsDecodeTaskDispatched || mIsFlushing) {
mon.Wait();
}
return NS_OK;
}
void
WMFMediaDataDecoder::ProcessDrain()
{
if (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()
{
mTaskQueue->Dispatch(NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessDrain));
return NS_OK;
}
bool
WMFMediaDataDecoder::IsHardwareAccelerated() const {
return mMFTManager && mMFTManager->IsHardwareAccelerated();
}
} // namespace mozilla