Bug 1314833 - Part 2.1: Factor out AbstractThread::MainThread() used in Media Playback. r=billm,jwwang

MozReview-Commit-ID: 9yJi3iDtVZG

--HG--
extra : rebase_source : 39c720ccc576ed9247b5e8abb70d99d7873b3ad6
This commit is contained in:
Bevis Tseng 2016-11-29 13:03:36 +08:00
Родитель da8bace3ac
Коммит f2bdbd8fd1
36 изменённых файлов: 196 добавлений и 63 удалений

Просмотреть файл

@ -3573,7 +3573,8 @@ NS_IMPL_ISUPPORTS(HTMLMediaElement::ShutdownObserver, nsIObserver)
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mWatchManager(this, AbstractThread::MainThread()),
mAbstractMainThread(OwnerDoc()->AbstractMainThreadFor(TaskCategory::Other)),
mWatchManager(this, mAbstractMainThread),
mSrcStreamTracksAvailable(false),
mSrcStreamPausedCurrentTime(-1),
mShutdownObserver(new ShutdownObserver),
@ -4637,7 +4638,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
// Not every decoder will produce waitingForKey events, only add ones that can
if (waitingForKeyProducer) {
mWaitingForKeyListener = waitingForKeyProducer->Connect(
AbstractThread::MainThread(), this, &HTMLMediaElement::CannotDecryptWaitingForKey);
mAbstractMainThread, this, &HTMLMediaElement::CannotDecryptWaitingForKey);
}
if (mChannelLoader) {
@ -7136,6 +7137,14 @@ HTMLMediaElement::UpdateCustomPolicyAfterPlayed()
}
}
AbstractThread*
HTMLMediaElement::AbstractMainThread() const
{
MOZ_ASSERT(mAbstractMainThread);
return mAbstractMainThread;
}
nsTArray<RefPtr<Promise>>
HTMLMediaElement::TakePendingPlayPromises()
{

Просмотреть файл

@ -41,6 +41,7 @@ typedef uint32_t AudibleChangedReasons;
typedef uint8_t AudibleState;
namespace mozilla {
class AbstractThread;
class DecoderDoctorDiagnostics;
class DOMMediaStream;
class ErrorResult;
@ -1172,6 +1173,8 @@ protected:
return this;
}
virtual AbstractThread* AbstractMainThread() const final override;
// Return true if decoding should be paused
virtual bool GetPaused() final override
{
@ -1273,6 +1276,9 @@ protected:
// At most one of mDecoder and mSrcStream can be non-null.
RefPtr<MediaDecoder> mDecoder;
// The DocGroup-specific AbstractThread::MainThread() of this HTML element.
RefPtr<AbstractThread> mAbstractMainThread;
// Observers listening to changes to the mDecoder principal.
// Used by streams captured from this element.
nsTArray<DecoderPrincipalChangeObserver*> mDecoderPrincipalChangeObservers;

Просмотреть файл

@ -25,6 +25,7 @@ namespace layers
class ImageContainer;
class KnowsCompositor;
} // namespace layers
class AbstractThread;
class MediaResource;
class ReentrantMonitor;
class VideoFrameContainer;
@ -90,6 +91,9 @@ public:
return nullptr;
}
// Return an abstract thread on which to run main thread runnables.
virtual AbstractThread* AbstractMainThread() const = 0;
protected:
virtual void UpdateEstimatedMediaDuration(int64_t aDuration) {};
public:

Просмотреть файл

@ -10,6 +10,7 @@
#include "MediaPrefs.h"
#include "PDMFactory.h"
#include "WebMDemuxer.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "mozilla/dom/ContentChild.h"
@ -57,6 +58,7 @@ VP9Benchmark::IsVP9DecodeFast()
Preferences::GetUint("media.benchmark.timeout", 1000))
});
estimiser->Run()->Then(
// Non-DocGroup version of AbstractThread::MainThread for utility function.
AbstractThread::MainThread(), __func__,
[](uint32_t aDecodeFps) {
if (XRE_IsContentProcess()) {

Просмотреть файл

@ -23,6 +23,7 @@
#include <algorithm>
#include "MediaShutdownManager.h"
#include "AudioChannelService.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/dom/AudioTrack.h"
#include "mozilla/dom/AudioTrackList.h"
#include "mozilla/dom/HTMLMediaElement.h"
@ -139,6 +140,11 @@ NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
NS_IMPL_ISUPPORTS0(MediaDecoder)
MediaDecoder::ResourceCallback::ResourceCallback(AbstractThread* aMainThread)
: mAbstractMainThread(aMainThread)
{
MOZ_ASSERT(aMainThread);
}
void
MediaDecoder::ResourceCallback::Connect(MediaDecoder* aDecoder)
@ -193,7 +199,7 @@ MediaDecoder::ResourceCallback::NotifyDecodeError()
self->mDecoder->DecodeError(NS_ERROR_DOM_MEDIA_FATAL_ERR);
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
}
/* static */ void
@ -251,7 +257,7 @@ MediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
self->mDecoder->NotifySuspendedStatusChanged();
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
}
void
@ -282,7 +288,7 @@ MediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
}
void
@ -373,19 +379,20 @@ MediaDecoder::IsInfinite() const
}
#define INIT_MIRROR(name, val) \
name(AbstractThread::MainThread(), val, "MediaDecoder::" #name " (Mirror)")
name(aOwner->AbstractMainThread(), val, "MediaDecoder::" #name " (Mirror)")
#define INIT_CANONICAL(name, val) \
name(AbstractThread::MainThread(), val, "MediaDecoder::" #name " (Canonical)")
name(aOwner->AbstractMainThread(), val, "MediaDecoder::" #name " (Canonical)")
MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
: mWatchManager(this, AbstractThread::MainThread())
: mWatchManager(this, aOwner->AbstractMainThread())
, mLogicalPosition(0.0)
, mDuration(std::numeric_limits<double>::quiet_NaN())
, mResourceCallback(new ResourceCallback())
, mResourceCallback(new ResourceCallback(aOwner->AbstractMainThread()))
, mCDMProxyPromise(mCDMProxyPromiseHolder.Ensure(__func__))
, mIgnoreProgressData(false)
, mInfiniteStream(false)
, mOwner(aOwner)
, mAbstractMainThread(aOwner->AbstractMainThread())
, mFrameStats(new FrameStatistics())
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
, mPlaybackStatistics(new MediaChannelStatistics())
@ -420,6 +427,7 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
, mElement(aOwner->GetMediaElement())
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mAbstractMainThread);
MediaMemoryTracker::AddMediaDecoder(this);
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
@ -486,7 +494,7 @@ MediaDecoder::Shutdown()
mOnMediaNotSeekable.Disconnect();
mDecoderStateMachine->BeginShutdown()
->Then(AbstractThread::MainThread(), __func__, this,
->Then(mAbstractMainThread, __func__, this,
&MediaDecoder::FinishShutdown,
&MediaDecoder::FinishShutdown);
} else {
@ -497,7 +505,7 @@ MediaDecoder::Shutdown()
self->mVideoFrameContainer = nullptr;
MediaShutdownManager::Instance().Unregister(self);
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
}
// Force any outstanding seek and byterange requests to complete
@ -637,20 +645,20 @@ MediaDecoder::SetStateMachineParameters()
mDecoderStateMachine->DispatchSetPlaybackRate(mPlaybackRate);
}
mTimedMetadataListener = mDecoderStateMachine->TimedMetadataEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnMetadataUpdate);
mAbstractMainThread, this, &MediaDecoder::OnMetadataUpdate);
mMetadataLoadedListener = mDecoderStateMachine->MetadataLoadedEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::MetadataLoaded);
mAbstractMainThread, this, &MediaDecoder::MetadataLoaded);
mFirstFrameLoadedListener = mDecoderStateMachine->FirstFrameLoadedEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::FirstFrameLoaded);
mAbstractMainThread, this, &MediaDecoder::FirstFrameLoaded);
mOnPlaybackEvent = mDecoderStateMachine->OnPlaybackEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnPlaybackEvent);
mAbstractMainThread, this, &MediaDecoder::OnPlaybackEvent);
mOnPlaybackErrorEvent = mDecoderStateMachine->OnPlaybackErrorEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnPlaybackErrorEvent);
mAbstractMainThread, this, &MediaDecoder::OnPlaybackErrorEvent);
mOnDecoderDoctorEvent = mDecoderStateMachine->OnDecoderDoctorEvent().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnDecoderDoctorEvent);
mAbstractMainThread, this, &MediaDecoder::OnDecoderDoctorEvent);
mOnMediaNotSeekable = mDecoderStateMachine->OnMediaNotSeekable().Connect(
AbstractThread::MainThread(), this, &MediaDecoder::OnMediaNotSeekable);
mAbstractMainThread, this, &MediaDecoder::OnMediaNotSeekable);
}
void
@ -718,7 +726,7 @@ MediaDecoder::AsyncResolveSeekDOMPromiseIfExists()
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
promise->MaybeResolveWithUndefined();
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
mSeekDOMPromise = nullptr;
}
}
@ -732,7 +740,7 @@ MediaDecoder::AsyncRejectSeekDOMPromiseIfExists()
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
mSeekDOMPromise = nullptr;
}
}
@ -753,7 +761,7 @@ MediaDecoder::CallSeek(const SeekTarget& aTarget, dom::Promise* aPromise)
mSeekDOMPromise = aPromise;
mDecoderStateMachine->InvokeSeek(aTarget)
->Then(AbstractThread::MainThread(), __func__, this,
->Then(mAbstractMainThread, __func__, this,
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected)
->Track(mSeekRequest);
}
@ -1605,7 +1613,9 @@ MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
nsCOMPtr<nsISupports> data = aData;
resourceSizes->Promise()->Then(
AbstractThread::MainThread(), __func__,
// Non-DocGroup version of AbstractThread::MainThread is fine for memory report.
AbstractThread::MainThread(),
__func__,
[handleReport, data] (size_t size) {
handleReport->Callback(
EmptyCString(), NS_LITERAL_CSTRING("explicit/media/resources"),

Просмотреть файл

@ -45,6 +45,7 @@ class Promise;
class HTMLMediaElement;
}
class AbstractThread;
class VideoFrameContainer;
class MediaDecoderStateMachine;
@ -67,6 +68,7 @@ public:
static const uint32_t sDelay = 500;
public:
explicit ResourceCallback(AbstractThread* aMainThread);
// Start to receive notifications from ResourceCallback.
void Connect(MediaDecoder* aDecoder);
// Called upon shutdown to stop receiving notifications.
@ -91,6 +93,7 @@ public:
MediaDecoder* mDecoder = nullptr;
nsCOMPtr<nsITimer> mTimer;
bool mTimerArmed = false;
const RefPtr<AbstractThread> mAbstractMainThread;
};
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
@ -422,6 +425,11 @@ private:
MediaDecoderOwner* GetOwner() const override;
AbstractThread* AbstractMainThread() const final override
{
return mAbstractMainThread;
}
typedef MozPromise<RefPtr<CDMProxy>, bool /* aIgnored */, /* IsExclusive = */ true> CDMProxyPromise;
// Resolved when a CDMProxy is available and the capabilities are known or
@ -629,6 +637,9 @@ protected:
// away. The decoder does not add a reference the element.
MediaDecoderOwner* mOwner;
// The AbstractThread from mOwner.
const RefPtr<AbstractThread> mAbstractMainThread;
// Counters related to decode and presentation of frames.
const RefPtr<FrameStatistics> mFrameStats;

Просмотреть файл

@ -10,6 +10,7 @@
namespace mozilla {
class AbstractThread;
class VideoFrameContainer;
class MediaResult;
@ -44,6 +45,9 @@ public:
return nullptr;
}
// Return an abstract thread on which to run main thread runnables.
virtual AbstractThread* AbstractMainThread() const = 0;
// Return true if decoding should be paused
virtual bool GetPaused() = 0;

Просмотреть файл

@ -1942,8 +1942,12 @@ StateObject::HandleResumeVideoDecoding()
type,
true /* aVideoOnly */);
// Hold mMaster->mAbstractMainThread here because this->mMaster will be invalid
// after the current state object is deleted in SetState();
RefPtr<AbstractThread> mainThread = mMaster->mAbstractMainThread;
SetSeekingState(Move(seekJob), EventVisibility::Suppressed)->Then(
AbstractThread::MainThread(), __func__,
mainThread, __func__,
[start, info, hw](){ ReportRecoveryTelemetry(start, info, hw); },
[](){});
}
@ -2477,6 +2481,7 @@ ShutdownState::Enter()
MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
MediaDecoderReader* aReader) :
mDecoderID(aDecoder),
mAbstractMainThread(aDecoder->AbstractMainThread()),
mFrameStats(&aDecoder->GetFrameStatistics()),
mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
mAudioChannel(aDecoder->GetAudioChannel()),
@ -2612,7 +2617,7 @@ already_AddRefed<media::MediaSink>
MediaDecoderStateMachine::CreateMediaSink(bool aAudioCaptured)
{
RefPtr<media::MediaSink> audioSink = aAudioCaptured
? new DecodedStream(mTaskQueue, mAudioQueue, mVideoQueue,
? new DecodedStream(mTaskQueue, mAbstractMainThread, mAudioQueue, mVideoQueue,
mOutputStreamManager, mSameOriginMedia.Ref(),
mMediaPrincipalHandle.Ref())
: CreateAudioSink();

Просмотреть файл

@ -104,6 +104,7 @@ namespace media {
class MediaSink;
}
class AbstractThread;
class AudioSegment;
class DecodedStream;
class MediaDecoderReaderWrapper;
@ -464,6 +465,7 @@ private:
void OnMediaSinkVideoError();
void* const mDecoderID;
const RefPtr<AbstractThread> mAbstractMainThread;
const RefPtr<FrameStatistics> mFrameStats;
const RefPtr<VideoFrameContainer> mVideoFrameContainer;
const dom::AudioChannel mAudioChannel;

Просмотреть файл

@ -15,6 +15,7 @@
#include "VideoFrameContainer.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/CDMProxy.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
@ -118,6 +119,7 @@ DecoderAllocPolicy::DecoderAllocPolicy(TrackType aTrack)
, mDecoderLimit(MediaPrefs::MediaDecoderLimit())
, mTrack(aTrack)
{
// Non DocGroup-version AbstractThread::MainThread is fine for ClearOnShutdown().
AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction([this] () {
ClearOnShutdown(this, ShutdownPhase::ShutdownThreads);
}));
@ -439,9 +441,10 @@ class MediaFormatReader::DemuxerProxy
class Wrapper;
public:
explicit DemuxerProxy(MediaDataDemuxer* aDemuxer)
explicit DemuxerProxy(MediaDataDemuxer* aDemuxer, AbstractThread* mainThread)
: mTaskQueue(new AutoTaskQueue(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER)))
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
mainThread))
, mData(new Data(aDemuxer))
{
MOZ_COUNT_CTOR(DemuxerProxy);
@ -788,7 +791,7 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
Preferences::GetUint("media.audio-max-decode-error", 3))
, mVideo(this, MediaData::VIDEO_DATA,
Preferences::GetUint("media.video-max-decode-error", 2))
, mDemuxer(new DemuxerProxy(aDemuxer))
, mDemuxer(new DemuxerProxy(aDemuxer, aDecoder->AbstractMainThread()))
, mDemuxerInitDone(false)
, mLastReportedNumDecodedFrames(0)
, mPreviousDecodedKeyframeTime_us(sNoPreviousDecodedKeyframe)

Просмотреть файл

@ -56,7 +56,7 @@ TextTrackCue::TextTrackCue(nsPIDOMWindowInner* aOwnerWindow,
, mEndTime(aEndTime)
, mReset(false, "TextTrackCue::mReset")
, mHaveStartedWatcher(false)
, mWatchManager(this, AbstractThread::MainThread())
, mWatchManager(this, GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other))
{
SetDefaultCueSettings();
MOZ_ASSERT(aOwnerWindow);
@ -78,7 +78,7 @@ TextTrackCue::TextTrackCue(nsPIDOMWindowInner* aOwnerWindow,
, mTrackElement(aTrackElement)
, mReset(false, "TextTrackCue::mReset")
, mHaveStartedWatcher(false)
, mWatchManager(this, AbstractThread::MainThread())
, mWatchManager(this, GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other))
{
SetDefaultCueSettings();
MOZ_ASSERT(aOwnerWindow);

Просмотреть файл

@ -252,7 +252,8 @@ MP4Decoder::IsVideoAccelerated(layers::KnowsCompositor* aKnowsCompositor, nsIGlo
}
decoder->Init()
->Then(AbstractThread::MainThread(), __func__,
->Then(aParent->AbstractMainThreadFor(dom::TaskCategory::Other),
__func__,
[promise, decoder, taskQueue] (TrackInfo::TrackType aTrack) {
nsCString failureReason;
bool ok = decoder->IsHardwareAccelerated(failureReason);

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsIRunnable.h"
#include "nsIWritablePropertyBag2.h"
#include "mozIGeckoMediaPluginService.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/SSE.h"
#include "mozilla/SyncRunnable.h"
@ -743,6 +744,7 @@ GMPParent::ReadChromiumManifestFile(nsIFile* aFile)
// DOM JSON parsing needs to run on the main thread.
return InvokeAsync<nsString&&>(
// Non DocGroup-version of AbstractThread::MainThread for the task in parent.
AbstractThread::MainThread(), this, __func__,
&GMPParent::ParseChromiumManifest, NS_ConvertUTF8toUTF16(json));
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "GMPService.h"
#include "prio.h"
#include "base/task.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/ContentParent.h"
#include "GMPParent.h"
@ -614,7 +615,9 @@ GeckoMediaPluginServiceParent::AsyncAddPluginDirectory(const nsAString& aDirecto
return InvokeAsync<nsString&&>(
thread, this, __func__,
&GeckoMediaPluginServiceParent::AddOnGMPThread, dir)
->Then(AbstractThread::MainThread(), __func__,
->Then(
AbstractThread::MainThread(), // Non DocGroup-version for the task in parent.
__func__,
[dir, self]() -> void {
LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s succeeded",
NS_ConvertUTF16toUTF8(dir).get()));

Просмотреть файл

@ -6,6 +6,7 @@
#define MOCK_MEDIA_DECODER_OWNER_H_
#include "MediaDecoderOwner.h"
#include "mozilla/AbstractThread.h"
#include "nsAutoPtr.h"
namespace mozilla
@ -48,6 +49,11 @@ public:
}
void SetAudibleState(bool aAudible) override {}
void NotifyXPCOMShutdown() override {}
AbstractThread* AbstractMainThread() const override
{
// Non-DocGroup version for Mock.
return AbstractThread::MainThread();
}
};
}

Просмотреть файл

@ -12,6 +12,7 @@
#include "MP4Demuxer.h"
#include "WebMDecoder.h"
#include "WebMDemuxer.h"
#include "mozilla/AbstractThread.h"
using namespace mozilla;
@ -28,6 +29,7 @@ public:
mBenchmark->Init();
mBenchmark->Run()->Then(
// Non DocGroup-version of AbstractThread::MainThread() is fine for testing.
AbstractThread::MainThread(), __func__,
[&](uint32_t aDecodeFps) { result = aDecodeFps; done = true; },
[&]() { done = true; });

Просмотреть файл

@ -4,6 +4,7 @@
* 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 "mozilla/AbstractThread.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/SyncRunnable.h"
@ -70,7 +71,7 @@ public:
void Forget()
{
AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction([this] () {
mAbstractMainThread->Dispatch(NS_NewRunnableFunction([this] () {
MOZ_ASSERT(NS_IsMainThread());
mFinishPromise.ResolveIfExists(true, __func__);
}));
@ -94,7 +95,7 @@ private:
};
static void
UpdateStreamSuspended(MediaStream* aStream, bool aBlocking)
UpdateStreamSuspended(AbstractThread* aMainThread, MediaStream* aStream, bool aBlocking)
{
if (NS_IsMainThread()) {
if (aBlocking) {
@ -109,7 +110,7 @@ UpdateStreamSuspended(MediaStream* aStream, bool aBlocking)
} else {
r = NewRunnableMethod(aStream, &MediaStream::Resume);
}
AbstractThread::MainThread()->Dispatch(r.forget());
aMainThread->Dispatch(r.forget());
}
}
@ -125,7 +126,8 @@ class DecodedStreamData {
public:
DecodedStreamData(OutputStreamManager* aOutputStreamManager,
PlaybackInfoInit&& aInit,
MozPromiseHolder<GenericPromise>&& aPromise);
MozPromiseHolder<GenericPromise>&& aPromise,
AbstractThread* aMainThread);
~DecodedStreamData();
void SetPlaying(bool aPlaying);
MediaEventSource<int64_t>& OnOutput();
@ -159,11 +161,13 @@ public:
bool mEOSVideoCompensation;
const RefPtr<OutputStreamManager> mOutputStreamManager;
const RefPtr<AbstractThread> mAbstractMainThread;
};
DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
PlaybackInfoInit&& aInit,
MozPromiseHolder<GenericPromise>&& aPromise)
MozPromiseHolder<GenericPromise>&& aPromise,
AbstractThread* aMainThread)
: mAudioFramesWritten(0)
, mNextVideoTime(aInit.mStartTime)
, mNextAudioTime(aInit.mStartTime)
@ -172,12 +176,13 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
, mHaveSentFinishVideo(false)
, mStream(aOutputStreamManager->Graph()->CreateSourceStream())
// DecodedStreamGraphListener will resolve this promise.
, mListener(new DecodedStreamGraphListener(mStream, Move(aPromise)))
, mListener(new DecodedStreamGraphListener(mStream, Move(aPromise), aMainThread))
// mPlaying is initially true because MDSM won't start playback until playing
// becomes true. This is consistent with the settings of AudioSink.
, mPlaying(true)
, mEOSVideoCompensation(false)
, mOutputStreamManager(aOutputStreamManager)
, mAbstractMainThread(aMainThread)
{
mStream->AddListener(mListener);
mOutputStreamManager->Connect(mStream);
@ -210,7 +215,7 @@ DecodedStreamData::SetPlaying(bool aPlaying)
{
if (mPlaying != aPlaying) {
mPlaying = aPlaying;
UpdateStreamSuspended(mStream, !mPlaying);
UpdateStreamSuspended(mAbstractMainThread, mStream, !mPlaying);
}
}
@ -232,12 +237,14 @@ DecodedStreamData::DumpDebugInfo()
}
DecodedStream::DecodedStream(AbstractThread* aOwnerThread,
AbstractThread* aMainThread,
MediaQueue<MediaData>& aAudioQueue,
MediaQueue<MediaData>& aVideoQueue,
OutputStreamManager* aOutputStreamManager,
const bool& aSameOrigin,
const PrincipalHandle& aPrincipalHandle)
: mOwnerThread(aOwnerThread)
, mAbstractMainThread(aMainThread)
, mOutputStreamManager(aOutputStreamManager)
, mPlaying(false)
, mSameOrigin(aSameOrigin)
@ -298,8 +305,9 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
class R : public Runnable {
typedef MozPromiseHolder<GenericPromise> Promise;
public:
R(PlaybackInfoInit&& aInit, Promise&& aPromise, OutputStreamManager* aManager)
: mInit(Move(aInit)), mOutputStreamManager(aManager)
R(PlaybackInfoInit&& aInit, Promise&& aPromise,
OutputStreamManager* aManager, AbstractThread* aMainThread)
: mInit(Move(aInit)), mOutputStreamManager(aManager), mAbstractMainThread(aMainThread)
{
mPromise = Move(aPromise);
}
@ -314,7 +322,7 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
return NS_OK;
}
mData = MakeUnique<DecodedStreamData>(
mOutputStreamManager, Move(mInit), Move(mPromise));
mOutputStreamManager, Move(mInit), Move(mPromise), mAbstractMainThread);
return NS_OK;
}
UniquePtr<DecodedStreamData> ReleaseData()
@ -326,6 +334,7 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
Promise mPromise;
RefPtr<OutputStreamManager> mOutputStreamManager;
UniquePtr<DecodedStreamData> mData;
const RefPtr<AbstractThread> mAbstractMainThread;
};
MozPromiseHolder<GenericPromise> promise;
@ -333,7 +342,8 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
PlaybackInfoInit init {
aStartTime, aInfo
};
nsCOMPtr<nsIRunnable> r = new R(Move(init), Move(promise), mOutputStreamManager);
nsCOMPtr<nsIRunnable> r =
new R(Move(init), Move(promise), mOutputStreamManager, mAbstractMainThread);
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
SyncRunnable::DispatchToThread(mainThread, r);
mData = static_cast<R*>(r.get())->ReleaseData();
@ -391,7 +401,7 @@ DecodedStream::DestroyData(UniquePtr<DecodedStreamData> aData)
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
delete data;
});
AbstractThread::MainThread()->Dispatch(r.forget());
mAbstractMainThread->Dispatch(r.forget());
}
void

Просмотреть файл

@ -34,6 +34,7 @@ class DecodedStream : public media::MediaSink {
public:
DecodedStream(AbstractThread* aOwnerThread,
AbstractThread* aMainThread,
MediaQueue<MediaData>& aAudioQueue,
MediaQueue<MediaData>& aVideoQueue,
OutputStreamManager* aOutputStreamManager,
@ -85,6 +86,8 @@ private:
const RefPtr<AbstractThread> mOwnerThread;
const RefPtr<AbstractThread> mAbstractMainThread;
/*
* Main thread only members.
*/

Просмотреть файл

@ -17,9 +17,12 @@ namespace mozilla {
class AutoTaskQueue : public AbstractThread
{
public:
explicit AutoTaskQueue(already_AddRefed<SharedThreadPool> aPool, bool aSupportsTailDispatch = false)
explicit AutoTaskQueue(already_AddRefed<SharedThreadPool> aPool,
AbstractThread* aAbstractMainThread,
bool aSupportsTailDispatch = false)
: AbstractThread(aSupportsTailDispatch)
, mTaskQueue(new TaskQueue(Move(aPool), aSupportsTailDispatch))
, mAbstractMainThread(aAbstractMainThread)
{}
TaskDispatcher& TailDispatcher() override
@ -49,9 +52,10 @@ private:
RefPtr<TaskQueue> taskqueue = mTaskQueue;
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction([taskqueue]() { taskqueue->BeginShutdown(); });
AbstractThread::MainThread()->Dispatch(task.forget());
mAbstractMainThread->Dispatch(task.forget());
}
RefPtr<TaskQueue> mTaskQueue;
const RefPtr<AbstractThread> mAbstractMainThread;
};
} // namespace mozilla

Просмотреть файл

@ -454,6 +454,7 @@ MediaSource::MediaSource(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow)
, mDecoder(nullptr)
, mPrincipal(nullptr)
, mAbstractMainThread(GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other))
, mReadyState(MediaSourceReadyState::Closed)
{
MOZ_ASSERT(NS_IsMainThread());

Просмотреть файл

@ -27,6 +27,7 @@ class nsPIDOMWindowInner;
namespace mozilla {
class AbstractThread;
class ErrorResult;
template <typename T> class AsyncEventRunner;
class MediaResult;
@ -113,6 +114,11 @@ public:
return mLiveSeekableRange.value();
}
AbstractThread* AbstractMainThread() const
{
return mAbstractMainThread;
}
private:
// SourceBuffer uses SetDuration and SourceBufferIsActive
friend class mozilla::dom::SourceBuffer;
@ -143,6 +149,8 @@ private:
RefPtr<nsIPrincipal> mPrincipal;
const RefPtr<AbstractThread> mAbstractMainThread;
MediaSourceReadyState mReadyState;
Maybe<media::TimeInterval> mLiveSeekableRange;

Просмотреть файл

@ -44,7 +44,7 @@ MediaDecoderStateMachine*
MediaSourceDecoder::CreateStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
mDemuxer = new MediaSourceDemuxer();
mDemuxer = new MediaSourceDemuxer(AbstractMainThread());
mReader = new MediaFormatReader(this, mDemuxer, GetVideoFrameContainer());
return new MediaDecoderStateMachine(this, mReader);
}

Просмотреть файл

@ -20,8 +20,9 @@ typedef TrackInfo::TrackType TrackType;
using media::TimeUnit;
using media::TimeIntervals;
MediaSourceDemuxer::MediaSourceDemuxer()
MediaSourceDemuxer::MediaSourceDemuxer(AbstractThread* aAbstractMainThread)
: mTaskQueue(new AutoTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
aAbstractMainThread,
/* aSupportsTailDispatch = */ false))
, mMonitor("MediaSourceDemuxer")
{

Просмотреть файл

@ -20,13 +20,14 @@
namespace mozilla {
class AbstractThread;
class MediaResult;
class MediaSourceTrackDemuxer;
class MediaSourceDemuxer : public MediaDataDemuxer
{
public:
explicit MediaSourceDemuxer();
explicit MediaSourceDemuxer(AbstractThread* aAbstractMainThread);
RefPtr<InitPromise> Init() override;

Просмотреть файл

@ -260,7 +260,7 @@ SourceBuffer::RangeRemoval(double aStart, double aEnd)
RefPtr<SourceBuffer> self = this;
mTrackBuffersManager->RangeRemoval(TimeUnit::FromSeconds(aStart),
TimeUnit::FromSeconds(aEnd))
->Then(AbstractThread::MainThread(), __func__,
->Then(mAbstractMainThread, __func__,
[self] (bool) {
self->mPendingRemoval.Complete();
self->StopUpdating();
@ -301,6 +301,7 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource,
const MediaContainerType& aType)
: DOMEventTargetHelper(aMediaSource->GetParentObject())
, mMediaSource(aMediaSource)
, mAbstractMainThread(aMediaSource->AbstractMainThread())
, mCurrentAttributes(aType.Type() == MEDIAMIMETYPE("audio/mpeg") ||
aType.Type() == MEDIAMIMETYPE("audio/aac"))
, mUpdating(false)
@ -417,7 +418,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
StartUpdating();
mTrackBuffersManager->AppendData(data, mCurrentAttributes)
->Then(AbstractThread::MainThread(), __func__, this,
->Then(mAbstractMainThread, __func__, this,
&SourceBuffer::AppendDataCompletedWithSuccess,
&SourceBuffer::AppendDataErrored)
->Track(mPendingAppend);

Просмотреть файл

@ -32,6 +32,7 @@ struct JSContext;
namespace mozilla {
class AbstractThread;
class ErrorResult;
class MediaByteBuffer;
template <typename T> class AsyncEventRunner;
@ -167,6 +168,7 @@ private:
void AppendDataErrored(const MediaResult& aError);
RefPtr<MediaSource> mMediaSource;
const RefPtr<AbstractThread> mAbstractMainThread;
RefPtr<TrackBuffersManager> mTrackBuffersManager;
SourceBufferAttributes mCurrentAttributes;

Просмотреть файл

@ -96,6 +96,7 @@ TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder,
, mProcessedInput(0)
, mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue())
, mParentDecoder(new nsMainThreadPtrHolder<MediaSourceDecoder>(aParentDecoder, false /* strict */))
, mAbstractMainThread(aParentDecoder->AbstractMainThread())
, mEnded(false)
, mVideoEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold.video",
100 * 1024 * 1024))
@ -962,10 +963,10 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
int64_t duration = std::max(videoDuration, audioDuration);
// 1. Update the duration attribute if it currently equals NaN.
// Those steps are performed by the MediaSourceDecoder::SetInitialDuration
AbstractThread::MainThread()->Dispatch(NewRunnableMethod<int64_t>
(mParentDecoder.get(),
&MediaSourceDecoder::SetInitialDuration,
duration ? duration : -1));
mAbstractMainThread->Dispatch(NewRunnableMethod<int64_t>
(mParentDecoder.get(),
&MediaSourceDecoder::SetInitialDuration,
duration ? duration : -1));
// 2. If the initialization segment has no audio, video, or text tracks, then
// run the append error algorithm with the decode error parameter set to true

Просмотреть файл

@ -26,6 +26,7 @@
namespace mozilla {
class AbstractThread;
class ContainerParser;
class MediaByteBuffer;
class MediaRawData;
@ -467,6 +468,8 @@ private:
// Strong references to external objects.
nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;
const RefPtr<AbstractThread> mAbstractMainThread;
// Return public highest end time across all aTracks.
// Monitor must be held.
media::TimeUnit HighestEndTime(nsTArray<const media::TimeIntervals*>& aTracks) const;

Просмотреть файл

@ -9,6 +9,7 @@
#include "AbstractMediaDecoder.h"
#include "OggDemuxer.h"
#include "OggCodecState.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Atomics.h"
#include "mozilla/PodOperations.h"
#include "mozilla/SharedThreadPool.h"
@ -131,6 +132,7 @@ OggDemuxer::~OggDemuxer()
OGG_DEBUG("Reporting telemetry MEDIA_OGG_LOADED_IS_CHAINED=%d", isChained);
Telemetry::Accumulate(Telemetry::ID::MEDIA_OGG_LOADED_IS_CHAINED, isChained);
});
// Non-DocGroup version of AbstractThread::MainThread is fine for Telemetry.
AbstractThread::MainThread()->Dispatch(task.forget());
}
}

Просмотреть файл

@ -76,7 +76,7 @@ MediaDataDecoderProxy::Shutdown()
#if defined(DEBUG)
mIsShutdown = true;
#endif
mProxyThread->AsXPCOMThread()->Dispatch(NewRunnableMethod(mProxyDecoder,
mProxyThread->AsEventTarget()->Dispatch(NewRunnableMethod(mProxyDecoder,
&MediaDataDecoder::Shutdown),
NS_DISPATCH_SYNC);
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "WMFUtils.h"
#include "nsTArray.h"
#include "TimeUnits.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Logging.h"
@ -254,6 +255,7 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset,
LOG("Reporting telemetry AUDIO_MFT_OUTPUT_NULL_SAMPLES");
Telemetry::Accumulate(Telemetry::ID::AUDIO_MFT_OUTPUT_NULL_SAMPLES, 1);
});
// Non-DocGroup version of AbstractThread::MainThread is fine for Telemetry.
AbstractThread::MainThread()->Dispatch(task.forget());
return E_FAIL;
}

Просмотреть файл

@ -16,6 +16,7 @@
#include "DXVA2Manager.h"
#include "nsThreadUtils.h"
#include "Layers.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/layers/LayersTypes.h"
#include "MediaInfo.h"
@ -130,6 +131,7 @@ WMFVideoMFTManager::~WMFVideoMFTManager()
LOG(nsPrintfCString("Reporting telemetry VIDEO_MFT_OUTPUT_NULL_SAMPLES=%d", telemetry).get());
Telemetry::Accumulate(Telemetry::ID::VIDEO_MFT_OUTPUT_NULL_SAMPLES, telemetry);
});
// Non-DocGroup version of AbstractThread::MainThread is fine for Telemetry.
AbstractThread::MainThread()->Dispatch(task.forget());
}

Просмотреть файл

@ -14,8 +14,11 @@ namespace mozilla {
NS_IMPL_ISUPPORTS0(BufferDecoder)
BufferDecoder::BufferDecoder(MediaResource* aResource, GMPCrashHelper* aCrashHelper)
BufferDecoder::BufferDecoder(MediaResource* aResource,
AbstractThread* aMainThread,
GMPCrashHelper* aCrashHelper)
: mResource(aResource)
, mAbstractMainThread(aMainThread)
, mCrashHelper(aCrashHelper)
{
MOZ_ASSERT(NS_IsMainThread());
@ -72,4 +75,10 @@ BufferDecoder::GetCrashHelper()
return do_AddRef(mCrashHelper);
}
AbstractThread*
BufferDecoder::AbstractMainThread() const
{
return mAbstractMainThread;
}
} // namespace mozilla

Просмотреть файл

@ -24,7 +24,9 @@ class BufferDecoder final : public AbstractMediaDecoder
public:
// This class holds a weak pointer to MediaResource. It's the responsibility
// of the caller to manage the memory of the MediaResource object.
explicit BufferDecoder(MediaResource* aResource, GMPCrashHelper* aCrashHelper);
explicit BufferDecoder(MediaResource* aResource,
AbstractThread* aMainThread,
GMPCrashHelper* aCrashHelper);
NS_DECL_THREADSAFE_ISUPPORTS
@ -42,10 +44,13 @@ public:
already_AddRefed<GMPCrashHelper> GetCrashHelper() override;
AbstractThread* AbstractMainThread() const final override;
private:
virtual ~BufferDecoder();
RefPtr<TaskQueue> mTaskQueueIdentity;
RefPtr<MediaResource> mResource;
const RefPtr<AbstractThread> mAbstractMainThread;
RefPtr<GMPCrashHelper> mCrashHelper;
};

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/dom/BaseAudioContextBinding.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/AbstractThread.h"
#include <speex/speex_resampler.h>
#include "nsXPCOMCIDInternal.h"
#include "nsComponentManagerUtils.h"
@ -186,9 +187,11 @@ MediaDecodeTask::CreateReader()
{
MOZ_ASSERT(NS_IsMainThread());
nsPIDOMWindowInner* parent = mDecodeJob.mContext->GetParentObject();
MOZ_ASSERT(parent);
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(mDecodeJob.mContext->GetParentObject());
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(parent);
if (sop) {
principal = sop->GetPrincipal();
}
@ -198,8 +201,10 @@ MediaDecodeTask::CreateReader()
mLength, principal, mContainerType);
MOZ_ASSERT(!mBufferDecoder);
mBufferDecoder = new BufferDecoder(resource,
new BufferDecoderGMPCrashHelper(mDecodeJob.mContext->GetParentObject()));
RefPtr<AbstractThread> mainThread =
mDecodeJob.mContext->GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other);
mBufferDecoder = new BufferDecoder(resource, mainThread,
new BufferDecoderGMPCrashHelper(parent));
// If you change this list to add support for new decoders, please consider
// updating HTMLMediaElement::CreateDecoder as well.
@ -286,6 +291,7 @@ MediaDecodeTask::OnMetadataRead(MetadataHolder* aMetadata)
("Telemetry (WebAudio) MEDIA_CODEC_USED= '%s'", codec.get()));
Telemetry::Accumulate(Telemetry::ID::MEDIA_CODEC_USED, codec);
});
// Non-DocGroup version of AbstractThread::MainThread is fine for Telemetry.
AbstractThread::MainThread()->Dispatch(task.forget());
RequestSample();

Просмотреть файл

@ -24,6 +24,7 @@
#include "nsISettingsService.h"
#include "nsPrintfCString.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Hal.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
@ -1035,7 +1036,8 @@ AudioManager::InitVolumeFromDatabase()
RefPtr<VolumeInitCallback> callback = new VolumeInitCallback();
MOZ_ASSERT(callback);
callback->GetPromise()->Then(AbstractThread::MainThread(), __func__, this,
callback->GetPromise()->Then(AbstractThread::MainThread(), // Non DocGroup-version for the task in parent.
__func__, this,
&AudioManager::InitDeviceVolumeSucceeded,
&AudioManager::InitDeviceVolumeFailed);