summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java236
1 files changed, 236 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java
new file mode 100644
index 0000000000..4fe7b137b6
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/source/MaskingMediaPeriod.java
@@ -0,0 +1,236 @@
+/*
+ * 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 org.mozilla.thirdparty.com.google.android.exoplayer2.source;
+
+import static org.mozilla.thirdparty.com.google.android.exoplayer2.util.Util.castNonNull;
+
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.SeekParameters;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.trackselection.TrackSelection;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.Allocator;
+import java.io.IOException;
+import org.checkerframework.checker.nullness.compatqual.NullableType;
+
+/**
+ * Media period that wraps a media source and defers calling its {@link
+ * MediaSource#createPeriod(MediaPeriodId, Allocator, long)} method until {@link
+ * #createPeriod(MediaPeriodId)} has been called. This is useful if you need to return a media
+ * period immediately but the media source that should create it is not yet prepared.
+ */
+public final class MaskingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
+
+ /** Listener for preparation errors. */
+ public interface PrepareErrorListener {
+
+ /**
+ * Called the first time an error occurs while refreshing source info or preparing the period.
+ */
+ void onPrepareError(MediaPeriodId mediaPeriodId, IOException exception);
+ }
+
+ /** The {@link MediaSource} which will create the actual media period. */
+ public final MediaSource mediaSource;
+ /** The {@link MediaPeriodId} used to create the masking media period. */
+ public final MediaPeriodId id;
+
+ private final Allocator allocator;
+
+ @Nullable private MediaPeriod mediaPeriod;
+ @Nullable private Callback callback;
+ private long preparePositionUs;
+ @Nullable private PrepareErrorListener listener;
+ private boolean notifiedPrepareError;
+ private long preparePositionOverrideUs;
+
+ /**
+ * Creates a new masking media period.
+ *
+ * @param mediaSource The media source to wrap.
+ * @param id The identifier used to create the masking media period.
+ * @param allocator The allocator used to create the media period.
+ * @param preparePositionUs The expected start position, in microseconds.
+ */
+ public MaskingMediaPeriod(
+ MediaSource mediaSource, MediaPeriodId id, Allocator allocator, long preparePositionUs) {
+ this.id = id;
+ this.allocator = allocator;
+ this.mediaSource = mediaSource;
+ this.preparePositionUs = preparePositionUs;
+ preparePositionOverrideUs = C.TIME_UNSET;
+ }
+
+ /**
+ * Sets a listener for preparation errors.
+ *
+ * @param listener An listener to be notified of media period preparation errors. If a listener is
+ * set, {@link #maybeThrowPrepareError()} will not throw but will instead pass the first
+ * preparation error (if any) to the listener.
+ */
+ public void setPrepareErrorListener(PrepareErrorListener listener) {
+ this.listener = listener;
+ }
+
+ /** Returns the position at which the masking media period was prepared, in microseconds. */
+ public long getPreparePositionUs() {
+ return preparePositionUs;
+ }
+
+ /**
+ * Overrides the default prepare position at which to prepare the media period. This value is only
+ * used if called before {@link #createPeriod(MediaPeriodId)}.
+ *
+ * @param preparePositionUs The default prepare position to use, in microseconds.
+ */
+ public void overridePreparePositionUs(long preparePositionUs) {
+ preparePositionOverrideUs = preparePositionUs;
+ }
+
+ /**
+ * Calls {@link MediaSource#createPeriod(MediaPeriodId, Allocator, long)} on the wrapped source
+ * then prepares it if {@link #prepare(Callback, long)} has been called. Call {@link
+ * #releasePeriod()} to release the period.
+ *
+ * @param id The identifier that should be used to create the media period from the media source.
+ */
+ public void createPeriod(MediaPeriodId id) {
+ long preparePositionUs = getPreparePositionWithOverride(this.preparePositionUs);
+ mediaPeriod = mediaSource.createPeriod(id, allocator, preparePositionUs);
+ if (callback != null) {
+ mediaPeriod.prepare(this, preparePositionUs);
+ }
+ }
+
+ /**
+ * Releases the period.
+ */
+ public void releasePeriod() {
+ if (mediaPeriod != null) {
+ mediaSource.releasePeriod(mediaPeriod);
+ }
+ }
+
+ @Override
+ public void prepare(Callback callback, long preparePositionUs) {
+ this.callback = callback;
+ if (mediaPeriod != null) {
+ mediaPeriod.prepare(this, getPreparePositionWithOverride(this.preparePositionUs));
+ }
+ }
+
+ @Override
+ public void maybeThrowPrepareError() throws IOException {
+ try {
+ if (mediaPeriod != null) {
+ mediaPeriod.maybeThrowPrepareError();
+ } else {
+ mediaSource.maybeThrowSourceInfoRefreshError();
+ }
+ } catch (final IOException e) {
+ if (listener == null) {
+ throw e;
+ }
+ if (!notifiedPrepareError) {
+ notifiedPrepareError = true;
+ listener.onPrepareError(id, e);
+ }
+ }
+ }
+
+ @Override
+ public TrackGroupArray getTrackGroups() {
+ return castNonNull(mediaPeriod).getTrackGroups();
+ }
+
+ @Override
+ public long selectTracks(
+ @NullableType TrackSelection[] selections,
+ boolean[] mayRetainStreamFlags,
+ @NullableType SampleStream[] streams,
+ boolean[] streamResetFlags,
+ long positionUs) {
+ if (preparePositionOverrideUs != C.TIME_UNSET && positionUs == preparePositionUs) {
+ positionUs = preparePositionOverrideUs;
+ preparePositionOverrideUs = C.TIME_UNSET;
+ }
+ return castNonNull(mediaPeriod)
+ .selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs);
+ }
+
+ @Override
+ public void discardBuffer(long positionUs, boolean toKeyframe) {
+ castNonNull(mediaPeriod).discardBuffer(positionUs, toKeyframe);
+ }
+
+ @Override
+ public long readDiscontinuity() {
+ return castNonNull(mediaPeriod).readDiscontinuity();
+ }
+
+ @Override
+ public long getBufferedPositionUs() {
+ return castNonNull(mediaPeriod).getBufferedPositionUs();
+ }
+
+ @Override
+ public long seekToUs(long positionUs) {
+ return castNonNull(mediaPeriod).seekToUs(positionUs);
+ }
+
+ @Override
+ public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
+ return castNonNull(mediaPeriod).getAdjustedSeekPositionUs(positionUs, seekParameters);
+ }
+
+ @Override
+ public long getNextLoadPositionUs() {
+ return castNonNull(mediaPeriod).getNextLoadPositionUs();
+ }
+
+ @Override
+ public void reevaluateBuffer(long positionUs) {
+ castNonNull(mediaPeriod).reevaluateBuffer(positionUs);
+ }
+
+ @Override
+ public boolean continueLoading(long positionUs) {
+ return mediaPeriod != null && mediaPeriod.continueLoading(positionUs);
+ }
+
+ @Override
+ public boolean isLoading() {
+ return mediaPeriod != null && mediaPeriod.isLoading();
+ }
+
+ @Override
+ public void onContinueLoadingRequested(MediaPeriod source) {
+ castNonNull(callback).onContinueLoadingRequested(this);
+ }
+
+ // MediaPeriod.Callback implementation
+
+ @Override
+ public void onPrepared(MediaPeriod mediaPeriod) {
+ castNonNull(callback).onPrepared(this);
+ }
+
+ private long getPreparePositionWithOverride(long preparePositionUs) {
+ return preparePositionOverrideUs != C.TIME_UNSET
+ ? preparePositionOverrideUs
+ : preparePositionUs;
+ }
+}