Commit dd19bc89 by apodob Committed by Ian Baker

Integrate ExoplayerCuesDecoder and SubtitleExtractor

This CL contains integration of the ExoplayerCuesDecoder and the
SubtitleExtractor with the player. The SubtitleExtractor is integrated
inside the DefaultMediaSourceFactory. The flag was added to the
state of the DefaultMediaSourceFactory to let user decide between the
ProgressiveMediaSource and the SingleSampleMediaSource as a source for
subtitles. Choosing the ProgressiveMediaSource will cause data to flow
through the SubtitleExtractor and eventually the ExoplayerCuesDecoder.

PiperOrigin-RevId: 394500305
parent 3213f969
......@@ -21,14 +21,18 @@ import android.content.Context;
import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManagerProvider;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.subtitle.SubtitleExtractor;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
......@@ -112,6 +116,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
private long liveMaxOffsetMs;
private float liveMinSpeed;
private float liveMaxSpeed;
private boolean useProgressiveMediaSourceForSubtitles;
/**
* Creates a new instance.
......@@ -167,6 +172,23 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
}
/**
* Sets whether a {@link ProgressiveMediaSource} or {@link SingleSampleMediaSource} is constructed
* to handle {@link MediaItem.PlaybackProperties#subtitles}. Defaults to false (i.e. {@link
* SingleSampleMediaSource}.
*
* <p>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.
*/
public DefaultMediaSourceFactory experimentalUseProgressiveMediaSourceForSubtitles(
boolean useProgressiveMediaSourceForSubtitles) {
this.useProgressiveMediaSourceForSubtitles = useProgressiveMediaSourceForSubtitles;
return this;
}
/**
* Sets the {@link AdsLoaderProvider} that provides {@link AdsLoader} instances for media items
* that have {@link MediaItem.PlaybackProperties#adsConfiguration ads configurations}.
*
......@@ -370,14 +392,38 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
if (!subtitles.isEmpty()) {
MediaSource[] mediaSources = new MediaSource[subtitles.size() + 1];
mediaSources[0] = mediaSource;
SingleSampleMediaSource.Factory singleSampleSourceFactory =
new SingleSampleMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
for (int i = 0; i < subtitles.size(); i++) {
mediaSources[i + 1] =
singleSampleSourceFactory.createMediaSource(
subtitles.get(i), /* durationUs= */ C.TIME_UNSET);
if (useProgressiveMediaSourceForSubtitles
&& subtitles.get(i).mimeType.equals(MimeTypes.TEXT_VTT)) {
int index = i;
ProgressiveMediaSource.Factory progressiveMediaSourceFactory =
new ProgressiveMediaSource.Factory(
dataSourceFactory,
() ->
new Extractor[] {
new SubtitleExtractor(
new WebvttDecoder(),
new Format.Builder()
.setSampleMimeType(subtitles.get(index).mimeType)
.setLanguage(subtitles.get(index).language)
.setSelectionFlags(subtitles.get(index).selectionFlags)
.setRoleFlags(subtitles.get(index).roleFlags)
.setLabel(subtitles.get(index).label)
.build())
});
mediaSources[i + 1] =
progressiveMediaSourceFactory.createMediaSource(
MediaItem.fromUri(subtitles.get(i).uri.toString()));
} else {
SingleSampleMediaSource.Factory singleSampleSourceFactory =
new SingleSampleMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
mediaSources[i + 1] =
singleSampleSourceFactory.createMediaSource(
subtitles.get(i), /* durationUs= */ C.TIME_UNSET);
}
}
mediaSource = new MergingMediaSource(mediaSources);
}
return maybeWrapWithAdsMediaSource(mediaItem, maybeClipMediaSource(mediaItem, mediaSource));
......
......@@ -66,6 +66,7 @@ public interface SubtitleDecoderFactory {
* <li>Cea708 ({@link Cea708Decoder})
* <li>DVB ({@link DvbDecoder})
* <li>PGS ({@link PgsDecoder})
* <li>Exoplayer Cues ({@link ExoplayerCuesDecoder})
* </ul>
*/
SubtitleDecoderFactory DEFAULT =
......@@ -84,7 +85,8 @@ public interface SubtitleDecoderFactory {
|| MimeTypes.APPLICATION_MP4CEA608.equals(mimeType)
|| MimeTypes.APPLICATION_CEA708.equals(mimeType)
|| MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)
|| MimeTypes.APPLICATION_PGS.equals(mimeType);
|| MimeTypes.APPLICATION_PGS.equals(mimeType)
|| MimeTypes.TEXT_EXOPLAYER_CUES.equals(mimeType);
}
@Override
......@@ -116,6 +118,8 @@ public interface SubtitleDecoderFactory {
return new DvbDecoder(format.initializationData);
case MimeTypes.APPLICATION_PGS:
return new PgsDecoder();
case MimeTypes.TEXT_EXOPLAYER_CUES:
return new ExoplayerCuesDecoder();
default:
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment