Skip to content

Commit 963bae9

Browse files
copybara-githubtonihei
authored andcommitted
Merge pull request #2235 from MGaetan89:add_CastPlayer_playlistMetadata
PiperOrigin-RevId: 738455260 (cherry picked from commit 2d1bcc7)
1 parent dcb6710 commit 963bae9

File tree

3 files changed

+123
-8
lines changed

3 files changed

+123
-8
lines changed

RELEASENOTES.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,83 @@
11
# Release notes
22

3+
* Cast extension:
4+
* Add support for playlist metadata
5+
([#2235](https://github.com/androidx/media/pull/2235)).
6+
7+
### Unreleased changes
8+
9+
* Common Library:
10+
* ExoPlayer:
11+
* Transformer:
12+
* Track Selection:
13+
* Extractors:
14+
* MP3: Use duration and data size from unseekable Xing, VBRI and similar
15+
variable bitrate metadata when falling back to constant bitrate seeking
16+
due to `FLAG_ENABLE_CONSTANT_BITRATE_SEEKING(_ALWAYS)`
17+
([#2194](https://github.com/androidx/media/issues/2194)).
18+
* DataSource:
19+
* Audio:
20+
* Allow constant power upmixing/downmixing in DefaultAudioMixer.
21+
* Video:
22+
* Add experimental `ExoPlayer` API to include the
23+
`MediaCodec.BUFFER_FLAG_DECODE_ONLY` flag when queuing decode-only input
24+
buffers. This flag will signal the decoder to skip the decode-only
25+
buffers thereby resulting in faster seeking. Enable it with
26+
`DefaultRenderersFactory.experimentalSetEnableMediaCodecBufferDecodeOnlyFlag`.
27+
* Text:
28+
* Metadata:
29+
* Image:
30+
* DataSource:
31+
* DRM:
32+
* Effect:
33+
* Add `Presentation.createForShortSide(int)` that creates a `Presentation`
34+
that ensures the shortest side always matches the given value,
35+
regardless of input orientation.
36+
* Muxers:
37+
* `writeSampleData()` API now uses muxer specific `BufferInfo` class
38+
instead of `MediaCodec.BufferInfo`.
39+
* IMA extension:
40+
* Session:
41+
* UI:
42+
* Downloads:
43+
* Add partial download support for progressive streams. Apps can prepare a
44+
progressive stream with `DownloadHelper`, and request a
45+
`DownloadRequest` from the helper with specifying the time-based media
46+
start and end positions that the download should cover. The returned
47+
`DownloadRequest` carries the resolved byte range, with which a
48+
`ProgressiveDownloader` can be created and download the content
49+
correspondingly.
50+
* OkHttp extension:
51+
* Cronet extension:
52+
* RTMP extension:
53+
* HLS extension:
54+
* DASH extension:
55+
* Smooth Streaming extension:
56+
* RTSP extension:
57+
* Decoder extensions (FFmpeg, VP9, AV1, etc.):
58+
* MIDI extension:
59+
* Leanback extension:
60+
* Cast extension:
61+
* Test Utilities:
62+
* Demo app:
63+
* Add `PlaybackSpeedPopUpButton` Composable UI element to be part of
64+
`ExtraControls` in `demo-compose`.
65+
* Remove deprecated symbols:
66+
* Removed deprecated `SegmentDownloader` constructor
67+
`SegmentDownloader(MediaItem, Parser<M>, CacheDataSource.Factory,
68+
Executor)` and the corresponding constructors in its subclasses
69+
`DashDownloader`, `HlsDownloader` and `SsDownloader`.
70+
* Removed deprecated `Player.hasNext()`, `Player.hasNextWindow()`. Use
71+
`Player.hasNextMediaItem()` instead.
72+
* Removed deprecated `Player.next()`. Use `Player.seekToNextMediaItem()`
73+
instead.
74+
* Removed deprecated `Player.seekToPreviousWindow()`. Use
75+
`Player.seekToPreviousMediaItem()` instead.
76+
* Removed deprecated `Player.seekToNextWindow()`. Use
77+
`Player.seekToNextMediaItem()` instead.
78+
* Removed deprecated `BaseAudioProcessor` in `exoplayer` module. Use
79+
`BaseAudioProcessor` under `common` module.
80+
381
## 1.6
482

583
### 1.6.0 (2025-03-26)

libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package androidx.media3.cast;
1717

1818
import static androidx.media3.common.util.Assertions.checkArgument;
19+
import static androidx.media3.common.util.Assertions.checkNotNull;
1920
import static androidx.media3.common.util.Util.SDK_INT;
2021
import static androidx.media3.common.util.Util.castNonNull;
2122
import static java.lang.Math.min;
@@ -166,6 +167,7 @@ public final class CastPlayer extends BasePlayer {
166167
private long pendingSeekPositionMs;
167168
@Nullable private PositionInfo pendingMediaItemRemovalPosition;
168169
private MediaMetadata mediaMetadata;
170+
private MediaMetadata playlistMetadata;
169171
private DeviceInfo deviceInfo;
170172

171173
/**
@@ -268,6 +270,7 @@ public CastPlayer(
268270
playbackState = STATE_IDLE;
269271
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
270272
mediaMetadata = MediaMetadata.EMPTY;
273+
playlistMetadata = MediaMetadata.EMPTY;
271274
currentTracks = Tracks.EMPTY;
272275
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
273276
pendingSeekWindowIndex = C.INDEX_UNSET;
@@ -656,14 +659,19 @@ public MediaMetadata getMediaMetadataInternal() {
656659

657660
@Override
658661
public MediaMetadata getPlaylistMetadata() {
659-
// CastPlayer does not currently support metadata.
660-
return MediaMetadata.EMPTY;
662+
return playlistMetadata;
661663
}
662664

663-
/** This method is not supported and does nothing. */
664665
@Override
665-
public void setPlaylistMetadata(MediaMetadata mediaMetadata) {
666-
// CastPlayer does not currently support metadata.
666+
public void setPlaylistMetadata(MediaMetadata playlistMetadata) {
667+
checkNotNull(playlistMetadata);
668+
if (playlistMetadata.equals(this.playlistMetadata)) {
669+
return;
670+
}
671+
this.playlistMetadata = playlistMetadata;
672+
listeners.sendEvent(
673+
EVENT_PLAYLIST_METADATA_CHANGED,
674+
listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata));
667675
}
668676

669677
@Override

libraries/cast/src/test/java/androidx/media3/cast/CastPlayerTest.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,7 @@ public void setRepeatMode_one_doesNotNotifyAvailableCommandsChanged() {
18001800
}
18011801

18021802
@Test
1803-
public void setMediaItems_doesNotifyOnMetadataChanged() {
1803+
public void setMediaItems_doesNotifyOnMediaMetadataChanged() {
18041804
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
18051805
.thenReturn(mockPendingResult);
18061806
ArgumentCaptor<MediaMetadata> metadataCaptor = ArgumentCaptor.forClass(MediaMetadata.class);
@@ -1827,7 +1827,7 @@ public void setMediaItems_doesNotifyOnMetadataChanged() {
18271827
.build());
18281828
castPlayer.addListener(mockListener);
18291829

1830-
MediaMetadata intitalMetadata = castPlayer.getMediaMetadata();
1830+
MediaMetadata initialMetadata = castPlayer.getMediaMetadata();
18311831
castPlayer.setMediaItems(firstPlaylist, /* startIndex= */ 0, /* startPositionMs= */ 2000L);
18321832
updateTimeLine(firstPlaylist, /* mediaQueueItemIds= */ new int[] {1}, /* currentItemId= */ 1);
18331833
MediaMetadata firstMetadata = castPlayer.getMediaMetadata();
@@ -1850,7 +1850,7 @@ public void setMediaItems_doesNotifyOnMetadataChanged() {
18501850
secondPlaylist.get(1).mediaMetadata,
18511851
secondPlaylist.get(0).mediaMetadata)
18521852
.inOrder();
1853-
assertThat(intitalMetadata).isEqualTo(MediaMetadata.EMPTY);
1853+
assertThat(initialMetadata).isEqualTo(MediaMetadata.EMPTY);
18541854
assertThat(ImmutableList.of(firstMetadata, secondMetadata, thirdMetadata))
18551855
.containsExactly(
18561856
firstPlaylist.get(0).mediaMetadata,
@@ -1898,6 +1898,35 @@ public void setMediaItems_equalMetadata_doesNotNotifyOnMediaMetadataChanged() {
18981898
verify(mockListener, never()).onMediaMetadataChanged(any());
18991899
}
19001900

1901+
@Test
1902+
public void setPlaylistMetadata_doesNotifyOnPlaylistMetadataChanged() {
1903+
castPlayer.addListener(mockListener);
1904+
1905+
MediaMetadata metadata = new MediaMetadata.Builder().setArtist("foo").build();
1906+
1907+
assertThat(castPlayer.getPlaylistMetadata()).isEqualTo(MediaMetadata.EMPTY);
1908+
1909+
castPlayer.setPlaylistMetadata(metadata);
1910+
1911+
assertThat(castPlayer.getPlaylistMetadata()).isEqualTo(metadata);
1912+
1913+
verify(mockListener).onPlaylistMetadataChanged(metadata);
1914+
}
1915+
1916+
@Test
1917+
public void setPlaylistMetadata_equalMetadata_doesNotNotifyOnPlaylistMetadataChanged() {
1918+
castPlayer.addListener(mockListener);
1919+
1920+
MediaMetadata metadata = new MediaMetadata.Builder().setArtist("foo").build();
1921+
1922+
castPlayer.setPlaylistMetadata(metadata);
1923+
castPlayer.setPlaylistMetadata(metadata);
1924+
1925+
assertThat(castPlayer.getPlaylistMetadata()).isEqualTo(metadata);
1926+
1927+
verify(mockListener, times(1)).onPlaylistMetadataChanged(metadata);
1928+
}
1929+
19011930
@Test
19021931
public void getDeviceInfo_returnsCorrectDeviceInfoWithPlaybackTypeRemote() {
19031932
DeviceInfo deviceInfo = castPlayer.getDeviceInfo();

0 commit comments

Comments
 (0)