public final class

ExternallyLoadedMediaSource

extends BaseMediaSource

 java.lang.Object

androidx.media3.exoplayer.source.BaseMediaSource

↳androidx.media3.exoplayer.source.ExternallyLoadedMediaSource

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

A MediaSource for media loaded outside of the usual ExoPlayer loading mechanism.

Puts the (encoded with ) in a single sample belonging to a single MediaPeriod.

Typically used for image content that is managed by an external image management framework (for example, Glide).

Summary

Methods
public booleancanUpdateMediaItem(MediaItem mediaItem)

public MediaPeriodcreatePeriod(MediaSource.MediaPeriodId id, Allocator allocator, long startPositionUs)

public synchronized MediaItemgetMediaItem()

public voidmaybeThrowSourceInfoRefreshError()

protected abstract voidprepareSourceInternal(TransferListener mediaTransferListener)

Starts source preparation and enables the source, see MediaSource.prepareSource(MediaSource.MediaSourceCaller, TransferListener, PlayerId).

public voidreleasePeriod(MediaPeriod mediaPeriod)

protected abstract voidreleaseSourceInternal()

Releases the source, see MediaSource.releaseSource(MediaSource.MediaSourceCaller).

public synchronized voidupdateMediaItem(MediaItem mediaItem)

from BaseMediaSourceaddDrmEventListener, addEventListener, createDrmEventDispatcher, createDrmEventDispatcher, createEventDispatcher, createEventDispatcher, createEventDispatcher, createEventDispatcher, disable, disableInternal, enable, enableInternal, getPlayerId, isEnabled, prepareSource, prepareSource, prepareSourceCalled, refreshSourceInfo, releaseSource, removeDrmEventListener, removeEventListener, setPlayerId
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

protected abstract void prepareSourceInternal(TransferListener mediaTransferListener)

Starts source preparation and enables the source, see MediaSource.prepareSource(MediaSource.MediaSourceCaller, TransferListener, PlayerId). This method is called at most once until the next call to BaseMediaSource.releaseSourceInternal().

Parameters:

mediaTransferListener: The transfer listener which should be informed of any media data transfers. May be null if no listener is available. Note that this listener should usually be only informed of transfers related to the media loads and not of auxiliary loads for manifests and other data.

protected abstract void releaseSourceInternal()

Releases the source, see MediaSource.releaseSource(MediaSource.MediaSourceCaller). This method is called exactly once after each call to BaseMediaSource.prepareSourceInternal(TransferListener).

public synchronized MediaItem getMediaItem()

public boolean canUpdateMediaItem(MediaItem mediaItem)

public synchronized void updateMediaItem(MediaItem mediaItem)

public void maybeThrowSourceInfoRefreshError()

public MediaPeriod createPeriod(MediaSource.MediaPeriodId id, Allocator allocator, long startPositionUs)

public void releasePeriod(MediaPeriod mediaPeriod)

Source

/*
 * Copyright 2023 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.source;

import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Util.msToUs;

import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.Timeline;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.TransferListener;
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import com.google.common.base.Charsets;
import java.util.Objects;

/**
 * A {@link MediaSource} for media loaded outside of the usual ExoPlayer loading mechanism.
 *
 * <p>Puts the {@link MediaItem.LocalConfiguration#uri} (encoded with {@link Charsets#UTF_8}) in a
 * single sample belonging to a single {@link MediaPeriod}.
 *
 * <p>Typically used for image content that is managed by an external image management framework
 * (for example, Glide).
 */
@UnstableApi
public final class ExternallyLoadedMediaSource extends BaseMediaSource {

  private final ExternalLoader externalLoader;

  /** Factory for {@link ExternallyLoadedMediaSource}. */
  public static final class Factory implements MediaSource.Factory {
    private final long timelineDurationUs;
    private final ExternalLoader externalLoader;

    /**
     * Creates an instance.
     *
     * @param timelineDurationUs The duration of the {@link SinglePeriodTimeline} created, in
     *     microseconds.
     * @param externalLoader The {@link ExternalLoader} to load the media in preparation for
     *     playback.
     */
    public Factory(long timelineDurationUs, ExternalLoader externalLoader) {
      this.timelineDurationUs = timelineDurationUs;
      this.externalLoader = externalLoader;
    }

    /** Does nothing. {@link ExternallyLoadedMediaSource} does not support DRM. */
    @Override
    public MediaSource.Factory setDrmSessionManagerProvider(
        DrmSessionManagerProvider drmSessionManagerProvider) {
      return this;
    }

    /**
     * Does nothing. {@link ExternallyLoadedMediaSource} does not support error handling policies.
     */
    @Override
    public MediaSource.Factory setLoadErrorHandlingPolicy(
        LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
      return this;
    }

    @Override
    public @C.ContentType int[] getSupportedTypes() {
      return new int[] {C.CONTENT_TYPE_OTHER};
    }

    @Override
    public ExternallyLoadedMediaSource createMediaSource(MediaItem mediaItem) {
      return new ExternallyLoadedMediaSource(mediaItem, timelineDurationUs, externalLoader);
    }
  }

  private final long timelineDurationUs;

  @GuardedBy("this")
  private MediaItem mediaItem;

  private ExternallyLoadedMediaSource(
      MediaItem mediaItem, long timelineDurationUs, ExternalLoader externalLoader) {
    this.mediaItem = mediaItem;
    this.timelineDurationUs = timelineDurationUs;
    this.externalLoader = externalLoader;
  }

  @Override
  protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
    Timeline timeline =
        new SinglePeriodTimeline(
            timelineDurationUs,
            /* isSeekable= */ true,
            /* isDynamic= */ false,
            /* useLiveConfiguration= */ false,
            /* manifest= */ null,
            getMediaItem());
    refreshSourceInfo(timeline);
  }

  @Override
  protected void releaseSourceInternal() {
    // Do nothing.
  }

  @Override
  public synchronized MediaItem getMediaItem() {
    return mediaItem;
  }

  @Override
  public boolean canUpdateMediaItem(MediaItem mediaItem) {
    @Nullable MediaItem.LocalConfiguration newConfiguration = mediaItem.localConfiguration;
    MediaItem.LocalConfiguration oldConfiguration = checkNotNull(getMediaItem().localConfiguration);
    return newConfiguration != null
        && newConfiguration.uri.equals(oldConfiguration.uri)
        && Objects.equals(newConfiguration.mimeType, oldConfiguration.mimeType)
        && (newConfiguration.imageDurationMs == C.TIME_UNSET
            || msToUs(newConfiguration.imageDurationMs) == timelineDurationUs);
  }

  @Override
  public synchronized void updateMediaItem(MediaItem mediaItem) {
    this.mediaItem = mediaItem;
  }

  @Override
  public void maybeThrowSourceInfoRefreshError() {
    // Do nothing.
  }

  @Override
  public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
    MediaItem mediaItem = getMediaItem();
    checkNotNull(mediaItem.localConfiguration);
    checkNotNull(
        mediaItem.localConfiguration.mimeType, "Externally loaded mediaItems require a MIME type.");
    return new ExternallyLoadedMediaPeriod(
        mediaItem.localConfiguration.uri, mediaItem.localConfiguration.mimeType, externalLoader);
  }

  @Override
  public void releasePeriod(MediaPeriod mediaPeriod) {
    ((ExternallyLoadedMediaPeriod) mediaPeriod).releasePeriod();
  }
}