1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
// 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_
|