mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1179665. Part 4 - remove MDSM::RecreateDecodedStream() which runs on the main thread and doesn't fit into the thread model of MDSM. r=roc.
This commit is contained in:
parent
3786032de9
commit
9866f1a6d4
@ -88,7 +88,7 @@ UpdateStreamBlocking(MediaStream* aStream, bool aBlocking)
|
||||
}
|
||||
}
|
||||
|
||||
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream)
|
||||
DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream, bool aPlaying)
|
||||
: mAudioFramesWritten(0)
|
||||
, mNextVideoTime(-1)
|
||||
, mNextAudioTime(-1)
|
||||
@ -97,13 +97,16 @@ DecodedStreamData::DecodedStreamData(SourceMediaStream* aStream)
|
||||
, mHaveSentFinishAudio(false)
|
||||
, mHaveSentFinishVideo(false)
|
||||
, mStream(aStream)
|
||||
, mPlaying(false)
|
||||
, mPlaying(aPlaying)
|
||||
, mEOSVideoCompensation(false)
|
||||
{
|
||||
mListener = new DecodedStreamGraphListener(mStream);
|
||||
mStream->AddListener(mListener);
|
||||
// Block the stream as mPlaying is initially false.
|
||||
UpdateStreamBlocking(mStream, true);
|
||||
|
||||
// Block the stream if we are not playing.
|
||||
if (!aPlaying) {
|
||||
UpdateStreamBlocking(mStream, true);
|
||||
}
|
||||
}
|
||||
|
||||
DecodedStreamData::~DecodedStreamData()
|
||||
@ -184,17 +187,11 @@ OutputStreamData::Init(DecodedStream* aDecodedStream, ProcessedMediaStream* aStr
|
||||
|
||||
DecodedStream::DecodedStream()
|
||||
: mMonitor("DecodedStream::mMonitor")
|
||||
, mPlaying(false)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
DecodedStreamData*
|
||||
DecodedStream::GetData() const
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
return mData.get();
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::DestroyData()
|
||||
{
|
||||
@ -230,6 +227,16 @@ DecodedStream::DestroyData()
|
||||
mData = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::RecreateData()
|
||||
{
|
||||
nsRefPtr<DecodedStream> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void {
|
||||
self->RecreateData(nullptr);
|
||||
});
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::RecreateData(MediaStreamGraph* aGraph)
|
||||
{
|
||||
@ -243,7 +250,7 @@ DecodedStream::RecreateData(MediaStreamGraph* aGraph)
|
||||
}
|
||||
auto source = aGraph->CreateSourceStream(nullptr);
|
||||
DestroyData();
|
||||
mData.reset(new DecodedStreamData(source));
|
||||
mData.reset(new DecodedStreamData(source, mPlaying));
|
||||
|
||||
// Note that the delay between removing ports in DestroyDecodedStream
|
||||
// and adding new ones won't cause a glitch since all graph operations
|
||||
@ -292,6 +299,10 @@ DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (!mData) {
|
||||
RecreateData(aStream->Graph());
|
||||
}
|
||||
|
||||
OutputStreamData* os = OutputStreams().AppendElement();
|
||||
os->Init(this, aStream);
|
||||
Connect(os);
|
||||
@ -326,8 +337,10 @@ void
|
||||
DecodedStream::SetPlaying(bool aPlaying)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mData);
|
||||
mData->SetPlaying(aPlaying);
|
||||
mPlaying = aPlaying;
|
||||
if (mData) {
|
||||
mData->SetPlaying(aPlaying);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -643,4 +656,18 @@ DecodedStream::AudioEndTime(int64_t aStartTime, uint32_t aRate) const
|
||||
return aStartTime + FramesToUsecs(mData->mAudioFramesWritten, aRate);
|
||||
}
|
||||
|
||||
int64_t
|
||||
DecodedStream::GetPosition() const
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
return mData->GetPosition();
|
||||
}
|
||||
|
||||
bool
|
||||
DecodedStream::IsFinished() const
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
return mData->IsFinished();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -47,7 +47,7 @@ class Image;
|
||||
*/
|
||||
class DecodedStreamData {
|
||||
public:
|
||||
explicit DecodedStreamData(SourceMediaStream* aStream);
|
||||
DecodedStreamData(SourceMediaStream* aStream, bool aPlaying);
|
||||
~DecodedStreamData();
|
||||
bool IsFinished() const;
|
||||
int64_t GetPosition() const;
|
||||
@ -94,17 +94,19 @@ public:
|
||||
};
|
||||
|
||||
class DecodedStream {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodedStream);
|
||||
public:
|
||||
DecodedStream();
|
||||
DecodedStreamData* GetData() const;
|
||||
void DestroyData();
|
||||
void RecreateData(MediaStreamGraph* aGraph);
|
||||
void RecreateData();
|
||||
void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
void Remove(MediaStream* aStream);
|
||||
void SetPlaying(bool aPlaying);
|
||||
bool HaveEnoughAudio(const MediaInfo& aInfo) const;
|
||||
bool HaveEnoughVideo(const MediaInfo& aInfo) const;
|
||||
CheckedInt64 AudioEndTime(int64_t aStartTime, uint32_t aRate) const;
|
||||
int64_t GetPosition() const;
|
||||
bool IsFinished() const;
|
||||
|
||||
// Return true if stream is finished.
|
||||
bool SendData(int64_t aStartTime,
|
||||
@ -113,8 +115,12 @@ public:
|
||||
MediaQueue<VideoData>& aVideoQueue,
|
||||
double aVolume, bool aIsSameOrigin);
|
||||
|
||||
protected:
|
||||
virtual ~DecodedStream() {}
|
||||
|
||||
private:
|
||||
ReentrantMonitor& GetReentrantMonitor() const;
|
||||
void RecreateData(MediaStreamGraph* aGraph);
|
||||
void Connect(OutputStreamData* aStream);
|
||||
nsTArray<OutputStreamData>& OutputStreams();
|
||||
void InitTracks(int64_t aStartTime, const MediaInfo& aInfo);
|
||||
@ -142,6 +148,8 @@ private:
|
||||
// Please move all capture-stream related code from MDSM into DecodedStream
|
||||
// and apply "dispatch + mirroring" to get rid of this monitor in the future.
|
||||
mutable ReentrantMonitor mMonitor;
|
||||
|
||||
bool mPlaying;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -239,7 +239,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mDecodingFrozenAtStateDecoding(false),
|
||||
mSentLoadedMetadataEvent(false),
|
||||
mSentFirstFrameLoadedEvent(false),
|
||||
mSentPlaybackEndedEvent(false)
|
||||
mSentPlaybackEndedEvent(false),
|
||||
mDecodedStream(new DecodedStream())
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
@ -363,12 +364,12 @@ void MediaDecoderStateMachine::SendStreamData()
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(!mAudioSink, "Should've been stopped in RunStateMachine()");
|
||||
|
||||
bool finished = mDecodedStream.SendData(
|
||||
bool finished = mDecodedStream->SendData(
|
||||
mStreamStartTime, mInfo, AudioQueue(), VideoQueue(),
|
||||
mVolume, mDecoder->IsSameOriginMedia());
|
||||
|
||||
if (mInfo.HasAudio()) {
|
||||
CheckedInt64 playedUsecs = mDecodedStream.AudioEndTime(
|
||||
CheckedInt64 playedUsecs = mDecodedStream->AudioEndTime(
|
||||
mStreamStartTime, mInfo.mAudio.mRate);
|
||||
if (playedUsecs.isValid()) {
|
||||
OnAudioEndTimeUpdate(playedUsecs.value());
|
||||
@ -406,7 +407,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
|
||||
return false;
|
||||
}
|
||||
|
||||
return !mAudioCaptured || mDecodedStream.HaveEnoughAudio(mInfo);
|
||||
return !mAudioCaptured || mDecodedStream->HaveEnoughAudio(mInfo);
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
|
||||
@ -418,7 +419,7 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
|
||||
return false;
|
||||
}
|
||||
|
||||
return !mAudioCaptured || mDecodedStream.HaveEnoughVideo(mInfo);
|
||||
return !mAudioCaptured || mDecodedStream->HaveEnoughVideo(mInfo);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1563,9 +1564,7 @@ MediaDecoderStateMachine::InitiateSeek()
|
||||
mCurrentSeek.mTarget.mTime = seekTime;
|
||||
|
||||
if (mAudioCaptured) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArgs<MediaStreamGraph*>(
|
||||
this, &MediaDecoderStateMachine::RecreateDecodedStream, nullptr);
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
mDecodedStream->RecreateData();
|
||||
}
|
||||
|
||||
mDropAudioUntilNextDiscontinuity = HasAudio();
|
||||
@ -2386,7 +2385,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
// end of the media, and so that we update the readyState.
|
||||
if (VideoQueue().GetSize() > 0 ||
|
||||
(HasAudio() && !mAudioCompleted) ||
|
||||
(mAudioCaptured && !GetDecodedStream()->IsFinished()))
|
||||
(mAudioCaptured && !mDecodedStream->IsFinished()))
|
||||
{
|
||||
// Start playback if necessary to play the remaining media.
|
||||
MaybeStartPlayback();
|
||||
@ -2545,7 +2544,7 @@ int64_t MediaDecoderStateMachine::GetStreamClock() const
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
return mStreamStartTime + GetDecodedStream()->GetPosition();
|
||||
return mStreamStartTime + mDecodedStream->GetPosition();
|
||||
}
|
||||
|
||||
int64_t MediaDecoderStateMachine::GetVideoStreamPosition() const
|
||||
@ -2929,9 +2928,11 @@ void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp)
|
||||
|
||||
if (mAudioSink) {
|
||||
mAudioSink->SetPlaying(!mPlayStartTime.IsNull());
|
||||
} else if (mAudioCaptured) {
|
||||
mDecodedStream.SetPlaying(!mPlayStartTime.IsNull());
|
||||
}
|
||||
// Have DecodedStream remember the playing state so it doesn't need to
|
||||
// ask MDSM about IsPlaying(). Note we have to do this even before capture
|
||||
// happens since capture could happen in the middle of playback.
|
||||
mDecodedStream->SetPlaying(!mPlayStartTime.IsNull());
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
|
||||
@ -3112,11 +3113,6 @@ uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
|
||||
: std::max<uint32_t>(sVideoQueueDefaultSize, MIN_VIDEO_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
DecodedStreamData* MediaDecoderStateMachine::GetDecodedStream() const
|
||||
{
|
||||
return mDecodedStream.GetData();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::DispatchAudioCaptured()
|
||||
{
|
||||
nsRefPtr<MediaDecoderStateMachine> self = this;
|
||||
@ -3143,28 +3139,10 @@ void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
|
||||
|
||||
if (!GetDecodedStream()) {
|
||||
RecreateDecodedStream(aStream->Graph());
|
||||
}
|
||||
mDecodedStream.Connect(aStream, aFinishWhenEnded);
|
||||
mDecodedStream->Connect(aStream, aFinishWhenEnded);
|
||||
DispatchAudioCaptured();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::RecreateDecodedStream(MediaStreamGraph* aGraph)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mDecodedStream.RecreateData(aGraph);
|
||||
|
||||
nsRefPtr<MediaDecoderStateMachine> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
|
||||
self->mDecodedStream.SetPlaying(self->IsPlaying());
|
||||
});
|
||||
TaskQueue()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// avoid redefined macro in unified build
|
||||
|
@ -145,8 +145,6 @@ public:
|
||||
DECODER_STATE_ERROR
|
||||
};
|
||||
|
||||
DecodedStreamData* GetDecodedStream() const;
|
||||
|
||||
void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
|
||||
// Set/Unset dormant state.
|
||||
@ -160,11 +158,6 @@ private:
|
||||
|
||||
void DispatchAudioCaptured();
|
||||
|
||||
// Recreates mDecodedStream. Call this to create mDecodedStream at first,
|
||||
// and when seeking, to ensure a new stream is set up with fresh buffers.
|
||||
// Decoder monitor must be held.
|
||||
void RecreateDecodedStream(MediaStreamGraph* aGraph);
|
||||
|
||||
void Shutdown();
|
||||
public:
|
||||
|
||||
@ -320,7 +313,7 @@ public:
|
||||
if (mReader) {
|
||||
mReader->BreakCycles();
|
||||
}
|
||||
mDecodedStream.DestroyData();
|
||||
mDecodedStream->DestroyData();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
@ -1356,7 +1349,7 @@ protected:
|
||||
// Only written on the main thread while holding the monitor. Therefore it
|
||||
// can be read on any thread while holding the monitor, or on the main thread
|
||||
// without holding the monitor.
|
||||
DecodedStream mDecodedStream;
|
||||
nsRefPtr<DecodedStream> mDecodedStream;
|
||||
};
|
||||
|
||||
} // namespace mozilla;
|
||||
|
@ -28,6 +28,7 @@ MediaOmxCommonDecoder::MediaOmxCommonDecoder()
|
||||
, mReader(nullptr)
|
||||
, mCanOffloadAudio(false)
|
||||
, mFallbackToStateMachine(false)
|
||||
, mIsCaptured(false)
|
||||
{
|
||||
mDormantSupported = true;
|
||||
if (!gMediaDecoderLog) {
|
||||
@ -48,8 +49,7 @@ bool
|
||||
MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
|
||||
{
|
||||
return (mCanOffloadAudio && !mFallbackToStateMachine &&
|
||||
!(GetStateMachine() && GetStateMachine()->GetDecodedStream()) &&
|
||||
mPlaybackRate == 1.0);
|
||||
!mIsCaptured && mPlaybackRate == 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -183,6 +183,8 @@ MediaOmxCommonDecoder::AddOutputStream(ProcessedMediaStream* aStream,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mIsCaptured = true;
|
||||
|
||||
if (mAudioOffloadPlayer) {
|
||||
ResumeStateMachine();
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ protected:
|
||||
// Set when offload playback of current track fails in the middle and need to
|
||||
// fallback to state machine
|
||||
bool mFallbackToStateMachine;
|
||||
|
||||
// True if the media element is captured.
|
||||
bool mIsCaptured;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user