diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index c2fa35275c..c0548791fc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -336,7 +336,7 @@ public final class ExtractorMediaSource extends CompositeMediaSource { .setTag(tag) .build(), dataSourceFactory, - extractorsFactory, + () -> new BundledExtractorsAdapter(extractorsFactory), DrmSessionManager.DRM_UNSUPPORTED, loadableLoadErrorHandlingPolicy, continueLoadingCheckIntervalBytes); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java index 9efe6acba1..ed4f6ac604 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaExtractor.java @@ -26,7 +26,14 @@ import java.util.List; import java.util.Map; /** Extracts the contents of a container file from a progressive media stream. */ -/* package */ interface ProgressiveMediaExtractor { +public interface ProgressiveMediaExtractor { + + /** Creates {@link ProgressiveMediaExtractor} instances. */ + interface Factory { + + /** Returns a new {@link ProgressiveMediaExtractor} instance. */ + ProgressiveMediaExtractor createProgressiveMediaExtractor(); + } /** * Initializes the underlying infrastructure for reading from the input. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index 57b4d2be2b..66af0e5eee 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -31,7 +31,6 @@ import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorOutput; -import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints; @@ -147,7 +146,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * @param uri The {@link Uri} of the media stream. * @param dataSource The data source to read the media. - * @param extractorsFactory The {@link ExtractorsFactory} to use to read the data source. + * @param progressiveMediaExtractor The {@link ProgressiveMediaExtractor} to use to read the data + * source. * @param drmSessionManager A {@link DrmSessionManager} to allow DRM interactions. * @param drmEventDispatcher A dispatcher to notify of {@link DrmSessionEventListener} events. * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}. @@ -168,7 +168,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public ProgressiveMediaPeriod( Uri uri, DataSource dataSource, - ExtractorsFactory extractorsFactory, + ProgressiveMediaExtractor progressiveMediaExtractor, DrmSessionManager drmSessionManager, DrmSessionEventListener.EventDispatcher drmEventDispatcher, LoadErrorHandlingPolicy loadErrorHandlingPolicy, @@ -188,7 +188,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.customCacheKey = customCacheKey; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; loader = new Loader("ProgressiveMediaPeriod"); - this.progressiveMediaExtractor = new BundledExtractorsAdapter(extractorsFactory); + this.progressiveMediaExtractor = progressiveMediaExtractor; loadCondition = new ConditionVariable(); maybeFinishPrepareRunnable = this::maybeFinishPrepare; onContinueLoadingRequestedRunnable = diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java index fe249df6ff..e7d97dbf8b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaSource.java @@ -54,7 +54,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource private final DataSource.Factory dataSourceFactory; - private ExtractorsFactory extractorsFactory; + private ProgressiveMediaExtractor.Factory progressiveMediaExtractorFactory; private boolean usingCustomDrmSessionManagerProvider; private DrmSessionManagerProvider drmSessionManagerProvider; private LoadErrorHandlingPolicy loadErrorHandlingPolicy; @@ -72,15 +72,26 @@ public final class ProgressiveMediaSource extends BaseMediaSource this(dataSourceFactory, new DefaultExtractorsFactory()); } + /** + * Equivalent to {@link #Factory(DataSource.Factory, ProgressiveMediaExtractor.Factory) new + * Factory(dataSourceFactory, () -> new BundledExtractorsAdapter(extractorsFactory)}. + */ + public Factory(DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) { + this(dataSourceFactory, () -> new BundledExtractorsAdapter(extractorsFactory)); + } + /** * 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. + * @param progressiveMediaExtractorFactory A factory for the {@link ProgressiveMediaExtractor} + * to extract media from its container. */ - public Factory(DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) { + public Factory( + DataSource.Factory dataSourceFactory, + ProgressiveMediaExtractor.Factory progressiveMediaExtractorFactory) { this.dataSourceFactory = dataSourceFactory; - this.extractorsFactory = extractorsFactory; + this.progressiveMediaExtractorFactory = progressiveMediaExtractorFactory; drmSessionManagerProvider = new DefaultDrmSessionManagerProvider(); loadErrorHandlingPolicy = new DefaultLoadErrorHandlingPolicy(); continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES; @@ -93,8 +104,10 @@ public final class ProgressiveMediaSource extends BaseMediaSource */ @Deprecated public Factory setExtractorsFactory(@Nullable ExtractorsFactory extractorsFactory) { - this.extractorsFactory = - extractorsFactory != null ? extractorsFactory : new DefaultExtractorsFactory(); + this.progressiveMediaExtractorFactory = + () -> + new BundledExtractorsAdapter( + extractorsFactory != null ? extractorsFactory : new DefaultExtractorsFactory()); return this; } @@ -220,7 +233,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource return new ProgressiveMediaSource( mediaItem, dataSourceFactory, - extractorsFactory, + progressiveMediaExtractorFactory, drmSessionManagerProvider.get(mediaItem), loadErrorHandlingPolicy, continueLoadingCheckIntervalBytes); @@ -241,7 +254,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource private final MediaItem mediaItem; private final MediaItem.PlaybackProperties playbackProperties; private final DataSource.Factory dataSourceFactory; - private final ExtractorsFactory extractorsFactory; + private final ProgressiveMediaExtractor.Factory progressiveMediaExtractorFactory; private final DrmSessionManager drmSessionManager; private final LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy; private final int continueLoadingCheckIntervalBytes; @@ -256,14 +269,14 @@ public final class ProgressiveMediaSource extends BaseMediaSource /* package */ ProgressiveMediaSource( MediaItem mediaItem, DataSource.Factory dataSourceFactory, - ExtractorsFactory extractorsFactory, + ProgressiveMediaExtractor.Factory progressiveMediaExtractorFactory, DrmSessionManager drmSessionManager, LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy, int continueLoadingCheckIntervalBytes) { this.playbackProperties = checkNotNull(mediaItem.playbackProperties); this.mediaItem = mediaItem; this.dataSourceFactory = dataSourceFactory; - this.extractorsFactory = extractorsFactory; + this.progressiveMediaExtractorFactory = progressiveMediaExtractorFactory; this.drmSessionManager = drmSessionManager; this.loadableLoadErrorHandlingPolicy = loadableLoadErrorHandlingPolicy; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; @@ -308,7 +321,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource return new ProgressiveMediaPeriod( playbackProperties.uri, dataSource, - extractorsFactory, + progressiveMediaExtractorFactory.createProgressiveMediaExtractor(), drmSessionManager, createDrmEventDispatcher(id), loadableLoadErrorHandlingPolicy, diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java index aaf00388f6..2ca6ee6343 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java @@ -24,22 +24,37 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; -import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.upstream.AssetDataSource; import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; /** Unit test for {@link ProgressiveMediaPeriod}. */ @RunWith(AndroidJUnit4.class) public final class ProgressiveMediaPeriodTest { @Test - public void prepare_updatesSourceInfoBeforeOnPreparedCallback() throws Exception { + public void prepareUsingBundledExtractors_updatesSourceInfoBeforeOnPreparedCallback() + throws TimeoutException { + testExtractorsUpdatesSourceInfoBeforeOnPreparedCallback( + new BundledExtractorsAdapter(Mp4Extractor.FACTORY)); + } + + @Test + @Config(sdk = 30) + public void prepareUsingMediaParser_updatesSourceInfoBeforeOnPreparedCallback() + throws TimeoutException { + testExtractorsUpdatesSourceInfoBeforeOnPreparedCallback(new MediaParserExtractorAdapter()); + } + + private static void testExtractorsUpdatesSourceInfoBeforeOnPreparedCallback( + ProgressiveMediaExtractor extractor) throws TimeoutException { AtomicBoolean sourceInfoRefreshCalled = new AtomicBoolean(false); ProgressiveMediaPeriod.Listener sourceInfoRefreshListener = (durationUs, isSeekable, isLive) -> sourceInfoRefreshCalled.set(true); @@ -48,7 +63,7 @@ public final class ProgressiveMediaPeriodTest { new ProgressiveMediaPeriod( Uri.parse("asset://android_asset/media/mp4/sample.mp4"), new AssetDataSource(ApplicationProvider.getApplicationContext()), - () -> new Extractor[] {new Mp4Extractor()}, + extractor, DrmSessionManager.DRM_UNSUPPORTED, new DrmSessionEventListener.EventDispatcher() .withParameters(/* windowIndex= */ 0, mediaPeriodId),