Bug 1348432 - move the mMediaTracksConstructed flag back to MediaDecoder; r?jwwang
This mMediaTracksConstructed flag should belong to a MediaDecoder,
every time a HTMLMediaElement switches its MediaDecoder, the flag should be reset to false again.
So, we move the mMediaTracksConstructed flag back to MediaDecoder, by this way,
HTMLMediaElement provides only the mechanism to construct and remove media tracks,
and MediaDecoder uses the flag, mMediaTracksConstructed, to provide policy.
MozReview-Commit-ID: L7mMAmLjQCy
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3718,17 +3718,16 @@ HTMLMediaElement::HTMLMediaElement(alrea
mDownloadSuspendedByCache(false, "HTMLMediaElement::mDownloadSuspendedByCache"),
mAudioChannel(AudioChannelService::GetDefaultAudioChannel()),
mDisableVideo(false),
mHasUserInteraction(false),
mFirstFrameLoaded(false),
mDefaultPlaybackStartPosition(0.0),
mIsAudioTrackAudible(false),
mHasSuspendTaint(false),
- mMediaTracksConstructed(false),
mVisibilityState(Visibility::UNTRACKED),
mErrorSink(new ErrorSink(this)),
mAudioChannelWrapper(new AudioChannelAgentCallback(this, mAudioChannel))
{
ErrorResult rv;
double defaultVolume = Preferences::GetFloat("media.default_volume", 1.0);
SetVolume(defaultVolume, rv);
@@ -7418,21 +7417,17 @@ nsIDocument*
HTMLMediaElement::GetDocument() const
{
return OwnerDoc();
}
void
HTMLMediaElement::ConstructMediaTracks(const MediaInfo* aInfo)
{
- if (mMediaTracksConstructed || !aInfo) {
- return;
- }
-
- mMediaTracksConstructed = true;
+ MOZ_ASSERT(aInfo);
AudioTrackList* audioList = AudioTracks();
if (audioList && aInfo->HasAudio()) {
const TrackInfo& info = aInfo->mAudio;
RefPtr<AudioTrack> track = MediaTrackList::CreateAudioTrack(
info.mId, info.mKind, info.mLabel, info.mLanguage, info.mEnabled);
audioList->AddTrack(track);
@@ -7456,18 +7451,16 @@ HTMLMediaElement::RemoveMediaTracks()
if (audioList) {
audioList->RemoveTracks();
}
VideoTrackList* videoList = VideoTracks();
if (videoList) {
videoList->RemoveTracks();
}
-
- mMediaTracksConstructed = false;
}
class MediaElementGMPCrashHelper : public GMPCrashHelper
{
public:
explicit MediaElementGMPCrashHelper(HTMLMediaElement* aElement)
: mElement(aElement)
{
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1736,20 +1736,16 @@ private:
// True if the audio track is not silent.
bool mIsAudioTrackAudible;
// True if media element has been marked as 'tainted' and can't
// participate in video decoder suspending.
bool mHasSuspendTaint;
- // True if audio tracks and video tracks are constructed and added into the
- // track list, false if all tracks are removed from the track list.
- bool mMediaTracksConstructed;
-
Visibility mVisibilityState;
UniquePtr<ErrorSink> mErrorSink;
// This wrapper will handle all audio channel related stuffs, eg. the operations
// of tab audio indicator, Fennec's media control.
// Note: mAudioChannelWrapper might be null after GC happened.
RefPtr<AudioChannelAgentCallback> mAudioChannelWrapper;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -388,16 +388,17 @@ MediaDecoder::MediaDecoder(MediaDecoderO
, mInfiniteStream(false)
, mOwner(aOwner)
, mAbstractMainThread(aOwner->AbstractMainThread())
, mFrameStats(new FrameStatistics())
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
, mPlaybackStatistics(new MediaChannelStatistics())
, mPinnedForSeek(false)
, mMinimizePreroll(false)
+ , mMediaTracksConstructed(false)
, mFiredMetadataLoaded(false)
, mIsDocumentVisible(false)
, mElementVisibility(Visibility::UNTRACKED)
, mIsElementInTree(false)
, mForcedHidden(false)
, mHasSuspendTaint(false)
, INIT_MIRROR(mStateMachineIsShutdown, true)
, INIT_MIRROR(mBuffered, TimeIntervals())
@@ -801,17 +802,17 @@ MediaDecoder::GetCurrentPrincipal()
MOZ_ASSERT(NS_IsMainThread());
return mResource ? mResource->GetCurrentPrincipal() : nullptr;
}
void
MediaDecoder::OnMetadataUpdate(TimedMetadata&& aMetadata)
{
MOZ_ASSERT(NS_IsMainThread());
- GetOwner()->RemoveMediaTracks();
+ RemoveMediaTracks();
MetadataLoaded(nsAutoPtr<MediaInfo>(new MediaInfo(*aMetadata.mInfo)),
Move(aMetadata.mTags),
MediaDecoderEventVisibility::Observable);
FirstFrameLoaded(Move(aMetadata.mInfo),
MediaDecoderEventVisibility::Observable);
}
void
@@ -824,17 +825,17 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<M
DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
aInfo->HasAudio(), aInfo->HasVideo());
mMediaSeekable = aInfo->mMediaSeekable;
mMediaSeekableOnlyInBufferedRanges = aInfo->mMediaSeekableOnlyInBufferedRanges;
mInfo = aInfo.forget();
- GetOwner()->ConstructMediaTracks(mInfo);
+ ConstructMediaTracks();
// Make sure the element and the frame (if any) are told about
// our new size.
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
mFiredMetadataLoaded = true;
GetOwner()->MetadataLoaded(mInfo,
nsAutoPtr<const MetadataTags>(aTags.forget()));
}
@@ -1189,19 +1190,19 @@ MediaDecoder::ChangeState(PlayState aSta
if (mNextState == aState) {
mNextState = PLAY_STATE_PAUSED;
}
DECODER_LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
mPlayState = aState;
if (mPlayState == PLAY_STATE_PLAYING) {
- GetOwner()->ConstructMediaTracks(mInfo);
+ ConstructMediaTracks();
} else if (IsEnded()) {
- GetOwner()->RemoveMediaTracks();
+ RemoveMediaTracks();
}
}
void
MediaDecoder::UpdateLogicalPositionInternal()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
@@ -1758,16 +1759,42 @@ MediaDecoder::GetOwner() const
{
MOZ_ASSERT(NS_IsMainThread());
// Check object lifetime when mOwner points to a media element.
MOZ_DIAGNOSTIC_ASSERT(!mOwner || !mIsMediaElement || mElement);
// mOwner is valid until shutdown.
return mOwner;
}
+void
+MediaDecoder::ConstructMediaTracks()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
+
+ if (mMediaTracksConstructed || !mInfo) {
+ return;
+ }
+
+ GetOwner()->ConstructMediaTracks(mInfo);
+
+ mMediaTracksConstructed = true;
+}
+
+void
+MediaDecoder::RemoveMediaTracks()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
+
+ GetOwner()->RemoveMediaTracks();
+
+ mMediaTracksConstructed = false;
+}
+
MediaDecoderOwner::NextFrameStatus
MediaDecoder::NextFrameBufferedStatus()
{
MOZ_ASSERT(NS_IsMainThread());
// Next frame hasn't been decoded yet.
// Use the buffered range to consider if we have the next frame available.
media::TimeUnit currentPosition =
media::TimeUnit::FromMicroseconds(CurrentPosition());
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -395,16 +395,27 @@ private:
* thread.
******/
// Change to a new play state. This updates the mState variable and
// notifies any thread blocking on this object's monitor of the
// change. Call on the main thread only.
virtual void ChangeState(PlayState aState);
+ // Called from MetadataLoaded(). Ask its owner to create audio/video tracks
+ // and adds them to its owner's audio/video track list.
+ // Call on the main thread only.
+ void ConstructMediaTracks();
+
+ // Ask its owner to remove all audio tracks and video tracks that are
+ // previously added into the track list.
+ // Call on the main thread only.
+ void RemoveMediaTracks();
+
+
// Called when the video has completed playing.
// Call on the main thread only.
void PlaybackEnded();
void OnSeekRejected();
void OnSeekResolved();
void SeekingChanged()
@@ -689,16 +700,21 @@ protected:
dom::AudioChannel mAudioChannel;
// True if the decoder has been directed to minimize its preroll before
// playback starts. After the first time playback starts, we don't attempt
// to minimize preroll, as we assume the user is likely to keep playing,
// or play the media again.
bool mMinimizePreroll;
+ // True if audio tracks and video tracks are constructed and added into the
+ // owenr's track list, false if all tracks are removed from the owner's track
+ // list.
+ bool mMediaTracksConstructed;
+
// True if we've already fired metadataloaded.
bool mFiredMetadataLoaded;
// True if the media is seekable (i.e. supports random access).
bool mMediaSeekable = true;
// True if the media is only seekable within its buffered ranges
// like WebMs with no cues.