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:
JW Wang 2015-07-06 11:36:26 +08:00
parent 3786032de9
commit 9866f1a6d4
6 changed files with 75 additions and 64 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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