зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1627999 - part1 : manage the audio focus in `MediaPlaybackStatus` r=bryce
This patch will do : - introduce a concept `audio focus` among different contexts within a tab - determine the audio focus owner when the context becomes audible or the owner destroys The advantage of doing so : - the audio focus helps us to decide the active media session that would be implemented in the following part More details: When there are serveral contexts playing at the same time within a tab, we would like to determine an audible context from them to represent the tab, and that is the `audio focus` we mean in this bug. Differential Revision: https://phabricator.services.mozilla.com/D72495
This commit is contained in:
Родитель
bba064955e
Коммит
36c9f9f54a
|
@ -46,6 +46,11 @@ void MediaPlaybackStatus::DestroyContextInfo(uint64_t aContextId) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
LOG("Remove context %" PRIu64, aContextId);
|
LOG("Remove context %" PRIu64, aContextId);
|
||||||
mContextInfoMap.Remove(aContextId);
|
mContextInfoMap.Remove(aContextId);
|
||||||
|
// If the removed context is owning the audio focus, we would find another
|
||||||
|
// context to take the audio focus if it's possible.
|
||||||
|
if (IsContextOwningAudioFocus(aContextId)) {
|
||||||
|
ChooseNewContextToOwnAudioFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlaybackStatus::UpdateMediaAudibleState(uint64_t aContextId,
|
void MediaPlaybackStatus::UpdateMediaAudibleState(uint64_t aContextId,
|
||||||
|
@ -60,6 +65,11 @@ void MediaPlaybackStatus::UpdateMediaAudibleState(uint64_t aContextId,
|
||||||
MOZ_ASSERT(aState == MediaAudibleState::eInaudible);
|
MOZ_ASSERT(aState == MediaAudibleState::eInaudible);
|
||||||
info.DecreaseAudibleMediaNum();
|
info.DecreaseAudibleMediaNum();
|
||||||
}
|
}
|
||||||
|
if (ShouldRequestAudioFocusForInfo(info)) {
|
||||||
|
SetOwningAudioFocusContextId(Some(aContextId));
|
||||||
|
} else if (ShouldAbandonAudioFocusForInfo(info)) {
|
||||||
|
ChooseNewContextToOwnAudioFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaPlaybackStatus::IsPlaying() const {
|
bool MediaPlaybackStatus::IsPlaying() const {
|
||||||
|
@ -101,5 +111,46 @@ MediaPlaybackStatus::GetNotNullContextInfo(uint64_t aContextId) {
|
||||||
return *(mContextInfoMap.GetValue(aContextId)->get());
|
return *(mContextInfoMap.GetValue(aContextId)->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<uint64_t> MediaPlaybackStatus::GetAudioFocusOwnerContextId() const {
|
||||||
|
return mOwningAudioFocusContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaPlaybackStatus::ChooseNewContextToOwnAudioFocus() {
|
||||||
|
for (auto iter = mContextInfoMap.ConstIter(); !iter.Done(); iter.Next()) {
|
||||||
|
if (iter.Data()->IsAudible()) {
|
||||||
|
SetOwningAudioFocusContextId(Some(iter.Data()->Id()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No context is audible, so no one should the own audio focus.
|
||||||
|
SetOwningAudioFocusContextId(Nothing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaPlaybackStatus::SetOwningAudioFocusContextId(
|
||||||
|
Maybe<uint64_t>&& aContextId) {
|
||||||
|
if (mOwningAudioFocusContextId == aContextId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mOwningAudioFocusContextId = aContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaPlaybackStatus::ShouldRequestAudioFocusForInfo(
|
||||||
|
const ContextMediaInfo& aInfo) const {
|
||||||
|
return aInfo.IsAudible() && !IsContextOwningAudioFocus(aInfo.Id());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaPlaybackStatus::ShouldAbandonAudioFocusForInfo(
|
||||||
|
const ContextMediaInfo& aInfo) const {
|
||||||
|
// The owner becomes inaudible and there is other context still playing, so we
|
||||||
|
// should switch the audio focus to the audible context.
|
||||||
|
return !aInfo.IsAudible() && IsContextOwningAudioFocus(aInfo.Id()) &&
|
||||||
|
IsAudible();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaPlaybackStatus::IsContextOwningAudioFocus(uint64_t aContextId) const {
|
||||||
|
return mOwningAudioFocusContextId ? *mOwningAudioFocusContextId == aContextId
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -27,6 +27,13 @@ namespace dom {
|
||||||
*
|
*
|
||||||
* Use `UpdateMediaXXXState()` to update controlled media status, and use
|
* Use `UpdateMediaXXXState()` to update controlled media status, and use
|
||||||
* `IsXXX()` methods to acquire the playback status of the tab.
|
* `IsXXX()` methods to acquire the playback status of the tab.
|
||||||
|
*
|
||||||
|
* As we know each context's audible state, we can decide which context should
|
||||||
|
* owns the audio focus when multiple contexts are all playing audible media at
|
||||||
|
* the same time. In that cases, the latest context that plays media would own
|
||||||
|
* the audio focus. When the context owning the audio focus is destroyed, we
|
||||||
|
* would see if there is another other context still playing audible media, and
|
||||||
|
* switch the audio focus to another context.
|
||||||
*/
|
*/
|
||||||
class MediaPlaybackStatus final {
|
class MediaPlaybackStatus final {
|
||||||
public:
|
public:
|
||||||
|
@ -37,6 +44,8 @@ class MediaPlaybackStatus final {
|
||||||
bool IsAudible() const;
|
bool IsAudible() const;
|
||||||
bool IsAnyMediaBeingControlled() const;
|
bool IsAnyMediaBeingControlled() const;
|
||||||
|
|
||||||
|
Maybe<uint64_t> GetAudioFocusOwnerContextId() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* This internal class stores detailed media status of controlled media for
|
* This internal class stores detailed media status of controlled media for
|
||||||
|
@ -90,8 +99,15 @@ class MediaPlaybackStatus final {
|
||||||
ContextMediaInfo& GetNotNullContextInfo(uint64_t aContextId);
|
ContextMediaInfo& GetNotNullContextInfo(uint64_t aContextId);
|
||||||
void DestroyContextInfo(uint64_t aContextId);
|
void DestroyContextInfo(uint64_t aContextId);
|
||||||
|
|
||||||
|
void ChooseNewContextToOwnAudioFocus();
|
||||||
|
void SetOwningAudioFocusContextId(Maybe<uint64_t>&& aContextId);
|
||||||
|
bool IsContextOwningAudioFocus(uint64_t aContextId) const;
|
||||||
|
bool ShouldRequestAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
|
||||||
|
bool ShouldAbandonAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
|
||||||
|
|
||||||
// This contains all the media status of browsing contexts within a tab.
|
// This contains all the media status of browsing contexts within a tab.
|
||||||
nsDataHashtable<nsUint64HashKey, UniquePtr<ContextMediaInfo>> mContextInfoMap;
|
nsDataHashtable<nsUint64HashKey, UniquePtr<ContextMediaInfo>> mContextInfoMap;
|
||||||
|
Maybe<uint64_t> mOwningAudioFocusContextId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
Загрузка…
Ссылка в новой задаче