Bug 1347402 part 4 - move ConstructMediaTracks/RemoveMediaTracks to HTMLMediaElemnt; r?jwwang
ConstructMediaTracks and RemoveMediaTracks are actually HTMLMediaElement's responsibilities.
MozReview-Commit-ID: 8lOdzD4pN7N
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3715,16 +3715,17 @@ 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::APPROXIMATELY_NONVISIBLE),
mErrorSink(new ErrorSink(this)),
mAudioChannelWrapper(new AudioChannelAgentCallback(this, mAudioChannel))
{
ErrorResult rv;
double defaultVolume = Preferences::GetFloat("media.default_volume", 1.0);
SetVolume(defaultVolume, rv);
@@ -7410,16 +7411,61 @@ HTMLMediaElement::NotifyDecoderActivityC
}
nsIDocument*
HTMLMediaElement::GetDocument() const
{
return OwnerDoc();
}
+void
+HTMLMediaElement::ConstructMediaTracks(const MediaInfo* aInfo)
+{
+ if (mMediaTracksConstructed || !aInfo) {
+ return;
+ }
+
+ mMediaTracksConstructed = true;
+
+ 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);
+ }
+
+ VideoTrackList* videoList = VideoTracks();
+ if (videoList && aInfo->HasVideo()) {
+ const TrackInfo& info = aInfo->mVideo;
+ RefPtr<VideoTrack> track = MediaTrackList::CreateVideoTrack(
+ info.mId, info.mKind, info.mLabel, info.mLanguage);
+
+ videoList->AddTrack(track);
+ track->SetEnabledInternal(info.mEnabled, MediaTrack::FIRE_NO_EVENTS);
+ }
+}
+
+void
+HTMLMediaElement::RemoveMediaTracks()
+{
+ AudioTrackList* audioList = AudioTracks();
+ if (audioList) {
+ audioList->RemoveTracks();
+ }
+
+ VideoTrackList* videoList = VideoTracks();
+ if (videoList) {
+ videoList->RemoveTracks();
+ }
+
+ mMediaTracksConstructed = false;
+}
+
bool HasDebuggerPrivilege(JSContext* aCx, JSObject* aObj)
{
return nsContentUtils::CallerHasPermission(aCx,
NS_LITERAL_STRING("debugger"));
}
} // namespace dom
} // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -771,16 +771,20 @@ public:
CREATE_PATTERN,
CREATE_IMAGEBITMAP,
CAPTURE_STREAM,
};
void MarkAsContentSource(CallerAPI aAPI);
nsIDocument* GetDocument() const override;
+ void ConstructMediaTracks(const MediaInfo* aInfo) override;
+
+ void RemoveMediaTracks() override;
+
protected:
virtual ~HTMLMediaElement();
class AudioChannelAgentCallback;
class ChannelLoader;
class ErrorSink;
class MediaLoadListener;
class MediaStreamTracksAvailableCallback;
@@ -1730,16 +1734,20 @@ 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
@@ -389,17 +389,16 @@ 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)
, mIsElementVisible(false)
, mIsElementInTree(false)
, mForcedHidden(false)
, mHasSuspendTaint(false)
, INIT_MIRROR(mStateMachineIsShutdown, true)
, INIT_MIRROR(mBuffered, TimeIntervals())
@@ -803,17 +802,17 @@ MediaDecoder::GetCurrentPrincipal()
MOZ_ASSERT(NS_IsMainThread());
return mResource ? mResource->GetCurrentPrincipal() : nullptr;
}
void
MediaDecoder::OnMetadataUpdate(TimedMetadata&& aMetadata)
{
MOZ_ASSERT(NS_IsMainThread());
- RemoveMediaTracks();
+ GetOwner()->RemoveMediaTracks();
MetadataLoaded(nsAutoPtr<MediaInfo>(new MediaInfo(*aMetadata.mInfo)),
Move(aMetadata.mTags),
MediaDecoderEventVisibility::Observable);
FirstFrameLoaded(Move(aMetadata.mInfo),
MediaDecoderEventVisibility::Observable);
}
void
@@ -826,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();
- ConstructMediaTracks();
+ GetOwner()->ConstructMediaTracks(mInfo);
// 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()));
}
@@ -1214,19 +1213,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) {
- ConstructMediaTracks();
+ GetOwner()->ConstructMediaTracks(mInfo);
} else if (IsEnded()) {
- RemoveMediaTracks();
+ GetOwner()->RemoveMediaTracks();
}
}
void
MediaDecoder::UpdateLogicalPositionInternal()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
@@ -1776,77 +1775,16 @@ 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;
- }
-
- HTMLMediaElement* element = GetOwner()->GetMediaElement();
- if (!element) {
- return;
- }
-
- mMediaTracksConstructed = true;
-
- AudioTrackList* audioList = element->AudioTracks();
- if (audioList && mInfo->HasAudio()) {
- const TrackInfo& info = mInfo->mAudio;
- RefPtr<AudioTrack> track = MediaTrackList::CreateAudioTrack(
- info.mId, info.mKind, info.mLabel, info.mLanguage, info.mEnabled);
-
- audioList->AddTrack(track);
- }
-
- VideoTrackList* videoList = element->VideoTracks();
- if (videoList && mInfo->HasVideo()) {
- const TrackInfo& info = mInfo->mVideo;
- RefPtr<VideoTrack> track = MediaTrackList::CreateVideoTrack(
- info.mId, info.mKind, info.mLabel, info.mLanguage);
-
- videoList->AddTrack(track);
- track->SetEnabledInternal(info.mEnabled, MediaTrack::FIRE_NO_EVENTS);
- }
-}
-
-void
-MediaDecoder::RemoveMediaTracks()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
-
- HTMLMediaElement* element = GetOwner()->GetMediaElement();
- if (!element) {
- return;
- }
-
- AudioTrackList* audioList = element->AudioTracks();
- if (audioList) {
- audioList->RemoveTracks();
- }
-
- VideoTrackList* videoList = element->VideoTracks();
- if (videoList) {
- videoList->RemoveTracks();
- }
-
- 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
@@ -394,25 +394,16 @@ 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(). Creates audio tracks and adds them to its
- // owner's audio track list, and implies to video tracks respectively.
- // Call on the main thread only.
- void ConstructMediaTracks();
-
- // Removes 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()
@@ -697,20 +688,16 @@ 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
- // track list, false if all tracks are removed from the 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.
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -7,16 +7,17 @@
#define MediaDecoderOwner_h_
#include "AbstractMediaDecoder.h"
#include "nsAutoPtr.h"
namespace mozilla {
class AbstractThread;
class VideoFrameContainer;
+class MediaInfo;
class MediaResult;
namespace dom {
class HTMLMediaElement;
} // namespace dom
class MediaDecoderOwner
{
@@ -155,14 +156,22 @@ public:
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
// Main thread only.
virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType) = 0;
// Return the decoder owner's owner document.
virtual nsIDocument* GetDocument() const = 0;
+
+ // Called by the media decoder to create audio/video tracks and add to its
+ // owner's track list.
+ virtual void ConstructMediaTracks(const MediaInfo* aInfo) = 0;
+
+ // Called by the media decoder to removes all audio/video tracks from its
+ // owner's track list.
+ virtual void RemoveMediaTracks() = 0;
};
} // namespace mozilla
#endif
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -50,12 +50,14 @@ public:
void SetAudibleState(bool aAudible) override {}
void NotifyXPCOMShutdown() override {}
AbstractThread* AbstractMainThread() const override
{
// Non-DocGroup version for Mock.
return AbstractThread::MainThread();
}
nsIDocument* GetDocument() const { return nullptr; }
+ void ConstructMediaTracks(const MediaInfo* aInfo) {}
+ void RemoveMediaTracks() {}
};
}
#endif