public final class

DashUtil

extends java.lang.Object

 java.lang.Object

↳androidx.media3.exoplayer.dash.DashUtil

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-exoplayer-dash', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-exoplayer-dash
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-exoplayer-dash:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

Utility methods for DASH streams.

Summary

Methods
public static DataSpecbuildDataSpec(Representation representation, RangedUri requestUri, int flags)

Builds a DataSpec for a given RangedUri belonging to Representation.

public static DataSpecbuildDataSpec(Representation representation, java.lang.String baseUrl, RangedUri requestUri, int flags)

Builds a DataSpec for a given RangedUri belonging to Representation.

public static ChunkIndexloadChunkIndex(DataSource dataSource, int trackType, Representation representation)

Loads initialization and index data for the representation and returns the ChunkIndex.

public static ChunkIndexloadChunkIndex(DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)

Loads initialization and index data for the representation and returns the ChunkIndex.

public static FormatloadFormatWithDrmInitData(DataSource dataSource, Period period)

Loads a Format for acquiring keys for a given period in a DASH manifest.

public static voidloadInitializationData(ChunkExtractor chunkExtractor, DataSource dataSource, Representation representation, boolean loadIndex)

Loads initialization data for the representation and optionally index data then returns a BundledChunkExtractor which contains the output.

public static DashManifestloadManifest(DataSource dataSource, Uri uri)

Loads a DASH manifest.

public static FormatloadSampleFormat(DataSource dataSource, int trackType, Representation representation)

Loads initialization data for the representation and returns the sample Format.

public static FormatloadSampleFormat(DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)

Loads initialization data for the representation and returns the sample Format.

public static java.lang.StringresolveCacheKey(Representation representation, RangedUri rangedUri)

Resolves the cache key to be used when requesting the given ranged URI for the given Representation.

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

Methods

public static DataSpec buildDataSpec(Representation representation, java.lang.String baseUrl, RangedUri requestUri, int flags)

Builds a DataSpec for a given RangedUri belonging to Representation.

Parameters:

representation: The Representation to which the request belongs.
baseUrl: The base url with which to resolve the request URI.
requestUri: The RangedUri of the data to request.
flags: Flags to be set on the returned DataSpec. See .

Returns:

The DataSpec.

public static DataSpec buildDataSpec(Representation representation, RangedUri requestUri, int flags)

Builds a DataSpec for a given RangedUri belonging to Representation.

Uses the first base URL of the representation to build the data spec.

Parameters:

representation: The Representation to which the request belongs.
requestUri: The RangedUri of the data to request.
flags: Flags to be set on the returned DataSpec. See .

Returns:

The DataSpec.

public static DashManifest loadManifest(DataSource dataSource, Uri uri)

Loads a DASH manifest.

Parameters:

dataSource: The HttpDataSource from which the manifest should be read.
uri: The of the manifest to be read.

Returns:

An instance of DashManifest.

public static Format loadFormatWithDrmInitData(DataSource dataSource, Period period)

Loads a Format for acquiring keys for a given period in a DASH manifest.

Parameters:

dataSource: The HttpDataSource from which data should be loaded.
period: The Period.

Returns:

The loaded Format, or null if none is defined.

public static Format loadSampleFormat(DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)

Loads initialization data for the representation and returns the sample Format.

Parameters:

dataSource: The source from which the data should be loaded.
trackType: The type of the representation. Typically one of the androidx.media3.common.C TRACK_TYPE_* constants.
representation: The representation which initialization chunk belongs to.
baseUrlIndex: The index of the base URL to be picked from the list of base URLs.

Returns:

the sample Format of the given representation.

public static Format loadSampleFormat(DataSource dataSource, int trackType, Representation representation)

Loads initialization data for the representation and returns the sample Format.

Uses the first base URL for loading the format.

Parameters:

dataSource: The source from which the data should be loaded.
trackType: The type of the representation. Typically one of the androidx.media3.common.C TRACK_TYPE_* constants.
representation: The representation which initialization chunk belongs to.

Returns:

the sample Format of the given representation.

public static ChunkIndex loadChunkIndex(DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)

Loads initialization and index data for the representation and returns the ChunkIndex.

Parameters:

dataSource: The source from which the data should be loaded.
trackType: The type of the representation. Typically one of the androidx.media3.common.C TRACK_TYPE_* constants.
representation: The representation which initialization chunk belongs to.
baseUrlIndex: The index of the base URL with which to resolve the request URI.

Returns:

The ChunkIndex of the given representation, or null if no initialization or index data exists.

public static ChunkIndex loadChunkIndex(DataSource dataSource, int trackType, Representation representation)

Loads initialization and index data for the representation and returns the ChunkIndex.

Uses the first base URL for loading the index.

Parameters:

dataSource: The source from which the data should be loaded.
trackType: The type of the representation. Typically one of the androidx.media3.common.C TRACK_TYPE_* constants.
representation: The representation which initialization chunk belongs to.

Returns:

The ChunkIndex of the given representation, or null if no initialization or index data exists.

public static void loadInitializationData(ChunkExtractor chunkExtractor, DataSource dataSource, Representation representation, boolean loadIndex)

Loads initialization data for the representation and optionally index data then returns a BundledChunkExtractor which contains the output.

Uses the first base URL for loading the initialization data.

Parameters:

chunkExtractor: The ChunkExtractor to use.
dataSource: The source from which the data should be loaded.
representation: The representation which initialization chunk belongs to.
loadIndex: Whether to load index data too.

public static java.lang.String resolveCacheKey(Representation representation, RangedUri rangedUri)

Resolves the cache key to be used when requesting the given ranged URI for the given Representation.

Parameters:

representation: The Representation to which the URI belongs to.
rangedUri: The URI for which to resolve the cache key.

Returns:

The cache key.

Source

/*
 * Copyright (C) 2017 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.dash;

import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.HttpDataSource;
import androidx.media3.exoplayer.dash.manifest.DashManifest;
import androidx.media3.exoplayer.dash.manifest.DashManifestParser;
import androidx.media3.exoplayer.dash.manifest.Period;
import androidx.media3.exoplayer.dash.manifest.RangedUri;
import androidx.media3.exoplayer.dash.manifest.Representation;
import androidx.media3.exoplayer.source.chunk.BundledChunkExtractor;
import androidx.media3.exoplayer.source.chunk.ChunkExtractor;
import androidx.media3.exoplayer.source.chunk.InitializationChunk;
import androidx.media3.exoplayer.upstream.ParsingLoadable;
import androidx.media3.extractor.ChunkIndex;
import androidx.media3.extractor.Extractor;
import androidx.media3.extractor.mkv.MatroskaExtractor;
import androidx.media3.extractor.mp4.FragmentedMp4Extractor;
import java.io.IOException;
import java.util.List;

/** Utility methods for DASH streams. */
@UnstableApi
public final class DashUtil {

  /**
   * Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}.
   *
   * @param representation The {@link Representation} to which the request belongs.
   * @param baseUrl The base url with which to resolve the request URI.
   * @param requestUri The {@link RangedUri} of the data to request.
   * @param flags Flags to be set on the returned {@link DataSpec}. See {@link
   *     DataSpec.Builder#setFlags(int)}.
   * @return The {@link DataSpec}.
   */
  public static DataSpec buildDataSpec(
      Representation representation, String baseUrl, RangedUri requestUri, int flags) {
    return new DataSpec.Builder()
        .setUri(requestUri.resolveUri(baseUrl))
        .setPosition(requestUri.start)
        .setLength(requestUri.length)
        .setKey(resolveCacheKey(representation, requestUri))
        .setFlags(flags)
        .build();
  }

  /**
   * Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}.
   *
   * <p>Uses the first base URL of the representation to build the data spec.
   *
   * @param representation The {@link Representation} to which the request belongs.
   * @param requestUri The {@link RangedUri} of the data to request.
   * @param flags Flags to be set on the returned {@link DataSpec}. See {@link
   *     DataSpec.Builder#setFlags(int)}.
   * @return The {@link DataSpec}.
   */
  public static DataSpec buildDataSpec(
      Representation representation, RangedUri requestUri, int flags) {
    return buildDataSpec(representation, representation.baseUrls.get(0).url, requestUri, flags);
  }

  /**
   * Loads a DASH manifest.
   *
   * @param dataSource The {@link HttpDataSource} from which the manifest should be read.
   * @param uri The {@link Uri} of the manifest to be read.
   * @return An instance of {@link DashManifest}.
   * @throws IOException Thrown when there is an error while loading.
   */
  public static DashManifest loadManifest(DataSource dataSource, Uri uri) throws IOException {
    return ParsingLoadable.load(dataSource, new DashManifestParser(), uri, C.DATA_TYPE_MANIFEST);
  }

  /**
   * Loads a {@link Format} for acquiring keys for a given period in a DASH manifest.
   *
   * @param dataSource The {@link HttpDataSource} from which data should be loaded.
   * @param period The {@link Period}.
   * @return The loaded {@link Format}, or null if none is defined.
   * @throws IOException Thrown when there is an error while loading.
   */
  @Nullable
  public static Format loadFormatWithDrmInitData(DataSource dataSource, Period period)
      throws IOException {
    @C.TrackType int primaryTrackType = C.TRACK_TYPE_VIDEO;
    Representation representation = getFirstRepresentation(period, primaryTrackType);
    if (representation == null) {
      primaryTrackType = C.TRACK_TYPE_AUDIO;
      representation = getFirstRepresentation(period, primaryTrackType);
      if (representation == null) {
        return null;
      }
    }
    Format manifestFormat = representation.format;
    @Nullable
    Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
    return sampleFormat == null
        ? manifestFormat
        : sampleFormat.withManifestFormatInfo(manifestFormat);
  }

  /**
   * Loads initialization data for the {@code representation} and returns the sample {@link Format}.
   *
   * @param dataSource The source from which the data should be loaded.
   * @param trackType The type of the representation. Typically one of the {@link C
   *     androidx.media3.common.C} {@code TRACK_TYPE_*} constants.
   * @param representation The representation which initialization chunk belongs to.
   * @param baseUrlIndex The index of the base URL to be picked from the {@link
   *     Representation#baseUrls list of base URLs}.
   * @return the sample {@link Format} of the given representation.
   * @throws IOException Thrown when there is an error while loading.
   */
  @Nullable
  public static Format loadSampleFormat(
      DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)
      throws IOException {
    if (representation.getInitializationUri() == null) {
      return null;
    }
    ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
    try {
      loadInitializationData(
          chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ false);
    } finally {
      chunkExtractor.release();
    }
    return Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0];
  }

  /**
   * Loads initialization data for the {@code representation} and returns the sample {@link Format}.
   *
   * <p>Uses the first base URL for loading the format.
   *
   * @param dataSource The source from which the data should be loaded.
   * @param trackType The type of the representation. Typically one of the {@link C
   *     androidx.media3.common.C} {@code TRACK_TYPE_*} constants.
   * @param representation The representation which initialization chunk belongs to.
   * @return the sample {@link Format} of the given representation.
   * @throws IOException Thrown when there is an error while loading.
   */
  @Nullable
  public static Format loadSampleFormat(
      DataSource dataSource, int trackType, Representation representation) throws IOException {
    return loadSampleFormat(dataSource, trackType, representation, /* baseUrlIndex= */ 0);
  }

  /**
   * Loads initialization and index data for the {@code representation} and returns the {@link
   * ChunkIndex}.
   *
   * @param dataSource The source from which the data should be loaded.
   * @param trackType The type of the representation. Typically one of the {@link C
   *     androidx.media3.common.C} {@code TRACK_TYPE_*} constants.
   * @param representation The representation which initialization chunk belongs to.
   * @param baseUrlIndex The index of the base URL with which to resolve the request URI.
   * @return The {@link ChunkIndex} of the given representation, or null if no initialization or
   *     index data exists.
   * @throws IOException Thrown when there is an error while loading.
   */
  @Nullable
  public static ChunkIndex loadChunkIndex(
      DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)
      throws IOException {
    if (representation.getInitializationUri() == null) {
      return null;
    }
    ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
    try {
      loadInitializationData(
          chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ true);
    } finally {
      chunkExtractor.release();
    }
    return chunkExtractor.getChunkIndex();
  }

  /**
   * Loads initialization and index data for the {@code representation} and returns the {@link
   * ChunkIndex}.
   *
   * <p>Uses the first base URL for loading the index.
   *
   * @param dataSource The source from which the data should be loaded.
   * @param trackType The type of the representation. Typically one of the {@link C
   *     androidx.media3.common.C} {@code TRACK_TYPE_*} constants.
   * @param representation The representation which initialization chunk belongs to.
   * @return The {@link ChunkIndex} of the given representation, or null if no initialization or
   *     index data exists.
   * @throws IOException Thrown when there is an error while loading.
   */
  @Nullable
  public static ChunkIndex loadChunkIndex(
      DataSource dataSource, int trackType, Representation representation) throws IOException {
    return loadChunkIndex(dataSource, trackType, representation, /* baseUrlIndex= */ 0);
  }

  /**
   * Loads initialization data for the {@code representation} and optionally index data then returns
   * a {@link BundledChunkExtractor} which contains the output.
   *
   * @param chunkExtractor The {@link ChunkExtractor} to use.
   * @param dataSource The source from which the data should be loaded.
   * @param representation The representation which initialization chunk belongs to.
   * @param baseUrlIndex The index of the base URL with which to resolve the request URI.
   * @param loadIndex Whether to load index data too.
   * @throws IOException Thrown when there is an error while loading.
   */
  private static void loadInitializationData(
      ChunkExtractor chunkExtractor,
      DataSource dataSource,
      Representation representation,
      int baseUrlIndex,
      boolean loadIndex)
      throws IOException {
    RangedUri initializationUri = Assertions.checkNotNull(representation.getInitializationUri());
    @Nullable RangedUri requestUri;
    if (loadIndex) {
      @Nullable RangedUri indexUri = representation.getIndexUri();
      if (indexUri == null) {
        return;
      }
      // It's common for initialization and index data to be stored adjacently. Attempt to merge
      // the two requests together to request both at once.
      requestUri =
          initializationUri.attemptMerge(indexUri, representation.baseUrls.get(baseUrlIndex).url);
      if (requestUri == null) {
        loadInitializationData(
            dataSource, representation, baseUrlIndex, chunkExtractor, initializationUri);
        requestUri = indexUri;
      }
    } else {
      requestUri = initializationUri;
    }
    loadInitializationData(dataSource, representation, baseUrlIndex, chunkExtractor, requestUri);
  }

  /**
   * Loads initialization data for the {@code representation} and optionally index data then returns
   * a {@link BundledChunkExtractor} which contains the output.
   *
   * <p>Uses the first base URL for loading the initialization data.
   *
   * @param chunkExtractor The {@link ChunkExtractor} to use.
   * @param dataSource The source from which the data should be loaded.
   * @param representation The representation which initialization chunk belongs to.
   * @param loadIndex Whether to load index data too.
   * @throws IOException Thrown when there is an error while loading.
   */
  public static void loadInitializationData(
      ChunkExtractor chunkExtractor,
      DataSource dataSource,
      Representation representation,
      boolean loadIndex)
      throws IOException {
    loadInitializationData(
        chunkExtractor, dataSource, representation, /* baseUrlIndex= */ 0, loadIndex);
  }

  private static void loadInitializationData(
      DataSource dataSource,
      Representation representation,
      int baseUrlIndex,
      ChunkExtractor chunkExtractor,
      RangedUri requestUri)
      throws IOException {
    DataSpec dataSpec =
        DashUtil.buildDataSpec(
            representation,
            representation.baseUrls.get(baseUrlIndex).url,
            requestUri,
            /* flags= */ 0);
    InitializationChunk initializationChunk =
        new InitializationChunk(
            dataSource,
            dataSpec,
            representation.format,
            C.SELECTION_REASON_UNKNOWN,
            null /* trackSelectionData */,
            chunkExtractor);
    initializationChunk.load();
  }

  /**
   * Resolves the cache key to be used when requesting the given ranged URI for the given {@link
   * Representation}.
   *
   * @param representation The {@link Representation} to which the URI belongs to.
   * @param rangedUri The URI for which to resolve the cache key.
   * @return The cache key.
   */
  public static String resolveCacheKey(Representation representation, RangedUri rangedUri) {
    @Nullable String cacheKey = representation.getCacheKey();
    return cacheKey != null
        ? cacheKey
        : rangedUri.resolveUri(representation.baseUrls.get(0).url).toString();
  }

  private static ChunkExtractor newChunkExtractor(int trackType, Format format) {
    String mimeType = format.containerMimeType;
    boolean isWebm =
        mimeType != null
            && (mimeType.startsWith(MimeTypes.VIDEO_WEBM)
                || mimeType.startsWith(MimeTypes.AUDIO_WEBM));
    Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
    return new BundledChunkExtractor(extractor, trackType, format);
  }

  @Nullable
  private static Representation getFirstRepresentation(Period period, @C.TrackType int type) {
    int index = period.getAdaptationSetIndex(type);
    if (index == C.INDEX_UNSET) {
      return null;
    }
    List<Representation> representations = period.adaptationSets.get(index).representations;
    return representations.isEmpty() ? null : representations.get(0);
  }

  private DashUtil() {}
}