Bug 1576836 - Let audio elements end when a MediaStream becomes inaudible. r=jib

Depends on D43628

Differential Revision: https://phabricator.services.mozilla.com/D43629

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andreas Pehrson 2019-08-31 00:13:42 +00:00
Родитель 9f05e3f58b
Коммит df0968cae9
3 изменённых файлов: 123 добавлений и 12 удалений

Просмотреть файл

@ -4720,10 +4720,8 @@ class HTMLMediaElement::MediaStreamTrackListener
mElement->NotifyMediaStreamTrackRemoved(aTrack);
}
void NotifyActive() override {
if (!mElement) {
return;
}
void OnActive() {
MOZ_ASSERT(mElement);
// mediacapture-main says:
// Note that once ended equals true the HTMLVideoElement will not play media
@ -4756,20 +4754,70 @@ class HTMLMediaElement::MediaStreamTrackListener
mElement->DoLoad();
}
void NotifyInactive() override {
void NotifyActive() override {
if (!mElement) {
return;
}
if (!mElement->IsVideo()) {
// Audio elements use NotifyAudible().
return;
}
OnActive();
}
void NotifyAudible() override {
if (!mElement) {
return;
}
if (mElement->IsVideo()) {
// Video elements use NotifyActive().
return;
}
OnActive();
}
void OnInactive() {
MOZ_ASSERT(mElement);
if (mElement->IsPlaybackEnded()) {
return;
}
LOG(LogLevel::Debug, ("%p, mSrcStream %p became inactive", mElement.get(),
mElement->mSrcStream.get()));
MOZ_ASSERT(!mElement->mSrcStream->Active());
mElement->PlaybackEnded();
mElement->UpdateReadyStateInternal();
}
void NotifyInactive() override {
if (!mElement) {
return;
}
if (!mElement->IsVideo()) {
// Audio elements use NotifyInaudible().
return;
}
OnInactive();
}
void NotifyInaudible() override {
if (!mElement) {
return;
}
if (mElement->IsVideo()) {
// Video elements use NotifyInactive().
return;
}
OnInactive();
}
protected:
const WeakPtr<HTMLMediaElement> mElement;
};

Просмотреть файл

@ -57,6 +57,18 @@ static bool ContainsLiveTracks(
return false;
}
static bool ContainsLiveAudioTracks(
const nsTArray<RefPtr<MediaStreamTrack>>& aTracks) {
for (const auto& track : aTracks) {
if (track->AsAudioStreamTrack() &&
track->ReadyState() == MediaStreamTrackState::Live) {
return true;
}
}
return false;
}
class DOMMediaStream::PlaybackTrackListener : public MediaStreamTrackConsumer {
public:
explicit PlaybackTrackListener(DOMMediaStream* aStream) : mStream(aStream) {}
@ -420,6 +432,24 @@ void DOMMediaStream::NotifyInactive() {
}
}
void DOMMediaStream::NotifyAudible() {
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyAudible(). ", this));
MOZ_ASSERT(mAudible);
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
mTrackListeners[i]->NotifyAudible();
}
}
void DOMMediaStream::NotifyInaudible() {
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyInaudible(). ", this));
MOZ_ASSERT(!mAudible);
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
mTrackListeners[i]->NotifyInaudible();
}
}
void DOMMediaStream::RegisterTrackListener(TrackListener* aListener) {
MOZ_ASSERT(NS_IsMainThread());
@ -454,14 +484,20 @@ void DOMMediaStream::NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) {
mTrackListeners[i]->NotifyTrackAdded(aTrack);
}
if (mActive) {
return;
if (!mActive) {
// Check if we became active.
if (ContainsLiveTracks(mTracks)) {
mActive = true;
NotifyActive();
}
}
// Check if we became active.
if (ContainsLiveTracks(mTracks)) {
mActive = true;
NotifyActive();
if (!mAudible) {
// Check if we became audible.
if (ContainsLiveAudioTracks(mTracks)) {
mAudible = true;
NotifyAudible();
}
}
}
@ -491,6 +527,14 @@ void DOMMediaStream::NotifyTrackRemoved(
return;
}
if (mAudible) {
// Check if we became inaudible.
if (!ContainsLiveAudioTracks(mTracks)) {
mAudible = false;
NotifyInaudible();
}
}
// Check if we became inactive.
if (!ContainsLiveTracks(mTracks)) {
mActive = false;

Просмотреть файл

@ -91,6 +91,16 @@ class DOMMediaStream : public DOMEventTargetHelper,
* Called when the DOMMediaStream has become inactive.
*/
virtual void NotifyInactive(){};
/**
* Called when the DOMMediaStream has become audible.
*/
virtual void NotifyAudible(){};
/**
* Called when the DOMMediaStream has become inaudible.
*/
virtual void NotifyInaudible(){};
};
explicit DOMMediaStream(nsPIDOMWindowInner* aWindow);
@ -196,6 +206,12 @@ class DOMMediaStream : public DOMEventTargetHelper,
// Dispatches NotifyInactive() to all registered track listeners.
void NotifyInactive();
// Dispatches NotifyAudible() to all registered track listeners.
void NotifyAudible();
// Dispatches NotifyInaudible() to all registered track listeners.
void NotifyInaudible();
// Dispatches NotifyTrackAdded() to all registered track listeners.
void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack);
@ -227,6 +243,9 @@ class DOMMediaStream : public DOMEventTargetHelper,
// True if this stream has live tracks.
bool mActive;
// True if this stream has live audio tracks.
bool mAudible;
// For compatibility with mozCaptureStream, we in some cases do not go
// inactive until the MediaDecoder lets us. (Remove this in Bug 1302379)
bool mFinishedOnInactive;