Commit 339d99b8 by tonihei Committed by kim-vde

Add preferredVideoRoleFlags to TrackSelectionParameters.

And also tweak existing role flag logic to strictly prefer perfect
matches over partial matches.

Caveat: Video role flags only supported for fixed track selections
(same issue as Issue: google/ExoPlayer#9519).

Issue: google/ExoPlayer#9402
PiperOrigin-RevId: 412292835
parent e846e9f0
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
### dev-v2 (not yet released) ### dev-v2 (not yet released)
* Core library:
* Support preferred video role flags in track selection
((#9402)[https://github.com/google/ExoPlayer/issues/9402]).
* DRM: * DRM:
* Remove `playbackLooper` from `DrmSessionManager.(pre)acquireSession`. * Remove `playbackLooper` from `DrmSessionManager.(pre)acquireSession`.
When a `DrmSessionManager` is used by an app in a custom `MediaSource`, When a `DrmSessionManager` is used by an app in a custom `MediaSource`,
...@@ -545,8 +548,8 @@ ...@@ -545,8 +548,8 @@
* The most used methods of `Player`'s audio, video, text and metadata * The most used methods of `Player`'s audio, video, text and metadata
components have been added directly to `Player`. components have been added directly to `Player`.
* Add `Player.getAvailableCommands`, `Player.isCommandAvailable` and * Add `Player.getAvailableCommands`, `Player.isCommandAvailable` and
`Listener.onAvailableCommandsChanged` to query which commands `Listener.onAvailableCommandsChanged` to query which commands that can
that can be executed on the player. be executed on the player.
* Add a `Player.Listener` interface to receive all player events. * Add a `Player.Listener` interface to receive all player events.
Component listeners and `EventListener` have been deprecated. Component listeners and `EventListener` have been deprecated.
* Add `Player.getMediaMetadata`, which returns a combined and structured * Add `Player.getMediaMetadata`, which returns a combined and structured
...@@ -555,8 +558,8 @@ ...@@ -555,8 +558,8 @@
* `Player.setPlaybackParameters` no longer accepts null, use * `Player.setPlaybackParameters` no longer accepts null, use
`PlaybackParameters.DEFAULT` instead. `PlaybackParameters.DEFAULT` instead.
* Report information about the old and the new playback positions to * Report information about the old and the new playback positions to
`Listener.onPositionDiscontinuity`. Add `DISCONTINUITY_REASON_SKIP` `Listener.onPositionDiscontinuity`. Add `DISCONTINUITY_REASON_SKIP` and
and `DISCONTINUITY_REASON_REMOVE` as discontinuity reasons, and rename `DISCONTINUITY_REASON_REMOVE` as discontinuity reasons, and rename
`DISCONTINUITY_REASON_PERIOD_TRANSITION` to `DISCONTINUITY_REASON_PERIOD_TRANSITION` to
`DISCONTINUITY_REASON_AUTO_TRANSITION`. Remove `DISCONTINUITY_REASON_AUTO_TRANSITION`. Remove
`DISCONTINUITY_REASON_AD_INSERTION`, for which `DISCONTINUITY_REASON_AD_INSERTION`, for which
...@@ -611,8 +614,8 @@ ...@@ -611,8 +614,8 @@
dispatched for each track in each period. dispatched for each track in each period.
* Include the session state in DRM session-acquired listener methods. * Include the session state in DRM session-acquired listener methods.
* UI: * UI:
* Add `PlayerNotificationManager.Builder`, with the ability to * Add `PlayerNotificationManager.Builder`, with the ability to specify
specify which group the notification should belong to. which group the notification should belong to.
* Remove `setUseSensorRotation` from `PlayerView` and `StyledPlayerView`. * Remove `setUseSensorRotation` from `PlayerView` and `StyledPlayerView`.
Instead, cast the view returned by `getVideoSurfaceView` to Instead, cast the view returned by `getVideoSurfaceView` to
`SphericalGLSurfaceView`, and then call `setUseSensorRotation` on the `SphericalGLSurfaceView`, and then call `setUseSensorRotation` on the
...@@ -684,7 +687,8 @@ ...@@ -684,7 +687,8 @@
### 2.13.3 (2021-04-14) ### 2.13.3 (2021-04-14)
* Published via the Google Maven repository (i.e., google()) rather than JCenter. * Published via the Google Maven repository (i.e., google()) rather than
JCenter.
* Core: * Core:
* Reset playback speed when live playback speed control becomes unused * Reset playback speed when live playback speed control becomes unused
([#8664](https://github.com/google/ExoPlayer/issues/8664)). ([#8664](https://github.com/google/ExoPlayer/issues/8664)).
...@@ -839,8 +843,8 @@ ...@@ -839,8 +843,8 @@
* Remove `Player.setVideoDecoderOutputBufferRenderer` from Player API. Use * Remove `Player.setVideoDecoderOutputBufferRenderer` from Player API. Use
`setVideoSurfaceView` and `clearVideoSurfaceView` instead. `setVideoSurfaceView` and `clearVideoSurfaceView` instead.
* Default `SingleSampleMediaSource.treatLoadErrorsAsEndOfStream` to `true` * Default `SingleSampleMediaSource.treatLoadErrorsAsEndOfStream` to `true`
so that errors loading external subtitle files do not cause playback so that errors loading external subtitle files do not cause playback to
to fail ([#8430](https://github.com/google/ExoPlayer/issues/8430)). A fail ([#8430](https://github.com/google/ExoPlayer/issues/8430)). A
warning will be logged by `SingleSampleMediaPeriod` whenever a load warning will be logged by `SingleSampleMediaPeriod` whenever a load
error is treated as though the end of the stream has been reached. error is treated as though the end of the stream has been reached.
* Time out on release to prevent ANRs if an underlying platform call is * Time out on release to prevent ANRs if an underlying platform call is
...@@ -921,9 +925,8 @@ ...@@ -921,9 +925,8 @@
([#7847](https://github.com/google/ExoPlayer/issues/7847)). ([#7847](https://github.com/google/ExoPlayer/issues/7847)).
* Drop key and provision responses if `DefaultDrmSession` is released * Drop key and provision responses if `DefaultDrmSession` is released
while waiting for the response. This prevents harmless log messages of while waiting for the response. This prevents harmless log messages of
the form: the form: `IllegalStateException: sending message to a Handler on a dead
`IllegalStateException: sending message to a Handler on a dead thread` thread` ([#8328](https://github.com/google/ExoPlayer/issues/8328)).
([#8328](https://github.com/google/ExoPlayer/issues/8328)).
* Allow apps to fully customize DRM behaviour for each `MediaItem` by * Allow apps to fully customize DRM behaviour for each `MediaItem` by
passing a `DrmSessionManagerProvider` to `MediaSourceFactory` passing a `DrmSessionManagerProvider` to `MediaSourceFactory`
([#8466](https://github.com/google/ExoPlayer/issues/8466)). ([#8466](https://github.com/google/ExoPlayer/issues/8466)).
...@@ -938,8 +941,8 @@ ...@@ -938,8 +941,8 @@
existing decoder instance for the new format, and if not then the existing decoder instance for the new format, and if not then the
reasons why. reasons why.
* Video: * Video:
* Fall back to AVC/HEVC decoders for Dolby Vision streams with level 10 * Fall back to AVC/HEVC decoders for Dolby Vision streams with level 10 to
to 13 ([#8530](https://github.com/google/ExoPlayer/issues/8530)). 13 ([#8530](https://github.com/google/ExoPlayer/issues/8530)).
* Fix VP9 format capability checks on API level 23 and earlier. The * Fix VP9 format capability checks on API level 23 and earlier. The
platform does not correctly report the VP9 level supported by the platform does not correctly report the VP9 level supported by the
decoder in this case, so we estimate it based on the decoder's maximum decoder in this case, so we estimate it based on the decoder's maximum
...@@ -1021,8 +1024,8 @@ ...@@ -1021,8 +1024,8 @@
* `ExtractorsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use * `ExtractorsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use
`ExtractorsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)` `ExtractorsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
instead. instead.
* `FixedTrackSelection.Factory`. If you need to disable adaptive * `FixedTrackSelection.Factory`. If you need to disable adaptive selection
selection in `DefaultTrackSelector`, enable the in `DefaultTrackSelector`, enable the
`DefaultTrackSelector.Parameters.forceHighestSupportedBitrate` flag. `DefaultTrackSelector.Parameters.forceHighestSupportedBitrate` flag.
* `HlsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use * `HlsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use
`HlsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)` `HlsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
...@@ -1035,8 +1038,8 @@ ...@@ -1035,8 +1038,8 @@
`MappedTrackInfo.getUnmappedTrackGroups()` instead. `MappedTrackInfo.getUnmappedTrackGroups()` instead.
* `MappedTrackInfo.length`. Use `MappedTrackInfo.getRendererCount()` * `MappedTrackInfo.length`. Use `MappedTrackInfo.getRendererCount()`
instead. instead.
* `Player.DefaultEventListener.onTimelineChanged(Timeline, Object)`. * `Player.DefaultEventListener.onTimelineChanged(Timeline, Object)`. Use
Use `Player.EventListener.onTimelineChanged(Timeline, int)` instead. `Player.EventListener.onTimelineChanged(Timeline, int)` instead.
* `Player.setAudioAttributes(AudioAttributes)`. Use * `Player.setAudioAttributes(AudioAttributes)`. Use
`Player.AudioComponent.setAudioAttributes(AudioAttributes, boolean)` `Player.AudioComponent.setAudioAttributes(AudioAttributes, boolean)`
instead. instead.
...@@ -1052,8 +1055,8 @@ ...@@ -1052,8 +1055,8 @@
`SimpleExoPlayer.removeVideoListener(VideoListener)` instead. `SimpleExoPlayer.removeVideoListener(VideoListener)` instead.
* `SimpleExoPlayer.getAudioStreamType()`. Use * `SimpleExoPlayer.getAudioStreamType()`. Use
`SimpleExoPlayer.getAudioAttributes()` instead. `SimpleExoPlayer.getAudioAttributes()` instead.
* `SimpleExoPlayer.setAudioDebugListener(AudioRendererEventListener)`. * `SimpleExoPlayer.setAudioDebugListener(AudioRendererEventListener)`. Use
Use `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead. `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
* `SimpleExoPlayer.setAudioStreamType(int)`. Use * `SimpleExoPlayer.setAudioStreamType(int)`. Use
`SimpleExoPlayer.setAudioAttributes(AudioAttributes)` instead. `SimpleExoPlayer.setAudioAttributes(AudioAttributes)` instead.
* `SimpleExoPlayer.setMetadataOutput(MetadataOutput)`. Use * `SimpleExoPlayer.setMetadataOutput(MetadataOutput)`. Use
...@@ -1064,12 +1067,11 @@ ...@@ -1064,12 +1067,11 @@
* `SimpleExoPlayer.setPlaybackParams(PlaybackParams)`. Use * `SimpleExoPlayer.setPlaybackParams(PlaybackParams)`. Use
`SimpleExoPlayer.setPlaybackParameters(PlaybackParameters)` instead. `SimpleExoPlayer.setPlaybackParameters(PlaybackParameters)` instead.
* `SimpleExoPlayer.setTextOutput(TextOutput)`. Use * `SimpleExoPlayer.setTextOutput(TextOutput)`. Use
`SimpleExoPlayer.addTextOutput(TextOutput)` instead. If your `SimpleExoPlayer.addTextOutput(TextOutput)` instead. If your application
application is calling `SimpleExoPlayer.setTextOutput(null)`, make sure is calling `SimpleExoPlayer.setTextOutput(null)`, make sure to replace
to replace this call with a call to this call with a call to `SimpleExoPlayer.removeTextOutput(TextOutput)`.
`SimpleExoPlayer.removeTextOutput(TextOutput)`. * `SimpleExoPlayer.setVideoDebugListener(VideoRendererEventListener)`. Use
* `SimpleExoPlayer.setVideoDebugListener(VideoRendererEventListener)`. `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
Use `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
* `SimpleExoPlayer.setVideoListener(VideoListener)`. Use * `SimpleExoPlayer.setVideoListener(VideoListener)`. Use
`SimpleExoPlayer.addVideoListener(VideoListener)` instead. If your `SimpleExoPlayer.addVideoListener(VideoListener)` instead. If your
application is calling `SimpleExoPlayer.setVideoListener(null)`, make application is calling `SimpleExoPlayer.setVideoListener(null)`, make
...@@ -1093,7 +1095,7 @@ ...@@ -1093,7 +1095,7 @@
`SsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)` `SsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
instead. instead.
### 2.12.3 (2021-01-13) ### ### 2.12.3 (2021-01-13)
* Core library: * Core library:
* Fix `MediaCodecRenderer` issue where empty streams would fail to play in * Fix `MediaCodecRenderer` issue where empty streams would fail to play in
...@@ -1130,7 +1132,7 @@ ...@@ -1130,7 +1132,7 @@
fix a deadlock while creating PlaybackStateCompat internally. fix a deadlock while creating PlaybackStateCompat internally.
([#8011](https://github.com/google/ExoPlayer/issues/8011)). ([#8011](https://github.com/google/ExoPlayer/issues/8011)).
### 2.12.2 (2020-12-01) ### ### 2.12.2 (2020-12-01)
* Core library: * Core library:
* Suppress exceptions from registering and unregistering the stream volume * Suppress exceptions from registering and unregistering the stream volume
...@@ -1191,7 +1193,7 @@ ...@@ -1191,7 +1193,7 @@
* Allow to remove all playlist items that makes the player reset * Allow to remove all playlist items that makes the player reset
([#8047](https://github.com/google/ExoPlayer/issues/8047)). ([#8047](https://github.com/google/ExoPlayer/issues/8047)).
### 2.12.1 (2020-10-23) ### ### 2.12.1 (2020-10-23)
* Core library: * Core library:
* Fix issue where `Player.setMediaItems` would ignore its `resetPosition` * Fix issue where `Player.setMediaItems` would ignore its `resetPosition`
...@@ -1230,7 +1232,7 @@ ...@@ -1230,7 +1232,7 @@
([#8058](https://github.com/google/ExoPlayer/issues/8058)). ([#8058](https://github.com/google/ExoPlayer/issues/8058)).
* Extractors: * Extractors:
* MP4: * MP4:
* Add support for `_mp2` boxes * Add support for `_mp2` boxes
([#7967](https://github.com/google/ExoPlayer/issues/7967)). ([#7967](https://github.com/google/ExoPlayer/issues/7967)).
* Fix playback of files containing `pcm_alaw` or `pcm_mulaw` audio * Fix playback of files containing `pcm_alaw` or `pcm_mulaw` audio
tracks, by enabling sample rechunking for such tracks. tracks, by enabling sample rechunking for such tracks.
...@@ -1266,11 +1268,11 @@ ...@@ -1266,11 +1268,11 @@
([#7961](https://github.com/google/ExoPlayer/issues/7961)). ([#7961](https://github.com/google/ExoPlayer/issues/7961)).
* Fix incorrect truncation of large cue point positions * Fix incorrect truncation of large cue point positions
([#8067](https://github.com/google/ExoPlayer/issues/8067)). ([#8067](https://github.com/google/ExoPlayer/issues/8067)).
* Upgrade IMA SDK dependency to 3.20.1. This brings in a fix for * Upgrade IMA SDK dependency to 3.20.1. This brings in a fix for companion
companion ads rendering when targeting API 29 ads rendering when targeting API 29
([#6432](https://github.com/google/ExoPlayer/issues/6432)). ([#6432](https://github.com/google/ExoPlayer/issues/6432)).
### 2.12.0 (2020-09-11) ### ### 2.12.0 (2020-09-11)
To learn more about what's new in 2.12, read the corresponding To learn more about what's new in 2.12, read the corresponding
[blog post](https://medium.com/google-exoplayer/exoplayer-2-12-whats-new-e43ef8ff72e7). [blog post](https://medium.com/google-exoplayer/exoplayer-2-12-whats-new-e43ef8ff72e7).
...@@ -1301,8 +1303,7 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1301,8 +1303,7 @@ To learn more about what's new in 2.12, read the corresponding
* Remove `PlaybackParameters.skipSilence`, and replace it with * Remove `PlaybackParameters.skipSilence`, and replace it with
`AudioComponent.setSkipSilenceEnabled`. This method is also `AudioComponent.setSkipSilenceEnabled`. This method is also
available on `SimpleExoPlayer`. An available on `SimpleExoPlayer`. An
`AudioListener.onSkipSilenceEnabledChanged` callback is also `AudioListener.onSkipSilenceEnabledChanged` callback is also added.
added.
* Add `TextComponent.getCurrentCues` to get the current cues. This * Add `TextComponent.getCurrentCues` to get the current cues. This
method is also available on `SimpleExoPlayer`. The current cues are method is also available on `SimpleExoPlayer`. The current cues are
no longer automatically forwarded to a `TextOutput` when it's added no longer automatically forwarded to a `TextOutput` when it's added
...@@ -1630,20 +1631,19 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1630,20 +1631,19 @@ To learn more about what's new in 2.12, read the corresponding
* Add support for downloading DRM-protected content using offline Widevine * Add support for downloading DRM-protected content using offline Widevine
licenses. licenses.
### 2.11.8 (2020-08-25) ### ### 2.11.8 (2020-08-25)
* Fix distorted playback of floating point audio when samples exceed the * Fix distorted playback of floating point audio when samples exceed the `[-1,
`[-1, 1]` nominal range. 1]` nominal range.
* MP4: * MP4:
* Add support for `piff` and `isml` brands * Add support for `piff` and `isml` brands
([#7584](https://github.com/google/ExoPlayer/issues/7584)). ([#7584](https://github.com/google/ExoPlayer/issues/7584)).
* Fix playback of very short MP4 files. * Fix playback of very short MP4 files.
* FMP4: * FMP4:
* Fix `saiz` and `senc` sample count checks, resolving a "length * Fix `saiz` and `senc` sample count checks, resolving a "length mismatch"
mismatch" `ParserException` when playing certain protected FMP4 streams `ParserException` when playing certain protected FMP4 streams
([#7592](https://github.com/google/ExoPlayer/issues/7592)). ([#7592](https://github.com/google/ExoPlayer/issues/7592)).
* Fix handling of `traf` boxes containing multiple `sbgp` or `sgpd` * Fix handling of `traf` boxes containing multiple `sbgp` or `sgpd` boxes.
boxes.
* FLV: Ignore `SCRIPTDATA` segments with invalid name types, rather than * FLV: Ignore `SCRIPTDATA` segments with invalid name types, rather than
failing playback ([#7675](https://github.com/google/ExoPlayer/issues/7675)). failing playback ([#7675](https://github.com/google/ExoPlayer/issues/7675)).
* Better infer the content type of `.ism` and `.isml` streaming URLs. * Better infer the content type of `.ism` and `.isml` streaming URLs.
...@@ -1656,12 +1656,12 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1656,12 +1656,12 @@ To learn more about what's new in 2.12, read the corresponding
* Demo app: Fix playback of ClearKey protected content on API level 26 and * Demo app: Fix playback of ClearKey protected content on API level 26 and
earlier ([#7735](https://github.com/google/ExoPlayer/issues/7735)). earlier ([#7735](https://github.com/google/ExoPlayer/issues/7735)).
### 2.11.7 (2020-06-29) ### ### 2.11.7 (2020-06-29)
* IMA extension: Fix the way postroll "content complete" notifications are * IMA extension: Fix the way postroll "content complete" notifications are
handled to avoid repeatedly refreshing the timeline after playback ends. handled to avoid repeatedly refreshing the timeline after playback ends.
### 2.11.6 (2020-06-19) ### ### 2.11.6 (2020-06-19)
* UI: Prevent `PlayerView` from temporarily hiding the video surface when * UI: Prevent `PlayerView` from temporarily hiding the video surface when
seeking to an unprepared period within the current window. For example when seeking to an unprepared period within the current window. For example when
...@@ -1676,14 +1676,14 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1676,14 +1676,14 @@ To learn more about what's new in 2.12, read the corresponding
([#7508](https://github.com/google/ExoPlayer/issues/7508)). ([#7508](https://github.com/google/ExoPlayer/issues/7508)).
* Fix a bug where the number of ads in an ad group couldn't change * Fix a bug where the number of ads in an ad group couldn't change
([#7477](https://github.com/google/ExoPlayer/issues/7477)). ([#7477](https://github.com/google/ExoPlayer/issues/7477)).
* Work around unexpected `pauseAd`/`stopAd` for ads that have preloaded * Work around unexpected `pauseAd`/`stopAd` for ads that have preloaded on
on seeking to another position seeking to another position
([#7492](https://github.com/google/ExoPlayer/issues/7492)). ([#7492](https://github.com/google/ExoPlayer/issues/7492)).
* Fix incorrect rounding of ad cue points. * Fix incorrect rounding of ad cue points.
* Fix handling of postrolls preloading * Fix handling of postrolls preloading
([#7518](https://github.com/google/ExoPlayer/issues/7518)). ([#7518](https://github.com/google/ExoPlayer/issues/7518)).
### 2.11.5 (2020-06-05) ### ### 2.11.5 (2020-06-05)
* Improve the smoothness of video playback immediately after starting, seeking * Improve the smoothness of video playback immediately after starting, seeking
or resuming a playback or resuming a playback
...@@ -1691,8 +1691,8 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1691,8 +1691,8 @@ To learn more about what's new in 2.12, read the corresponding
* Add `SilenceMediaSource.Factory` to support tags. * Add `SilenceMediaSource.Factory` to support tags.
* Enable the configuration of `SilenceSkippingAudioProcessor` * Enable the configuration of `SilenceSkippingAudioProcessor`
([#6705](https://github.com/google/ExoPlayer/issues/6705)). ([#6705](https://github.com/google/ExoPlayer/issues/6705)).
* Fix bug where `PlayerMessages` throw an exception after `MediaSources` * Fix bug where `PlayerMessages` throw an exception after `MediaSources` are
are removed from the playlist removed from the playlist
([#7278](https://github.com/google/ExoPlayer/issues/7278)). ([#7278](https://github.com/google/ExoPlayer/issues/7278)).
* Fix "Not allowed to start service" `IllegalStateException` in * Fix "Not allowed to start service" `IllegalStateException` in
`DownloadService` `DownloadService`
...@@ -1724,13 +1724,11 @@ To learn more about what's new in 2.12, read the corresponding ...@@ -1724,13 +1724,11 @@ To learn more about what's new in 2.12, read the corresponding
([#7303](https://github.com/google/ExoPlayer/issues/7303)). ([#7303](https://github.com/google/ExoPlayer/issues/7303)).
* Add `showScrubber` and `hideScrubber` methods to `DefaultTimeBar`. * Add `showScrubber` and `hideScrubber` methods to `DefaultTimeBar`.
* Text: * Text:
* Use anti-aliasing and bitmap filtering when displaying bitmap * Use anti-aliasing and bitmap filtering when displaying bitmap subtitles.
subtitles.
* Fix `SubtitlePainter` to render `EDGE_TYPE_OUTLINE` using the correct * Fix `SubtitlePainter` to render `EDGE_TYPE_OUTLINE` using the correct
color. color.
* IMA extension: * IMA extension:
* Upgrade to IMA SDK version 3.19.0, and migrate to new * Upgrade to IMA SDK version 3.19.0, and migrate to new preloading APIs
preloading APIs
([#6429](https://github.com/google/ExoPlayer/issues/6429)). This fixes ([#6429](https://github.com/google/ExoPlayer/issues/6429)). This fixes
several issues involving preloading and handling of ad loading error several issues involving preloading and handling of ad loading error
cases: ([#4140](https://github.com/google/ExoPlayer/issues/4140), cases: ([#4140](https://github.com/google/ExoPlayer/issues/4140),
......
...@@ -80,6 +80,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -80,6 +80,7 @@ public class TrackSelectionParameters implements Bundleable {
private int viewportHeight; private int viewportHeight;
private boolean viewportOrientationMayChange; private boolean viewportOrientationMayChange;
private ImmutableList<String> preferredVideoMimeTypes; private ImmutableList<String> preferredVideoMimeTypes;
private @C.RoleFlags int preferredVideoRoleFlags;
// Audio // Audio
private ImmutableList<String> preferredAudioLanguages; private ImmutableList<String> preferredAudioLanguages;
private @C.RoleFlags int preferredAudioRoleFlags; private @C.RoleFlags int preferredAudioRoleFlags;
...@@ -111,6 +112,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -111,6 +112,7 @@ public class TrackSelectionParameters implements Bundleable {
viewportHeight = Integer.MAX_VALUE; viewportHeight = Integer.MAX_VALUE;
viewportOrientationMayChange = true; viewportOrientationMayChange = true;
preferredVideoMimeTypes = ImmutableList.of(); preferredVideoMimeTypes = ImmutableList.of();
preferredVideoRoleFlags = 0;
// Audio // Audio
preferredAudioLanguages = ImmutableList.of(); preferredAudioLanguages = ImmutableList.of();
preferredAudioRoleFlags = 0; preferredAudioRoleFlags = 0;
...@@ -183,6 +185,10 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -183,6 +185,10 @@ public class TrackSelectionParameters implements Bundleable {
firstNonNull( firstNonNull(
bundle.getStringArray(keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES)), bundle.getStringArray(keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES)),
new String[0])); new String[0]));
preferredVideoRoleFlags =
bundle.getInt(
keyForField(FIELD_PREFERRED_VIDEO_ROLE_FLAGS),
DEFAULT_WITHOUT_CONTEXT.preferredVideoRoleFlags);
// Audio // Audio
String[] preferredAudioLanguages1 = String[] preferredAudioLanguages1 =
firstNonNull( firstNonNull(
...@@ -261,6 +267,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -261,6 +267,7 @@ public class TrackSelectionParameters implements Bundleable {
viewportHeight = parameters.viewportHeight; viewportHeight = parameters.viewportHeight;
viewportOrientationMayChange = parameters.viewportOrientationMayChange; viewportOrientationMayChange = parameters.viewportOrientationMayChange;
preferredVideoMimeTypes = parameters.preferredVideoMimeTypes; preferredVideoMimeTypes = parameters.preferredVideoMimeTypes;
preferredVideoRoleFlags = parameters.preferredVideoRoleFlags;
// Audio // Audio
preferredAudioLanguages = parameters.preferredAudioLanguages; preferredAudioLanguages = parameters.preferredAudioLanguages;
preferredAudioRoleFlags = parameters.preferredAudioRoleFlags; preferredAudioRoleFlags = parameters.preferredAudioRoleFlags;
...@@ -441,6 +448,17 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -441,6 +448,17 @@ public class TrackSelectionParameters implements Bundleable {
return this; return this;
} }
/**
* Sets the preferred {@link C.RoleFlags} for video tracks.
*
* @param preferredVideoRoleFlags Preferred video role flags.
* @return This builder.
*/
public Builder setPreferredVideoRoleFlags(@C.RoleFlags int preferredVideoRoleFlags) {
this.preferredVideoRoleFlags = preferredVideoRoleFlags;
return this;
}
// Audio // Audio
/** /**
...@@ -770,6 +788,11 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -770,6 +788,11 @@ public class TrackSelectionParameters implements Bundleable {
* no preference. The default is an empty list. * no preference. The default is an empty list.
*/ */
public final ImmutableList<String> preferredVideoMimeTypes; public final ImmutableList<String> preferredVideoMimeTypes;
/**
* The preferred {@link C.RoleFlags} for video tracks. {@code 0} selects the default track if
* there is one, or the first track if there's no default. The default value is {@code 0}.
*/
public final @C.RoleFlags int preferredVideoRoleFlags;
// Audio // Audio
/** /**
* The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in
...@@ -853,6 +876,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -853,6 +876,7 @@ public class TrackSelectionParameters implements Bundleable {
this.viewportHeight = builder.viewportHeight; this.viewportHeight = builder.viewportHeight;
this.viewportOrientationMayChange = builder.viewportOrientationMayChange; this.viewportOrientationMayChange = builder.viewportOrientationMayChange;
this.preferredVideoMimeTypes = builder.preferredVideoMimeTypes; this.preferredVideoMimeTypes = builder.preferredVideoMimeTypes;
this.preferredVideoRoleFlags = builder.preferredVideoRoleFlags;
// Audio // Audio
this.preferredAudioLanguages = builder.preferredAudioLanguages; this.preferredAudioLanguages = builder.preferredAudioLanguages;
this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags; this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags;
...@@ -898,6 +922,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -898,6 +922,7 @@ public class TrackSelectionParameters implements Bundleable {
&& viewportWidth == other.viewportWidth && viewportWidth == other.viewportWidth
&& viewportHeight == other.viewportHeight && viewportHeight == other.viewportHeight
&& preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes) && preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes)
&& preferredVideoRoleFlags == other.preferredVideoRoleFlags
// Audio // Audio
&& preferredAudioLanguages.equals(other.preferredAudioLanguages) && preferredAudioLanguages.equals(other.preferredAudioLanguages)
&& preferredAudioRoleFlags == other.preferredAudioRoleFlags && preferredAudioRoleFlags == other.preferredAudioRoleFlags
...@@ -930,6 +955,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -930,6 +955,7 @@ public class TrackSelectionParameters implements Bundleable {
result = 31 * result + viewportWidth; result = 31 * result + viewportWidth;
result = 31 * result + viewportHeight; result = 31 * result + viewportHeight;
result = 31 * result + preferredVideoMimeTypes.hashCode(); result = 31 * result + preferredVideoMimeTypes.hashCode();
result = 31 * result + preferredVideoRoleFlags;
// Audio // Audio
result = 31 * result + preferredAudioLanguages.hashCode(); result = 31 * result + preferredAudioLanguages.hashCode();
result = 31 * result + preferredAudioRoleFlags; result = 31 * result + preferredAudioRoleFlags;
...@@ -978,6 +1004,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -978,6 +1004,7 @@ public class TrackSelectionParameters implements Bundleable {
FIELD_SELECTION_OVERRIDE_KEYS, FIELD_SELECTION_OVERRIDE_KEYS,
FIELD_SELECTION_OVERRIDE_VALUES, FIELD_SELECTION_OVERRIDE_VALUES,
FIELD_DISABLED_TRACK_TYPE, FIELD_DISABLED_TRACK_TYPE,
FIELD_PREFERRED_VIDEO_ROLE_FLAGS
}) })
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -1006,6 +1033,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -1006,6 +1033,7 @@ public class TrackSelectionParameters implements Bundleable {
private static final int FIELD_SELECTION_OVERRIDE_KEYS = 23; private static final int FIELD_SELECTION_OVERRIDE_KEYS = 23;
private static final int FIELD_SELECTION_OVERRIDE_VALUES = 24; private static final int FIELD_SELECTION_OVERRIDE_VALUES = 24;
private static final int FIELD_DISABLED_TRACK_TYPE = 25; private static final int FIELD_DISABLED_TRACK_TYPE = 25;
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 26;
@Override @Override
public Bundle toBundle() { public Bundle toBundle() {
...@@ -1027,6 +1055,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -1027,6 +1055,7 @@ public class TrackSelectionParameters implements Bundleable {
bundle.putStringArray( bundle.putStringArray(
keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES), keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES),
preferredVideoMimeTypes.toArray(new String[0])); preferredVideoMimeTypes.toArray(new String[0]));
bundle.putInt(keyForField(FIELD_PREFERRED_VIDEO_ROLE_FLAGS), preferredVideoRoleFlags);
// Audio // Audio
bundle.putStringArray( bundle.putStringArray(
keyForField(FIELD_PREFERRED_AUDIO_LANGUAGES), keyForField(FIELD_PREFERRED_AUDIO_LANGUAGES),
......
...@@ -27,6 +27,7 @@ import androidx.annotation.Nullable; ...@@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Bundleable; import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.C.FormatSupport; import com.google.android.exoplayer2.C.FormatSupport;
import com.google.android.exoplayer2.C.RoleFlags;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
...@@ -368,6 +369,13 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -368,6 +369,13 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return this; return this;
} }
@Override
public DefaultTrackSelector.ParametersBuilder setPreferredVideoRoleFlags(
@RoleFlags int preferredVideoRoleFlags) {
super.setPreferredVideoRoleFlags(preferredVideoRoleFlags);
return this;
}
// Audio // Audio
@Override @Override
...@@ -2468,6 +2476,14 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2468,6 +2476,14 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
} }
private static int getRoleFlagMatchScore(int trackRoleFlags, int preferredRoleFlags) {
if (trackRoleFlags != 0 && trackRoleFlags == preferredRoleFlags) {
// Prefer perfect match over partial matches.
return Integer.MAX_VALUE;
}
return Integer.bitCount(trackRoleFlags & preferredRoleFlags);
}
/** Represents how well a video track matches the selection {@link Parameters}. */ /** Represents how well a video track matches the selection {@link Parameters}. */
protected static final class VideoTrackScore implements Comparable<VideoTrackScore> { protected static final class VideoTrackScore implements Comparable<VideoTrackScore> {
...@@ -2483,6 +2499,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2483,6 +2499,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private final int bitrate; private final int bitrate;
private final int pixelCount; private final int pixelCount;
private final int preferredMimeTypeMatchIndex; private final int preferredMimeTypeMatchIndex;
private final int preferredRoleFlagsScore;
private final boolean hasMainOrNoRoleFlag;
public VideoTrackScore( public VideoTrackScore(
Format format, Format format,
...@@ -2510,6 +2528,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2510,6 +2528,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
isSupported(formatSupport, /* allowExceedsCapabilities= */ false); isSupported(formatSupport, /* allowExceedsCapabilities= */ false);
bitrate = format.bitrate; bitrate = format.bitrate;
pixelCount = format.getPixelCount(); pixelCount = format.getPixelCount();
preferredRoleFlagsScore =
getRoleFlagMatchScore(format.roleFlags, parameters.preferredVideoRoleFlags);
hasMainOrNoRoleFlag = format.roleFlags == 0 || (format.roleFlags & C.ROLE_FLAG_MAIN) != 0;
int bestMimeTypeMatchIndex = Integer.MAX_VALUE; int bestMimeTypeMatchIndex = Integer.MAX_VALUE;
for (int i = 0; i < parameters.preferredVideoMimeTypes.size(); i++) { for (int i = 0; i < parameters.preferredVideoMimeTypes.size(); i++) {
if (format.sampleMimeType != null if (format.sampleMimeType != null
...@@ -2537,6 +2558,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2537,6 +2558,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
: FORMAT_VALUE_ORDERING.reverse(); : FORMAT_VALUE_ORDERING.reverse();
return ComparisonChain.start() return ComparisonChain.start()
.compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities) .compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities)
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
.compareFalseFirst(this.hasMainOrNoRoleFlag, other.hasMainOrNoRoleFlag)
.compareFalseFirst(this.isWithinMaxConstraints, other.isWithinMaxConstraints) .compareFalseFirst(this.isWithinMaxConstraints, other.isWithinMaxConstraints)
.compareFalseFirst(this.isWithinMinConstraints, other.isWithinMinConstraints) .compareFalseFirst(this.isWithinMinConstraints, other.isWithinMinConstraints)
.compare( .compare(
...@@ -2568,6 +2591,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2568,6 +2591,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private final int preferredLanguageScore; private final int preferredLanguageScore;
private final int preferredLanguageIndex; private final int preferredLanguageIndex;
private final int preferredRoleFlagsScore; private final int preferredRoleFlagsScore;
private final boolean hasMainOrNoRoleFlag;
private final int localeLanguageMatchIndex; private final int localeLanguageMatchIndex;
private final int localeLanguageScore; private final int localeLanguageScore;
private final boolean isDefaultSelectionFlag; private final boolean isDefaultSelectionFlag;
...@@ -2598,7 +2622,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2598,7 +2622,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
preferredLanguageIndex = bestLanguageIndex; preferredLanguageIndex = bestLanguageIndex;
preferredLanguageScore = bestLanguageScore; preferredLanguageScore = bestLanguageScore;
preferredRoleFlagsScore = preferredRoleFlagsScore =
Integer.bitCount(format.roleFlags & parameters.preferredAudioRoleFlags); getRoleFlagMatchScore(format.roleFlags, parameters.preferredAudioRoleFlags);
hasMainOrNoRoleFlag = format.roleFlags == 0 || (format.roleFlags & C.ROLE_FLAG_MAIN) != 0;
isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
channelCount = format.channelCount; channelCount = format.channelCount;
sampleRate = format.sampleRate; sampleRate = format.sampleRate;
...@@ -2656,6 +2681,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2656,6 +2681,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
Ordering.natural().reverse()) Ordering.natural().reverse())
.compare(this.preferredLanguageScore, other.preferredLanguageScore) .compare(this.preferredLanguageScore, other.preferredLanguageScore)
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore) .compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
.compareFalseFirst(this.hasMainOrNoRoleFlag, other.hasMainOrNoRoleFlag)
.compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints) .compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints)
.compare( .compare(
this.preferredMimeTypeMatchIndex, this.preferredMimeTypeMatchIndex,
...@@ -2732,7 +2758,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2732,7 +2758,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
preferredLanguageIndex = bestLanguageIndex; preferredLanguageIndex = bestLanguageIndex;
preferredLanguageScore = bestLanguageScore; preferredLanguageScore = bestLanguageScore;
preferredRoleFlagsScore = preferredRoleFlagsScore =
Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags); getRoleFlagMatchScore(format.roleFlags, parameters.preferredTextRoleFlags);
hasCaptionRoleFlags = hasCaptionRoleFlags =
(format.roleFlags & (C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND)) != 0; (format.roleFlags & (C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND)) != 0;
boolean selectedAudioLanguageUndetermined = boolean selectedAudioLanguageUndetermined =
......
...@@ -594,7 +594,7 @@ public final class DefaultTrackSelectorTest { ...@@ -594,7 +594,7 @@ public final class DefaultTrackSelectorTest {
} }
/** /**
* Tests that track selector will select audio track with the highest number of matching role * Tests that track selector will select the audio track with the highest number of matching role
* flags given by {@link Parameters}. * flags given by {@link Parameters}.
*/ */
@Test @Test
...@@ -619,6 +619,17 @@ public final class DefaultTrackSelectorTest { ...@@ -619,6 +619,17 @@ public final class DefaultTrackSelectorTest {
periodId, periodId,
TIMELINE); TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, moreRoleFlags); assertFixedSelection(result.selections[0], trackGroups, moreRoleFlags);
// Also verify that exact match between parameters and tracks is preferred.
trackSelector.setParameters(
defaultParameters.buildUpon().setPreferredAudioRoleFlags(C.ROLE_FLAG_CAPTION));
result =
trackSelector.selectTracks(
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
trackGroups,
periodId,
TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, lessRoleFlags);
} }
/** /**
...@@ -1280,6 +1291,45 @@ public final class DefaultTrackSelectorTest { ...@@ -1280,6 +1291,45 @@ public final class DefaultTrackSelectorTest {
} }
/** /**
* Tests that track selector will select the text track with the highest number of matching role
* flags given by {@link Parameters}.
*/
@Test
public void selectTracks_withPreferredTextRoleFlags_selectPreferredTrack() throws Exception {
Format.Builder formatBuilder = TEXT_FORMAT.buildUpon();
Format noRoleFlags = formatBuilder.build();
Format lessRoleFlags = formatBuilder.setRoleFlags(C.ROLE_FLAG_CAPTION).build();
Format moreRoleFlags =
formatBuilder
.setRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY | C.ROLE_FLAG_DUB)
.build();
TrackGroupArray trackGroups = wrapFormats(noRoleFlags, moreRoleFlags, lessRoleFlags);
trackSelector.setParameters(
defaultParameters
.buildUpon()
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY));
TrackSelectorResult result =
trackSelector.selectTracks(
new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
trackGroups,
periodId,
TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, moreRoleFlags);
// Also verify that exact match between parameters and tracks is preferred.
trackSelector.setParameters(
defaultParameters.buildUpon().setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION));
result =
trackSelector.selectTracks(
new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
trackGroups,
periodId,
TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, lessRoleFlags);
}
/**
* Tests that track selector will select the lowest bitrate supported audio track when {@link * Tests that track selector will select the lowest bitrate supported audio track when {@link
* Parameters#forceLowestBitrate} is set. * Parameters#forceLowestBitrate} is set.
*/ */
...@@ -1809,6 +1859,39 @@ public final class DefaultTrackSelectorTest { ...@@ -1809,6 +1859,39 @@ public final class DefaultTrackSelectorTest {
assertFixedSelection(result.selections[0], trackGroups, formatAv1); assertFixedSelection(result.selections[0], trackGroups, formatAv1);
} }
/**
* Tests that track selector will select the video track with the highest number of matching role
* flags given by {@link Parameters}.
*/
@Test
public void selectTracks_withPreferredVideoRoleFlags_selectPreferredTrack() throws Exception {
Format.Builder formatBuilder = VIDEO_FORMAT.buildUpon();
Format noRoleFlags = formatBuilder.build();
Format lessRoleFlags = formatBuilder.setRoleFlags(C.ROLE_FLAG_CAPTION).build();
Format moreRoleFlags =
formatBuilder
.setRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY | C.ROLE_FLAG_DUB)
.build();
TrackGroupArray trackGroups = wrapFormats(noRoleFlags, moreRoleFlags, lessRoleFlags);
trackSelector.setParameters(
defaultParameters
.buildUpon()
.setPreferredVideoRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY));
TrackSelectorResult result =
trackSelector.selectTracks(
new RendererCapabilities[] {VIDEO_CAPABILITIES}, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, moreRoleFlags);
// Also verify that exact match between parameters and tracks is preferred.
trackSelector.setParameters(
defaultParameters.buildUpon().setPreferredVideoRoleFlags(C.ROLE_FLAG_CAPTION));
result =
trackSelector.selectTracks(
new RendererCapabilities[] {VIDEO_CAPABILITIES}, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, lessRoleFlags);
}
@Test @Test
public void selectTracks_withPreferredAudioMimeTypes_selectsTrackWithPreferredMimeType() public void selectTracks_withPreferredAudioMimeTypes_selectsTrackWithPreferredMimeType()
throws Exception { throws Exception {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment