зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1123535 - Make MP4Reader and WMFMediaDataDecoder support going dormant. r=kentuckyfriedtakahe
This commit is contained in:
Родитель
6a682696a6
Коммит
df4bec5ff7
|
@ -117,6 +117,9 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
|
|||
, mIsEncrypted(false)
|
||||
, mIndexReady(false)
|
||||
, mDemuxerMonitor("MP4 Demuxer")
|
||||
#if defined(XP_WIN)
|
||||
, mDormantEnabled(Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||
MOZ_COUNT_CTOR(MP4Reader);
|
||||
|
@ -252,15 +255,15 @@ private:
|
|||
#endif
|
||||
|
||||
void MP4Reader::RequestCodecResource() {
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
if(mVideo.mDecoder) {
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
if (mVideo.mDecoder) {
|
||||
mVideo.mDecoder->AllocateMediaResources();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MP4Reader::IsWaitingOnCodecResource() {
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
|
||||
#endif
|
||||
return false;
|
||||
|
@ -446,7 +449,8 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||
mVideo.mCallback = new DecoderCallback(this, kVideo);
|
||||
if (mSharedDecoderManager) {
|
||||
mVideo.mDecoder =
|
||||
mSharedDecoderManager->CreateVideoDecoder(video,
|
||||
mSharedDecoderManager->CreateVideoDecoder(mPlatform,
|
||||
video,
|
||||
mLayersBackendType,
|
||||
mDecoder->GetImageContainer(),
|
||||
mVideo.mTaskQueue,
|
||||
|
@ -1001,15 +1005,20 @@ MP4Reader::GetBuffered(dom::TimeRanges* aBuffered)
|
|||
|
||||
bool MP4Reader::IsDormantNeeded()
|
||||
{
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
return mVideo.mDecoder && mVideo.mDecoder->IsDormantNeeded();
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
return
|
||||
#if defined(XP_WIN)
|
||||
mDormantEnabled &&
|
||||
#endif
|
||||
mVideo.mDecoder &&
|
||||
mVideo.mDecoder->IsDormantNeeded();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void MP4Reader::ReleaseMediaResources()
|
||||
{
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
// Before freeing a video codec, all video buffers needed to be released
|
||||
// even from graphics pipeline.
|
||||
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
|
||||
|
@ -1024,7 +1033,7 @@ void MP4Reader::ReleaseMediaResources()
|
|||
|
||||
void MP4Reader::NotifyResourcesStatusChanged()
|
||||
{
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
if (mDecoder) {
|
||||
mDecoder->NotifyWaitingForResourcesStatusChanged();
|
||||
}
|
||||
|
@ -1043,7 +1052,7 @@ MP4Reader::SetIdle()
|
|||
void
|
||||
MP4Reader::SetSharedDecoderManager(SharedDecoderManager* aManager)
|
||||
{
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN)
|
||||
mSharedDecoderManager = aManager;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -267,6 +267,10 @@ private:
|
|||
bool mIndexReady;
|
||||
Monitor mDemuxerMonitor;
|
||||
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
const bool mDormantEnabled;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -55,11 +55,14 @@ public:
|
|||
};
|
||||
|
||||
SharedDecoderManager::SharedDecoderManager()
|
||||
: mActiveProxy(nullptr)
|
||||
: mTaskQueue(new MediaTaskQueue(GetMediaDecodeThreadPool()))
|
||||
, mActiveProxy(nullptr)
|
||||
, mActiveCallback(nullptr)
|
||||
, mWaitForInternalDrain(false)
|
||||
, mMonitor("SharedDecoderProxy")
|
||||
, mDecoderReleasedResources(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread()); // taskqueue must be created on main thread.
|
||||
mCallback = new SharedDecoderCallback(this);
|
||||
}
|
||||
|
||||
|
@ -67,14 +70,18 @@ SharedDecoderManager::~SharedDecoderManager() {}
|
|||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
SharedDecoderManager::CreateVideoDecoder(
|
||||
PlatformDecoderModule* aPDM,
|
||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer,
|
||||
MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback)
|
||||
{
|
||||
if (!mDecoder) {
|
||||
nsRefPtr<PlatformDecoderModule> platform(PlatformDecoderModule::Create());
|
||||
mDecoder = platform->CreateVideoDecoder(
|
||||
aConfig, aLayersBackend, aImageContainer, aVideoTaskQueue, mCallback);
|
||||
// We use the manager's task queue for the decoder, rather than the one
|
||||
// passed in, so that none of the objects sharing the decoder can shutdown
|
||||
// the task queue while we're potentially still using it for a *different*
|
||||
// object also sharing the decoder.
|
||||
mDecoder = aPDM->CreateVideoDecoder(
|
||||
aConfig, aLayersBackend, aImageContainer, mTaskQueue, mCallback);
|
||||
if (!mDecoder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -96,6 +103,11 @@ SharedDecoderManager::Select(SharedDecoderProxy* aProxy)
|
|||
|
||||
mActiveProxy = aProxy;
|
||||
mActiveCallback = aProxy->mCallback;
|
||||
|
||||
if (mDecoderReleasedResources) {
|
||||
mDecoder->AllocateMediaResources();
|
||||
mDecoderReleasedResources = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -125,6 +137,28 @@ SharedDecoderManager::DrainComplete()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SharedDecoderManager::ReleaseMediaResources()
|
||||
{
|
||||
mDecoderReleasedResources = true;
|
||||
mDecoder->ReleaseMediaResources();
|
||||
mActiveProxy = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SharedDecoderManager::Shutdown()
|
||||
{
|
||||
if (mDecoder) {
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
if (mTaskQueue) {
|
||||
mTaskQueue->BeginShutdown();
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
mTaskQueue = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SharedDecoderProxy::SharedDecoderProxy(
|
||||
SharedDecoderManager* aManager, MediaDataDecoderCallback* aCallback)
|
||||
: mManager(aManager), mCallback(aCallback)
|
||||
|
@ -146,7 +180,6 @@ SharedDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
|
|||
mManager->Select(this);
|
||||
}
|
||||
return mManager->mDecoder->Input(aSample);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -193,7 +226,7 @@ void
|
|||
SharedDecoderProxy::ReleaseMediaResources()
|
||||
{
|
||||
if (mManager->mActiveProxy == this) {
|
||||
mManager->mDecoder->ReleaseMediaResources();
|
||||
mManager->ReleaseMediaResources();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
SharedDecoderManager();
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||
PlatformDecoderModule* aPDM,
|
||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
layers::LayersBackend aLayersBackend,
|
||||
layers::ImageContainer* aImageContainer, MediaTaskQueue* aVideoTaskQueue,
|
||||
|
@ -33,6 +34,8 @@ public:
|
|||
void SetReader(MediaDecoderReader* aReader);
|
||||
void Select(SharedDecoderProxy* aProxy);
|
||||
void SetIdle(MediaDataDecoder* aProxy);
|
||||
void ReleaseMediaResources();
|
||||
void Shutdown();
|
||||
|
||||
friend class SharedDecoderProxy;
|
||||
friend class SharedDecoderCallback;
|
||||
|
@ -42,11 +45,13 @@ private:
|
|||
void DrainComplete();
|
||||
|
||||
nsRefPtr<MediaDataDecoder> mDecoder;
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
SharedDecoderProxy* mActiveProxy;
|
||||
MediaDataDecoderCallback* mActiveCallback;
|
||||
nsAutoPtr<MediaDataDecoderCallback> mCallback;
|
||||
bool mWaitForInternalDrain;
|
||||
Monitor mMonitor;
|
||||
bool mDecoderReleasedResources;
|
||||
};
|
||||
|
||||
class SharedDecoderProxy : public MediaDataDecoder
|
||||
|
|
|
@ -48,7 +48,13 @@ WMFMediaDataDecoder::Init()
|
|||
nsresult
|
||||
WMFMediaDataDecoder::Shutdown()
|
||||
{
|
||||
mTaskQueue->FlushAndDispatch(NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
|
||||
DebugOnly<nsresult> rv = mTaskQueue->FlushAndDispatch(
|
||||
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("WMFMediaDataDecoder::Shutdown() dispatch of task failed!");
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -60,6 +66,13 @@ WMFMediaDataDecoder::ProcessShutdown()
|
|||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
WMFMediaDataDecoder::ProcessReleaseDecoder()
|
||||
{
|
||||
mMFTManager->Shutdown();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
// Inserts data into the decoder's pipeline.
|
||||
nsresult
|
||||
WMFMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
|
||||
|
@ -142,4 +155,28 @@ WMFMediaDataDecoder::Drain()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WMFMediaDataDecoder::AllocateMediaResources()
|
||||
{
|
||||
mDecoder = mMFTManager->Init();
|
||||
}
|
||||
|
||||
void
|
||||
WMFMediaDataDecoder::ReleaseMediaResources()
|
||||
{
|
||||
DebugOnly<nsresult> rv = mTaskQueue->FlushAndDispatch(
|
||||
NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessReleaseDecoder));
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("WMFMediaDataDecoder::ReleaseMediaResources() dispatch of task failed!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WMFMediaDataDecoder::ReleaseDecoder()
|
||||
{
|
||||
ReleaseMediaResources();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -70,6 +70,12 @@ public:
|
|||
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool IsWaitingMediaResources() { return false; };
|
||||
virtual bool IsDormantNeeded() { return true; };
|
||||
virtual void AllocateMediaResources() MOZ_OVERRIDE;
|
||||
virtual void ReleaseMediaResources() MOZ_OVERRIDE;
|
||||
virtual void ReleaseDecoder() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
// Called on the task queue. Inserts the sample into the decoder, and
|
||||
|
@ -85,6 +91,7 @@ private:
|
|||
void ProcessDrain();
|
||||
|
||||
void ProcessShutdown();
|
||||
void ProcessReleaseDecoder();
|
||||
|
||||
RefPtr<MediaTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
|
|
|
@ -100,7 +100,9 @@ WMFVideoMFTManager::~WMFVideoMFTManager()
|
|||
{
|
||||
MOZ_COUNT_DTOR(WMFVideoMFTManager);
|
||||
// Ensure DXVA/D3D9 related objects are released on the main thread.
|
||||
DeleteOnMainThread(mDXVA2Manager);
|
||||
if (mDXVA2Manager) {
|
||||
DeleteOnMainThread(mDXVA2Manager);
|
||||
}
|
||||
}
|
||||
|
||||
const GUID&
|
||||
|
@ -140,6 +142,8 @@ public:
|
|||
bool
|
||||
WMFVideoMFTManager::InitializeDXVA()
|
||||
{
|
||||
MOZ_ASSERT(!mDXVA2Manager);
|
||||
|
||||
// If we use DXVA but aren't running with a D3D layer manager then the
|
||||
// readback of decoded video frames from GPU to CPU memory grinds painting
|
||||
// to a halt, and makes playback performance *worse*.
|
||||
|
@ -488,6 +492,7 @@ void
|
|||
WMFVideoMFTManager::Shutdown()
|
||||
{
|
||||
mDecoder = nullptr;
|
||||
DeleteOnMainThread(mDXVA2Manager);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -411,6 +411,11 @@ MediaSourceReader::ContinueShutdown()
|
|||
mVideoTrack = nullptr;
|
||||
mVideoReader = nullptr;
|
||||
|
||||
if (mSharedDecoderManager) {
|
||||
mSharedDecoderManager->Shutdown();
|
||||
mSharedDecoderManager = nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mAudioPromise.IsEmpty());
|
||||
MOZ_ASSERT(mVideoPromise.IsEmpty());
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче