0

Fix a bug where content does not play on Spotify.

Apparently spotify's initial audio config specifies that the content is
unencrypted, despite a DRM system being required to play the content.
Other apps correctly set the encryption type in the config.

To work around this, we can always pass an SbDrmSystem to the SbPlayer.
This seems to work fine even for unencrypted content (e.g. Big Buck
Bunny, cast via CACTool).

Test: Cast Spotify to a 3P TV. Playback works now.
Bug: b:416755033
Change-Id: I67b9a32e0a9b149e583c707631c48e35ff7b787c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6534429
Reviewed-by: Shawn Quereshi <shawnq@google.com>
Commit-Queue: Antonio Rivera <antoniori@google.com>
Cr-Commit-Position: refs/heads/main@{#1459629}
This commit is contained in:
Antonio Rivera
2025-05-13 12:09:10 -07:00
committed by Chromium LUCI CQ
parent 4210b8d5c3
commit 36db52f940
3 changed files with 12 additions and 23 deletions

@ -112,6 +112,7 @@ test("media_pipeline_backend_starboard_test") {
"//base/test:test_support",
"//chromecast/public",
"//chromecast/public/media",
"//chromecast/starboard/media/cdm:starboard_drm_wrapper",
"//testing/gmock",
"//testing/gtest",
]

@ -221,20 +221,12 @@ void MediaPipelineBackendStarboard::OnGeometryChanged(
void MediaPipelineBackendStarboard::CreatePlayer() {
DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
bool has_drm = false;
StarboardPlayerCreationParam params = {};
if (audio_decoder_) {
const std::optional<StarboardAudioSampleInfo>& audio_info =
audio_decoder_->GetAudioSampleInfo();
CHECK(audio_info);
params.audio_sample_info = *audio_info;
std::optional<EncryptionScheme> encryption_scheme =
audio_decoder_->GetEncryptionScheme();
if (encryption_scheme.has_value() &&
*encryption_scheme != EncryptionScheme::kUnencrypted) {
has_drm = true;
}
}
if (video_decoder_) {
const std::optional<StarboardVideoSampleInfo>& video_info =
@ -247,21 +239,9 @@ void MediaPipelineBackendStarboard::CreatePlayer() {
// prioritize minimizing latency (render the frames as soon as possible).
params.video_sample_info.max_video_capabilities = "streaming=1";
}
std::optional<EncryptionScheme> encryption_scheme =
video_decoder_->GetEncryptionScheme();
if (encryption_scheme.has_value() &&
*encryption_scheme != EncryptionScheme::kUnencrypted) {
has_drm = true;
}
}
if (has_drm) {
params.drm_system = StarboardDrmWrapper::GetInstance().GetDrmSystem();
} else {
params.drm_system = nullptr;
}
params.drm_system = StarboardDrmWrapper::GetInstance().GetDrmSystem();
params.output_mode = kStarboardPlayerOutputModePunchOut;
player_ =
starboard_->CreatePlayer(&params,

@ -8,6 +8,7 @@
#include "chromecast/public/graphics_types.h"
#include "chromecast/public/media/media_pipeline_device_params.h"
#include "chromecast/public/volume_control.h"
#include "chromecast/starboard/media/cdm/starboard_drm_wrapper.h"
#include "chromecast/starboard/media/media/mock_starboard_api_wrapper.h"
#include "chromecast/starboard/media/media/starboard_api_wrapper.h"
#include "testing/gmock/include/gmock/gmock.h"
@ -99,8 +100,12 @@ class MediaPipelineBackendStarboardTest : public ::testing::Test {
// Sets up default behavior for the mock functions that return values, so
// that tests that do not care about this functionality can ignore them.
ON_CALL(*starboard_, CreatePlayer).WillByDefault(Return(&fake_player_));
ON_CALL(*starboard_, CreateDrmSystem)
.WillByDefault(Return(&fake_drm_system_));
ON_CALL(*starboard_, EnsureInitialized).WillByDefault(Return(true));
ON_CALL(*starboard_, SetPlaybackRate).WillByDefault(Return(true));
StarboardDrmWrapper::SetSingletonForTesting(starboard_.get());
}
~MediaPipelineBackendStarboardTest() override = default;
@ -110,9 +115,12 @@ class MediaPipelineBackendStarboardTest : public ::testing::Test {
// This will be passed to the MediaPipelineBackendStarboard, and all calls to
// Starboard will go through it. Thus, we can mock out those calls.
std::unique_ptr<MockStarboardApiWrapper> starboard_;
// Since SbPlayer is just an opaque blob to the MPB, we will simply use an int
// to represent it.
// Since SbPlayer is just an opaque blob to cast code, we will simply use an
// int to represent it.
int fake_player_ = 1;
// Since SbDrmSystem is just an opaque blob to cast code, we will simply use
// an int to represent it.
int fake_drm_system_ = 2;
StarboardVideoPlane video_plane_;
MediaPipelineDeviceParams device_params_;
};