mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1200099. Stop using a distinct mPlaybackStream to play a media stream through an HTMLMediaElement. r=jwwang
This commit is contained in:
parent
713f74c164
commit
ec9072a5d4
@ -471,7 +471,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcMediaSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaybackStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcAttrStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourcePointer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDoc)
|
||||
@ -623,8 +622,8 @@ NS_IMETHODIMP HTMLMediaElement::GetError(nsIDOMMediaError * *aError)
|
||||
bool
|
||||
HTMLMediaElement::Ended()
|
||||
{
|
||||
if (mSrcStream) {
|
||||
return GetSrcMediaStream()->IsFinished();
|
||||
if (MediaStream* stream = GetSrcMediaStream()) {
|
||||
return stream->IsFinished();
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
@ -1391,11 +1390,11 @@ NS_IMETHODIMP HTMLMediaElement::GetSeeking(bool* aSeeking)
|
||||
double
|
||||
HTMLMediaElement::CurrentTime() const
|
||||
{
|
||||
if (mSrcStream) {
|
||||
MediaStream* stream = GetSrcMediaStream();
|
||||
if (stream) {
|
||||
return stream->StreamTimeToSeconds(stream->GetCurrentTime());
|
||||
if (MediaStream* stream = GetSrcMediaStream()) {
|
||||
if (mSrcStreamPausedCurrentTime >= 0) {
|
||||
return mSrcStreamPausedCurrentTime;
|
||||
}
|
||||
return stream->StreamTimeToSeconds(stream->GetCurrentTime());
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
@ -1703,14 +1702,9 @@ HTMLMediaElement::Pause(ErrorResult& aRv)
|
||||
mAutoplaying = false;
|
||||
// We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
UpdateSrcMediaStreamPlaying();
|
||||
|
||||
if (!oldPaused) {
|
||||
if (mSrcStream) {
|
||||
MediaStream* stream = GetSrcMediaStream();
|
||||
if (stream) {
|
||||
stream->ChangeExplicitBlockerCount(1);
|
||||
}
|
||||
}
|
||||
FireTimeUpdate(false);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("pause"));
|
||||
}
|
||||
@ -1825,8 +1819,10 @@ void HTMLMediaElement::SetVolumeInternal()
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetVolume(effectiveVolume);
|
||||
} else if (mSrcStream) {
|
||||
GetSrcMediaStream()->SetAudioOutputVolume(this, effectiveVolume);
|
||||
} else if (MediaStream* stream = GetSrcMediaStream()) {
|
||||
if (mSrcStreamIsPlaying) {
|
||||
stream->SetAudioOutputVolume(this, effectiveVolume);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAudioChannelPlayingState();
|
||||
@ -2038,6 +2034,7 @@ HTMLMediaElement::LookupMediaElementURITable(nsIURI* aURI)
|
||||
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mWatchManager(this, AbstractThread::MainThread()),
|
||||
mSrcStreamPausedCurrentTime(-1),
|
||||
mCurrentLoadID(0),
|
||||
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
|
||||
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING, "HTMLMediaElement::mReadyState"),
|
||||
@ -2080,6 +2077,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
||||
mHasSelfReference(false),
|
||||
mShuttingDown(false),
|
||||
mSuspendedForPreloadNone(false),
|
||||
mSrcStreamIsPlaying(false),
|
||||
mMediaSecurityVerified(false),
|
||||
mCORSMode(CORS_NONE),
|
||||
mIsEncrypted(false),
|
||||
@ -2255,9 +2253,6 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
// TODO: If the playback has ended, then the user agent must set
|
||||
// seek to the effective start.
|
||||
if (mPaused) {
|
||||
if (mSrcStream) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
|
||||
}
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("play"));
|
||||
switch (mReadyState) {
|
||||
case nsIDOMHTMLMediaElement::HAVE_NOTHING:
|
||||
@ -2281,6 +2276,7 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
// and our preload status.
|
||||
AddRemoveSelfReference();
|
||||
UpdatePreloadAction();
|
||||
UpdateSrcMediaStreamPlaying();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
@ -2889,6 +2885,7 @@ public:
|
||||
mElement(aElement),
|
||||
mHaveCurrentData(false),
|
||||
mBlocked(false),
|
||||
mFinished(false),
|
||||
mMutex(aName),
|
||||
mPendingNotifyOutput(false)
|
||||
{}
|
||||
@ -2897,23 +2894,29 @@ public:
|
||||
// Main thread
|
||||
void DoNotifyFinished()
|
||||
{
|
||||
mFinished = true;
|
||||
if (mElement) {
|
||||
nsRefPtr<HTMLMediaElement> deathGrip = mElement;
|
||||
mElement->PlaybackEnded();
|
||||
|
||||
// Update NextFrameStatus() to move to NEXT_FRAME_UNAVAILABLE and
|
||||
// HAVE_CURRENT_DATA.
|
||||
mElement = nullptr;
|
||||
// NotifyWatchers before calling PlaybackEnded since PlaybackEnded
|
||||
// can remove watchers.
|
||||
NotifyWatchers();
|
||||
|
||||
deathGrip->PlaybackEnded();
|
||||
}
|
||||
}
|
||||
|
||||
MediaDecoderOwner::NextFrameStatus NextFrameStatus()
|
||||
{
|
||||
if (!mElement || !mHaveCurrentData) {
|
||||
if (!mElement || !mHaveCurrentData || mFinished) {
|
||||
return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
|
||||
}
|
||||
return mBlocked ? MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING
|
||||
: MediaDecoderOwner::NEXT_FRAME_AVAILABLE;
|
||||
return mBlocked
|
||||
? MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING
|
||||
: MediaDecoderOwner::NEXT_FRAME_AVAILABLE;
|
||||
}
|
||||
|
||||
void DoNotifyBlocked()
|
||||
@ -2993,6 +2996,7 @@ private:
|
||||
HTMLMediaElement* mElement;
|
||||
bool mHaveCurrentData;
|
||||
bool mBlocked;
|
||||
bool mFinished;
|
||||
|
||||
// mMutex protects the fields below; they can be accessed on any thread
|
||||
Mutex mMutex;
|
||||
@ -3072,6 +3076,77 @@ private:
|
||||
HTMLMediaElement* mElement;
|
||||
};
|
||||
|
||||
void HTMLMediaElement::UpdateSrcMediaStreamPlaying(uint32_t aFlags)
|
||||
{
|
||||
if (!mSrcStream) {
|
||||
return;
|
||||
}
|
||||
// We might be in cycle collection with mSrcStream->GetStream() already
|
||||
// returning null due to unlinking.
|
||||
|
||||
MediaStream* stream = mSrcStream->GetStream();
|
||||
bool shouldPlay = !(aFlags & REMOVING_SRC_STREAM) && !mPaused &&
|
||||
!mPausedForInactiveDocumentOrChannel && stream;
|
||||
if (shouldPlay == mSrcStreamIsPlaying) {
|
||||
return;
|
||||
}
|
||||
mSrcStreamIsPlaying = shouldPlay;
|
||||
|
||||
if (shouldPlay) {
|
||||
mSrcStreamPausedCurrentTime = -1;
|
||||
|
||||
mMediaStreamListener = new StreamListener(this,
|
||||
"HTMLMediaElement::mMediaStreamListener");
|
||||
mMediaStreamSizeListener = new StreamSizeListener(this);
|
||||
stream->AddListener(mMediaStreamListener);
|
||||
stream->AddListener(mMediaStreamSizeListener);
|
||||
|
||||
mWatchManager.Watch(*mMediaStreamListener,
|
||||
&HTMLMediaElement::UpdateReadyStateInternal);
|
||||
|
||||
stream->AddAudioOutput(this);
|
||||
SetVolumeInternal();
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
bool bUseOverlayImage = mSrcStream->AsDOMHwMediaStream() != nullptr;
|
||||
#else
|
||||
bool bUseOverlayImage = false;
|
||||
#endif
|
||||
VideoFrameContainer* container;
|
||||
if (bUseOverlayImage) {
|
||||
container = GetOverlayImageVideoFrameContainer();
|
||||
} else {
|
||||
container = GetVideoFrameContainer();
|
||||
}
|
||||
if (container) {
|
||||
stream->AddVideoOutput(container);
|
||||
}
|
||||
} else {
|
||||
if (stream) {
|
||||
mSrcStreamPausedCurrentTime = CurrentTime();
|
||||
|
||||
stream->RemoveListener(mMediaStreamListener);
|
||||
stream->RemoveListener(mMediaStreamSizeListener);
|
||||
|
||||
stream->RemoveAudioOutput(this);
|
||||
VideoFrameContainer* container = GetVideoFrameContainer();
|
||||
if (container) {
|
||||
stream->RemoveVideoOutput(container);
|
||||
}
|
||||
}
|
||||
// If stream is null, then DOMMediaStream::Destroy must have been
|
||||
// called and that will remove all listeners/outputs.
|
||||
|
||||
mWatchManager.Unwatch(*mMediaStreamListener,
|
||||
&HTMLMediaElement::UpdateReadyStateInternal);
|
||||
|
||||
mMediaStreamListener->Forget();
|
||||
mMediaStreamListener = nullptr;
|
||||
mMediaStreamSizeListener->Forget();
|
||||
mMediaStreamSizeListener = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
|
||||
{
|
||||
NS_ASSERTION(!mSrcStream && !mMediaStreamListener && !mMediaStreamSizeListener,
|
||||
@ -3084,121 +3159,38 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX Remove this if with CameraPreviewMediaStream per bug 1124630.
|
||||
if (!mSrcStream->GetStream()->AsCameraPreviewStream()) {
|
||||
// Now that we have access to |mSrcStream| we can pipe it to our shadow
|
||||
// version |mPlaybackStream|. If two media elements are playing the
|
||||
// same realtime DOMMediaStream, this allows them to pause playback
|
||||
// independently of each other.
|
||||
MediaStreamGraph* graph = mSrcStream->GetStream()->Graph();
|
||||
mPlaybackStream = DOMMediaStream::CreateTrackUnionStream(window, graph);
|
||||
mPlaybackStreamInputPort = mPlaybackStream->GetStream()->AsProcessedStream()->
|
||||
AllocateInputPort(mSrcStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
|
||||
|
||||
nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
|
||||
mPlaybackStream->CombineWithPrincipal(principal);
|
||||
|
||||
// Let |mSrcStream| decide when the stream has finished.
|
||||
GetSrcMediaStream()->AsProcessedStream()->SetAutofinish(true);
|
||||
}
|
||||
|
||||
nsRefPtr<MediaStream> stream = mSrcStream->GetStream();
|
||||
if (stream) {
|
||||
stream->SetAudioChannelType(mAudioChannel);
|
||||
}
|
||||
|
||||
// XXX if we ever support capturing the output of a media element which is
|
||||
// playing a stream, we'll need to add a CombineWithPrincipal call here.
|
||||
mMediaStreamListener = new StreamListener(this, "HTMLMediaElement::mMediaStreamListener");
|
||||
mMediaStreamSizeListener = new StreamSizeListener(this);
|
||||
mWatchManager.Watch(*mMediaStreamListener, &HTMLMediaElement::UpdateReadyStateInternal);
|
||||
|
||||
GetSrcMediaStream()->AddListener(mMediaStreamListener);
|
||||
// Listen for an initial image size on mSrcStream so we can get results even
|
||||
// if we block the mPlaybackStream.
|
||||
stream->AddListener(mMediaStreamSizeListener);
|
||||
if (mPaused) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
|
||||
}
|
||||
if (mPausedForInactiveDocumentOrChannel) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
|
||||
}
|
||||
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
|
||||
|
||||
ChangeDelayLoadStatus(false);
|
||||
GetSrcMediaStream()->AddAudioOutput(this);
|
||||
SetVolumeInternal();
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
bool bUseOverlayImage = mSrcStream->AsDOMHwMediaStream() != nullptr;
|
||||
#else
|
||||
bool bUseOverlayImage = false;
|
||||
#endif
|
||||
VideoFrameContainer* container;
|
||||
|
||||
if (bUseOverlayImage) {
|
||||
container = GetOverlayImageVideoFrameContainer();
|
||||
}
|
||||
else {
|
||||
container = GetVideoFrameContainer();
|
||||
}
|
||||
|
||||
if (container) {
|
||||
GetSrcMediaStream()->AddVideoOutput(container);
|
||||
}
|
||||
|
||||
CheckAutoplayDataReady();
|
||||
UpdateSrcMediaStreamPlaying();
|
||||
|
||||
// Note: we must call DisconnectTrackListListeners(...) before dropping
|
||||
// mSrcStream
|
||||
// mSrcStream.
|
||||
// If we pause this media element, track changes in the underlying stream
|
||||
// will continue to fire events at this element and alter its track list.
|
||||
// That's simpler than delaying the events, but probably confusing...
|
||||
mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
|
||||
|
||||
mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this));
|
||||
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
|
||||
ChangeDelayLoadStatus(false);
|
||||
CheckAutoplayDataReady();
|
||||
|
||||
// FirstFrameLoaded() will be called when the stream has current data.
|
||||
}
|
||||
|
||||
void HTMLMediaElement::EndSrcMediaStreamPlayback()
|
||||
{
|
||||
MediaStream* stream = GetSrcMediaStream();
|
||||
if (stream) {
|
||||
stream->RemoveListener(mMediaStreamListener);
|
||||
}
|
||||
if (mSrcStream->GetStream()) {
|
||||
mSrcStream->GetStream()->RemoveListener(mMediaStreamSizeListener);
|
||||
}
|
||||
MOZ_ASSERT(mSrcStream);
|
||||
|
||||
UpdateSrcMediaStreamPlaying(REMOVING_SRC_STREAM);
|
||||
|
||||
mSrcStream->DisconnectTrackListListeners(AudioTracks(), VideoTracks());
|
||||
|
||||
if (mPlaybackStreamInputPort) {
|
||||
mPlaybackStreamInputPort->Destroy();
|
||||
}
|
||||
|
||||
// Kill its reference to this element
|
||||
mWatchManager.Unwatch(*mMediaStreamListener, &HTMLMediaElement::UpdateReadyStateInternal);
|
||||
mMediaStreamListener->Forget();
|
||||
mMediaStreamListener = nullptr;
|
||||
mMediaStreamSizeListener->Forget();
|
||||
mMediaStreamSizeListener = nullptr;
|
||||
if (stream) {
|
||||
stream->RemoveAudioOutput(this);
|
||||
}
|
||||
VideoFrameContainer* container = GetVideoFrameContainer();
|
||||
if (container) {
|
||||
if (stream) {
|
||||
stream->RemoveVideoOutput(container);
|
||||
}
|
||||
container->ClearCurrentFrame();
|
||||
}
|
||||
if (mPaused && stream) {
|
||||
stream->ChangeExplicitBlockerCount(-1);
|
||||
}
|
||||
if (mPausedForInactiveDocumentOrChannel && stream) {
|
||||
stream->ChangeExplicitBlockerCount(-1);
|
||||
}
|
||||
mSrcStream = nullptr;
|
||||
mPlaybackStreamInputPort = nullptr;
|
||||
mPlaybackStream = nullptr;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::ProcessMediaFragmentURI()
|
||||
@ -3791,6 +3783,7 @@ void HTMLMediaElement::CheckAutoplayDataReady()
|
||||
mPaused = false;
|
||||
// We changed mPaused which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
UpdateSrcMediaStreamPlaying();
|
||||
|
||||
if (mDecoder) {
|
||||
SetPlayedOrSeeked(true);
|
||||
@ -3800,7 +3793,6 @@ void HTMLMediaElement::CheckAutoplayDataReady()
|
||||
mDecoder->Play();
|
||||
} else if (mSrcStream) {
|
||||
SetPlayedOrSeeked(true);
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
|
||||
}
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("play"));
|
||||
|
||||
@ -3990,6 +3982,7 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
|
||||
|
||||
if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
|
||||
mPausedForInactiveDocumentOrChannel = aPauseElement;
|
||||
UpdateSrcMediaStreamPlaying();
|
||||
if (aPauseElement) {
|
||||
if (mMediaSource) {
|
||||
ReportMSETelemetry();
|
||||
@ -4015,8 +4008,6 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
|
||||
if (mDecoder) {
|
||||
mDecoder->Pause();
|
||||
mDecoder->Suspend();
|
||||
} else if (mSrcStream) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
|
||||
}
|
||||
mEventDeliveryPaused = aSuspendEvents;
|
||||
} else {
|
||||
@ -4028,8 +4019,6 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
|
||||
if (!mPaused && !mDecoder->IsEndedOrShutdown()) {
|
||||
mDecoder->Play();
|
||||
}
|
||||
} else if (mSrcStream) {
|
||||
GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
|
||||
}
|
||||
if (mEventDeliveryPaused) {
|
||||
mEventDeliveryPaused = false;
|
||||
@ -4770,11 +4759,11 @@ NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
||||
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
|
||||
AudioChannel::Normal);
|
||||
|
||||
if (!mPlaybackStream) {
|
||||
if (mSrcStream) {
|
||||
mCaptureStreamPort = msg->ConnectToCaptureStream(id, mSrcStream->GetStream());
|
||||
} else {
|
||||
nsRefPtr<DOMMediaStream> stream = CaptureStreamInternal(false, msg);
|
||||
mCaptureStreamPort = msg->ConnectToCaptureStream(id, stream->GetStream());
|
||||
} else {
|
||||
mCaptureStreamPort = msg->ConnectToCaptureStream(id, mPlaybackStream->GetStream());
|
||||
}
|
||||
} else {
|
||||
mAudioCapturedByWindow = false;
|
||||
|
@ -347,14 +347,14 @@ public:
|
||||
*/
|
||||
virtual void FireTimeUpdate(bool aPeriodic) final override;
|
||||
|
||||
/**
|
||||
* This will return null if mSrcStream is null, or if mSrcStream is not
|
||||
* null but its GetStream() returns null --- which can happen during
|
||||
* cycle collection unlinking!
|
||||
*/
|
||||
MediaStream* GetSrcMediaStream() const
|
||||
{
|
||||
NS_ASSERTION(mSrcStream, "Don't call this when not playing a stream");
|
||||
if (!mPlaybackStream) {
|
||||
// XXX Remove this check with CameraPreviewMediaStream per bug 1124630.
|
||||
return mSrcStream->GetStream();
|
||||
}
|
||||
return mPlaybackStream->GetStream();
|
||||
return mSrcStream ? mSrcStream->GetStream() : nullptr;
|
||||
}
|
||||
|
||||
// WebIDL
|
||||
@ -747,6 +747,11 @@ protected:
|
||||
* Stop playback on mSrcStream.
|
||||
*/
|
||||
void EndSrcMediaStreamPlayback();
|
||||
/**
|
||||
* Ensure we're playing mSrcStream if and only if we're not paused.
|
||||
*/
|
||||
enum { REMOVING_SRC_STREAM = 0x1 };
|
||||
void UpdateSrcMediaStreamPlaying(uint32_t aFlags = 0);
|
||||
|
||||
/**
|
||||
* Returns an nsDOMMediaStream containing the played contents of this
|
||||
@ -1081,8 +1086,9 @@ protected:
|
||||
// At most one of mDecoder and mSrcStream can be non-null.
|
||||
nsRefPtr<DOMMediaStream> mSrcStream;
|
||||
|
||||
// Holds a reference to a MediaInputPort connecting mSrcStream to mPlaybackStream.
|
||||
nsRefPtr<MediaInputPort> mPlaybackStreamInputPort;
|
||||
// If non-negative, the time we should return for currentTime while playing
|
||||
// mSrcStream.
|
||||
double mSrcStreamPausedCurrentTime;
|
||||
|
||||
// Holds a reference to the stream connecting this stream to the capture sink.
|
||||
nsRefPtr<MediaInputPort> mCaptureStreamPort;
|
||||
@ -1370,6 +1376,9 @@ protected:
|
||||
// stored in mPreloadURI.
|
||||
bool mSuspendedForPreloadNone;
|
||||
|
||||
// True if we've connected mSrcStream to the media element output.
|
||||
bool mSrcStreamIsPlaying;
|
||||
|
||||
// True if a same-origin check has been done for the media element and resource.
|
||||
bool mMediaSecurityVerified;
|
||||
|
||||
|
@ -461,6 +461,9 @@ public:
|
||||
}
|
||||
void RemoveVideoOutputImpl(VideoFrameContainer* aContainer)
|
||||
{
|
||||
// Ensure that any frames currently queued for playback by the compositor
|
||||
// are removed.
|
||||
aContainer->ClearFutureFrames();
|
||||
mVideoOutputs.RemoveElement(aContainer);
|
||||
}
|
||||
void ChangeExplicitBlockerCountImpl(GraphTime aTime, int32_t aDelta)
|
||||
|
@ -93,7 +93,24 @@ void VideoFrameContainer::ClearCurrentFrame()
|
||||
mImageContainer->GetCurrentImages(&kungFuDeathGrip);
|
||||
|
||||
mImageContainer->ClearAllImages();
|
||||
mImageSizeChanged = false;
|
||||
}
|
||||
|
||||
void VideoFrameContainer::ClearFutureFrames()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
// See comment in SetCurrentFrame for the reasoning behind
|
||||
// using a kungFuDeathGrip here.
|
||||
nsTArray<ImageContainer::OwningImage> kungFuDeathGrip;
|
||||
mImageContainer->GetCurrentImages(&kungFuDeathGrip);
|
||||
|
||||
if (!kungFuDeathGrip.IsEmpty()) {
|
||||
nsTArray<ImageContainer::NonOwningImage> currentFrame;
|
||||
const ImageContainer::OwningImage& img = kungFuDeathGrip[0];
|
||||
currentFrame.AppendElement(ImageContainer::NonOwningImage(img.mImage,
|
||||
img.mTimeStamp, img.mFrameID, img.mProducerID));
|
||||
mImageContainer->SetCurrentImages(currentFrame);
|
||||
}
|
||||
}
|
||||
|
||||
ImageContainer* VideoFrameContainer::GetImageContainer() {
|
||||
|
@ -52,6 +52,9 @@ public:
|
||||
}
|
||||
|
||||
void ClearCurrentFrame();
|
||||
// Make the current frame the only frame in the container, i.e. discard
|
||||
// all future frames.
|
||||
void ClearFutureFrames();
|
||||
// Time in seconds by which the last painted video frame was late by.
|
||||
// E.g. if the last painted frame should have been painted at time t,
|
||||
// but was actually painted at t+n, this returns n in seconds. Threadsafe.
|
||||
|
Loading…
Reference in New Issue
Block a user