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:
alwu 2020-05-14 05:50:09 +00:00
Родитель bba064955e
Коммит 36c9f9f54a
2 изменённых файлов: 67 добавлений и 0 удалений

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

@ -46,6 +46,11 @@ void MediaPlaybackStatus::DestroyContextInfo(uint64_t aContextId) {
MOZ_ASSERT(NS_IsMainThread());
LOG("Remove context %" PRIu64, 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,
@ -60,6 +65,11 @@ void MediaPlaybackStatus::UpdateMediaAudibleState(uint64_t aContextId,
MOZ_ASSERT(aState == MediaAudibleState::eInaudible);
info.DecreaseAudibleMediaNum();
}
if (ShouldRequestAudioFocusForInfo(info)) {
SetOwningAudioFocusContextId(Some(aContextId));
} else if (ShouldAbandonAudioFocusForInfo(info)) {
ChooseNewContextToOwnAudioFocus();
}
}
bool MediaPlaybackStatus::IsPlaying() const {
@ -101,5 +111,46 @@ MediaPlaybackStatus::GetNotNullContextInfo(uint64_t aContextId) {
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 mozilla

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

@ -27,6 +27,13 @@ namespace dom {
*
* Use `UpdateMediaXXXState()` to update controlled media status, and use
* `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 {
public:
@ -37,6 +44,8 @@ class MediaPlaybackStatus final {
bool IsAudible() const;
bool IsAnyMediaBeingControlled() const;
Maybe<uint64_t> GetAudioFocusOwnerContextId() const;
private:
/**
* This internal class stores detailed media status of controlled media for
@ -90,8 +99,15 @@ class MediaPlaybackStatus final {
ContextMediaInfo& GetNotNullContextInfo(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.
nsDataHashtable<nsUint64HashKey, UniquePtr<ContextMediaInfo>> mContextInfoMap;
Maybe<uint64_t> mOwningAudioFocusContextId;
};
} // namespace dom