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