Add a setter of SubtitleParser.Factory to MediaSource.Factory

DASH: `DashMediaSource.Factory` would only propagate it to `DashChunkSource.Factory` -> `BundledChunkExtractor.Factory`

SS: `SSMediaSource.Factory` -> `SsChunkSource.Factory`

HLS: `HlsMediaSource.Factory` -> `HlsExtractorFactory`

Remove nullability of SubtitleParser.Factory across the stack

#minor-release

PiperOrigin-RevId: 601250013
This commit is contained in:
jbibik 2024-01-24 15:17:14 -08:00 committed by Copybara-Service
parent 85db94782a
commit f103a2dcf5
8 changed files with 84 additions and 15 deletions

View File

@ -20,6 +20,9 @@
`setSubtitleParserFactory` and disallow passing `null`. Use the new
`experimentalParseSubtitlesDuringExtraction(boolean)` methods to control
parsing behaviour.
* Add support for customising the `SubtitleParser.Factory` used during
extraction. This can be achieved with
`MediaSource.Factory.setSubtitleParserFactory()`.
* Transformer:
* Track Selection:
* Extractors:

View File

@ -52,6 +52,7 @@ import androidx.media3.extractor.TrackOutput;
import androidx.media3.extractor.jpeg.JpegExtractor;
import androidx.media3.extractor.text.DefaultSubtitleParserFactory;
import androidx.media3.extractor.text.SubtitleExtractor;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints;
@ -115,6 +116,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
private final DelegateFactoryLoader delegateFactoryLoader;
private DataSource.Factory dataSourceFactory;
private SubtitleParser.Factory subtitleParserFactory;
@Nullable private MediaSource.Factory serverSideAdInsertionMediaSourceFactory;
@Nullable private ExternalLoader externalImageLoader;
@Nullable private AdsLoader.Provider adsLoaderProvider;
@ -181,7 +183,8 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
public DefaultMediaSourceFactory(
DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
this.dataSourceFactory = dataSourceFactory;
delegateFactoryLoader = new DelegateFactoryLoader(extractorsFactory);
this.subtitleParserFactory = new DefaultSubtitleParserFactory();
delegateFactoryLoader = new DelegateFactoryLoader(extractorsFactory, subtitleParserFactory);
delegateFactoryLoader.setDataSourceFactory(dataSourceFactory);
liveTargetOffsetMs = C.TIME_UNSET;
liveMinOffsetMs = C.TIME_UNSET;
@ -200,6 +203,16 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
return this;
}
@CanIgnoreReturnValue
@Override
@UnstableApi
public DefaultMediaSourceFactory setSubtitleParserFactory(
SubtitleParser.Factory subtitleParserFactory) {
this.subtitleParserFactory = checkNotNull(subtitleParserFactory);
delegateFactoryLoader.setSubtitleParserFactory(subtitleParserFactory);
return this;
}
/**
* Sets the {@link AdsLoader.Provider} that provides {@link AdsLoader} instances for media items
* that have {@link MediaItem.LocalConfiguration#adsConfiguration ads configurations}.
@ -509,7 +522,6 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
.setLabel(subtitleConfigurations.get(i).label)
.setId(subtitleConfigurations.get(i).id)
.build();
DefaultSubtitleParserFactory subtitleParserFactory = new DefaultSubtitleParserFactory();
ExtractorsFactory extractorsFactory =
() ->
new Extractor[] {
@ -602,12 +614,15 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
private DataSource.@MonotonicNonNull Factory dataSourceFactory;
private boolean parseSubtitlesDuringExtraction;
private SubtitleParser.Factory subtitleParserFactory;
@Nullable private CmcdConfiguration.Factory cmcdConfigurationFactory;
@Nullable private DrmSessionManagerProvider drmSessionManagerProvider;
@Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy;
public DelegateFactoryLoader(ExtractorsFactory extractorsFactory) {
public DelegateFactoryLoader(
ExtractorsFactory extractorsFactory, SubtitleParser.Factory subtitleParserFactory) {
this.extractorsFactory = extractorsFactory;
this.subtitleParserFactory = subtitleParserFactory;
mediaSourceFactorySuppliers = new HashMap<>();
supportedTypes = new HashSet<>();
mediaSourceFactories = new HashMap<>();
@ -641,6 +656,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
if (loadErrorHandlingPolicy != null) {
mediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
}
mediaSourceFactory.setSubtitleParserFactory(subtitleParserFactory);
mediaSourceFactory.experimentalParseSubtitlesDuringExtraction(parseSubtitlesDuringExtraction);
mediaSourceFactories.put(contentType, mediaSourceFactory);
return mediaSourceFactory;
@ -665,6 +681,14 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
}
}
public void setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
this.subtitleParserFactory = subtitleParserFactory;
extractorsFactory.setSubtitleParserFactory(subtitleParserFactory);
for (MediaSource.Factory mediaSourceFactory : mediaSourceFactories.values()) {
mediaSourceFactory.setSubtitleParserFactory(subtitleParserFactory);
}
}
public void setCmcdConfigurationFactory(CmcdConfiguration.Factory cmcdConfigurationFactory) {
this.cmcdConfigurationFactory = cmcdConfigurationFactory;
for (MediaSource.Factory mediaSourceFactory : mediaSourceFactories.values()) {
@ -736,7 +760,6 @@ 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;

View File

@ -30,6 +30,7 @@ import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.CmcdConfiguration;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.extractor.text.SubtitleParser;
import java.io.IOException;
/**
@ -116,6 +117,19 @@ public interface MediaSource {
return this;
}
/**
* Sets the {@link SubtitleParser.Factory} to be used for parsing subtitles during extraction if
* {@link #experimentalParseSubtitlesDuringExtraction} is enabled.
*
* @param subtitleParserFactory The {@link SubtitleParser.Factory} for parsing subtitles during
* extraction.
* @return This factory, for convenience.
*/
@UnstableApi
default Factory setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
return this;
}
/**
* Returns the {@link C.ContentType content types} supported by media sources created by this
* factory.

View File

@ -77,6 +77,7 @@ import androidx.media3.exoplayer.upstream.Loader.LoadErrorAction;
import androidx.media3.exoplayer.upstream.LoaderErrorThrower;
import androidx.media3.exoplayer.upstream.ParsingLoadable;
import androidx.media3.exoplayer.util.SntpClient;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.base.Charsets;
import com.google.common.math.LongMath;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
@ -196,6 +197,13 @@ public final class DashMediaSource extends BaseMediaSource {
return this;
}
@Override
@CanIgnoreReturnValue
public Factory setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
chunkSourceFactory.setSubtitleParserFactory(checkNotNull(subtitleParserFactory));
return this;
}
@Override
@CanIgnoreReturnValue
public Factory experimentalParseSubtitlesDuringExtraction(

View File

@ -58,6 +58,7 @@ import androidx.media3.exoplayer.upstream.CmcdConfiguration;
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.extractor.Extractor;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
import java.lang.annotation.Documented;
@ -197,6 +198,13 @@ public final class HlsMediaSource extends BaseMediaSource
return this;
}
@CanIgnoreReturnValue
@Override
public Factory setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
extractorFactory.setSubtitleParserFactory(checkNotNull(subtitleParserFactory));
return this;
}
@Override
@CanIgnoreReturnValue
public Factory experimentalParseSubtitlesDuringExtraction(

View File

@ -65,6 +65,7 @@ import androidx.media3.exoplayer.upstream.Loader;
import androidx.media3.exoplayer.upstream.Loader.LoadErrorAction;
import androidx.media3.exoplayer.upstream.LoaderErrorThrower;
import androidx.media3.exoplayer.upstream.ParsingLoadable;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
@ -152,6 +153,13 @@ public final class SsMediaSource extends BaseMediaSource
return this;
}
@Override
@CanIgnoreReturnValue
public Factory setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
chunkSourceFactory.setSubtitleParserFactory(checkNotNull(subtitleParserFactory));
return this;
}
@Override
@CanIgnoreReturnValue
public Factory experimentalParseSubtitlesDuringExtraction(

View File

@ -368,23 +368,14 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
}
@Override
public DefaultExtractorsFactory experimentalSetTextTrackTranscodingEnabled(
public synchronized DefaultExtractorsFactory experimentalSetTextTrackTranscodingEnabled(
boolean textTrackTranscodingEnabled) {
this.textTrackTranscodingEnabled = textTrackTranscodingEnabled;
return this;
}
/**
* Sets a {@link SubtitleParser.Factory} to use when transcoding text tracks.
*
* <p>This is only used if {@link #setTextTrackTranscodingEnabled(boolean)} is enabled.
*
* <p>The default value is {@link DefaultSubtitleParserFactory}.
*
* @param subtitleParserFactory The factory for {@link SubtitleParser} instances.
* @return The factory, for convenience.
*/
@CanIgnoreReturnValue
@Override
public synchronized DefaultExtractorsFactory setSubtitleParserFactory(
SubtitleParser.Factory subtitleParserFactory) {
this.subtitleParserFactory = subtitleParserFactory;

View File

@ -18,6 +18,7 @@ package androidx.media3.extractor;
import android.net.Uri;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.text.SubtitleParser;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.List;
import java.util.Map;
@ -50,6 +51,19 @@ public interface ExtractorsFactory {
return this;
}
/**
* Sets a {@link SubtitleParser.Factory} to use when transcoding text tracks.
*
* <p>This is only works if {@link #experimentalSetTextTrackTranscodingEnabled(boolean)} is
* enabled.
*
* @param subtitleParserFactory The factory for {@link SubtitleParser} instances.
* @return The factory, for convenience.
*/
default ExtractorsFactory setSubtitleParserFactory(SubtitleParser.Factory subtitleParserFactory) {
return this;
}
/** Returns an array of new {@link Extractor} instances. */
Extractor[] createExtractors();