summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java327
1 files changed, 327 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java
new file mode 100644
index 0000000000..bed34a354b
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/ProgressiveMediaSource.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2016 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 org.mozilla.thirdparty.com.google.android.exoplayer2.source;
+
+import android.net.Uri;
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.DrmSession;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.DrmSessionManager;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.Extractor;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ExtractorsFactory;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.Allocator;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DataSource;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.TransferListener;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import java.io.IOException;
+
+/**
+ * Provides one period that loads data from a {@link Uri} and extracted using an {@link Extractor}.
+ *
+ * <p>If the possible input stream container formats are known, pass a factory that instantiates
+ * extractors for them to the constructor. Otherwise, pass a {@link DefaultExtractorsFactory} to use
+ * the default extractors. When reading a new stream, the first {@link Extractor} in the array of
+ * extractors created by the factory that returns {@code true} from {@link Extractor#sniff} will be
+ * used to extract samples from the input stream.
+ *
+ * <p>Note that the built-in extractor for FLV streams does not support seeking.
+ */
+public final class ProgressiveMediaSource extends BaseMediaSource
+ implements ProgressiveMediaPeriod.Listener {
+
+ /** Factory for {@link ProgressiveMediaSource}s. */
+ public static final class Factory implements MediaSourceFactory {
+
+ private final DataSource.Factory dataSourceFactory;
+
+ private ExtractorsFactory extractorsFactory;
+ @Nullable private String customCacheKey;
+ @Nullable private Object tag;
+ private DrmSessionManager<?> drmSessionManager;
+ private LoadErrorHandlingPolicy loadErrorHandlingPolicy;
+ private int continueLoadingCheckIntervalBytes;
+ private boolean isCreateCalled;
+
+ /**
+ * Creates a new factory for {@link ProgressiveMediaSource}s, using the extractors provided by
+ * {@link DefaultExtractorsFactory}.
+ *
+ * @param dataSourceFactory A factory for {@link DataSource}s to read the media.
+ */
+ public Factory(DataSource.Factory dataSourceFactory) {
+ this(dataSourceFactory, new DefaultExtractorsFactory());
+ }
+
+ /**
+ * Creates a new factory for {@link ProgressiveMediaSource}s.
+ *
+ * @param dataSourceFactory A factory for {@link DataSource}s to read the media.
+ * @param extractorsFactory A factory for extractors used to extract media from its container.
+ */
+ public Factory(DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
+ this.dataSourceFactory = dataSourceFactory;
+ this.extractorsFactory = extractorsFactory;
+ drmSessionManager = DrmSessionManager.getDummyDrmSessionManager();
+ loadErrorHandlingPolicy = new DefaultLoadErrorHandlingPolicy();
+ continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES;
+ }
+
+ /**
+ * Sets the factory for {@link Extractor}s to process the media stream. The default value is an
+ * instance of {@link DefaultExtractorsFactory}.
+ *
+ * @param extractorsFactory A factory for {@link Extractor}s to process the media stream. If the
+ * possible formats are known, pass a factory that instantiates extractors for those
+ * formats.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If {@link #createMediaSource(Uri)} has already been called.
+ * @deprecated Pass the {@link ExtractorsFactory} via {@link #Factory(DataSource.Factory,
+ * ExtractorsFactory)}. This is necessary so that proguard can treat the default extractors
+ * factory as unused.
+ */
+ @Deprecated
+ public Factory setExtractorsFactory(ExtractorsFactory extractorsFactory) {
+ Assertions.checkState(!isCreateCalled);
+ this.extractorsFactory = extractorsFactory;
+ return this;
+ }
+
+ /**
+ * Sets the custom key that uniquely identifies the original stream. Used for cache indexing.
+ * The default value is {@code null}.
+ *
+ * @param customCacheKey A custom key that uniquely identifies the original stream. Used for
+ * cache indexing.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If {@link #createMediaSource(Uri)} has already been called.
+ */
+ public Factory setCustomCacheKey(@Nullable String customCacheKey) {
+ Assertions.checkState(!isCreateCalled);
+ this.customCacheKey = customCacheKey;
+ return this;
+ }
+
+ /**
+ * Sets a tag for the media source which will be published in the {@link
+ * com.google.android.exoplayer2.Timeline} of the source as {@link
+ * com.google.android.exoplayer2.Timeline.Window#tag}.
+ *
+ * @param tag A tag for the media source.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If {@link #createMediaSource(Uri)} has already been called.
+ */
+ public Factory setTag(Object tag) {
+ Assertions.checkState(!isCreateCalled);
+ this.tag = tag;
+ return this;
+ }
+
+ /**
+ * Sets the {@link LoadErrorHandlingPolicy}. The default value is created by calling {@link
+ * DefaultLoadErrorHandlingPolicy#DefaultLoadErrorHandlingPolicy()}.
+ *
+ * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If {@link #createMediaSource(Uri)} has already been called.
+ */
+ public Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
+ Assertions.checkState(!isCreateCalled);
+ this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
+ return this;
+ }
+
+ /**
+ * Sets the number of bytes that should be loaded between each invocation of {@link
+ * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. The default value is
+ * {@link #DEFAULT_LOADING_CHECK_INTERVAL_BYTES}.
+ *
+ * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between
+ * each invocation of {@link
+ * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If {@link #createMediaSource(Uri)} has already been called.
+ */
+ public Factory setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) {
+ Assertions.checkState(!isCreateCalled);
+ this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
+ return this;
+ }
+
+ /**
+ * Sets the {@link DrmSessionManager} to use for acquiring {@link DrmSession DrmSessions}. The
+ * default value is {@link DrmSessionManager#DUMMY}.
+ *
+ * @param drmSessionManager The {@link DrmSessionManager}.
+ * @return This factory, for convenience.
+ * @throws IllegalStateException If one of the {@code create} methods has already been called.
+ */
+ @Override
+ public Factory setDrmSessionManager(DrmSessionManager<?> drmSessionManager) {
+ Assertions.checkState(!isCreateCalled);
+ this.drmSessionManager = drmSessionManager;
+ return this;
+ }
+
+ /**
+ * Returns a new {@link ProgressiveMediaSource} using the current parameters.
+ *
+ * @param uri The {@link Uri}.
+ * @return The new {@link ProgressiveMediaSource}.
+ */
+ @Override
+ public ProgressiveMediaSource createMediaSource(Uri uri) {
+ isCreateCalled = true;
+ return new ProgressiveMediaSource(
+ uri,
+ dataSourceFactory,
+ extractorsFactory,
+ drmSessionManager,
+ loadErrorHandlingPolicy,
+ customCacheKey,
+ continueLoadingCheckIntervalBytes,
+ tag);
+ }
+
+ @Override
+ public int[] getSupportedTypes() {
+ return new int[] {C.TYPE_OTHER};
+ }
+ }
+
+ /**
+ * The default number of bytes that should be loaded between each each invocation of {@link
+ * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
+ */
+ public static final int DEFAULT_LOADING_CHECK_INTERVAL_BYTES = 1024 * 1024;
+
+ private final Uri uri;
+ private final DataSource.Factory dataSourceFactory;
+ private final ExtractorsFactory extractorsFactory;
+ private final DrmSessionManager<?> drmSessionManager;
+ private final LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy;
+ @Nullable private final String customCacheKey;
+ private final int continueLoadingCheckIntervalBytes;
+ @Nullable private final Object tag;
+
+ private long timelineDurationUs;
+ private boolean timelineIsSeekable;
+ private boolean timelineIsLive;
+ @Nullable private TransferListener transferListener;
+
+ // TODO: Make private when ExtractorMediaSource is deleted.
+ /* package */ ProgressiveMediaSource(
+ Uri uri,
+ DataSource.Factory dataSourceFactory,
+ ExtractorsFactory extractorsFactory,
+ DrmSessionManager<?> drmSessionManager,
+ LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy,
+ @Nullable String customCacheKey,
+ int continueLoadingCheckIntervalBytes,
+ @Nullable Object tag) {
+ this.uri = uri;
+ this.dataSourceFactory = dataSourceFactory;
+ this.extractorsFactory = extractorsFactory;
+ this.drmSessionManager = drmSessionManager;
+ this.loadableLoadErrorHandlingPolicy = loadableLoadErrorHandlingPolicy;
+ this.customCacheKey = customCacheKey;
+ this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
+ this.timelineDurationUs = C.TIME_UNSET;
+ this.tag = tag;
+ }
+
+ @Override
+ @Nullable
+ public Object getTag() {
+ return tag;
+ }
+
+ @Override
+ protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
+ transferListener = mediaTransferListener;
+ drmSessionManager.prepare();
+ notifySourceInfoRefreshed(timelineDurationUs, timelineIsSeekable, timelineIsLive);
+ }
+
+ @Override
+ public void maybeThrowSourceInfoRefreshError() throws IOException {
+ // Do nothing.
+ }
+
+ @Override
+ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
+ DataSource dataSource = dataSourceFactory.createDataSource();
+ if (transferListener != null) {
+ dataSource.addTransferListener(transferListener);
+ }
+ return new ProgressiveMediaPeriod(
+ uri,
+ dataSource,
+ extractorsFactory.createExtractors(),
+ drmSessionManager,
+ loadableLoadErrorHandlingPolicy,
+ createEventDispatcher(id),
+ this,
+ allocator,
+ customCacheKey,
+ continueLoadingCheckIntervalBytes);
+ }
+
+ @Override
+ public void releasePeriod(MediaPeriod mediaPeriod) {
+ ((ProgressiveMediaPeriod) mediaPeriod).release();
+ }
+
+ @Override
+ protected void releaseSourceInternal() {
+ drmSessionManager.release();
+ }
+
+ // ProgressiveMediaPeriod.Listener implementation.
+
+ @Override
+ public void onSourceInfoRefreshed(long durationUs, boolean isSeekable, boolean isLive) {
+ // If we already have the duration from a previous source info refresh, use it.
+ durationUs = durationUs == C.TIME_UNSET ? timelineDurationUs : durationUs;
+ if (timelineDurationUs == durationUs
+ && timelineIsSeekable == isSeekable
+ && timelineIsLive == isLive) {
+ // Suppress no-op source info changes.
+ return;
+ }
+ notifySourceInfoRefreshed(durationUs, isSeekable, isLive);
+ }
+
+ // Internal methods.
+
+ private void notifySourceInfoRefreshed(long durationUs, boolean isSeekable, boolean isLive) {
+ timelineDurationUs = durationUs;
+ timelineIsSeekable = isSeekable;
+ timelineIsLive = isLive;
+ // TODO: Split up isDynamic into multiple fields to indicate which values may change. Then
+ // indicate that the duration may change until it's known. See [internal: b/69703223].
+ refreshSourceInfo(
+ new SinglePeriodTimeline(
+ timelineDurationUs,
+ timelineIsSeekable,
+ /* isDynamic= */ false,
+ /* isLive= */ timelineIsLive,
+ /* manifest= */ null,
+ tag));
+ }
+}