diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e57cf2039c..17e588cf63 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -27,6 +27,9 @@ * Fix issue where manual seeks outside of the `LiveConfiguration.min/maxOffset` range keep adjusting the offset back to `min/maxOffset`. + * Add experimental support for parsing subtitles during extraction. You + can enable this using + `MediaSource.Factory.experimentalParseSubtitlesDuringExtraction()`. * Transformer: * Add support for flattening H.265/HEVC SEF slow motion videos. * Increase transmuxing speed, especially for 'remove video' edits. @@ -82,19 +85,10 @@ * HLS Extension: * Reduce `HlsMediaPeriod` to package-private visibility. This type shouldn't be directly depended on from outside the HLS package. - * Add experimental support for parsing subtitles during extraction. You - can enable this using - `HlsMediaSource.Factory.experimentalParseSubtitlesDuringExtraction()`. * DASH Extension: - * Extend experimental support for parsing subtitles during extraction to - work with standalone text files (previously it only worked with - subtitles muxed into MP4 segments). * Parse "f800" as channel count of 5 for Dolby in DASH manifest ([#688](https://github.com/androidx/media/issues/688)). * Smooth Streaming Extension: - * Add experimental support for parsing subtitles during extraction. You - can enable this using - `SsMediaSource.Factory.experimentalParseSubtitlesDuringExtraction()`. * RTSP Extension: * Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.): * MIDI decoder: Ignore SysEx event messages diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/DefaultMediaSourceFactory.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/DefaultMediaSourceFactory.java index fe1f2841e8..a595e5c706 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/DefaultMediaSourceFactory.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/DefaultMediaSourceFactory.java @@ -125,7 +125,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { private long liveMaxOffsetMs; private float liveMinSpeed; private float liveMaxSpeed; - private boolean useProgressiveMediaSourceForSubtitles; + private boolean parseSubtitlesDuringExtraction; /** * Creates a new instance. @@ -191,21 +191,18 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { } /** - * Sets whether a {@link ProgressiveMediaSource} or {@link SingleSampleMediaSource} is constructed - * to handle {@link MediaItem.LocalConfiguration#subtitleConfigurations}. Defaults to false (i.e. - * {@link SingleSampleMediaSource}. + * {@inheritDoc} * - *

This method is experimental, and will be renamed or removed in a future release. - * - * @param useProgressiveMediaSourceForSubtitles Indicates that {@link ProgressiveMediaSource} - * should be used for subtitles instead of {@link SingleSampleMediaSource}. - * @return This factory, for convenience. + *

The current limitation is that this method will have no effect when progressive media with + * muxed subtitles is {@linkplain #createMediaSource created}. */ @CanIgnoreReturnValue @UnstableApi - public DefaultMediaSourceFactory experimentalUseProgressiveMediaSourceForSubtitles( - boolean useProgressiveMediaSourceForSubtitles) { - this.useProgressiveMediaSourceForSubtitles = useProgressiveMediaSourceForSubtitles; + @Override + public DefaultMediaSourceFactory experimentalParseSubtitlesDuringExtraction( + boolean parseSubtitlesDuringExtraction) { + this.parseSubtitlesDuringExtraction = parseSubtitlesDuringExtraction; + delegateFactoryLoader.setParseSubtitlesDuringExtraction(parseSubtitlesDuringExtraction); return this; } @@ -508,7 +505,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { MediaSource[] mediaSources = new MediaSource[subtitleConfigurations.size() + 1]; mediaSources[0] = mediaSource; for (int i = 0; i < subtitleConfigurations.size(); i++) { - if (useProgressiveMediaSourceForSubtitles) { + if (parseSubtitlesDuringExtraction) { Format format = new Format.Builder() .setSampleMimeType(subtitleConfigurations.get(i).mimeType) @@ -610,6 +607,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { private final Map mediaSourceFactories; private DataSource.@MonotonicNonNull Factory dataSourceFactory; + private boolean parseSubtitlesDuringExtraction; @Nullable private CmcdConfiguration.Factory cmcdConfigurationFactory; @Nullable private DrmSessionManagerProvider drmSessionManagerProvider; @Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy; @@ -649,6 +647,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { if (loadErrorHandlingPolicy != null) { mediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy); } + mediaSourceFactory.experimentalParseSubtitlesDuringExtraction(parseSubtitlesDuringExtraction); mediaSourceFactories.put(contentType, mediaSourceFactory); return mediaSourceFactory; } @@ -663,6 +662,14 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { } } + public void setParseSubtitlesDuringExtraction(boolean parseSubtitlesDuringExtraction) { + this.parseSubtitlesDuringExtraction = parseSubtitlesDuringExtraction; + for (MediaSource.Factory mediaSourceFactory : mediaSourceFactories.values()) { + mediaSourceFactory.experimentalParseSubtitlesDuringExtraction( + parseSubtitlesDuringExtraction); + } + } + public void setCmcdConfigurationFactory(CmcdConfiguration.Factory cmcdConfigurationFactory) { this.cmcdConfigurationFactory = cmcdConfigurationFactory; for (MediaSource.Factory mediaSourceFactory : mediaSourceFactories.values()) { @@ -734,6 +741,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { mediaSourceFactorySupplier = () -> newInstance(clazz); break; case C.CONTENT_TYPE_OTHER: + // TODO(181312195): potential setter on Default/ExtractorsFactory for subtitles mediaSourceFactorySupplier = () -> new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory); break; diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/MediaSource.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/MediaSource.java index c25a07b53c..df11e91827 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/MediaSource.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/MediaSource.java @@ -98,6 +98,24 @@ public interface MediaSource { @UnstableApi Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy); + /** + * Sets whether subtitles should be parsed as part of extraction (before being added to the + * sample queue) or as part of rendering (when being taken from the sample queue). Defaults to + * {@code false} (i.e. subtitles will be parsed as part of rendering). + * + *

This method is experimental and will be renamed or removed in a future release. + * + * @param parseSubtitlesDuringExtraction Whether to parse subtitles during extraction or + * rendering. + * @return This factory, for convenience. + */ + // TODO: b/289916598 - Flip the default of this to true. + @UnstableApi + default Factory experimentalParseSubtitlesDuringExtraction( + boolean parseSubtitlesDuringExtraction) { + return this; + } + /** * Returns the {@link C.ContentType content types} supported by media sources created by this * factory. diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java index 87663c39ce..5fcebe2c6d 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java @@ -103,7 +103,7 @@ public final class PlaylistPlaybackTest { new CapturingRenderersFactory(applicationContext); MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(applicationContext) - .experimentalUseProgressiveMediaSourceForSubtitles(true); + .experimentalParseSubtitlesDuringExtraction(true); ExoPlayer player = new ExoPlayer.Builder(applicationContext, capturingRenderersFactory) .setClock(new FakeClock(/* isAutoAdvancing= */ true)) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/WebvttPlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/WebvttPlaybackTest.java index 9297a017ad..8a53df893e 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/WebvttPlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/WebvttPlaybackTest.java @@ -60,7 +60,7 @@ public class WebvttPlaybackTest { new CapturingRenderersFactory(applicationContext); MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(applicationContext) - .experimentalUseProgressiveMediaSourceForSubtitles(true); + .experimentalParseSubtitlesDuringExtraction(true); ExoPlayer player = new ExoPlayer.Builder(applicationContext, capturingRenderersFactory) .setClock(new FakeClock(/* isAutoAdvancing= */ true)) diff --git a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java index 36fe6171db..4d02994303 100644 --- a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java +++ b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/DashMediaSource.java @@ -200,12 +200,7 @@ public final class DashMediaSource extends BaseMediaSource { } /** - * Sets whether subtitles should be parsed as part of extraction (before the sample queue) or as - * part of rendering (after the sample queue). Defaults to false (i.e. subtitles will be parsed - * as part of rendering). - * - *

This method is experimental. Its default value may change, or it may be renamed or removed - * in a future release. + * {@inheritDoc} * *

This method may only be used with {@link DefaultDashChunkSource.Factory}. * @@ -213,8 +208,8 @@ public final class DashMediaSource extends BaseMediaSource { * rendering. * @return This factory, for convenience. */ - // TODO: b/289916598 - Flip the default of this to true (probably wired up to a single method on - // DefaultMediaSourceFactory via the MediaSource.Factory interface). + // TODO: b/289916598 - Flip the default of this to true. + @Override public Factory experimentalParseSubtitlesDuringExtraction( boolean parseSubtitlesDuringExtraction) { if (parseSubtitlesDuringExtraction) { diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java index e2cf2e7b9d..f1697eb4da 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java @@ -200,12 +200,7 @@ public final class HlsMediaSource extends BaseMediaSource } /** - * Sets whether subtitles should be parsed as part of extraction (before the sample queue) or as - * part of rendering (after the sample queue). Defaults to false (i.e. subtitles will be parsed - * as part of rendering). - * - *

This method is experimental. Its default value may change, or it may be renamed or removed - * in a future release. + * {@inheritDoc} * *

This method may only be used with {@link DefaultHlsExtractorFactory}. * @@ -213,8 +208,8 @@ public final class HlsMediaSource extends BaseMediaSource * rendering. * @return This factory, for convenience. */ - // TODO: b/289916598 - Flip the default of this to true (probably wired up to a single method on - // DefaultMediaSourceFactory via the MediaSource.Factory interface). + // TODO: b/289916598 - Flip the default of this to true. + @Override public Factory experimentalParseSubtitlesDuringExtraction( boolean parseSubtitlesDuringExtraction) { if (parseSubtitlesDuringExtraction) { diff --git a/libraries/exoplayer_smoothstreaming/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java b/libraries/exoplayer_smoothstreaming/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java index 5b51c185a0..21fd45e906 100644 --- a/libraries/exoplayer_smoothstreaming/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java +++ b/libraries/exoplayer_smoothstreaming/src/main/java/androidx/media3/exoplayer/smoothstreaming/SsMediaSource.java @@ -156,12 +156,7 @@ public final class SsMediaSource extends BaseMediaSource } /** - * Sets whether subtitles should be parsed as part of extraction (before being added to the - * sample queue) or as part of rendering (when being taken from the sample queue). Defaults to - * {@code false} (i.e. subtitles will be parsed as part of rendering). - * - *

This method is experimental. Its default value may change, or it may be renamed or removed - * in a future release. + * {@inheritDoc} * *

This method may only be used with {@link DefaultSsChunkSource.Factory}. * @@ -169,8 +164,8 @@ public final class SsMediaSource extends BaseMediaSource * rendering. * @return This factory, for convenience. */ - // TODO: b/289916598 - Flip the default of this to true (probably wired up to a single method on - // DefaultMediaSourceFactory via the MediaSource.Factory interface). + // TODO: b/289916598 - Flip the default of this to true. + @Override public Factory experimentalParseSubtitlesDuringExtraction( boolean parseSubtitlesDuringExtraction) { if (parseSubtitlesDuringExtraction) {