mirror of
https://github.com/samsonjs/media.git
synced 2026-04-02 10:45:51 +00:00
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
This commit is contained in:
parent
e846e9f06c
commit
339d99b860
4 changed files with 192 additions and 56 deletions
104
RELEASENOTES.md
104
RELEASENOTES.md
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
### dev-v2 (not yet released)
|
||||
|
||||
* Core library:
|
||||
* Support preferred video role flags in track selection
|
||||
((#9402)[https://github.com/google/ExoPlayer/issues/9402]).
|
||||
* DRM:
|
||||
* Remove `playbackLooper` from `DrmSessionManager.(pre)acquireSession`.
|
||||
When a `DrmSessionManager` is used by an app in a custom `MediaSource`,
|
||||
|
|
@ -545,8 +548,8 @@
|
|||
* The most used methods of `Player`'s audio, video, text and metadata
|
||||
components have been added directly to `Player`.
|
||||
* Add `Player.getAvailableCommands`, `Player.isCommandAvailable` and
|
||||
`Listener.onAvailableCommandsChanged` to query which commands
|
||||
that can be executed on the player.
|
||||
`Listener.onAvailableCommandsChanged` to query which commands that can
|
||||
be executed on the player.
|
||||
* Add a `Player.Listener` interface to receive all player events.
|
||||
Component listeners and `EventListener` have been deprecated.
|
||||
* Add `Player.getMediaMetadata`, which returns a combined and structured
|
||||
|
|
@ -555,8 +558,8 @@
|
|||
* `Player.setPlaybackParameters` no longer accepts null, use
|
||||
`PlaybackParameters.DEFAULT` instead.
|
||||
* Report information about the old and the new playback positions to
|
||||
`Listener.onPositionDiscontinuity`. Add `DISCONTINUITY_REASON_SKIP`
|
||||
and `DISCONTINUITY_REASON_REMOVE` as discontinuity reasons, and rename
|
||||
`Listener.onPositionDiscontinuity`. Add `DISCONTINUITY_REASON_SKIP` and
|
||||
`DISCONTINUITY_REASON_REMOVE` as discontinuity reasons, and rename
|
||||
`DISCONTINUITY_REASON_PERIOD_TRANSITION` to
|
||||
`DISCONTINUITY_REASON_AUTO_TRANSITION`. Remove
|
||||
`DISCONTINUITY_REASON_AD_INSERTION`, for which
|
||||
|
|
@ -611,8 +614,8 @@
|
|||
dispatched for each track in each period.
|
||||
* Include the session state in DRM session-acquired listener methods.
|
||||
* UI:
|
||||
* Add `PlayerNotificationManager.Builder`, with the ability to
|
||||
specify which group the notification should belong to.
|
||||
* Add `PlayerNotificationManager.Builder`, with the ability to specify
|
||||
which group the notification should belong to.
|
||||
* Remove `setUseSensorRotation` from `PlayerView` and `StyledPlayerView`.
|
||||
Instead, cast the view returned by `getVideoSurfaceView` to
|
||||
`SphericalGLSurfaceView`, and then call `setUseSensorRotation` on the
|
||||
|
|
@ -684,7 +687,8 @@
|
|||
|
||||
### 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:
|
||||
* Reset playback speed when live playback speed control becomes unused
|
||||
([#8664](https://github.com/google/ExoPlayer/issues/8664)).
|
||||
|
|
@ -839,8 +843,8 @@
|
|||
* Remove `Player.setVideoDecoderOutputBufferRenderer` from Player API. Use
|
||||
`setVideoSurfaceView` and `clearVideoSurfaceView` instead.
|
||||
* Default `SingleSampleMediaSource.treatLoadErrorsAsEndOfStream` to `true`
|
||||
so that errors loading external subtitle files do not cause playback
|
||||
to fail ([#8430](https://github.com/google/ExoPlayer/issues/8430)). A
|
||||
so that errors loading external subtitle files do not cause playback to
|
||||
fail ([#8430](https://github.com/google/ExoPlayer/issues/8430)). A
|
||||
warning will be logged by `SingleSampleMediaPeriod` whenever a load
|
||||
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
|
||||
|
|
@ -921,9 +925,8 @@
|
|||
([#7847](https://github.com/google/ExoPlayer/issues/7847)).
|
||||
* Drop key and provision responses if `DefaultDrmSession` is released
|
||||
while waiting for the response. This prevents harmless log messages of
|
||||
the form:
|
||||
`IllegalStateException: sending message to a Handler on a dead thread`
|
||||
([#8328](https://github.com/google/ExoPlayer/issues/8328)).
|
||||
the form: `IllegalStateException: sending message to a Handler on a dead
|
||||
thread` ([#8328](https://github.com/google/ExoPlayer/issues/8328)).
|
||||
* Allow apps to fully customize DRM behaviour for each `MediaItem` by
|
||||
passing a `DrmSessionManagerProvider` to `MediaSourceFactory`
|
||||
([#8466](https://github.com/google/ExoPlayer/issues/8466)).
|
||||
|
|
@ -938,8 +941,8 @@
|
|||
existing decoder instance for the new format, and if not then the
|
||||
reasons why.
|
||||
* Video:
|
||||
* Fall back to AVC/HEVC decoders for Dolby Vision streams with level 10
|
||||
to 13 ([#8530](https://github.com/google/ExoPlayer/issues/8530)).
|
||||
* Fall back to AVC/HEVC decoders for Dolby Vision streams with level 10 to
|
||||
13 ([#8530](https://github.com/google/ExoPlayer/issues/8530)).
|
||||
* Fix VP9 format capability checks on API level 23 and earlier. 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
|
||||
|
|
@ -1021,8 +1024,8 @@
|
|||
* `ExtractorsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use
|
||||
`ExtractorsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
|
||||
instead.
|
||||
* `FixedTrackSelection.Factory`. If you need to disable adaptive
|
||||
selection in `DefaultTrackSelector`, enable the
|
||||
* `FixedTrackSelection.Factory`. If you need to disable adaptive selection
|
||||
in `DefaultTrackSelector`, enable the
|
||||
`DefaultTrackSelector.Parameters.forceHighestSupportedBitrate` flag.
|
||||
* `HlsMediaSource.Factory.setMinLoadableRetryCount(int)`. Use
|
||||
`HlsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
|
||||
|
|
@ -1035,8 +1038,8 @@
|
|||
`MappedTrackInfo.getUnmappedTrackGroups()` instead.
|
||||
* `MappedTrackInfo.length`. Use `MappedTrackInfo.getRendererCount()`
|
||||
instead.
|
||||
* `Player.DefaultEventListener.onTimelineChanged(Timeline, Object)`.
|
||||
Use `Player.EventListener.onTimelineChanged(Timeline, int)` instead.
|
||||
* `Player.DefaultEventListener.onTimelineChanged(Timeline, Object)`. Use
|
||||
`Player.EventListener.onTimelineChanged(Timeline, int)` instead.
|
||||
* `Player.setAudioAttributes(AudioAttributes)`. Use
|
||||
`Player.AudioComponent.setAudioAttributes(AudioAttributes, boolean)`
|
||||
instead.
|
||||
|
|
@ -1052,8 +1055,8 @@
|
|||
`SimpleExoPlayer.removeVideoListener(VideoListener)` instead.
|
||||
* `SimpleExoPlayer.getAudioStreamType()`. Use
|
||||
`SimpleExoPlayer.getAudioAttributes()` instead.
|
||||
* `SimpleExoPlayer.setAudioDebugListener(AudioRendererEventListener)`.
|
||||
Use `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
|
||||
* `SimpleExoPlayer.setAudioDebugListener(AudioRendererEventListener)`. Use
|
||||
`SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
|
||||
* `SimpleExoPlayer.setAudioStreamType(int)`. Use
|
||||
`SimpleExoPlayer.setAudioAttributes(AudioAttributes)` instead.
|
||||
* `SimpleExoPlayer.setMetadataOutput(MetadataOutput)`. Use
|
||||
|
|
@ -1064,12 +1067,11 @@
|
|||
* `SimpleExoPlayer.setPlaybackParams(PlaybackParams)`. Use
|
||||
`SimpleExoPlayer.setPlaybackParameters(PlaybackParameters)` instead.
|
||||
* `SimpleExoPlayer.setTextOutput(TextOutput)`. Use
|
||||
`SimpleExoPlayer.addTextOutput(TextOutput)` instead. If your
|
||||
application is calling `SimpleExoPlayer.setTextOutput(null)`, make sure
|
||||
to replace this call with a call to
|
||||
`SimpleExoPlayer.removeTextOutput(TextOutput)`.
|
||||
* `SimpleExoPlayer.setVideoDebugListener(VideoRendererEventListener)`.
|
||||
Use `SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
|
||||
`SimpleExoPlayer.addTextOutput(TextOutput)` instead. If your application
|
||||
is calling `SimpleExoPlayer.setTextOutput(null)`, make sure to replace
|
||||
this call with a call to `SimpleExoPlayer.removeTextOutput(TextOutput)`.
|
||||
* `SimpleExoPlayer.setVideoDebugListener(VideoRendererEventListener)`. Use
|
||||
`SimpleExoPlayer.addAnalyticsListener(AnalyticsListener)` instead.
|
||||
* `SimpleExoPlayer.setVideoListener(VideoListener)`. Use
|
||||
`SimpleExoPlayer.addVideoListener(VideoListener)` instead. If your
|
||||
application is calling `SimpleExoPlayer.setVideoListener(null)`, make
|
||||
|
|
@ -1093,7 +1095,7 @@
|
|||
`SsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)`
|
||||
instead.
|
||||
|
||||
### 2.12.3 (2021-01-13) ###
|
||||
### 2.12.3 (2021-01-13)
|
||||
|
||||
* Core library:
|
||||
* Fix `MediaCodecRenderer` issue where empty streams would fail to play in
|
||||
|
|
@ -1130,7 +1132,7 @@
|
|||
fix a deadlock while creating PlaybackStateCompat internally.
|
||||
([#8011](https://github.com/google/ExoPlayer/issues/8011)).
|
||||
|
||||
### 2.12.2 (2020-12-01) ###
|
||||
### 2.12.2 (2020-12-01)
|
||||
|
||||
* Core library:
|
||||
* Suppress exceptions from registering and unregistering the stream volume
|
||||
|
|
@ -1191,7 +1193,7 @@
|
|||
* Allow to remove all playlist items that makes the player reset
|
||||
([#8047](https://github.com/google/ExoPlayer/issues/8047)).
|
||||
|
||||
### 2.12.1 (2020-10-23) ###
|
||||
### 2.12.1 (2020-10-23)
|
||||
|
||||
* Core library:
|
||||
* Fix issue where `Player.setMediaItems` would ignore its `resetPosition`
|
||||
|
|
@ -1230,7 +1232,7 @@
|
|||
([#8058](https://github.com/google/ExoPlayer/issues/8058)).
|
||||
* Extractors:
|
||||
* MP4:
|
||||
* Add support for `_mp2` boxes
|
||||
* Add support for `_mp2` boxes
|
||||
([#7967](https://github.com/google/ExoPlayer/issues/7967)).
|
||||
* Fix playback of files containing `pcm_alaw` or `pcm_mulaw` audio
|
||||
tracks, by enabling sample rechunking for such tracks.
|
||||
|
|
@ -1266,11 +1268,11 @@
|
|||
([#7961](https://github.com/google/ExoPlayer/issues/7961)).
|
||||
* Fix incorrect truncation of large cue point positions
|
||||
([#8067](https://github.com/google/ExoPlayer/issues/8067)).
|
||||
* Upgrade IMA SDK dependency to 3.20.1. This brings in a fix for
|
||||
companion ads rendering when targeting API 29
|
||||
* Upgrade IMA SDK dependency to 3.20.1. This brings in a fix for companion
|
||||
ads rendering when targeting API 29
|
||||
([#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
|
||||
[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
|
|||
* Remove `PlaybackParameters.skipSilence`, and replace it with
|
||||
`AudioComponent.setSkipSilenceEnabled`. This method is also
|
||||
available on `SimpleExoPlayer`. An
|
||||
`AudioListener.onSkipSilenceEnabledChanged` callback is also
|
||||
added.
|
||||
`AudioListener.onSkipSilenceEnabledChanged` callback is also added.
|
||||
* Add `TextComponent.getCurrentCues` to get the current cues. This
|
||||
method is also available on `SimpleExoPlayer`. The current cues are
|
||||
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
|
|||
* Add support for downloading DRM-protected content using offline Widevine
|
||||
licenses.
|
||||
|
||||
### 2.11.8 (2020-08-25) ###
|
||||
### 2.11.8 (2020-08-25)
|
||||
|
||||
* Fix distorted playback of floating point audio when samples exceed the
|
||||
`[-1, 1]` nominal range.
|
||||
* Fix distorted playback of floating point audio when samples exceed the `[-1,
|
||||
1]` nominal range.
|
||||
* MP4:
|
||||
* Add support for `piff` and `isml` brands
|
||||
([#7584](https://github.com/google/ExoPlayer/issues/7584)).
|
||||
* Fix playback of very short MP4 files.
|
||||
* FMP4:
|
||||
* Fix `saiz` and `senc` sample count checks, resolving a "length
|
||||
mismatch" `ParserException` when playing certain protected FMP4 streams
|
||||
* Fix `saiz` and `senc` sample count checks, resolving a "length mismatch"
|
||||
`ParserException` when playing certain protected FMP4 streams
|
||||
([#7592](https://github.com/google/ExoPlayer/issues/7592)).
|
||||
* Fix handling of `traf` boxes containing multiple `sbgp` or `sgpd`
|
||||
boxes.
|
||||
* Fix handling of `traf` boxes containing multiple `sbgp` or `sgpd` boxes.
|
||||
* FLV: Ignore `SCRIPTDATA` segments with invalid name types, rather than
|
||||
failing playback ([#7675](https://github.com/google/ExoPlayer/issues/7675)).
|
||||
* 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
|
|||
* Demo app: Fix playback of ClearKey protected content on API level 26 and
|
||||
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
|
||||
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
|
||||
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
|
|||
([#7508](https://github.com/google/ExoPlayer/issues/7508)).
|
||||
* Fix a bug where the number of ads in an ad group couldn't change
|
||||
([#7477](https://github.com/google/ExoPlayer/issues/7477)).
|
||||
* Work around unexpected `pauseAd`/`stopAd` for ads that have preloaded
|
||||
on seeking to another position
|
||||
* Work around unexpected `pauseAd`/`stopAd` for ads that have preloaded on
|
||||
seeking to another position
|
||||
([#7492](https://github.com/google/ExoPlayer/issues/7492)).
|
||||
* Fix incorrect rounding of ad cue points.
|
||||
* Fix handling of postrolls preloading
|
||||
([#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
|
||||
or resuming a playback
|
||||
|
|
@ -1691,8 +1691,8 @@ To learn more about what's new in 2.12, read the corresponding
|
|||
* Add `SilenceMediaSource.Factory` to support tags.
|
||||
* Enable the configuration of `SilenceSkippingAudioProcessor`
|
||||
([#6705](https://github.com/google/ExoPlayer/issues/6705)).
|
||||
* Fix bug where `PlayerMessages` throw an exception after `MediaSources`
|
||||
are removed from the playlist
|
||||
* Fix bug where `PlayerMessages` throw an exception after `MediaSources` are
|
||||
removed from the playlist
|
||||
([#7278](https://github.com/google/ExoPlayer/issues/7278)).
|
||||
* Fix "Not allowed to start service" `IllegalStateException` in
|
||||
`DownloadService`
|
||||
|
|
@ -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)).
|
||||
* Add `showScrubber` and `hideScrubber` methods to `DefaultTimeBar`.
|
||||
* Text:
|
||||
* Use anti-aliasing and bitmap filtering when displaying bitmap
|
||||
subtitles.
|
||||
* Use anti-aliasing and bitmap filtering when displaying bitmap subtitles.
|
||||
* Fix `SubtitlePainter` to render `EDGE_TYPE_OUTLINE` using the correct
|
||||
color.
|
||||
* IMA extension:
|
||||
* Upgrade to IMA SDK version 3.19.0, and migrate to new
|
||||
preloading APIs
|
||||
* Upgrade to IMA SDK version 3.19.0, and migrate to new preloading APIs
|
||||
([#6429](https://github.com/google/ExoPlayer/issues/6429)). This fixes
|
||||
several issues involving preloading and handling of ad loading error
|
||||
cases: ([#4140](https://github.com/google/ExoPlayer/issues/4140),
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
private int viewportHeight;
|
||||
private boolean viewportOrientationMayChange;
|
||||
private ImmutableList<String> preferredVideoMimeTypes;
|
||||
private @C.RoleFlags int preferredVideoRoleFlags;
|
||||
// Audio
|
||||
private ImmutableList<String> preferredAudioLanguages;
|
||||
private @C.RoleFlags int preferredAudioRoleFlags;
|
||||
|
|
@ -111,6 +112,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
viewportHeight = Integer.MAX_VALUE;
|
||||
viewportOrientationMayChange = true;
|
||||
preferredVideoMimeTypes = ImmutableList.of();
|
||||
preferredVideoRoleFlags = 0;
|
||||
// Audio
|
||||
preferredAudioLanguages = ImmutableList.of();
|
||||
preferredAudioRoleFlags = 0;
|
||||
|
|
@ -183,6 +185,10 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
firstNonNull(
|
||||
bundle.getStringArray(keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES)),
|
||||
new String[0]));
|
||||
preferredVideoRoleFlags =
|
||||
bundle.getInt(
|
||||
keyForField(FIELD_PREFERRED_VIDEO_ROLE_FLAGS),
|
||||
DEFAULT_WITHOUT_CONTEXT.preferredVideoRoleFlags);
|
||||
// Audio
|
||||
String[] preferredAudioLanguages1 =
|
||||
firstNonNull(
|
||||
|
|
@ -261,6 +267,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
viewportHeight = parameters.viewportHeight;
|
||||
viewportOrientationMayChange = parameters.viewportOrientationMayChange;
|
||||
preferredVideoMimeTypes = parameters.preferredVideoMimeTypes;
|
||||
preferredVideoRoleFlags = parameters.preferredVideoRoleFlags;
|
||||
// Audio
|
||||
preferredAudioLanguages = parameters.preferredAudioLanguages;
|
||||
preferredAudioRoleFlags = parameters.preferredAudioRoleFlags;
|
||||
|
|
@ -441,6 +448,17 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
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
|
||||
|
||||
/**
|
||||
|
|
@ -770,6 +788,11 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
* no preference. The default is an empty list.
|
||||
*/
|
||||
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
|
||||
/**
|
||||
* 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 {
|
|||
this.viewportHeight = builder.viewportHeight;
|
||||
this.viewportOrientationMayChange = builder.viewportOrientationMayChange;
|
||||
this.preferredVideoMimeTypes = builder.preferredVideoMimeTypes;
|
||||
this.preferredVideoRoleFlags = builder.preferredVideoRoleFlags;
|
||||
// Audio
|
||||
this.preferredAudioLanguages = builder.preferredAudioLanguages;
|
||||
this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags;
|
||||
|
|
@ -898,6 +922,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
&& viewportWidth == other.viewportWidth
|
||||
&& viewportHeight == other.viewportHeight
|
||||
&& preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes)
|
||||
&& preferredVideoRoleFlags == other.preferredVideoRoleFlags
|
||||
// Audio
|
||||
&& preferredAudioLanguages.equals(other.preferredAudioLanguages)
|
||||
&& preferredAudioRoleFlags == other.preferredAudioRoleFlags
|
||||
|
|
@ -930,6 +955,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
result = 31 * result + viewportWidth;
|
||||
result = 31 * result + viewportHeight;
|
||||
result = 31 * result + preferredVideoMimeTypes.hashCode();
|
||||
result = 31 * result + preferredVideoRoleFlags;
|
||||
// Audio
|
||||
result = 31 * result + preferredAudioLanguages.hashCode();
|
||||
result = 31 * result + preferredAudioRoleFlags;
|
||||
|
|
@ -978,6 +1004,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
FIELD_SELECTION_OVERRIDE_KEYS,
|
||||
FIELD_SELECTION_OVERRIDE_VALUES,
|
||||
FIELD_DISABLED_TRACK_TYPE,
|
||||
FIELD_PREFERRED_VIDEO_ROLE_FLAGS
|
||||
})
|
||||
private @interface FieldNumber {}
|
||||
|
||||
|
|
@ -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_VALUES = 24;
|
||||
private static final int FIELD_DISABLED_TRACK_TYPE = 25;
|
||||
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 26;
|
||||
|
||||
@Override
|
||||
public Bundle toBundle() {
|
||||
|
|
@ -1027,6 +1055,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||
bundle.putStringArray(
|
||||
keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES),
|
||||
preferredVideoMimeTypes.toArray(new String[0]));
|
||||
bundle.putInt(keyForField(FIELD_PREFERRED_VIDEO_ROLE_FLAGS), preferredVideoRoleFlags);
|
||||
// Audio
|
||||
bundle.putStringArray(
|
||||
keyForField(FIELD_PREFERRED_AUDIO_LANGUAGES),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
|
|||
import com.google.android.exoplayer2.Bundleable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
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.Format;
|
||||
import com.google.android.exoplayer2.Renderer;
|
||||
|
|
@ -368,6 +369,13 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultTrackSelector.ParametersBuilder setPreferredVideoRoleFlags(
|
||||
@RoleFlags int preferredVideoRoleFlags) {
|
||||
super.setPreferredVideoRoleFlags(preferredVideoRoleFlags);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Audio
|
||||
|
||||
@Override
|
||||
|
|
@ -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}. */
|
||||
protected static final class VideoTrackScore implements Comparable<VideoTrackScore> {
|
||||
|
||||
|
|
@ -2483,6 +2499,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
private final int bitrate;
|
||||
private final int pixelCount;
|
||||
private final int preferredMimeTypeMatchIndex;
|
||||
private final int preferredRoleFlagsScore;
|
||||
private final boolean hasMainOrNoRoleFlag;
|
||||
|
||||
public VideoTrackScore(
|
||||
Format format,
|
||||
|
|
@ -2510,6 +2528,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
isSupported(formatSupport, /* allowExceedsCapabilities= */ false);
|
||||
bitrate = format.bitrate;
|
||||
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;
|
||||
for (int i = 0; i < parameters.preferredVideoMimeTypes.size(); i++) {
|
||||
if (format.sampleMimeType != null
|
||||
|
|
@ -2537,6 +2558,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
: FORMAT_VALUE_ORDERING.reverse();
|
||||
return ComparisonChain.start()
|
||||
.compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities)
|
||||
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
|
||||
.compareFalseFirst(this.hasMainOrNoRoleFlag, other.hasMainOrNoRoleFlag)
|
||||
.compareFalseFirst(this.isWithinMaxConstraints, other.isWithinMaxConstraints)
|
||||
.compareFalseFirst(this.isWithinMinConstraints, other.isWithinMinConstraints)
|
||||
.compare(
|
||||
|
|
@ -2568,6 +2591,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
private final int preferredLanguageScore;
|
||||
private final int preferredLanguageIndex;
|
||||
private final int preferredRoleFlagsScore;
|
||||
private final boolean hasMainOrNoRoleFlag;
|
||||
private final int localeLanguageMatchIndex;
|
||||
private final int localeLanguageScore;
|
||||
private final boolean isDefaultSelectionFlag;
|
||||
|
|
@ -2598,7 +2622,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
preferredLanguageIndex = bestLanguageIndex;
|
||||
preferredLanguageScore = bestLanguageScore;
|
||||
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;
|
||||
channelCount = format.channelCount;
|
||||
sampleRate = format.sampleRate;
|
||||
|
|
@ -2656,6 +2681,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
Ordering.natural().reverse())
|
||||
.compare(this.preferredLanguageScore, other.preferredLanguageScore)
|
||||
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
|
||||
.compareFalseFirst(this.hasMainOrNoRoleFlag, other.hasMainOrNoRoleFlag)
|
||||
.compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints)
|
||||
.compare(
|
||||
this.preferredMimeTypeMatchIndex,
|
||||
|
|
@ -2732,7 +2758,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||
preferredLanguageIndex = bestLanguageIndex;
|
||||
preferredLanguageScore = bestLanguageScore;
|
||||
preferredRoleFlagsScore =
|
||||
Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags);
|
||||
getRoleFlagMatchScore(format.roleFlags, parameters.preferredTextRoleFlags);
|
||||
hasCaptionRoleFlags =
|
||||
(format.roleFlags & (C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND)) != 0;
|
||||
boolean selectedAudioLanguageUndetermined =
|
||||
|
|
|
|||
|
|
@ -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}.
|
||||
*/
|
||||
@Test
|
||||
|
|
@ -619,6 +619,17 @@ public final class DefaultTrackSelectorTest {
|
|||
periodId,
|
||||
TIMELINE);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1279,6 +1290,45 @@ public final class DefaultTrackSelectorTest {
|
|||
assertFixedSelection(result.selections[1], trackGroups, german);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Parameters#forceLowestBitrate} is set.
|
||||
|
|
@ -1809,6 +1859,39 @@ public final class DefaultTrackSelectorTest {
|
|||
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
|
||||
public void selectTracks_withPreferredAudioMimeTypes_selectsTrackWithPreferredMimeType()
|
||||
throws Exception {
|
||||
|
|
|
|||
Loading…
Reference in a new issue