blob: e4db1a3662fe0a769bb67e772a7f5909dd426047 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
#include <optional>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/browser/media/media_devices_util.h"
#include "content/browser/media/session/media_session_player_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/media_player_id.h"
#include "content/public/browser/web_contents_observer.h"
#include "media/audio/audio_device_description.h"
#include "media/base/media_content_type.h"
#include "media/base/picture_in_picture_events_info.h"
#include "services/media_session/public/cpp/media_position.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
namespace content {
class MediaSessionImpl;
class WebContentsImpl;
// Helper class for controlling a single player's MediaSession instance. Sends
// browser side MediaSession commands back to a player hosted in the renderer
// process.
// MediaSessionController registers itself with MediaSessionImpl as the
// MediaSessionPlayerObserver for the associated player, and for that player
// only. Consequently, it expects all MediaSessionPlayerObserver calls to
// occur for that player only.
class CONTENT_EXPORT MediaSessionController
: public MediaSessionPlayerObserver {
public:
MediaSessionController(const MediaPlayerId& id,
WebContentsImpl* web_contents);
MediaSessionController(const MediaSessionController&) = delete;
MediaSessionController& operator=(const MediaSessionController&) = delete;
~MediaSessionController() override;
// Must be called when media player metadata changes.
void SetMetadata(bool has_audio,
bool has_video,
media::MediaContentType media_content_type);
// Must be called when playback starts. Returns false if a media session
// cannot be created.
bool OnPlaybackStarted();
// Must be called when a pause occurs on the renderer side media player; keeps
// the MediaSession instance in sync with renderer side behavior.
void OnPlaybackPaused(bool reached_end_of_stream);
// MediaSessionPlayerObserver implementation.
void OnSuspend(int player_id) override;
void OnResume(int player_id) override;
void OnSeekForward(int player_id, base::TimeDelta seek_time) override;
void OnSeekBackward(int player_id, base::TimeDelta seek_time) override;
void OnSeekTo(int player_id, base::TimeDelta seek_time) override;
void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
void OnEnterPictureInPicture(int player_id) override;
void OnSetAudioSinkId(int player_id,
const std::string& raw_device_id) override;
void OnSetMute(int player_id, bool mute) override;
void OnRequestMediaRemoting(int player_id) override;
void OnRequestVisibility(
int player_id,
RequestVisibilityCallback request_visibility_callback) override;
RenderFrameHost* render_frame_host() const override;
std::optional<media_session::MediaPosition> GetPosition(
int player_id) const override;
bool IsPictureInPictureAvailable(int player_id) const override;
bool HasSufficientlyVisibleVideo(int player_id) const override;
bool HasAudio(int player_id) const override;
bool HasVideo(int player_id) const override;
bool IsPaused(int player_id) const override;
std::string GetAudioOutputSinkId(int player_id) const override;
bool SupportsAudioOutputDeviceSwitching(int player_id) const override;
media::MediaContentType GetMediaContentType() const override;
void OnAutoPictureInPictureInfoChanged(
int player_id,
const media::PictureInPictureEventsInfo::AutoPipInfo&
auto_picture_in_picture_info) override;
// Test helpers.
int get_player_id_for_testing() const { return player_id_; }
// Called when entering/leaving Picture-in-Picture for the given media
// player.
void PictureInPictureStateChanged(bool is_picture_in_picture);
// Called when the WebContents is either muted or unmuted.
void WebContentsMutedStateChanged(bool muted);
// Called when the media position state of the player has changed.
void OnMediaPositionStateChanged(
const media_session::MediaPosition& position);
void OnMediaMutedStatusChanged(bool mute);
// Called when the media picture-in-picture availability has changed.
void OnPictureInPictureAvailabilityChanged(bool available);
// Called when the audio output device has changed.
void OnAudioOutputSinkChanged(const std::string& raw_device_id);
// Called when the ability to switch audio output devices has been disabled.
void OnAudioOutputSinkChangingDisabled();
// Called when the RemotePlayback metadata has changed.
void OnRemotePlaybackMetadataChanged(
media_session::mojom::RemotePlaybackMetadataPtr metadata);
// Called when video visibility changes for the given media player.
void OnVideoVisibilityChanged(bool meets_visibility_threshold);
private:
bool IsMediaSessionNeeded() const;
// Determines whether a session is needed and adds or removes the player
// accordingly.
bool AddOrRemovePlayer();
void OnHashedSinkIdReceived(const std::string& hashed_sink_id);
const MediaPlayerId id_;
// Outlives |this|.
const raw_ptr<WebContentsImpl> web_contents_;
// Outlives |this|.
const raw_ptr<MediaSessionImpl> media_session_;
std::optional<media_session::MediaPosition> position_;
// These objects are only created on the UI thread, so this is safe.
static int player_count_;
const int player_id_ = player_count_++;
bool is_paused_ = true;
// Playing or paused, but not ended.
bool is_playback_in_progress_ = false;
bool has_audio_ = false;
bool has_video_ = false;
bool is_picture_in_picture_available_ = false;
bool has_sufficiently_visible_video_ = false;
std::string audio_output_sink_id_ =
media::AudioDeviceDescription::kDefaultDeviceId;
bool supports_audio_output_device_switching_ = true;
media::MediaContentType media_content_type_ =
media::MediaContentType::kPersistent;
base::WeakPtrFactory<MediaSessionController> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_