public final class

TrackSelectionUtil

extends java.lang.Object

 java.lang.Object

↳androidx.media3.exoplayer.trackselection.TrackSelectionUtil

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-exoplayer', version: '1.5.0-alpha01'

  • groupId: androidx.media3
  • artifactId: media3-exoplayer
  • version: 1.5.0-alpha01

Artifact androidx.media3:media3-exoplayer:1.5.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

Track selection related utility methods.

Summary

Methods
public static TracksbuildTracks(MappingTrackSelector.MappedTrackInfo mappedTrackInfo, java.util.List<TrackSelection> selections[])

Returns Tracks built from MappingTrackSelector.MappedTrackInfo and TrackSelections for each renderer.

public static TracksbuildTracks(MappingTrackSelector.MappedTrackInfo mappedTrackInfo, TrackSelection selections[])

Returns Tracks built from MappingTrackSelector.MappedTrackInfo and TrackSelections for each renderer.

public static LoadErrorHandlingPolicy.FallbackOptionscreateFallbackOptions(ExoTrackSelection trackSelection)

Returns the with the tracks of the given ExoTrackSelection and with a single location option indicating that there are no alternative locations available.

public static ExoTrackSelectioncreateTrackSelectionsForDefinitions(ExoTrackSelection.Definition definitions[], TrackSelectionUtil.AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory)

Creates track selections for an array of track selection definitions, with at most one multi-track adaptive selection.

public static PointgetMaxVideoSizeInViewport(boolean orientationMayChange, int viewportWidth, int viewportHeight, int videoWidth, int videoHeight)

Given viewport dimensions and video dimensions, computes the maximum size of the video as it will be rendered to fit inside of the viewport.

public static DefaultTrackSelector.ParametersupdateParametersWithOverride(DefaultTrackSelector.Parameters parameters, int rendererIndex, TrackGroupArray trackGroupArray, boolean isDisabled, DefaultTrackSelector.SelectionOverride override)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public static ExoTrackSelection createTrackSelectionsForDefinitions(ExoTrackSelection.Definition definitions[], TrackSelectionUtil.AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory)

Creates track selections for an array of track selection definitions, with at most one multi-track adaptive selection.

Parameters:

definitions: The list of track selection definitions. May include null values.
adaptiveTrackSelectionFactory: A factory for the multi-track adaptive track selection.

Returns:

The array of created track selection. For null entries in definitions returns null values.

public static DefaultTrackSelector.Parameters updateParametersWithOverride(DefaultTrackSelector.Parameters parameters, int rendererIndex, TrackGroupArray trackGroupArray, boolean isDisabled, DefaultTrackSelector.SelectionOverride override)

Deprecated: Use DefaultTrackSelector.Parameters.Builder.addOverride(TrackSelectionOverride) instead.

public static LoadErrorHandlingPolicy.FallbackOptions createFallbackOptions(ExoTrackSelection trackSelection)

Returns the with the tracks of the given ExoTrackSelection and with a single location option indicating that there are no alternative locations available.

Parameters:

trackSelection: The track selection to get the number of total and excluded tracks.

Returns:

The for the given track selection.

public static Tracks buildTracks(MappingTrackSelector.MappedTrackInfo mappedTrackInfo, TrackSelection selections[])

Returns Tracks built from MappingTrackSelector.MappedTrackInfo and TrackSelections for each renderer.

Parameters:

mappedTrackInfo: The MappingTrackSelector.MappedTrackInfo
selections: The track selections, indexed by renderer. A null entry indicates that a renderer does not have any selected tracks.

Returns:

The corresponding Tracks.

public static Tracks buildTracks(MappingTrackSelector.MappedTrackInfo mappedTrackInfo, java.util.List<TrackSelection> selections[])

Returns Tracks built from MappingTrackSelector.MappedTrackInfo and TrackSelections for each renderer.

Parameters:

mappedTrackInfo: The MappingTrackSelector.MappedTrackInfo
selections: The track selections, indexed by renderer. Null entries are not permitted. An empty list indicates that a renderer does not have any selected tracks.

Returns:

The corresponding Tracks.

public static Point getMaxVideoSizeInViewport(boolean orientationMayChange, int viewportWidth, int viewportHeight, int videoWidth, int videoHeight)

Given viewport dimensions and video dimensions, computes the maximum size of the video as it will be rendered to fit inside of the viewport.

Source

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media3.exoplayer.trackselection;

import android.graphics.Point;
import android.os.SystemClock;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.NullableType;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.RendererCapabilities;
import androidx.media3.exoplayer.source.TrackGroupArray;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector.SelectionOverride;
import androidx.media3.exoplayer.trackselection.ExoTrackSelection.Definition;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.List;

/** Track selection related utility methods. */
@UnstableApi
public final class TrackSelectionUtil {

  private TrackSelectionUtil() {}

  /** Functional interface to create a single adaptive track selection. */
  public interface AdaptiveTrackSelectionFactory {

    /**
     * Creates an adaptive track selection for the provided track selection definition.
     *
     * @param trackSelectionDefinition A {@link Definition} for the track selection.
     * @return The created track selection.
     */
    ExoTrackSelection createAdaptiveTrackSelection(Definition trackSelectionDefinition);
  }

  /**
   * Creates track selections for an array of track selection definitions, with at most one
   * multi-track adaptive selection.
   *
   * @param definitions The list of track selection {@link Definition definitions}. May include null
   *     values.
   * @param adaptiveTrackSelectionFactory A factory for the multi-track adaptive track selection.
   * @return The array of created track selection. For null entries in {@code definitions} returns
   *     null values.
   */
  public static @NullableType ExoTrackSelection[] createTrackSelectionsForDefinitions(
      @NullableType Definition[] definitions,
      AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory) {
    ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
    boolean createdAdaptiveTrackSelection = false;
    for (int i = 0; i < definitions.length; i++) {
      Definition definition = definitions[i];
      if (definition == null) {
        continue;
      }
      if (definition.tracks.length > 1 && !createdAdaptiveTrackSelection) {
        createdAdaptiveTrackSelection = true;
        selections[i] = adaptiveTrackSelectionFactory.createAdaptiveTrackSelection(definition);
      } else {
        selections[i] =
            new FixedTrackSelection(
                definition.group, definition.tracks[0], /* type= */ definition.type);
      }
    }
    return selections;
  }

  /**
   * @deprecated Use {@link DefaultTrackSelector.Parameters.Builder#addOverride} instead.
   */
  @SuppressWarnings("deprecation") // Forwarding to deprecated methods
  @Deprecated
  public static DefaultTrackSelector.Parameters updateParametersWithOverride(
      DefaultTrackSelector.Parameters parameters,
      int rendererIndex,
      TrackGroupArray trackGroupArray,
      boolean isDisabled,
      @Nullable SelectionOverride override) {
    DefaultTrackSelector.Parameters.Builder builder =
        parameters
            .buildUpon()
            .clearSelectionOverrides(rendererIndex)
            .setRendererDisabled(rendererIndex, isDisabled);
    if (override != null) {
      builder.setSelectionOverride(rendererIndex, trackGroupArray, override);
    }
    return builder.build();
  }

  /**
   * Returns the {@link LoadErrorHandlingPolicy.FallbackOptions} with the tracks of the given {@link
   * ExoTrackSelection} and with a single location option indicating that there are no alternative
   * locations available.
   *
   * @param trackSelection The track selection to get the number of total and excluded tracks.
   * @return The {@link LoadErrorHandlingPolicy.FallbackOptions} for the given track selection.
   */
  public static LoadErrorHandlingPolicy.FallbackOptions createFallbackOptions(
      ExoTrackSelection trackSelection) {
    long nowMs = SystemClock.elapsedRealtime();
    int numberOfTracks = trackSelection.length();
    int numberOfExcludedTracks = 0;
    for (int i = 0; i < numberOfTracks; i++) {
      if (trackSelection.isTrackExcluded(i, nowMs)) {
        numberOfExcludedTracks++;
      }
    }
    return new LoadErrorHandlingPolicy.FallbackOptions(
        /* numberOfLocations= */ 1,
        /* numberOfExcludedLocations= */ 0,
        numberOfTracks,
        numberOfExcludedTracks);
  }

  /**
   * Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
   * TrackSelection TrackSelections} for each renderer.
   *
   * @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
   * @param selections The track selections, indexed by renderer. A null entry indicates that a
   *     renderer does not have any selected tracks.
   * @return The corresponding {@link Tracks}.
   */
  @SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
  public static Tracks buildTracks(
      MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
      @NullableType TrackSelection[] selections) {
    List<? extends TrackSelection>[] listSelections = new List[selections.length];
    for (int i = 0; i < selections.length; i++) {
      @Nullable TrackSelection selection = selections[i];
      listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
    }
    return buildTracks(mappedTrackInfo, listSelections);
  }

  /**
   * Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
   * TrackSelection TrackSelections} for each renderer.
   *
   * @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
   * @param selections The track selections, indexed by renderer. Null entries are not permitted. An
   *     empty list indicates that a renderer does not have any selected tracks.
   * @return The corresponding {@link Tracks}.
   */
  public static Tracks buildTracks(
      MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
      List<? extends TrackSelection>[] selections) {
    ImmutableList.Builder<Tracks.Group> trackGroups = new ImmutableList.Builder<>();
    for (int rendererIndex = 0;
        rendererIndex < mappedTrackInfo.getRendererCount();
        rendererIndex++) {
      TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex);
      List<? extends TrackSelection> rendererTrackSelections = selections[rendererIndex];
      for (int groupIndex = 0; groupIndex < trackGroupArray.length; groupIndex++) {
        TrackGroup trackGroup = trackGroupArray.get(groupIndex);
        boolean adaptiveSupported =
            mappedTrackInfo.getAdaptiveSupport(
                    rendererIndex, groupIndex, /* includeCapabilitiesExceededTracks= */ false)
                != RendererCapabilities.ADAPTIVE_NOT_SUPPORTED;
        @C.FormatSupport int[] trackSupport = new int[trackGroup.length];
        boolean[] selected = new boolean[trackGroup.length];
        for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
          trackSupport[trackIndex] =
              mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex);
          boolean isTrackSelected = false;
          for (int i = 0; i < rendererTrackSelections.size(); i++) {
            TrackSelection trackSelection = rendererTrackSelections.get(i);
            if (trackSelection.getTrackGroup().equals(trackGroup)
                && trackSelection.indexOf(trackIndex) != C.INDEX_UNSET) {
              isTrackSelected = true;
              break;
            }
          }
          selected[trackIndex] = isTrackSelected;
        }
        trackGroups.add(new Tracks.Group(trackGroup, adaptiveSupported, trackSupport, selected));
      }
    }
    TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
    for (int groupIndex = 0; groupIndex < unmappedTrackGroups.length; groupIndex++) {
      TrackGroup trackGroup = unmappedTrackGroups.get(groupIndex);
      @C.FormatSupport int[] trackSupport = new int[trackGroup.length];
      Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
      boolean[] selected = new boolean[trackGroup.length];
      trackGroups.add(
          new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
    }
    return new Tracks(trackGroups.build());
  }

  /**
   * Given viewport dimensions and video dimensions, computes the maximum size of the video as it
   * will be rendered to fit inside of the viewport.
   */
  public static Point getMaxVideoSizeInViewport(
      boolean orientationMayChange,
      int viewportWidth,
      int viewportHeight,
      int videoWidth,
      int videoHeight) {
    if (orientationMayChange && (videoWidth > videoHeight) != (viewportWidth > viewportHeight)) {
      // Rotation is allowed, and the video will be larger in the rotated viewport.
      int tempViewportWidth = viewportWidth;
      viewportWidth = viewportHeight;
      viewportHeight = tempViewportWidth;
    }

    if (videoWidth * viewportHeight >= videoHeight * viewportWidth) {
      // Horizontal letter-boxing along top and bottom.
      return new Point(viewportWidth, Util.ceilDivide(viewportWidth * videoHeight, videoWidth));
    } else {
      // Vertical letter-boxing along edges.
      return new Point(Util.ceilDivide(viewportHeight * videoWidth, videoHeight), viewportHeight);
    }
  }
}