Add getter and callbacks for static metadata retrieval.

Issue:#7266
PiperOrigin-RevId: 335416280
This commit is contained in:
samrobinson 2020-10-05 15:54:44 +01:00 committed by kim-vde
parent 41192ee046
commit a552e35f6a
14 changed files with 216 additions and 22 deletions

View File

@ -10,6 +10,8 @@
still possible until the next major release using
`setThrowsWhenUsingWrongThread(false)`
([#4463](https://github.com/google/ExoPlayer/issues/4463)).
* Add a getter and callback for static metadata to the player
([#7266](https://github.com/google/ExoPlayer/issues/7266)).
* Track selection:
* Add option to specify multiple preferred audio or text languages.
* Data sources:

View File

@ -27,6 +27,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
@ -51,6 +52,7 @@ import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@ -561,6 +563,12 @@ public final class CastPlayer extends BasePlayer {
return currentTrackGroups;
}
@Override
public List<Metadata> getCurrentStaticMetadata() {
// CastPlayer does not currently support metadata.
return Collections.emptyList();
}
@Override
public Timeline getCurrentTimeline() {
return currentTimeline;

View File

@ -28,6 +28,7 @@ import android.util.Pair;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceFactory;
@ -43,6 +44,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@ -861,6 +863,11 @@ import java.util.concurrent.TimeoutException;
return playbackInfo.trackSelectorResult.selections;
}
@Override
public List<Metadata> getCurrentStaticMetadata() {
return playbackInfo.staticMetadata;
}
@Override
public Timeline getCurrentTimeline() {
return playbackInfo.timeline;
@ -1168,7 +1175,8 @@ import java.util.concurrent.TimeoutException;
/* requestedContentPositionUs= */ C.msToUs(maskingWindowPositionMs),
/* totalBufferedDurationUs= */ 0,
TrackGroupArray.EMPTY,
emptyTrackSelectorResult);
emptyTrackSelectorResult,
ImmutableList.of());
playbackInfo = playbackInfo.copyWithLoadingMediaPeriodId(dummyMediaPeriodId);
playbackInfo.bufferedPositionUs = playbackInfo.positionUs;
return playbackInfo;
@ -1195,7 +1203,8 @@ import java.util.concurrent.TimeoutException;
/* requestedContentPositionUs= */ newContentPositionUs,
/* totalBufferedDurationUs= */ 0,
playingPeriodChanged ? TrackGroupArray.EMPTY : playbackInfo.trackGroups,
playingPeriodChanged ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult);
playingPeriodChanged ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult,
playingPeriodChanged ? ImmutableList.of() : playbackInfo.staticMetadata);
playbackInfo = playbackInfo.copyWithLoadingMediaPeriodId(newPeriodId);
playbackInfo.bufferedPositionUs = newContentPositionUs;
} else if (newContentPositionUs == oldContentPositionUs) {
@ -1219,7 +1228,8 @@ import java.util.concurrent.TimeoutException;
/* requestedContentPositionUs= */ playbackInfo.positionUs,
/* totalBufferedDurationUs= */ maskedBufferedPositionUs - playbackInfo.positionUs,
playbackInfo.trackGroups,
playbackInfo.trackSelectorResult);
playbackInfo.trackSelectorResult,
playbackInfo.staticMetadata);
playbackInfo = playbackInfo.copyWithLoadingMediaPeriodId(newPeriodId);
playbackInfo.bufferedPositionUs = maskedBufferedPositionUs;
}
@ -1241,7 +1251,8 @@ import java.util.concurrent.TimeoutException;
/* requestedContentPositionUs= */ newContentPositionUs,
maskedTotalBufferedDurationUs,
playbackInfo.trackGroups,
playbackInfo.trackSelectorResult);
playbackInfo.trackSelectorResult,
playbackInfo.staticMetadata);
playbackInfo.bufferedPositionUs = maskedBufferedPositionUs;
}
return playbackInfo;
@ -1348,6 +1359,7 @@ import java.util.concurrent.TimeoutException;
private final boolean isLoadingChanged;
private final boolean timelineChanged;
private final boolean trackSelectorResultChanged;
private final boolean staticMetadataChanged;
private final boolean playWhenReadyChanged;
private final boolean playbackSuppressionReasonChanged;
private final boolean isPlayingChanged;
@ -1387,6 +1399,8 @@ import java.util.concurrent.TimeoutException;
timelineChanged = !previousPlaybackInfo.timeline.equals(playbackInfo.timeline);
trackSelectorResultChanged =
previousPlaybackInfo.trackSelectorResult != playbackInfo.trackSelectorResult;
staticMetadataChanged =
!previousPlaybackInfo.staticMetadata.equals(playbackInfo.staticMetadata);
playWhenReadyChanged = previousPlaybackInfo.playWhenReady != playbackInfo.playWhenReady;
playbackSuppressionReasonChanged =
previousPlaybackInfo.playbackSuppressionReason != playbackInfo.playbackSuppressionReason;
@ -1428,6 +1442,11 @@ import java.util.concurrent.TimeoutException;
listener.onTracksChanged(
playbackInfo.trackGroups, playbackInfo.trackSelectorResult.selections));
}
if (staticMetadataChanged) {
invokeAll(
listenerSnapshot,
listener -> listener.onStaticMetadataChanged(playbackInfo.staticMetadata));
}
if (isLoadingChanged) {
invokeAll(
listenerSnapshot, listener -> listener.onIsLoadingChanged(playbackInfo.isLoading));

View File

@ -33,12 +33,14 @@ import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.Player.RepeatMode;
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.ShuffleOrder;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
@ -49,6 +51,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@ -1338,6 +1341,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* isLoading= */ false,
resetTrackInfo ? TrackGroupArray.EMPTY : playbackInfo.trackGroups,
resetTrackInfo ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult,
resetTrackInfo ? ImmutableList.of() : playbackInfo.staticMetadata,
mediaPeriodId,
playbackInfo.playWhenReady,
playbackInfo.playbackSuppressionReason,
@ -2096,6 +2100,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
resetPendingPauseAtEndOfPeriod();
TrackGroupArray trackGroupArray = playbackInfo.trackGroups;
TrackSelectorResult trackSelectorResult = playbackInfo.trackSelectorResult;
List<Metadata> staticMetadata = playbackInfo.staticMetadata;
if (mediaSourceList.isPrepared()) {
@Nullable MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
trackGroupArray =
@ -2106,18 +2111,35 @@ import java.util.concurrent.atomic.AtomicBoolean;
playingPeriodHolder == null
? emptyTrackSelectorResult
: playingPeriodHolder.getTrackSelectorResult();
staticMetadata = extractMetadataFromTrackSelectionArray(trackSelectorResult.selections);
} else if (!mediaPeriodId.equals(playbackInfo.periodId)) {
// Reset previously kept track info if unprepared and the period changes.
trackGroupArray = TrackGroupArray.EMPTY;
trackSelectorResult = emptyTrackSelectorResult;
staticMetadata = ImmutableList.of();
}
return playbackInfo.copyWithNewPosition(
mediaPeriodId,
positionUs,
contentPositionUs,
getTotalBufferedDurationUs(),
trackGroupArray,
trackSelectorResult);
trackSelectorResult,
staticMetadata);
}
private ImmutableList<Metadata> extractMetadataFromTrackSelectionArray(
TrackSelectionArray trackSelectionArray) {
ImmutableList.Builder<Metadata> builder = new ImmutableList.Builder<>();
for (int i = 0; i < trackSelectionArray.length; i++) {
@Nullable TrackSelection trackSelection = trackSelectionArray.get(i);
if (trackSelection != null) {
Format format = trackSelection.getFormat(0);
builder.add(format.metadata == null ? new Metadata() : format.metadata);
}
}
return builder.build();
}
private void enableRenderers() throws ExoPlaybackException {

View File

@ -18,9 +18,12 @@ package com.google.android.exoplayer2;
import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.common.collect.ImmutableList;
import java.util.List;
/**
* Information about an ongoing playback.
@ -57,6 +60,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public final TrackGroupArray trackGroups;
/** The result of the current track selection. */
public final TrackSelectorResult trackSelectorResult;
/** The current static metadata of the track selections. */
public final List<Metadata> staticMetadata;
/** The {@link MediaPeriodId} of the currently loading media period in the {@link #timeline}. */
public final MediaPeriodId loadingMediaPeriodId;
/** Whether playback should proceed when {@link #playbackState} == {@link Player#STATE_READY}. */
@ -104,6 +109,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
/* isLoading= */ false,
TrackGroupArray.EMPTY,
emptyTrackSelectorResult,
/* staticMetadata= */ ImmutableList.of(),
PLACEHOLDER_MEDIA_PERIOD_ID,
/* playWhenReady= */ false,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
@ -126,6 +132,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* @param isLoading See {@link #isLoading}.
* @param trackGroups See {@link #trackGroups}.
* @param trackSelectorResult See {@link #trackSelectorResult}.
* @param staticMetadata See {@link #staticMetadata}.
* @param loadingMediaPeriodId See {@link #loadingMediaPeriodId}.
* @param playWhenReady See {@link #playWhenReady}.
* @param playbackSuppressionReason See {@link #playbackSuppressionReason}.
@ -145,6 +152,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
boolean isLoading,
TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult,
List<Metadata> staticMetadata,
MediaPeriodId loadingMediaPeriodId,
boolean playWhenReady,
@PlaybackSuppressionReason int playbackSuppressionReason,
@ -162,6 +170,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
this.isLoading = isLoading;
this.trackGroups = trackGroups;
this.trackSelectorResult = trackSelectorResult;
this.staticMetadata = staticMetadata;
this.loadingMediaPeriodId = loadingMediaPeriodId;
this.playWhenReady = playWhenReady;
this.playbackSuppressionReason = playbackSuppressionReason;
@ -189,6 +198,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* @param trackGroups The track groups for the new position. See {@link #trackGroups}.
* @param trackSelectorResult The track selector result for the new position. See {@link
* #trackSelectorResult}.
* @param staticMetadata The static metadata for the track selections. See {@link
* #staticMetadata}.
* @return Copied playback info with new playing position.
*/
@CheckResult
@ -198,7 +209,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
long requestedContentPositionUs,
long totalBufferedDurationUs,
TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult) {
TrackSelectorResult trackSelectorResult,
List<Metadata> staticMetadata) {
return new PlaybackInfo(
timeline,
periodId,
@ -208,6 +220,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -236,6 +249,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -264,6 +278,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -292,6 +307,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -320,6 +336,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -348,6 +365,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -380,6 +398,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -408,6 +427,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -437,6 +457,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
@ -465,6 +486,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
isLoading,
trackGroups,
trackSelectorResult,
staticMetadata,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,

View File

@ -28,12 +28,14 @@ import com.google.android.exoplayer2.audio.AudioListener;
import com.google.android.exoplayer2.audio.AuxEffectInfo;
import com.google.android.exoplayer2.device.DeviceInfo;
import com.google.android.exoplayer2.device.DeviceListener;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataOutput;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.util.StableApiCandidate;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
@ -491,6 +493,22 @@ public interface Player {
default void onTracksChanged(
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
/**
* Called when the static metadata changes.
*
* <p>The provided {@code metadataList} is an immutable list of {@link Metadata} instances,
* where the elements correspond to the {@link #getCurrentTrackSelections() current track
* selections}, or an empty list if there are no track selections or the implementation does not
* support metadata.
*
* <p>The metadata is considered static in the sense that it comes from the tracks' declared
* Formats, rather than being timed (or dynamic) metadata, which is represented within a
* metadata track.
*
* @param metadataList The static metadata.
*/
default void onStaticMetadataChanged(List<Metadata> metadataList) {}
/**
* Called when the player starts or stops loading the source.
*
@ -1226,16 +1244,25 @@ public interface Player {
@Nullable
TrackSelector getTrackSelector();
/**
* Returns the available track groups.
*/
/** Returns the available track groups. */
TrackGroupArray getCurrentTrackGroups();
/**
* Returns the current track selections for each renderer.
*/
/** Returns the current track selections for each renderer. */
TrackSelectionArray getCurrentTrackSelections();
/**
* Returns the current static metadata for the track selections.
*
* <p>The returned {@code metadataList} is an immutable list of {@link Metadata} instances, where
* the elements correspond to the {@link #getCurrentTrackSelections() current track selections},
* or an empty list if there are no track selections or the implementation does not support
* metadata.
*
* <p>This metadata is considered static in that it comes from the tracks' declared Formats,
* rather than being timed (or dynamic) metadata, which is represented within a metadata track.
*/
List<Metadata> getCurrentStaticMetadata();
/**
* Returns the current manifest. The type depends on the type of media being played. May be null.
*/

View File

@ -1761,6 +1761,12 @@ public class SimpleExoPlayer extends BasePlayer
return player.getCurrentTrackSelections();
}
@Override
public List<Metadata> getCurrentStaticMetadata() {
verifyApplicationThread();
return player.getCurrentStaticMetadata();
}
@Override
public Timeline getCurrentTimeline() {
verifyApplicationThread();

View File

@ -470,6 +470,14 @@ public class AnalyticsCollector
}
}
@Override
public final void onStaticMetadataChanged(List<Metadata> metadataList) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
for (AnalyticsListener listener : listeners) {
listener.onStaticMetadataChanged(eventTime, metadataList);
}
}
@Override
public final void onIsLoadingChanged(boolean isLoading) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();

View File

@ -38,6 +38,7 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.common.base.Objects;
import java.io.IOException;
import java.util.List;
/**
* A listener for analytics events.
@ -337,6 +338,23 @@ public interface AnalyticsListener {
default void onTracksChanged(
EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
/**
* Called when the static metadata changes.
*
* <p>The provided {@code metadataList} is an immutable list of {@link Metadata} instances, where
* the elements correspond to the current track selections (as returned by {@link
* #onTracksChanged(EventTime, TrackGroupArray, TrackSelectionArray)}, or an empty list if there
* are no track selections or the implementation does not support metadata.
*
* <p>The metadata is considered static in the sense that it comes from the tracks' declared
* Formats, rather than being timed (or dynamic) metadata, which is represented within a metadata
* track.
*
* @param eventTime The event time.
* @param metadataList The static metadata.
*/
default void onStaticMetadataChanged(EventTime eventTime, List<Metadata> metadataList) {}
/**
* Called when a media source started loading data.
*

View File

@ -45,6 +45,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
/** Logs events from {@link Player} and other core components using {@link Log}. */
@ -295,6 +296,16 @@ public class EventLogger implements AnalyticsListener {
logd("]");
}
@Override
public void onStaticMetadataChanged(EventTime eventTime, List<Metadata> metadataList) {
logd("staticMetadata [" + getEventTimeString(eventTime));
for (int i = 0; i < metadataList.size(); i++) {
logd(" " + i);
printMetadata(metadataList.get(i), " ");
}
logd("]");
}
@Override
public void onMetadata(EventTime eventTime, Metadata metadata) {
logd("metadata [" + getEventTimeString(eventTime));

View File

@ -56,6 +56,8 @@ import com.google.android.exoplayer2.analytics.AnalyticsListener;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.CompositeMediaSource;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
@ -104,6 +106,7 @@ import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.util.ArrayList;
@ -8309,6 +8312,54 @@ public final class ExoPlayerTest {
runUntilPlaybackState(player, Player.STATE_ENDED);
}
@Test
public void staticMetadata_callbackIsCalledCorrectlyAndMatchesGetter() throws Exception {
Format videoFormat =
new Format.Builder()
.setSampleMimeType(MimeTypes.VIDEO_H264)
.setWidth(1920)
.setHeight(720)
.setMetadata(
new Metadata(
new TextInformationFrame(
/* id= */ "TT2",
/* description= */ "Video",
/* value= */ "Video track name")))
.build();
Format audioFormat =
new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_AAC)
.setSampleRate(44_000)
.setMetadata(
new Metadata(
new TextInformationFrame(
/* id= */ "TT2",
/* description= */ "Audio",
/* value= */ "Audio track name")))
.build();
EventListener eventListener = mock(EventListener.class);
Timeline fakeTimeline =
new FakeTimeline(
new TimelineWindowDefinition(
/* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 100000));
SimpleExoPlayer player = new TestExoPlayer.Builder(context).build();
player.setMediaSource(new FakeMediaSource(fakeTimeline, videoFormat, audioFormat));
player.addListener(eventListener);
player.prepare();
player.play();
runUntilPlaybackState(player, Player.STATE_ENDED);
assertThat(player.getCurrentStaticMetadata())
.containsExactly(videoFormat.metadata, audioFormat.metadata)
.inOrder();
verify(eventListener)
.onStaticMetadataChanged(ImmutableList.of(videoFormat.metadata, audioFormat.metadata));
}
// Internal methods.
private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) {

View File

@ -432,6 +432,7 @@ public final class MediaPeriodQueueTest {
/* isLoading= */ false,
/* trackGroups= */ null,
/* trackSelectorResult= */ null,
/* staticMetadata= */ ImmutableList.of(),
/* loadingMediaPeriodId= */ null,
/* playWhenReady= */ false,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,

View File

@ -58,7 +58,6 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.ui.spherical.SingleTapListener;
@ -1369,15 +1368,9 @@ public class StyledPlayerView extends FrameLayout implements AdsLoader.AdViewPro
closeShutter();
// Display artwork if enabled and available, else hide it.
if (useArtwork()) {
for (int i = 0; i < selections.length; i++) {
@Nullable TrackSelection selection = selections.get(i);
if (selection != null) {
for (int j = 0; j < selection.length(); j++) {
@Nullable Metadata metadata = selection.getFormat(j).metadata;
if (metadata != null && setArtworkFromMetadata(metadata)) {
return;
}
}
for (Metadata metadata : player.getCurrentStaticMetadata()) {
if (setArtworkFromMetadata(metadata)) {
return;
}
}
if (setDrawableArtwork(defaultArtwork)) {

View File

@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.PlayerMessage;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ShuffleOrder;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -375,6 +376,11 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
throw new UnsupportedOperationException();
}
@Override
public List<Metadata> getCurrentStaticMetadata() {
throw new UnsupportedOperationException();
}
@Override
public Timeline getCurrentTimeline() {
throw new UnsupportedOperationException();